b48be1092a38198e97d30c76538a88f809871d16
[gcc.git] / gcc / config / sh / sh.md
1 ;;- Machine description for Renesas / SuperH SH.
2 ;; Copyright (C) 1993-2014 Free Software Foundation, Inc.
3 ;; Contributed by Steve Chamberlain (sac@cygnus.com).
4 ;; Improved by Jim Wilson (wilson@cygnus.com).
5
6 ;; This file is part of GCC.
7
8 ;; GCC is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 3, or (at your option)
11 ;; any later version.
12
13 ;; GCC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
17
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3. If not see
20 ;; <http://www.gnu.org/licenses/>.
21
22
23 ;; ??? Should prepend a * to all pattern names which are not used.
24 ;; This will make the compiler smaller, and rebuilds after changes faster.
25
26 ;; ??? Should be enhanced to include support for many more GNU superoptimizer
27 ;; sequences. Especially the sequences for arithmetic right shifts.
28
29 ;; ??? Should check all DImode patterns for consistency and usefulness.
30
31 ;; ??? The MAC.W and MAC.L instructions are not supported. There is no
32 ;; way to generate them.
33
34 ;; BSR is not generated by the compiler proper, but when relaxing, it
35 ;; generates .uses pseudo-ops that allow linker relaxation to create
36 ;; BSR. This is actually implemented in bfd/{coff,elf32}-sh.c
37
38 ;; Special constraints for SH machine description:
39 ;;
40 ;; t -- T
41 ;; x -- mac
42 ;; l -- pr
43 ;; z -- r0
44 ;;
45 ;; Special formats used for outputting SH instructions:
46 ;;
47 ;; %. -- print a .s if insn needs delay slot
48 ;; %@ -- print rte/rts if is/isn't an interrupt function
49 ;; %# -- output a nop if there is nothing to put in the delay slot
50 ;; %O -- print a constant without the #
51 ;; %R -- print the lsw reg of a double
52 ;; %S -- print the msw reg of a double
53 ;; %T -- print next word of a double REG or MEM
54 ;;
55 ;; Special predicates:
56 ;;
57 ;; arith_operand -- operand is valid source for arithmetic op
58 ;; arith_reg_operand -- operand is valid register for arithmetic op
59 ;; general_movdst_operand -- operand is valid move destination
60 ;; general_movsrc_operand -- operand is valid move source
61 ;; logical_operand -- operand is valid source for logical op
62
63 ;; -------------------------------------------------------------------------
64 ;; Constants
65 ;; -------------------------------------------------------------------------
66
67 (define_constants [
68 (AP_REG 145)
69 (PR_REG 146)
70 (T_REG 147)
71 (GBR_REG 144)
72 (MACH_REG 148)
73 (MACL_REG 149)
74 (FPUL_REG 150)
75 (RAP_REG 152)
76
77 (FPSCR_REG 151)
78
79 ;; Virtual FPSCR - bits that are used by FP ops.
80 (FPSCR_MODES_REG 154)
81
82 ;; Virtual FPSCR - bits that are updated by FP ops.
83 (FPSCR_STAT_REG 155)
84
85 (PIC_REG 12)
86 (FP_REG 14)
87 (SP_REG 15)
88
89 (PR_MEDIA_REG 18)
90 (T_MEDIA_REG 19)
91
92 (R0_REG 0)
93 (R1_REG 1)
94 (R2_REG 2)
95 (R3_REG 3)
96 (R4_REG 4)
97 (R5_REG 5)
98 (R6_REG 6)
99 (R7_REG 7)
100 (R8_REG 8)
101 (R9_REG 9)
102 (R10_REG 10)
103 (R20_REG 20)
104 (R21_REG 21)
105 (R22_REG 22)
106 (R23_REG 23)
107
108 (DR0_REG 64)
109 (DR2_REG 66)
110 (DR4_REG 68)
111 (FR23_REG 87)
112
113 (TR0_REG 128)
114 (TR1_REG 129)
115 (TR2_REG 130)
116
117 (XD0_REG 136)
118
119 (FPSCR_PR 524288) ;; 1 << 19
120 (FPSCR_SZ 1048576) ;; 1 << 20
121 (FPSCR_FR 2097152) ;; 1 << 21
122 ])
123
124 (define_c_enum "unspec" [
125 ;; These are used with unspec.
126 UNSPEC_COMPACT_ARGS
127 UNSPEC_MOVA
128 UNSPEC_CASESI
129 UNSPEC_DATALABEL
130 UNSPEC_BBR
131 UNSPEC_SFUNC
132 UNSPEC_PIC
133 UNSPEC_GOT
134 UNSPEC_GOTOFF
135 UNSPEC_PLT
136 UNSPEC_CALLER
137 UNSPEC_GOTPLT
138 UNSPEC_ICACHE
139 UNSPEC_INIT_TRAMP
140 UNSPEC_FCOSA
141 UNSPEC_FSRRA
142 UNSPEC_FSINA
143 UNSPEC_NSB
144 UNSPEC_ALLOCO
145 UNSPEC_TLSGD
146 UNSPEC_TLSLDM
147 UNSPEC_TLSIE
148 UNSPEC_DTPOFF
149 UNSPEC_GOTTPOFF
150 UNSPEC_TPOFF
151 UNSPEC_RA
152 UNSPEC_DIV_INV_M0
153 UNSPEC_DIV_INV_M1
154 UNSPEC_DIV_INV_M2
155 UNSPEC_DIV_INV_M3
156 UNSPEC_DIV_INV20
157 UNSPEC_DIV_INV_TABLE
158 UNSPEC_ASHIFTRT
159 UNSPEC_THUNK
160 UNSPEC_CHKADD
161 UNSPEC_SP_SET
162 UNSPEC_SP_TEST
163 UNSPEC_MOVUA
164 ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT).
165 ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent.
166 UNSPEC_EXTRACT_S16
167 UNSPEC_EXTRACT_U16
168 ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR.
169 UNSPEC_SYMOFF
170 ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
171 UNSPEC_PCREL_SYMOFF
172 ;; Misc builtins
173 UNSPEC_BUILTIN_STRLEN
174 ])
175
176 (define_c_enum "unspecv" [
177 ;; These are used with unspec_volatile.
178 UNSPECV_BLOCKAGE
179 UNSPECV_ALIGN
180 UNSPECV_CONST2
181 UNSPECV_CONST4
182 UNSPECV_CONST8
183 UNSPECV_WINDOW_END
184 UNSPECV_CONST_END
185 UNSPECV_EH_RETURN
186 UNSPECV_GBR
187 UNSPECV_SP_SWITCH_B
188 UNSPECV_SP_SWITCH_E
189
190 UNSPECV_FPSCR_MODES
191 UNSPECV_FPSCR_STAT
192 ])
193
194 ;; -------------------------------------------------------------------------
195 ;; Attributes
196 ;; -------------------------------------------------------------------------
197
198 ;; Target CPU.
199
200 (define_attr "cpu"
201 "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
202 (const (symbol_ref "sh_cpu_attr")))
203
204 (define_attr "endian" "big,little"
205 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
206 (const_string "little") (const_string "big"))))
207
208 ;; Indicate if the default fpu mode is single precision.
209 (define_attr "fpu_single" "yes,no"
210 (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
211 (const_string "yes") (const_string "no"))))
212
213 (define_attr "fmovd" "yes,no"
214 (const (if_then_else (symbol_ref "TARGET_FMOVD")
215 (const_string "yes") (const_string "no"))))
216 ;; pipeline model
217 (define_attr "pipe_model" "sh1,sh4,sh5media"
218 (const
219 (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
220 (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
221 (const_string "sh1"))))
222
223 ;; cbranch conditional branch instructions
224 ;; jump unconditional jumps
225 ;; arith ordinary arithmetic
226 ;; arith3 a compound insn that behaves similarly to a sequence of
227 ;; three insns of type arith
228 ;; arith3b like above, but might end with a redirected branch
229 ;; load from memory
230 ;; load_si Likewise, SImode variant for general register.
231 ;; fload Likewise, but load to fp register.
232 ;; store to memory
233 ;; fstore floating point register to memory
234 ;; move general purpose register to register
235 ;; movi8 8-bit immediate to general purpose register
236 ;; mt_group other sh4 mt instructions
237 ;; fmove register to register, floating point
238 ;; smpy word precision integer multiply
239 ;; dmpy longword or doublelongword precision integer multiply
240 ;; return rts
241 ;; pload load of pr reg, which can't be put into delay slot of rts
242 ;; prset copy register to pr reg, ditto
243 ;; pstore store of pr reg, which can't be put into delay slot of jsr
244 ;; prget copy pr to register, ditto
245 ;; pcload pc relative load of constant value
246 ;; pcfload Likewise, but load to fp register.
247 ;; pcload_si Likewise, SImode variant for general register.
248 ;; rte return from exception
249 ;; sfunc special function call with known used registers
250 ;; call function call
251 ;; fp floating point
252 ;; fpscr_toggle toggle a bit in the fpscr
253 ;; fdiv floating point divide (or square root)
254 ;; gp_fpul move from general purpose register to fpul
255 ;; fpul_gp move from fpul to general purpose register
256 ;; mac_gp move from mac[lh] to general purpose register
257 ;; gp_mac move from general purpose register to mac[lh]
258 ;; mac_mem move from mac[lh] to memory
259 ;; mem_mac move from memory to mac[lh]
260 ;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv
261 ;; ftrc_s fix_truncsfsi2_i4
262 ;; dfdiv double precision floating point divide (or square root)
263 ;; cwb ic_invalidate_line_i
264 ;; movua SH4a unaligned load
265 ;; fsrra square root reciprocal approximate
266 ;; fsca sine and cosine approximate
267 ;; tls_load load TLS related address
268 ;; arith_media SHmedia arithmetic, logical, and shift instructions
269 ;; cbranch_media SHmedia conditional branch instructions
270 ;; cmp_media SHmedia compare instructions
271 ;; dfdiv_media SHmedia double precision divide and square root
272 ;; dfmul_media SHmedia double precision multiply instruction
273 ;; dfparith_media SHmedia double precision floating point arithmetic
274 ;; dfpconv_media SHmedia double precision floating point conversions
275 ;; dmpy_media SHmedia longword multiply
276 ;; fcmp_media SHmedia floating point compare instructions
277 ;; fdiv_media SHmedia single precision divide and square root
278 ;; fload_media SHmedia floating point register load instructions
279 ;; fmove_media SHmedia floating point register moves (inc. fabs and fneg)
280 ;; fparith_media SHmedia single precision floating point arithmetic
281 ;; fpconv_media SHmedia single precision floating point conversions
282 ;; fstore_media SHmedia floating point register store instructions
283 ;; gettr_media SHmedia gettr instruction
284 ;; invalidate_line_media SHmedia invalidate_line sequence
285 ;; jump_media SHmedia unconditional branch instructions
286 ;; load_media SHmedia general register load instructions
287 ;; pt_media SHmedia pt instruction (expanded by assembler)
288 ;; ptabs_media SHmedia ptabs instruction
289 ;; store_media SHmedia general register store instructions
290 ;; mcmp_media SHmedia multimedia compare, absolute, saturating ops
291 ;; mac_media SHmedia mac-style fixed point operations
292 ;; d2mpy_media SHmedia: two 32-bit integer multiplies
293 ;; atrans_media SHmedia approximate transcendental functions
294 ;; ustore_media SHmedia unaligned stores
295 ;; nil no-op move, will be deleted.
296
297 (define_attr "type"
298 "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,
299 fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore,
300 prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s,
301 dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,
302 gp_mac,mac_mem,mem_mac,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load,
303 arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,
304 dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,
305 fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,
306 jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,
307 d2mpy_media,atrans_media,ustore_media,nil,other"
308 (const_string "other"))
309
310 ;; We define a new attribute namely "insn_class".We use
311 ;; this for the DFA based pipeline description.
312 ;;
313 ;; mt_group SH4 "mt" group instructions.
314 ;;
315 ;; ex_group SH4 "ex" group instructions.
316 ;;
317 ;; ls_group SH4 "ls" group instructions.
318 ;;
319 (define_attr "insn_class"
320 "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
321 (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
322 (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group")
323 (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,
324 store,fstore,gp_fpul,fpul_gp") (const_string "ls_group")
325 (eq_attr "type" "cbranch,jump") (const_string "br_group")
326 (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
327 (const_string "fe_group")
328 (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,
329 prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb,
330 gp_mac,mac_mem,mem_mac") (const_string "co_group")]
331 (const_string "none")))
332
333 ;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
334 ;; so these do not belong in an insn group, although they are modeled
335 ;; with their own define_insn_reservations.
336
337 ;; Indicate what precision must be selected in fpscr for this insn, if any.
338 (define_attr "fp_mode" "single,double,none" (const_string "none"))
339
340 ;; Indicate if the fpu mode is set by this instruction
341 ;; "unknown" must have the value as "none" in fp_mode, and means
342 ;; that the instruction/abi has left the processor in an unknown
343 ;; state.
344 ;; "none" means that nothing has changed and no mode is set.
345 ;; This attribute is only used for the Renesas ABI.
346 (define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
347
348 ; If a conditional branch destination is within -252..258 bytes away
349 ; from the instruction it can be 2 bytes long. Something in the
350 ; range -4090..4100 bytes can be 6 bytes long. All other conditional
351 ; branches are initially assumed to be 16 bytes long.
352 ; In machine_dependent_reorg, we split all branches that are longer than
353 ; 2 bytes.
354
355 ;; The maximum range used for SImode constant pool entries is 1018. A final
356 ;; instruction can add 8 bytes while only being 4 bytes in size, thus we
357 ;; can have a total of 1022 bytes in the pool. Add 4 bytes for a branch
358 ;; instruction around the pool table, 2 bytes of alignment before the table,
359 ;; and 30 bytes of alignment after the table. That gives a maximum total
360 ;; pool size of 1058 bytes.
361 ;; Worst case code/pool content size ratio is 1:2 (using asms).
362 ;; Thus, in the worst case, there is one instruction in front of a maximum
363 ;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
364 ;; code. For the last n bytes of code, there are 2n + 36 bytes of pool.
365 ;; If we have a forward branch, the initial table will be put after the
366 ;; unconditional branch.
367 ;;
368 ;; ??? We could do much better by keeping track of the actual pcloads within
369 ;; the branch range and in the pcload range in front of the branch range.
370
371 ;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
372 ;; inside an le.
373 (define_attr "short_cbranch_p" "no,yes"
374 (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
375 (const_string "no")
376 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
377 (const_string "yes")
378 (match_test "NEXT_INSN (PREV_INSN (insn)) != insn")
379 (const_string "no")
380 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
381 (const_string "yes")
382 ] (const_string "no")))
383
384 (define_attr "med_branch_p" "no,yes"
385 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
386 (const_int 1988))
387 (const_string "yes")
388 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
389 (const_string "no")
390 (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
391 (const_int 8186))
392 (const_string "yes")
393 ] (const_string "no")))
394
395 (define_attr "med_cbranch_p" "no,yes"
396 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
397 (const_int 1986))
398 (const_string "yes")
399 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
400 (const_string "no")
401 (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
402 (const_int 8184))
403 (const_string "yes")
404 ] (const_string "no")))
405
406 (define_attr "braf_branch_p" "no,yes"
407 (cond [(match_test "! TARGET_SH2")
408 (const_string "no")
409 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
410 (const_int 20660))
411 (const_string "yes")
412 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
413 (const_string "no")
414 (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
415 (const_int 65530))
416 (const_string "yes")
417 ] (const_string "no")))
418
419 (define_attr "braf_cbranch_p" "no,yes"
420 (cond [(match_test "! TARGET_SH2")
421 (const_string "no")
422 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
423 (const_int 20658))
424 (const_string "yes")
425 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
426 (const_string "no")
427 (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
428 (const_int 65528))
429 (const_string "yes")
430 ] (const_string "no")))
431
432 ;; An unconditional jump in the range -4092..4098 can be 2 bytes long.
433 ;; For wider ranges, we need a combination of a code and a data part.
434 ;; If we can get a scratch register for a long range jump, the code
435 ;; part can be 4 bytes long; otherwise, it must be 8 bytes long.
436 ;; If the jump is in the range -32764..32770, the data part can be 2 bytes
437 ;; long; otherwise, it must be 6 bytes long.
438
439 ;; All other instructions are two bytes long by default.
440
441 ;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
442 ;; but getattrtab doesn't understand this.
443 (define_attr "length" ""
444 (cond [(eq_attr "type" "cbranch")
445 (cond [(eq_attr "short_cbranch_p" "yes")
446 (const_int 2)
447 (eq_attr "med_cbranch_p" "yes")
448 (const_int 6)
449 (eq_attr "braf_cbranch_p" "yes")
450 (const_int 12)
451 ;; ??? using pc is not computed transitively.
452 (ne (match_dup 0) (match_dup 0))
453 (const_int 14)
454 (match_test "flag_pic")
455 (const_int 24)
456 ] (const_int 16))
457 (eq_attr "type" "jump")
458 (cond [(eq_attr "med_branch_p" "yes")
459 (const_int 2)
460 (and (match_test "prev_nonnote_insn (insn)")
461 (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
462 (symbol_ref "INSN"))
463 (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
464 (symbol_ref "code_for_indirect_jump_scratch"))))
465 (cond [(eq_attr "braf_branch_p" "yes")
466 (const_int 6)
467 (not (match_test "flag_pic"))
468 (const_int 10)
469 (match_test "TARGET_SH2")
470 (const_int 10)] (const_int 18))
471 (eq_attr "braf_branch_p" "yes")
472 (const_int 10)
473 ;; ??? using pc is not computed transitively.
474 (ne (match_dup 0) (match_dup 0))
475 (const_int 12)
476 (match_test "flag_pic")
477 (const_int 22)
478 ] (const_int 14))
479 (eq_attr "type" "pt_media")
480 (if_then_else (match_test "TARGET_SHMEDIA64")
481 (const_int 20) (const_int 12))
482 (and (eq_attr "type" "jump_media")
483 (match_test "TARGET_SH5_CUT2_WORKAROUND"))
484 (const_int 8)
485 ] (if_then_else (match_test "TARGET_SHMEDIA")
486 (const_int 4)
487 (const_int 2))))
488
489 ;; DFA descriptions for the pipelines
490
491 (include "sh1.md")
492 (include "shmedia.md")
493 (include "sh4.md")
494
495 (include "iterators.md")
496 (include "predicates.md")
497 (include "constraints.md")
498
499 ;; Definitions for filling delay slots
500
501 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
502
503 (define_attr "banked" "yes,no"
504 (cond [(match_test "sh_loads_bankedreg_p (insn)")
505 (const_string "yes")]
506 (const_string "no")))
507
508 ;; ??? This should be (nil) instead of (const_int 0)
509 (define_attr "hit_stack" "yes,no"
510 (cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)"))
511 (const_string "no")]
512 (const_string "yes")))
513
514 (define_attr "interrupt_function" "no,yes"
515 (const (symbol_ref "current_function_interrupt")))
516
517 (define_attr "in_delay_slot" "yes,no"
518 (cond [(eq_attr "type" "cbranch") (const_string "no")
519 (eq_attr "type" "pcload,pcload_si") (const_string "no")
520 (eq_attr "type" "fpscr_toggle") (const_string "no")
521 (eq_attr "needs_delay_slot" "yes") (const_string "no")
522 (eq_attr "length" "2") (const_string "yes")
523 ] (const_string "no")))
524
525 (define_attr "cond_delay_slot" "yes,no"
526 (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
527 ] (const_string "no")))
528
529 (define_attr "is_sfunc" ""
530 (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
531
532 (define_attr "is_mac_media" ""
533 (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
534
535 (define_attr "branch_zero" "yes,no"
536 (cond [(eq_attr "type" "!cbranch") (const_string "no")
537 (ne (symbol_ref "(next_active_insn (insn)\
538 == (prev_active_insn\
539 (XEXP (SET_SRC (PATTERN (insn)), 1))))\
540 && get_attr_length (next_active_insn (insn)) == 2")
541 (const_int 0))
542 (const_string "yes")]
543 (const_string "no")))
544
545 ;; SH4 Double-precision computation with double-precision result -
546 ;; the two halves are ready at different times.
547 (define_attr "dfp_comp" "yes,no"
548 (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
549 (const_string "no")))
550
551 ;; Insns for which the latency of a preceding fp insn is decreased by one.
552 (define_attr "late_fp_use" "yes,no" (const_string "no"))
553 ;; And feeding insns for which this relevant.
554 (define_attr "any_fp_comp" "yes,no"
555 (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
556 (const_string "yes")]
557 (const_string "no")))
558
559 (define_attr "any_int_load" "yes,no"
560 (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
561 (const_string "yes")]
562 (const_string "no")))
563
564 (define_attr "highpart" "user, ignore, extend, depend, must_split"
565 (const_string "user"))
566
567 (define_delay
568 (eq_attr "needs_delay_slot" "yes")
569 [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
570
571 ;; Since a normal return (rts) implicitly uses the PR register,
572 ;; we can't allow PR register loads in an rts delay slot.
573 ;; On the SH1* and SH2*, the rte instruction reads the return pc from the
574 ;; stack, and thus we can't put a pop instruction in its delay slot.
575 ;; On the SH3* and SH4*, the rte instruction does not use the stack, so a
576 ;; pop instruction can go in the delay slot, unless it references a banked
577 ;; register (the register bank is switched by rte).
578 (define_delay
579 (eq_attr "type" "return")
580 [(and (eq_attr "in_delay_slot" "yes")
581 (ior (and (eq_attr "interrupt_function" "no")
582 (eq_attr "type" "!pload,prset"))
583 (and (eq_attr "interrupt_function" "yes")
584 (ior (match_test "TARGET_SH3") (eq_attr "hit_stack" "no"))
585 (eq_attr "banked" "no"))))
586 (nil) (nil)])
587
588 ;; Since a call implicitly uses the PR register, we can't allow
589 ;; a PR register store in a jsr delay slot.
590
591 (define_delay
592 (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
593 [(and (eq_attr "in_delay_slot" "yes")
594 (eq_attr "type" "!pstore,prget")) (nil) (nil)])
595
596 ;; Say that we have annulled true branches, since this gives smaller and
597 ;; faster code when branches are predicted as not taken.
598
599 ;; ??? The non-annulled condition should really be "in_delay_slot",
600 ;; but insns that can be filled in non-annulled get priority over insns
601 ;; that can only be filled in anulled.
602
603 (define_delay
604 (and (eq_attr "type" "cbranch")
605 (match_test "TARGET_SH2"))
606 ;; SH2e has a hardware bug that pretty much prohibits the use of
607 ;; annulled delay slots.
608 [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
609 (not (eq_attr "cpu" "sh2e"))) (nil)])
610 \f
611 ;; -------------------------------------------------------------------------
612 ;; SImode signed integer comparisons
613 ;; -------------------------------------------------------------------------
614
615 ;; Various patterns to generate the TST #imm, R0 instruction.
616 ;; Although this adds some pressure on the R0 register, it can potentially
617 ;; result in faster code, even if the operand has to be moved to R0 first.
618 ;; This is because on SH4 TST #imm, R0 and MOV Rm, Rn are both MT group
619 ;; instructions and thus will be executed in parallel. On SH4A TST #imm, R0
620 ;; is an EX group instruction but still can be executed in parallel with the
621 ;; MT group MOV Rm, Rn instruction.
622
623 ;; Usual TST #imm, R0 patterns for SI, HI and QI
624 ;; This is usually used for bit patterns other than contiguous bits
625 ;; and single bits.
626 (define_insn "tstsi_t"
627 [(set (reg:SI T_REG)
628 (eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r")
629 (match_operand:SI 1 "logical_operand" "K08,r"))
630 (const_int 0)))]
631 "TARGET_SH1"
632 "tst %1,%0"
633 [(set_attr "type" "mt_group")])
634
635 (define_insn "tsthi_t"
636 [(set (reg:SI T_REG)
637 (eq:SI (subreg:SI (and:HI (match_operand:HI 0 "logical_operand" "%z")
638 (match_operand 1 "const_int_operand")) 0)
639 (const_int 0)))]
640 "TARGET_SH1
641 && CONST_OK_FOR_K08 (INTVAL (operands[1]))"
642 "tst %1,%0"
643 [(set_attr "type" "mt_group")])
644
645 (define_insn "tstqi_t"
646 [(set (reg:SI T_REG)
647 (eq:SI (subreg:SI (and:QI (match_operand:QI 0 "logical_operand" "%z")
648 (match_operand 1 "const_int_operand")) 0)
649 (const_int 0)))]
650 "TARGET_SH1
651 && (CONST_OK_FOR_K08 (INTVAL (operands[1]))
652 || CONST_OK_FOR_I08 (INTVAL (operands[1])))"
653 {
654 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
655 return "tst %1,%0";
656 }
657 [(set_attr "type" "mt_group")])
658
659 ;; Test low QI subreg against zero.
660 ;; This avoids unnecessary zero extension before the test.
661 (define_insn "*tstqi_t_zero"
662 [(set (reg:SI T_REG)
663 (eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))]
664 "TARGET_SH1"
665 "tst #255,%0"
666 [(set_attr "type" "mt_group")])
667
668 ;; This pattern might be risky because it also tests the upper bits and not
669 ;; only the subreg. However, it seems that combine will get to this only
670 ;; when testing sign/zero extended values. In this case the extended upper
671 ;; bits do not matter.
672 (define_insn "*tst<mode>_t_zero"
673 [(set (reg:SI T_REG)
674 (eq:SI
675 (subreg:QIHI
676 (and:SI (match_operand:SI 0 "arith_reg_operand" "%r")
677 (match_operand:SI 1 "arith_reg_operand" "r")) <lowpart_le>)
678 (const_int 0)))]
679 "TARGET_SH1 && TARGET_LITTLE_ENDIAN"
680 "tst %0,%1"
681 [(set_attr "type" "mt_group")])
682
683 (define_insn "*tst<mode>_t_zero"
684 [(set (reg:SI T_REG)
685 (eq:SI
686 (subreg:QIHI
687 (and:SI (match_operand:SI 0 "arith_reg_operand" "%r")
688 (match_operand:SI 1 "arith_reg_operand" "r")) <lowpart_be>)
689 (const_int 0)))]
690 "TARGET_SH1 && TARGET_BIG_ENDIAN"
691 "tst %0,%1"
692 [(set_attr "type" "mt_group")])
693
694 ;; Extract LSB, negate and store in T bit.
695 (define_insn "tstsi_t_and_not"
696 [(set (reg:SI T_REG)
697 (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z"))
698 (const_int 1)))]
699 "TARGET_SH1"
700 "tst #1,%0"
701 [(set_attr "type" "mt_group")])
702
703 ;; Extract contiguous bits and compare them against zero.
704 (define_insn "tst<mode>_t_zero_extract_eq"
705 [(set (reg:SI T_REG)
706 (eq:SI (zero_extract:SI (match_operand:QIHISIDI 0 "logical_operand" "z")
707 (match_operand:SI 1 "const_int_operand")
708 (match_operand:SI 2 "const_int_operand"))
709 (const_int 0)))]
710 "TARGET_SH1
711 && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))"
712 {
713 operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
714 return "tst %1,%0";
715 }
716 [(set_attr "type" "mt_group")])
717
718 ;; This split is required when testing bits in a QI subreg.
719 (define_split
720 [(set (reg:SI T_REG)
721 (eq:SI
722 (if_then_else:SI
723 (zero_extract:SI (match_operand 0 "logical_operand")
724 (match_operand 1 "const_int_operand")
725 (match_operand 2 "const_int_operand"))
726 (match_operand 3 "const_int_operand")
727 (const_int 0))
728 (const_int 0)))]
729 "TARGET_SH1
730 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
731 && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
732 [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3))
733 (const_int 0)))]
734 {
735 if (GET_MODE (operands[0]) == QImode)
736 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
737 })
738
739 ;; Extract single bit, negate and store it in the T bit.
740 ;; Not used for SH4A.
741 (define_insn "tstsi_t_zero_extract_xor"
742 [(set (reg:SI T_REG)
743 (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
744 (match_operand:SI 3 "const_int_operand"))
745 (match_operand:SI 1 "const_int_operand")
746 (match_operand:SI 2 "const_int_operand")))]
747 "TARGET_SH1
748 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
749 && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
750 "tst %3,%0"
751 [(set_attr "type" "mt_group")])
752
753 ;; Extract single bit, negate and store it in the T bit.
754 ;; Used for SH4A little endian.
755 (define_insn "tstsi_t_zero_extract_subreg_xor_little"
756 [(set (reg:SI T_REG)
757 (zero_extract:SI
758 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
759 (match_operand:SI 3 "const_int_operand")) 0)
760 (match_operand:SI 1 "const_int_operand")
761 (match_operand:SI 2 "const_int_operand")))]
762 "TARGET_SH1 && TARGET_LITTLE_ENDIAN
763 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
764 == (INTVAL (operands[3]) & 255)
765 && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
766 {
767 operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
768 return "tst %3,%0";
769 }
770 [(set_attr "type" "mt_group")])
771
772 ;; Extract single bit, negate and store it in the T bit.
773 ;; Used for SH4A big endian.
774 (define_insn "tstsi_t_zero_extract_subreg_xor_big"
775 [(set (reg:SI T_REG)
776 (zero_extract:SI
777 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
778 (match_operand:SI 3 "const_int_operand")) 3)
779 (match_operand:SI 1 "const_int_operand")
780 (match_operand:SI 2 "const_int_operand")))]
781 "TARGET_SH1 && TARGET_BIG_ENDIAN
782 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
783 == (INTVAL (operands[3]) & 255)
784 && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
785 {
786 operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
787 return "tst %3,%0";
788 }
789 [(set_attr "type" "mt_group")])
790
791 (define_insn "cmpeqsi_t"
792 [(set (reg:SI T_REG)
793 (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
794 (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
795 "TARGET_SH1"
796 "@
797 tst %0,%0
798 cmp/eq %1,%0
799 cmp/eq %1,%0"
800 [(set_attr "type" "mt_group")])
801
802 ;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this
803 ;; pattern by itself. What this actually does is:
804 ;; x == 0: (1 >> 0-0) & 1 = 1
805 ;; x != 0: (1 >> 0-x) & 1 = 0
806 ;; Without this the test pr51244-8.c fails on SH2A and SH4A.
807 (define_insn_and_split "*cmpeqsi_t"
808 [(set (reg:SI T_REG)
809 (and:SI (lshiftrt:SI
810 (const_int 1)
811 (neg:SI (match_operand:SI 0 "arith_reg_operand" "r")))
812 (const_int 1)))]
813 "TARGET_SH1"
814 "#"
815 "&& 1"
816 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))])
817
818 (define_insn "cmpgtsi_t"
819 [(set (reg:SI T_REG)
820 (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
821 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
822 "TARGET_SH1"
823 "@
824 cmp/pl %0
825 cmp/gt %1,%0"
826 [(set_attr "type" "mt_group")])
827
828 (define_insn "cmpgesi_t"
829 [(set (reg:SI T_REG)
830 (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
831 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
832 "TARGET_SH1"
833 "@
834 cmp/pz %0
835 cmp/ge %1,%0"
836 [(set_attr "type" "mt_group")])
837
838 ;; FIXME: This is actually wrong. There is no way to literally move a
839 ;; general reg to t reg. Luckily, it seems that this pattern will be only
840 ;; used when the general reg is known be either '0' or '1' during combine.
841 ;; What we actually need is reg != 0 -> T, but we have only reg == 0 -> T.
842 ;; Due to interactions with other patterns, combine fails to pick the latter
843 ;; and invert the dependent logic.
844 (define_insn "*negtstsi"
845 [(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))]
846 "TARGET_SH1"
847 "cmp/pl %0"
848 [(set_attr "type" "mt_group")])
849
850 ;; Some integer sign comparison patterns can be realized with the div0s insn.
851 ;; div0s Rm,Rn T = (Rm >> 31) ^ (Rn >> 31)
852 (define_insn "cmp_div0s_0"
853 [(set (reg:SI T_REG)
854 (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
855 (match_operand:SI 1 "arith_reg_operand" "r"))
856 (const_int 31)))]
857 "TARGET_SH1"
858 "div0s %0,%1"
859 [(set_attr "type" "arith")])
860
861 (define_insn "cmp_div0s_1"
862 [(set (reg:SI T_REG)
863 (lt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
864 (match_operand:SI 1 "arith_reg_operand" "r"))
865 (const_int 0)))]
866 "TARGET_SH1"
867 "div0s %0,%1"
868 [(set_attr "type" "arith")])
869
870 (define_insn_and_split "*cmp_div0s_0"
871 [(set (match_operand:SI 0 "arith_reg_dest" "")
872 (lshiftrt:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
873 (match_operand:SI 2 "arith_reg_operand" ""))
874 (const_int 31)))
875 (clobber (reg:SI T_REG))]
876 "TARGET_SH1"
877 "#"
878 "&& 1"
879 [(set (reg:SI T_REG)
880 (lshiftrt:SI (xor:SI (match_dup 1) (match_dup 2)) (const_int 31)))
881 (set (match_dup 0) (reg:SI T_REG))])
882
883 (define_insn "*cmp_div0s_0"
884 [(set (reg:SI T_REG)
885 (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand" "%r")
886 (const_int 31))
887 (ge:SI (match_operand:SI 1 "arith_reg_operand" "r")
888 (const_int 0))))]
889 "TARGET_SH1"
890 "div0s %0,%1"
891 [(set_attr "type" "arith")])
892
893 (define_insn_and_split "*cmp_div0s_1"
894 [(set (match_operand:SI 0 "arith_reg_dest" "")
895 (ge:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
896 (match_operand:SI 2 "arith_reg_operand" ""))
897 (const_int 0)))
898 (clobber (reg:SI T_REG))]
899 "TARGET_SH1"
900 "#"
901 "&& can_create_pseudo_p ()"
902 [(const_int 0)]
903 ;; We have to go through the movnegt expander here which will handle the
904 ;; SH2A vs non-SH2A cases.
905 {
906 emit_insn (gen_cmp_div0s_1 (operands[1], operands[2]));
907 emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
908 DONE;
909 })
910
911 (define_insn_and_split "*cmp_div0s_1"
912 [(set (reg:SI T_REG)
913 (ge:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
914 (match_operand:SI 1 "arith_reg_operand" ""))
915 (const_int 0)))]
916 "TARGET_SH1"
917 "#"
918 "&& can_create_pseudo_p ()"
919 [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 0) (match_dup 1))
920 (const_int 0)))
921 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
922
923 (define_insn_and_split "*cmp_div0s_1"
924 [(set (reg:SI T_REG)
925 (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
926 (const_int 31))
927 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
928 (const_int 31))))]
929 "TARGET_SH1"
930 "#"
931 "&& can_create_pseudo_p ()"
932 [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 0) (match_dup 1))
933 (const_int 0)))
934 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
935
936 ;; -------------------------------------------------------------------------
937 ;; SImode compare and branch
938 ;; -------------------------------------------------------------------------
939
940 (define_expand "cbranchsi4"
941 [(set (pc)
942 (if_then_else (match_operator 0 "comparison_operator"
943 [(match_operand:SI 1 "arith_operand" "")
944 (match_operand:SI 2 "arith_operand" "")])
945 (label_ref (match_operand 3 "" ""))
946 (pc)))
947 (clobber (reg:SI T_REG))]
948 ""
949 {
950 if (TARGET_SHMEDIA)
951 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
952 operands[2], operands[3]));
953 else
954 expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
955
956 DONE;
957 })
958
959 ;; Combine patterns to invert compare and branch operations for which we
960 ;; don't have actual comparison insns. These patterns are used in cases
961 ;; which appear after the initial cbranchsi expansion, which also does
962 ;; some condition inversion.
963 (define_split
964 [(set (pc)
965 (if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "")
966 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
967 (label_ref (match_operand 2))
968 (pc)))
969 (clobber (reg:SI T_REG))]
970 "TARGET_SH1"
971 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1)))
972 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
973 (label_ref (match_dup 2))
974 (pc)))])
975
976 ;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A
977 ;; and SH2A combine fails to simplify this pattern by itself.
978 ;; What this actually does is:
979 ;; x == 0: (1 >> 0-0) & 1 = 1
980 ;; x != 0: (1 >> 0-x) & 1 = 0
981 ;; Without this the test pr51244-8.c fails on SH2A and SH4A.
982 (define_split
983 [(set (pc)
984 (if_then_else
985 (eq (and:SI (lshiftrt:SI
986 (const_int 1)
987 (neg:SI (match_operand:SI 0 "arith_reg_operand" "")))
988 (const_int 1))
989 (const_int 0))
990 (label_ref (match_operand 2))
991 (pc)))
992 (clobber (reg:SI T_REG))]
993 "TARGET_SH1"
994 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))
995 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
996 (label_ref (match_dup 2))
997 (pc)))])
998
999 ;; FIXME: These could probably use code iterators for the compare op.
1000 (define_split
1001 [(set (pc)
1002 (if_then_else (le (match_operand:SI 0 "arith_reg_operand" "")
1003 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1004 (label_ref (match_operand 2))
1005 (pc)))
1006 (clobber (reg:SI T_REG))]
1007 "TARGET_SH1"
1008 [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1)))
1009 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1010 (label_ref (match_dup 2))
1011 (pc)))])
1012
1013 (define_split
1014 [(set (pc)
1015 (if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "")
1016 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1017 (label_ref (match_operand 2))
1018 (pc)))
1019 (clobber (reg:SI T_REG))]
1020 "TARGET_SH1"
1021 [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1)))
1022 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1023 (label_ref (match_dup 2))
1024 (pc)))])
1025
1026 (define_split
1027 [(set (pc)
1028 (if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "")
1029 (match_operand:SI 1 "arith_reg_operand" ""))
1030 (label_ref (match_operand 2))
1031 (pc)))
1032 (clobber (reg:SI T_REG))]
1033 "TARGET_SH1"
1034 [(set (reg:SI T_REG) (gtu:SI (match_dup 0) (match_dup 1)))
1035 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1036 (label_ref (match_dup 2))
1037 (pc)))])
1038
1039 (define_split
1040 [(set (pc)
1041 (if_then_else (ltu (match_operand:SI 0 "arith_reg_operand" "")
1042 (match_operand:SI 1 "arith_reg_operand" ""))
1043 (label_ref (match_operand 2))
1044 (pc)))
1045 (clobber (reg:SI T_REG))]
1046 "TARGET_SH1"
1047 [(set (reg:SI T_REG) (geu:SI (match_dup 0) (match_dup 1)))
1048 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1049 (label_ref (match_dup 2))
1050 (pc)))])
1051
1052 ;; Compare and branch combine patterns for div0s comparisons.
1053 (define_insn_and_split "*cbranch_div0s"
1054 [(set (pc)
1055 (if_then_else (lt (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
1056 (match_operand:SI 1 "arith_reg_operand" ""))
1057 (const_int 0))
1058 (label_ref (match_operand 2))
1059 (pc)))
1060 (clobber (reg:SI T_REG))]
1061 "TARGET_SH1"
1062 "#"
1063 "&& 1"
1064 [(set (reg:SI T_REG)
1065 (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1066 (set (pc)
1067 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1068 (label_ref (match_dup 2))
1069 (pc)))])
1070
1071 (define_insn_and_split "*cbranch_div0s"
1072 [(set (pc)
1073 (if_then_else (ge (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
1074 (match_operand:SI 1 "arith_reg_operand" ""))
1075 (const_int 0))
1076 (label_ref (match_operand 2))
1077 (pc)))
1078 (clobber (reg:SI T_REG))]
1079 "TARGET_SH1"
1080 "#"
1081 "&& 1"
1082 [(set (reg:SI T_REG)
1083 (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1084 (set (pc)
1085 (if_then_else (eq (reg:SI T_REG) (const_int 0))
1086 (label_ref (match_dup 2))
1087 (pc)))])
1088
1089 ;; Conditional move combine pattern for div0s comparisons.
1090 ;; This is used when TARGET_PRETEND_CMOVE is in effect.
1091 (define_insn_and_split "*movsicc_div0s"
1092 [(set (match_operand:SI 0 "arith_reg_dest" "")
1093 (if_then_else:SI (ge (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
1094 (match_operand:SI 2 "arith_reg_operand" ""))
1095 (const_int 0))
1096 (match_operand:SI 3 "arith_reg_operand" "")
1097 (match_operand:SI 4 "general_movsrc_operand" "")))
1098 (clobber (reg:SI T_REG))]
1099 "TARGET_PRETEND_CMOVE"
1100 "#"
1101 "&& 1"
1102 [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2))
1103 (const_int 0)))
1104 (set (match_dup 0)
1105 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1106 (match_dup 4)
1107 (match_dup 3)))])
1108
1109 (define_insn_and_split "*movsicc_div0s"
1110 [(set (match_operand:SI 0 "arith_reg_dest")
1111 (if_then_else:SI (eq (lshiftrt:SI
1112 (match_operand:SI 1 "arith_reg_operand")
1113 (const_int 31))
1114 (lshiftrt:SI
1115 (match_operand:SI 2 "arith_reg_operand")
1116 (const_int 31)))
1117 (match_operand:SI 3 "arith_reg_operand")
1118 (match_operand:SI 4 "general_movsrc_operand")))
1119 (clobber (reg:SI T_REG))]
1120 "TARGET_PRETEND_CMOVE"
1121 "#"
1122 "&& 1"
1123 [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2))
1124 (const_int 0)))
1125 (set (match_dup 0)
1126 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1127 (match_dup 4)
1128 (match_dup 3)))])
1129
1130 ;; -------------------------------------------------------------------------
1131 ;; SImode unsigned integer comparisons
1132 ;; -------------------------------------------------------------------------
1133
1134 ;; Usually comparisons of 'unsigned int >= 0' are optimized away completely.
1135 ;; However, especially when optimizations are off (e.g. -O0) such comparisons
1136 ;; might remain and we have to handle them. If the '>= 0' case wasn't
1137 ;; handled here, something else would just load a '0' into the second operand
1138 ;; and do the comparison. We can do slightly better by just setting the
1139 ;; T bit to '1'.
1140 (define_insn_and_split "cmpgeusi_t"
1141 [(set (reg:SI T_REG)
1142 (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1143 (match_operand:SI 1 "arith_reg_or_0_operand" "r")))]
1144 "TARGET_SH1"
1145 "cmp/hs %1,%0"
1146 "&& satisfies_constraint_Z (operands[1])"
1147 [(set (reg:SI T_REG) (const_int 1))]
1148 ""
1149 [(set_attr "type" "mt_group")])
1150
1151 (define_insn "cmpgtusi_t"
1152 [(set (reg:SI T_REG)
1153 (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1154 (match_operand:SI 1 "arith_reg_operand" "r")))]
1155 "TARGET_SH1"
1156 "cmp/hi %1,%0"
1157 [(set_attr "type" "mt_group")])
1158 \f
1159 ;; -------------------------------------------------------------------------
1160 ;; DImode compare and branch
1161 ;; -------------------------------------------------------------------------
1162
1163 ;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
1164 ;; Therefore, we aim to have a set of three branches that go straight to the
1165 ;; destination, i.e. only one of them is taken at any one time.
1166 ;; This mechanism should also be slightly better for the sh4-200.
1167
1168 (define_expand "cbranchdi4"
1169 [(set (pc)
1170 (if_then_else (match_operator 0 "comparison_operator"
1171 [(match_operand:DI 1 "arith_operand" "")
1172 (match_operand:DI 2 "arith_operand" "")])
1173 (label_ref (match_operand 3 "" ""))
1174 (pc)))
1175 (clobber (match_dup 4))
1176 (clobber (reg:SI T_REG))]
1177 "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
1178 {
1179 enum rtx_code comparison;
1180
1181 if (TARGET_SHMEDIA)
1182 {
1183 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
1184 operands[2], operands[3]));
1185 DONE;
1186 }
1187 else if (!TARGET_CBRANCHDI4)
1188 {
1189 sh_emit_compare_and_branch (operands, DImode);
1190 DONE;
1191 }
1192 else
1193 {
1194 if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
1195 DONE;
1196
1197 comparison = prepare_cbranch_operands (operands, DImode,
1198 LAST_AND_UNUSED_RTX_CODE);
1199 if (comparison != GET_CODE (operands[0]))
1200 operands[0]
1201 = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
1202 operands[4] = gen_rtx_SCRATCH (SImode);
1203 }
1204 })
1205
1206 (define_insn_and_split "cbranchdi4_i"
1207 [(set (pc)
1208 (if_then_else (match_operator 0 "comparison_operator"
1209 [(match_operand:DI 1 "arith_operand" "r,r")
1210 (match_operand:DI 2 "arith_operand" "rN,I08")])
1211 (label_ref (match_operand 3 "" ""))
1212 (pc)))
1213 (clobber (match_scratch:SI 4 "=X,&r"))
1214 (clobber (reg:SI T_REG))]
1215 "TARGET_CBRANCHDI4"
1216 "#"
1217 "&& reload_completed"
1218 [(pc)]
1219 {
1220 if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
1221 FAIL;
1222 DONE;
1223 })
1224
1225 ;; -------------------------------------------------------------------------
1226 ;; DImode signed integer comparisons
1227 ;; -------------------------------------------------------------------------
1228
1229 (define_insn ""
1230 [(set (reg:SI T_REG)
1231 (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
1232 (match_operand:DI 1 "arith_operand" "r"))
1233 (const_int 0)))]
1234 "TARGET_SH1"
1235 {
1236 return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0",
1237 insn, operands);
1238 }
1239 [(set_attr "length" "6")
1240 (set_attr "type" "arith3b")])
1241
1242 (define_insn "cmpeqdi_t"
1243 [(set (reg:SI T_REG)
1244 (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1245 (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
1246 "TARGET_SH1"
1247 {
1248 static const char* alt[] =
1249 {
1250 "tst %S0,%S0" "\n"
1251 " bf 0f" "\n"
1252 " tst %R0,%R0" "\n"
1253 "0:",
1254
1255 "cmp/eq %S1,%S0" "\n"
1256 " bf 0f" "\n"
1257 " cmp/eq %R1,%R0" "\n"
1258 "0:"
1259 };
1260 return alt[which_alternative];
1261 }
1262 [(set_attr "length" "6")
1263 (set_attr "type" "arith3b")])
1264
1265 (define_split
1266 [(set (reg:SI T_REG)
1267 (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
1268 (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
1269 ;; If we applied this split when not optimizing, it would only be
1270 ;; applied during the machine-dependent reorg, when no new basic blocks
1271 ;; may be created.
1272 "TARGET_SH1 && reload_completed && optimize"
1273 [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
1274 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1275 (label_ref (match_dup 6))
1276 (pc)))
1277 (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
1278 (match_dup 6)]
1279 {
1280 operands[2] = gen_highpart (SImode, operands[0]);
1281 operands[3] = operands[1] == const0_rtx
1282 ? const0_rtx
1283 : gen_highpart (SImode, operands[1]);
1284 operands[4] = gen_lowpart (SImode, operands[0]);
1285 operands[5] = gen_lowpart (SImode, operands[1]);
1286 operands[6] = gen_label_rtx ();
1287 })
1288
1289 (define_insn "cmpgtdi_t"
1290 [(set (reg:SI T_REG)
1291 (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1292 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1293 "TARGET_SH2"
1294 {
1295 static const char* alt[] =
1296 {
1297 "cmp/eq %S1,%S0" "\n"
1298 " bf{.|/}s 0f" "\n"
1299 " cmp/gt %S1,%S0" "\n"
1300 " cmp/hi %R1,%R0" "\n"
1301 "0:",
1302
1303 "tst %S0,%S0" "\n"
1304 " bf{.|/}s 0f" "\n"
1305 " cmp/pl %S0" "\n"
1306 " cmp/hi %S0,%R0" "\n"
1307 "0:"
1308 };
1309 return alt[which_alternative];
1310 }
1311 [(set_attr "length" "8")
1312 (set_attr "type" "arith3")])
1313
1314 (define_insn "cmpgedi_t"
1315 [(set (reg:SI T_REG)
1316 (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1317 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1318 "TARGET_SH2"
1319 {
1320 static const char* alt[] =
1321 {
1322 "cmp/eq %S1,%S0" "\n"
1323 " bf{.|/}s 0f" "\n"
1324 " cmp/ge %S1,%S0" "\n"
1325 " cmp/hs %R1,%R0" "\n"
1326 "0:",
1327
1328 "cmp/pz %S0"
1329 };
1330 return alt[which_alternative];
1331 }
1332 [(set_attr "length" "8,2")
1333 (set_attr "type" "arith3,mt_group")])
1334 \f
1335 ;; -------------------------------------------------------------------------
1336 ;; DImode unsigned integer comparisons
1337 ;; -------------------------------------------------------------------------
1338
1339 (define_insn "cmpgeudi_t"
1340 [(set (reg:SI T_REG)
1341 (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1342 (match_operand:DI 1 "arith_reg_operand" "r")))]
1343 "TARGET_SH2"
1344 {
1345 return "cmp/eq %S1,%S0" "\n"
1346 " bf{.|/}s 0f" "\n"
1347 " cmp/hs %S1,%S0" "\n"
1348 " cmp/hs %R1,%R0" "\n"
1349 "0:";
1350 }
1351 [(set_attr "length" "8")
1352 (set_attr "type" "arith3")])
1353
1354 (define_insn "cmpgtudi_t"
1355 [(set (reg:SI T_REG)
1356 (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1357 (match_operand:DI 1 "arith_reg_operand" "r")))]
1358 "TARGET_SH2"
1359 {
1360 return "cmp/eq %S1,%S0" "\n"
1361 " bf{.|/}s 0f" "\n"
1362 " cmp/hi %S1,%S0" "\n"
1363 " cmp/hi %R1,%R0" "\n"
1364 "0:";
1365 }
1366 [(set_attr "length" "8")
1367 (set_attr "type" "arith3")])
1368
1369 (define_insn "cmpeqsi_media"
1370 [(set (match_operand:SI 0 "register_operand" "=r")
1371 (eq:SI (match_operand:SI 1 "logical_operand" "%r")
1372 (match_operand:SI 2 "cmp_operand" "Nr")))]
1373 "TARGET_SHMEDIA"
1374 "cmpeq %1, %N2, %0"
1375 [(set_attr "type" "cmp_media")])
1376
1377 (define_insn "cmpeqdi_media"
1378 [(set (match_operand:SI 0 "register_operand" "=r")
1379 (eq:SI (match_operand:DI 1 "register_operand" "%r")
1380 (match_operand:DI 2 "cmp_operand" "Nr")))]
1381 "TARGET_SHMEDIA"
1382 "cmpeq %1, %N2, %0"
1383 [(set_attr "type" "cmp_media")])
1384
1385 (define_insn "cmpgtsi_media"
1386 [(set (match_operand:SI 0 "register_operand" "=r")
1387 (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
1388 (match_operand:SI 2 "cmp_operand" "rN")))]
1389 "TARGET_SHMEDIA"
1390 "cmpgt %N1, %N2, %0"
1391 [(set_attr "type" "cmp_media")])
1392
1393 (define_insn "cmpgtdi_media"
1394 [(set (match_operand:SI 0 "register_operand" "=r")
1395 (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1396 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1397 "TARGET_SHMEDIA"
1398 "cmpgt %N1, %N2, %0"
1399 [(set_attr "type" "cmp_media")])
1400
1401 (define_insn "cmpgtusi_media"
1402 [(set (match_operand:SI 0 "register_operand" "=r")
1403 (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
1404 (match_operand:SI 2 "cmp_operand" "rN")))]
1405 "TARGET_SHMEDIA"
1406 "cmpgtu %N1, %N2, %0"
1407 [(set_attr "type" "cmp_media")])
1408
1409 (define_insn "cmpgtudi_media"
1410 [(set (match_operand:SI 0 "register_operand" "=r")
1411 (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1412 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1413 "TARGET_SHMEDIA"
1414 "cmpgtu %N1, %N2, %0"
1415 [(set_attr "type" "cmp_media")])
1416
1417 ; This pattern is for combine.
1418 (define_insn "*cmpne0sisi_media"
1419 [(set (match_operand:SI 0 "register_operand" "=r")
1420 (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
1421 "TARGET_SHMEDIA"
1422 "cmpgtu %1,r63,%0"
1423 [(set_attr "type" "cmp_media")])
1424
1425 ;; -------------------------------------------------------------------------
1426 ;; Conditional move instructions
1427 ;; -------------------------------------------------------------------------
1428
1429 ;; The insn names may seem reversed, but note that cmveq performs the move
1430 ;; if op1 == 0, and cmvne does it if op1 != 0.
1431
1432 (define_insn "movdicc_false"
1433 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1434 (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
1435 (const_int 0))
1436 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1437 (match_operand:DI 3 "arith_reg_operand" "0")))]
1438 "TARGET_SHMEDIA"
1439 "cmveq %1, %N2, %0"
1440 [(set_attr "type" "arith_media")])
1441
1442 (define_insn "movdicc_true"
1443 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1444 (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
1445 (const_int 0))
1446 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1447 (match_operand:DI 3 "arith_reg_operand" "0")))]
1448 "TARGET_SHMEDIA"
1449 "cmvne %1, %N2, %0"
1450 [(set_attr "type" "arith_media")])
1451
1452 (define_peephole2
1453 [(set (match_operand:DI 0 "arith_reg_dest" "")
1454 (if_then_else:DI (match_operator 3 "equality_comparison_operator"
1455 [(match_operand:DI 1 "arith_reg_operand" "")
1456 (const_int 0)])
1457 (match_operand:DI 2 "arith_reg_dest" "")
1458 (match_dup 0)))
1459 (set (match_dup 2) (match_dup 0))]
1460 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1461 [(set (match_dup 2)
1462 (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
1463 {
1464 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1465 VOIDmode, operands[1], CONST0_RTX (DImode));
1466 })
1467
1468 (define_peephole2
1469 [(set (match_operand:DI 0 "general_movdst_operand" "")
1470 (match_operand:DI 1 "arith_reg_or_0_operand" ""))
1471 (set (match_operand:DI 2 "arith_reg_dest" "")
1472 (if_then_else:DI (match_operator 4 "equality_comparison_operator"
1473 [(match_operand:DI 3 "arith_reg_operand" "")
1474 (const_int 0)])
1475 (match_dup 0)
1476 (match_dup 2)))]
1477 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1478 [(set (match_dup 2)
1479 (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
1480 "")
1481
1482 (define_expand "movdicc"
1483 [(set (match_operand:DI 0 "register_operand" "")
1484 (if_then_else:DI (match_operand 1 "comparison_operator" "")
1485 (match_operand:DI 2 "register_operand" "")
1486 (match_operand:DI 3 "register_operand" "")))]
1487 "TARGET_SHMEDIA"
1488 {
1489 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1490 && GET_MODE (XEXP (operands[1], 0)) == DImode
1491 && XEXP (operands[1], 1) == const0_rtx)
1492 ;
1493 else
1494 {
1495 if (!can_create_pseudo_p ())
1496 FAIL;
1497
1498 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1499 GET_CODE (operands[1]),
1500 XEXP (operands[1], 0),
1501 XEXP (operands[1], 1));
1502 if (!operands[1])
1503 FAIL;
1504 }
1505 })
1506
1507 ;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1508 ;; SImode to DImode.
1509 (define_insn "movsicc_false"
1510 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1511 (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1512 (const_int 0))
1513 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1514 (match_operand:SI 3 "arith_reg_operand" "0")))]
1515 "TARGET_SHMEDIA"
1516 "cmveq %1, %N2, %0"
1517 [(set_attr "type" "arith_media")])
1518
1519 (define_insn "movsicc_true"
1520 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1521 (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1522 (const_int 0))
1523 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1524 (match_operand:SI 3 "arith_reg_operand" "0")))]
1525 "TARGET_SHMEDIA"
1526 "cmvne %1, %N2, %0"
1527 [(set_attr "type" "arith_media")])
1528
1529 (define_peephole2
1530 [(set (match_operand:SI 0 "arith_reg_dest" "")
1531 (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1532 [(match_operand:SI 1 "arith_reg_operand" "")
1533 (const_int 0)])
1534 (match_operand:SI 2 "arith_reg_dest" "")
1535 (match_dup 0)))
1536 (set (match_dup 2) (match_dup 0))]
1537 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1538 [(set (match_dup 2)
1539 (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1540 {
1541 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1542 VOIDmode, operands[1], CONST0_RTX (SImode));
1543 })
1544
1545 (define_peephole2
1546 [(set (match_operand:SI 0 "general_movdst_operand" "")
1547 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1548 (set (match_operand:SI 2 "arith_reg_dest" "")
1549 (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1550 [(match_operand:SI 3 "arith_reg_operand" "")
1551 (const_int 0)])
1552 (match_dup 0)
1553 (match_dup 2)))]
1554 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1555 && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1556 [(set (match_dup 2)
1557 (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1558 {
1559 replace_rtx (operands[4], operands[0], operands[1]);
1560 })
1561
1562 (define_peephole2
1563 [(set (match_operand 0 "any_register_operand" "")
1564 (match_operand 1 "any_register_operand" ""))
1565 (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1566 (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1567 "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1568 <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1569 && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1570 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1571 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1572 && ! reg_overlap_mentioned_p (operands[0], operands[3])
1573 && ! reg_overlap_mentioned_p (operands[2], operands[0])
1574 && ! reg_overlap_mentioned_p (operands[0], operands[1])
1575 && (REGNO_REG_CLASS (REGNO (operands[0]))
1576 == REGNO_REG_CLASS (REGNO (operands[2])))
1577 && (REGNO_REG_CLASS (REGNO (operands[1]))
1578 == REGNO_REG_CLASS (REGNO (operands[0])))"
1579 [(set (match_dup 0) (match_dup 3))
1580 (set (match_dup 4) (match_dup 5))]
1581 {
1582 rtx set1, set2;
1583 rtx_insn *insn1, *insn2;
1584 rtx replacements[4];
1585
1586 /* We want to replace occurrences of operands[0] with operands[1] and
1587 operands[2] with operands[0] in operands[4]/operands[5].
1588 Doing just two replace_rtx calls naively would result in the second
1589 replacement undoing all that the first did if operands[1] and operands[2]
1590 are identical, so we must do this simultaneously. */
1591 replacements[0] = operands[0];
1592 replacements[1] = operands[1];
1593 replacements[2] = operands[2];
1594 replacements[3] = operands[0];
1595 if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1596 || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1597 || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1598 FAIL;
1599
1600 operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1601 replace_n_hard_rtx (operands[4], replacements, 2, 1);
1602 operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1603 /* The operands array is aliased to recog_data.operand, which gets
1604 clobbered by extract_insn, so finish with it now. */
1605 set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1606 set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1607 /* ??? The last insn might be a jump insn, but the generic peephole2 code
1608 always uses emit_insn. */
1609 /* Check that we don't violate matching constraints or earlyclobbers. */
1610 basic_block bb = BLOCK_FOR_INSN (peep2_next_insn (2));
1611 insn1 = emit_insn (set1);
1612 extract_insn (insn1);
1613 if (! constrain_operands (1, get_preferred_alternatives (insn1, bb)))
1614 goto failure;
1615 insn2 = emit (set2);
1616 if (GET_CODE (insn2) == BARRIER)
1617 goto failure;
1618 extract_insn (insn2);
1619 if (! constrain_operands (1, get_preferred_alternatives (insn2, bb)))
1620 {
1621 rtx tmp;
1622 failure:
1623 tmp = replacements[0];
1624 replacements[0] = replacements[1];
1625 replacements[1] = tmp;
1626 tmp = replacements[2];
1627 replacements[2] = replacements[3];
1628 replacements[3] = tmp;
1629 replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1630 replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1631 replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1632 FAIL;
1633 }
1634 DONE;
1635 })
1636
1637 ;; The register allocator is rather clumsy in handling multi-way conditional
1638 ;; moves, so allow the combiner to make them, and we split them up after
1639 ;; reload. */
1640 (define_insn_and_split "*movsicc_umin"
1641 [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1642 (umin:SI (if_then_else:SI
1643 (eq (match_operand:SI 1 "arith_reg_operand" "r")
1644 (const_int 0))
1645 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1646 (match_operand:SI 3 "register_operand" "0"))
1647 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1648 (clobber (match_scratch:SI 5 "=&r"))]
1649 "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1650 "#"
1651 "TARGET_SHMEDIA && reload_completed"
1652 [(pc)]
1653 {
1654 emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1655 operands[3]));
1656 emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1657 emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1658 operands[0]));
1659 DONE;
1660 })
1661
1662 (define_insn "*movsicc_t_false"
1663 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1664 (if_then_else (eq (reg:SI T_REG) (const_int 0))
1665 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1666 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1667 "TARGET_PRETEND_CMOVE
1668 && (arith_reg_operand (operands[1], SImode)
1669 || (immediate_operand (operands[1], SImode)
1670 && satisfies_constraint_I08 (operands[1])))"
1671 {
1672 return "bt 0f" "\n"
1673 " mov %1,%0" "\n"
1674 "0:";
1675 }
1676 [(set_attr "type" "mt_group,arith") ;; poor approximation
1677 (set_attr "length" "4")])
1678
1679 (define_insn "*movsicc_t_true"
1680 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1681 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1682 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1683 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1684 "TARGET_PRETEND_CMOVE
1685 && (arith_reg_operand (operands[1], SImode)
1686 || (immediate_operand (operands[1], SImode)
1687 && satisfies_constraint_I08 (operands[1])))"
1688 {
1689 return "bf 0f" "\n"
1690 " mov %1,%0" "\n"
1691 "0:";
1692 }
1693 [(set_attr "type" "mt_group,arith") ;; poor approximation
1694 (set_attr "length" "4")])
1695
1696 (define_expand "movsicc"
1697 [(set (match_operand:SI 0 "arith_reg_dest" "")
1698 (if_then_else:SI (match_operand 1 "comparison_operator" "")
1699 (match_operand:SI 2 "arith_reg_or_0_operand" "")
1700 (match_operand:SI 3 "arith_reg_operand" "")))]
1701 "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1702 {
1703 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1704 && GET_MODE (XEXP (operands[1], 0)) == SImode
1705 && (TARGET_SHMEDIA
1706 || (REG_P (XEXP (operands[1], 0))
1707 && REGNO (XEXP (operands[1], 0)) == T_REG))
1708 && XEXP (operands[1], 1) == const0_rtx)
1709 ;
1710
1711 else if (TARGET_PRETEND_CMOVE)
1712 {
1713 enum rtx_code code = GET_CODE (operands[1]);
1714 enum rtx_code new_code = code;
1715 rtx op0 = XEXP (operands[1], 0);
1716 rtx op1 = XEXP (operands[1], 1);
1717
1718 if (! currently_expanding_to_rtl)
1719 FAIL;
1720 switch (code)
1721 {
1722 case LT: case LE: case LEU: case LTU:
1723 if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1724 break;
1725 case NE:
1726 new_code = reverse_condition (code);
1727 break;
1728 case EQ: case GT: case GE: case GEU: case GTU:
1729 break;
1730 default:
1731 FAIL;
1732 }
1733 sh_emit_scc_to_t (new_code, op0, op1);
1734 operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1735 gen_rtx_REG (SImode, T_REG), const0_rtx);
1736 }
1737 else
1738 {
1739 if (!can_create_pseudo_p ())
1740 FAIL;
1741
1742 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1743 GET_CODE (operands[1]),
1744 XEXP (operands[1], 0),
1745 XEXP (operands[1], 1));
1746 if (!operands[1])
1747 FAIL;
1748 }
1749 })
1750
1751 (define_expand "movqicc"
1752 [(set (match_operand:QI 0 "register_operand" "")
1753 (if_then_else:QI (match_operand 1 "comparison_operator" "")
1754 (match_operand:QI 2 "register_operand" "")
1755 (match_operand:QI 3 "register_operand" "")))]
1756 "TARGET_SHMEDIA"
1757 {
1758 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1759 operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1760 operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1761 emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1762 DONE;
1763 })
1764 \f
1765 ;; -------------------------------------------------------------------------
1766 ;; Addition instructions
1767 ;; -------------------------------------------------------------------------
1768
1769 (define_expand "adddi3"
1770 [(set (match_operand:DI 0 "arith_reg_operand")
1771 (plus:DI (match_operand:DI 1 "arith_reg_operand")
1772 (match_operand:DI 2 "arith_operand")))]
1773 ""
1774 {
1775 if (TARGET_SH1)
1776 {
1777 operands[2] = force_reg (DImode, operands[2]);
1778 emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1779 DONE;
1780 }
1781 })
1782
1783 (define_insn "*adddi3_media"
1784 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1785 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1786 (match_operand:DI 2 "arith_operand" "r,I10")))]
1787 "TARGET_SHMEDIA"
1788 "@
1789 add %1, %2, %0
1790 addi %1, %2, %0"
1791 [(set_attr "type" "arith_media")])
1792
1793 (define_insn "*adddisi3_media"
1794 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1795 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1796 (match_operand:DI 2 "arith_operand" "r,I10")))]
1797 "TARGET_SHMEDIA"
1798 "@
1799 add.l %1, %2, %0
1800 addi.l %1, %2, %0"
1801 [(set_attr "type" "arith_media")
1802 (set_attr "highpart" "ignore")])
1803
1804 (define_insn "adddi3z_media"
1805 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1806 (zero_extend:DI
1807 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1808 (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1809 "TARGET_SHMEDIA"
1810 "addz.l %1, %N2, %0"
1811 [(set_attr "type" "arith_media")
1812 (set_attr "highpart" "ignore")])
1813
1814 (define_insn_and_split "adddi3_compact"
1815 [(set (match_operand:DI 0 "arith_reg_dest")
1816 (plus:DI (match_operand:DI 1 "arith_reg_operand")
1817 (match_operand:DI 2 "arith_reg_operand")))
1818 (clobber (reg:SI T_REG))]
1819 "TARGET_SH1"
1820 "#"
1821 "&& can_create_pseudo_p ()"
1822 [(const_int 0)]
1823 {
1824 emit_insn (gen_clrt ());
1825 emit_insn (gen_addc (gen_lowpart (SImode, operands[0]),
1826 gen_lowpart (SImode, operands[1]),
1827 gen_lowpart (SImode, operands[2])));
1828 emit_insn (gen_addc (gen_highpart (SImode, operands[0]),
1829 gen_highpart (SImode, operands[1]),
1830 gen_highpart (SImode, operands[2])));
1831 DONE;
1832 })
1833
1834 (define_insn "addc"
1835 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1836 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1837 (match_operand:SI 2 "arith_reg_operand" "r"))
1838 (reg:SI T_REG)))
1839 (set (reg:SI T_REG)
1840 (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1841 "TARGET_SH1"
1842 "addc %2,%0"
1843 [(set_attr "type" "arith")])
1844
1845 ;; A simplified version of the addc insn, where the exact value of the
1846 ;; T bit doesn't matter. This is easier for combine to pick up.
1847 ;; We allow a reg or 0 for one of the operands in order to be able to
1848 ;; do 'reg + T' sequences. Reload will load the constant 0 into the reg
1849 ;; as needed.
1850 ;; FIXME: The load of constant 0 should be split out before reload, or else
1851 ;; it will be difficult to hoist or combine the constant load.
1852 (define_insn "*addc"
1853 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1854 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1855 (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
1856 (match_operand:SI 3 "t_reg_operand" "")))
1857 (clobber (reg:SI T_REG))]
1858 "TARGET_SH1"
1859 "addc %2,%0"
1860 [(set_attr "type" "arith")])
1861
1862 ;; Split 'reg + reg + 1' into a sett addc sequence, as it can be scheduled
1863 ;; better, if the sett insn can be done early.
1864 (define_insn_and_split "*addc_r_r_1"
1865 [(set (match_operand:SI 0 "arith_reg_dest" "")
1866 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
1867 (match_operand:SI 2 "arith_reg_operand" ""))
1868 (const_int 1)))
1869 (clobber (reg:SI T_REG))]
1870 "TARGET_SH1"
1871 "#"
1872 "&& 1"
1873 [(set (reg:SI T_REG) (const_int 1))
1874 (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
1875 (reg:SI T_REG)))
1876 (clobber (reg:SI T_REG))])])
1877
1878 ;; Left shifts by one are usually done with an add insn to avoid T_REG
1879 ;; clobbers. Thus addc can also be used to do something like '(x << 1) + 1'.
1880 (define_insn_and_split "*addc_2r_1"
1881 [(set (match_operand:SI 0 "arith_reg_dest")
1882 (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
1883 (const_int 2))
1884 (const_int 1)))
1885 (clobber (reg:SI T_REG))]
1886 "TARGET_SH1"
1887 "#"
1888 "&& 1"
1889 [(set (reg:SI T_REG) (const_int 1))
1890 (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 1))
1891 (reg:SI T_REG)))
1892 (clobber (reg:SI T_REG))])])
1893
1894 ;; Sometimes combine will try to do 'reg + (0-reg) + 1' if the *addc pattern
1895 ;; matched. Split this up into a simple sub add sequence, as this will save
1896 ;; us one sett insn.
1897 (define_insn_and_split "*minus_plus_one"
1898 [(set (match_operand:SI 0 "arith_reg_dest" "")
1899 (plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
1900 (match_operand:SI 2 "arith_reg_operand" ""))
1901 (const_int 1)))]
1902 "TARGET_SH1"
1903 "#"
1904 "&& 1"
1905 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1906 (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))])
1907
1908 ;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn.
1909 ;; If the 0 constant can be CSE-ed, this becomes a one instruction
1910 ;; operation, as opposed to sequences such as
1911 ;; movt r2
1912 ;; add r2,r3
1913 ;;
1914 ;; Even if the constant is not CSE-ed, a sequence such as
1915 ;; mov #0,r2
1916 ;; addc r2,r3
1917 ;; can be scheduled much better since the load of the constant can be
1918 ;; done earlier, before any comparison insns that store the result in
1919 ;; the T bit.
1920 (define_insn_and_split "*addc_t_r"
1921 [(set (match_operand:SI 0 "arith_reg_dest")
1922 (plus:SI (match_operand:SI 1 "t_reg_operand")
1923 (match_operand:SI 2 "arith_reg_operand")))
1924 (clobber (reg:SI T_REG))]
1925 "TARGET_SH1"
1926 "#"
1927 "&& 1"
1928 [(parallel [(set (match_dup 0)
1929 (plus:SI (plus:SI (match_dup 2) (const_int 0))
1930 (match_dup 1)))
1931 (clobber (reg:SI T_REG))])])
1932
1933 (define_insn_and_split "*addc_r_t"
1934 [(set (match_operand:SI 0 "arith_reg_dest")
1935 (plus:SI (match_operand:SI 1 "arith_reg_operand")
1936 (match_operand:SI 2 "t_reg_operand")))
1937 (clobber (reg:SI T_REG))]
1938 "TARGET_SH1"
1939 "#"
1940 "&& 1"
1941 [(parallel [(set (match_dup 0)
1942 (plus:SI (plus:SI (match_dup 1) (const_int 0))
1943 (match_dup 2)))
1944 (clobber (reg:SI T_REG))])])
1945
1946 ;; Use shlr-addc to do 'reg + (reg & 1)'.
1947 (define_insn_and_split "*addc_r_lsb"
1948 [(set (match_operand:SI 0 "arith_reg_dest")
1949 (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1950 (const_int 1))
1951 (match_operand:SI 2 "arith_reg_operand")))
1952 (clobber (reg:SI T_REG))]
1953 "TARGET_SH1"
1954 "#"
1955 "&& can_create_pseudo_p ()"
1956 [(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2)))
1957 (clobber (reg:SI T_REG))])]
1958 {
1959 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1]));
1960 })
1961
1962 ;; Use shlr-addc to do 'reg + reg + (reg & 1)'.
1963 (define_insn_and_split "*addc_r_r_lsb"
1964 [(set (match_operand:SI 0 "arith_reg_dest")
1965 (plus:SI (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1966 (const_int 1))
1967 (match_operand:SI 2 "arith_reg_operand"))
1968 (match_operand:SI 3 "arith_reg_operand")))
1969 (clobber (reg:SI T_REG))]
1970 "TARGET_SH1"
1971 "#"
1972 "&& can_create_pseudo_p ()"
1973 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
1974 (reg:SI T_REG)))
1975 (clobber (reg:SI T_REG))])]
1976 {
1977 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1]));
1978 })
1979
1980 ;; Canonicalize 'reg + (reg & 1) + reg' into 'reg + reg + (reg & 1)'.
1981 (define_insn_and_split "*addc_r_lsb_r"
1982 [(set (match_operand:SI 0 "arith_reg_dest")
1983 (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1984 (const_int 1))
1985 (plus:SI (match_operand:SI 2 "arith_reg_operand")
1986 (match_operand:SI 3 "arith_reg_operand"))))
1987 (clobber (reg:SI T_REG))]
1988 "TARGET_SH1"
1989 "#"
1990 "&& can_create_pseudo_p ()"
1991 [(parallel [(set (match_dup 0)
1992 (plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1))
1993 (match_dup 2))
1994 (match_dup 3)))
1995 (clobber (reg:SI T_REG))])])
1996
1997 ;; Canonicalize '2 * reg + (reg & 1)' into 'reg + reg + (reg & 1)'.
1998 (define_insn_and_split "*addc_2r_lsb"
1999 [(set (match_operand:SI 0 "arith_reg_dest")
2000 (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
2001 (const_int 1))
2002 (mult:SI (match_operand:SI 2 "arith_reg_operand")
2003 (const_int 2))))
2004 (clobber (reg:SI T_REG))]
2005 "TARGET_SH1"
2006 "#"
2007 "&& can_create_pseudo_p ()"
2008 [(parallel [(set (match_dup 0)
2009 (plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1))
2010 (match_dup 2))
2011 (match_dup 2)))
2012 (clobber (reg:SI T_REG))])])
2013
2014 ;; Use shll-addc to do 'reg + ((unsigned int)reg >> 31)'.
2015 (define_insn_and_split "*addc_r_msb"
2016 [(set (match_operand:SI 0 "arith_reg_dest")
2017 (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
2018 (const_int 31))
2019 (match_operand:SI 2 "arith_reg_operand")))
2020 (clobber (reg:SI T_REG))]
2021 "TARGET_SH1"
2022 "#"
2023 "&& can_create_pseudo_p ()"
2024 [(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2)))
2025 (clobber (reg:SI T_REG))])]
2026 {
2027 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1]));
2028 })
2029
2030 ;; Use shll-addc to do 'reg + reg + ((unsigned int)reg >> 31)'.
2031 (define_insn_and_split "*addc_r_r_msb"
2032 [(set (match_operand:SI 0 "arith_reg_dest")
2033 (plus:SI (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
2034 (const_int 31))
2035 (match_operand:SI 2 "arith_reg_operand"))
2036 (match_operand:SI 3 "arith_reg_operand")))
2037 (clobber (reg:SI T_REG))]
2038 "TARGET_SH1"
2039 "#"
2040 "&& can_create_pseudo_p ()"
2041 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
2042 (reg:SI T_REG)))
2043 (clobber (reg:SI T_REG))])]
2044 {
2045 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1]));
2046 })
2047
2048 ;; Canonicalize '2 * reg + ((unsigned int)reg >> 31)'
2049 ;; into 'reg + reg + (reg & 1)'.
2050 (define_insn_and_split "*addc_2r_msb"
2051 [(set (match_operand:SI 0 "arith_reg_dest")
2052 (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
2053 (const_int 2))
2054 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
2055 (const_int 31))))
2056 (clobber (reg:SI T_REG))]
2057 "TARGET_SH1"
2058 "#"
2059 "&& can_create_pseudo_p ()"
2060 [(parallel [(set (match_dup 0)
2061 (plus:SI (plus:SI (lshiftrt:SI (match_dup 2) (const_int 31))
2062 (match_dup 1))
2063 (match_dup 1)))
2064 (clobber (reg:SI T_REG))])])
2065
2066 (define_expand "addsi3"
2067 [(set (match_operand:SI 0 "arith_reg_operand" "")
2068 (plus:SI (match_operand:SI 1 "arith_operand" "")
2069 (match_operand:SI 2 "arith_operand" "")))]
2070 ""
2071 {
2072 if (TARGET_SHMEDIA)
2073 operands[1] = force_reg (SImode, operands[1]);
2074 })
2075
2076 (define_insn "addsi3_media"
2077 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
2078 (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
2079 (match_operand:SI 2 "arith_operand" "r,I10")))]
2080 "TARGET_SHMEDIA"
2081 "@
2082 add.l %1, %2, %0
2083 addi.l %1, %2, %0"
2084 [(set_attr "type" "arith_media")
2085 (set_attr "highpart" "ignore")])
2086
2087 (define_insn "addsidi3_media"
2088 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
2089 (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
2090 "%r,r")
2091 (match_operand:SI 2 "arith_operand"
2092 "r,I10"))))]
2093 "TARGET_SHMEDIA"
2094 "@
2095 add.l %1, %2, %0
2096 addi.l %1, %2, %0"
2097 [(set_attr "type" "arith_media")
2098 (set_attr "highpart" "ignore")])
2099
2100 (define_insn "*addsi3_compact"
2101 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2102 (plus:SI (match_operand:SI 1 "arith_operand" "%0")
2103 (match_operand:SI 2 "arith_operand" "rI08")))]
2104 "TARGET_SH1"
2105 "add %2,%0"
2106 [(set_attr "type" "arith")])
2107
2108 ;; -------------------------------------------------------------------------
2109 ;; Subtraction instructions
2110 ;; -------------------------------------------------------------------------
2111
2112 (define_expand "subdi3"
2113 [(set (match_operand:DI 0 "arith_reg_operand" "")
2114 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
2115 (match_operand:DI 2 "arith_reg_operand" "")))]
2116 ""
2117 {
2118 if (TARGET_SH1)
2119 {
2120 operands[1] = force_reg (DImode, operands[1]);
2121 emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
2122 DONE;
2123 }
2124 })
2125
2126 (define_insn "*subdi3_media"
2127 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2128 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
2129 (match_operand:DI 2 "arith_reg_operand" "r")))]
2130 "TARGET_SHMEDIA"
2131 "sub %N1, %2, %0"
2132 [(set_attr "type" "arith_media")])
2133
2134 (define_insn "subdisi3_media"
2135 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
2136 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
2137 (match_operand:DI 2 "arith_reg_operand" "r")))]
2138 "TARGET_SHMEDIA"
2139 "sub.l %N1, %2, %0"
2140 [(set_attr "type" "arith_media")
2141 (set_attr "highpart" "ignore")])
2142
2143 (define_insn_and_split "subdi3_compact"
2144 [(set (match_operand:DI 0 "arith_reg_dest")
2145 (minus:DI (match_operand:DI 1 "arith_reg_operand")
2146 (match_operand:DI 2 "arith_reg_operand")))
2147 (clobber (reg:SI T_REG))]
2148 "TARGET_SH1"
2149 "#"
2150 "&& can_create_pseudo_p ()"
2151 [(const_int 0)]
2152 {
2153 emit_insn (gen_clrt ());
2154 emit_insn (gen_subc (gen_lowpart (SImode, operands[0]),
2155 gen_lowpart (SImode, operands[1]),
2156 gen_lowpart (SImode, operands[2])));
2157 emit_insn (gen_subc (gen_highpart (SImode, operands[0]),
2158 gen_highpart (SImode, operands[1]),
2159 gen_highpart (SImode, operands[2])));
2160 DONE;
2161 })
2162
2163 (define_insn "subc"
2164 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2165 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2166 (match_operand:SI 2 "arith_reg_operand" "r"))
2167 (reg:SI T_REG)))
2168 (set (reg:SI T_REG)
2169 (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
2170 (reg:SI T_REG))
2171 (match_dup 1)))]
2172 "TARGET_SH1"
2173 "subc %2,%0"
2174 [(set_attr "type" "arith")])
2175
2176 ;; A simplified version of the subc insn, where the exact value of the
2177 ;; T bit doesn't matter. This is easier for combine to pick up.
2178 ;; We allow a reg or 0 for one of the operands in order to be able to
2179 ;; do 'reg - T' sequences. Reload will load the constant 0 into the reg
2180 ;; as needed.
2181 (define_insn "*subc"
2182 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2183 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2184 (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
2185 (match_operand:SI 3 "t_reg_operand" "")))
2186 (clobber (reg:SI T_REG))]
2187 "TARGET_SH1"
2188 "subc %2,%0"
2189 [(set_attr "type" "arith")])
2190
2191 ;; Split reg - reg - 1 into a sett subc sequence, as it can be scheduled
2192 ;; better, if the sett insn can be done early.
2193 ;; Notice that combine turns 'a - b - 1' into 'a + (~b)'.
2194 (define_insn_and_split "*subc"
2195 [(set (match_operand:SI 0 "arith_reg_dest" "")
2196 (plus:SI (not:SI (match_operand:SI 1 "arith_reg_operand" ""))
2197 (match_operand:SI 2 "arith_reg_operand" "")))
2198 (clobber (reg:SI T_REG))]
2199 "TARGET_SH1"
2200 "#"
2201 "&& 1"
2202 [(set (reg:SI T_REG) (const_int 1))
2203 (parallel [(set (match_dup 0)
2204 (minus:SI (minus:SI (match_dup 2) (match_dup 1))
2205 (reg:SI T_REG)))
2206 (clobber (reg:SI T_REG))])])
2207
2208 ;; Split 'reg - T' into 'reg - 0 - T' to utilize the subc insn.
2209 ;; If the 0 constant can be CSE-ed, this becomes a one instruction
2210 ;; operation, as opposed to sequences such as
2211 ;; movt r2
2212 ;; sub r2,r3
2213 ;;
2214 ;; Even if the constant is not CSE-ed, a sequence such as
2215 ;; mov #0,r2
2216 ;; subc r2,r3
2217 ;; can be scheduled much better since the load of the constant can be
2218 ;; done earlier, before any comparison insns that store the result in
2219 ;; the T bit.
2220 (define_insn_and_split "*subc"
2221 [(set (match_operand:SI 0 "arith_reg_dest" "")
2222 (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
2223 (match_operand:SI 2 "t_reg_operand" "")))
2224 (clobber (reg:SI T_REG))]
2225 "TARGET_SH1"
2226 "#"
2227 "&& 1"
2228 [(parallel [(set (match_dup 0)
2229 (minus:SI (minus:SI (match_dup 1) (const_int 0))
2230 (match_dup 2)))
2231 (clobber (reg:SI T_REG))])])
2232
2233 (define_insn "*subsi3_internal"
2234 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2235 (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2236 (match_operand:SI 2 "arith_reg_operand" "r")))]
2237 "TARGET_SH1"
2238 "sub %2,%0"
2239 [(set_attr "type" "arith")])
2240
2241 (define_insn_and_split "*subsi3_media"
2242 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2243 (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
2244 (match_operand:SI 2 "extend_reg_operand" "r")))]
2245 "TARGET_SHMEDIA
2246 && (operands[1] != constm1_rtx
2247 || (GET_CODE (operands[2]) != TRUNCATE
2248 && GET_CODE (operands[2]) != SUBREG))"
2249 "sub.l %N1, %2, %0"
2250 "operands[1] == constm1_rtx"
2251 [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
2252 ""
2253 [(set_attr "type" "arith_media")
2254 (set_attr "highpart" "ignore")])
2255
2256 (define_split
2257 [(set (match_operand:SI 0 "arith_reg_dest" "")
2258 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2259 "general_extend_operand"
2260 "") 0)) 0)))]
2261 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
2262 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2263 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2264 "")
2265
2266 (define_split
2267 [(set (match_operand:SI 0 "arith_reg_dest" "")
2268 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2269 "general_extend_operand"
2270 "") 0)) 3)))]
2271 "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
2272 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2273 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2274 "")
2275
2276 ;; Convert
2277 ;; constant - reg
2278 ;; to
2279 ;; neg reg
2280 ;; add reg, #const
2281 ;; since this will sometimes save one instruction.
2282 ;; Otherwise we might get a sequence like
2283 ;; mov #const, rY
2284 ;; sub rY, rX
2285 ;; mov rX, rY
2286 ;; if the source and dest regs are the same.
2287 (define_expand "subsi3"
2288 [(set (match_operand:SI 0 "arith_reg_operand" "")
2289 (minus:SI (match_operand:SI 1 "arith_operand" "")
2290 (match_operand:SI 2 "arith_reg_operand" "")))]
2291 ""
2292 {
2293 if (TARGET_SH1 && CONST_INT_P (operands[1]))
2294 {
2295 emit_insn (gen_negsi2 (operands[0], operands[2]));
2296 emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
2297 DONE;
2298 }
2299 if (TARGET_SHMEDIA)
2300 {
2301 if (!can_create_pseudo_p ()
2302 && ! arith_reg_or_0_operand (operands[1], SImode))
2303 FAIL;
2304 if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
2305 operands[1] = force_reg (SImode, operands[1]);
2306 }
2307 })
2308 \f
2309 ;; -------------------------------------------------------------------------
2310 ;; Division instructions
2311 ;; -------------------------------------------------------------------------
2312
2313 ;; We take advantage of the library routines which don't clobber as many
2314 ;; registers as a normal function call would.
2315
2316 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
2317 ;; also has an effect on the register that holds the address of the sfunc.
2318 ;; To make this work, we have an extra dummy insn that shows the use
2319 ;; of this register for reorg.
2320
2321 (define_insn "use_sfunc_addr"
2322 [(set (reg:SI PR_REG)
2323 (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
2324 "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
2325 ""
2326 [(set_attr "length" "0")])
2327
2328 (define_insn "udivsi3_sh2a"
2329 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2330 (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
2331 (match_operand:SI 2 "arith_reg_operand" "z")))]
2332 "TARGET_SH2A"
2333 "divu %2,%1"
2334 [(set_attr "type" "arith")
2335 (set_attr "in_delay_slot" "no")])
2336
2337 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
2338 ;; hard register 0. If we used hard register 0, then the next instruction
2339 ;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg
2340 ;; gets allocated to a stack slot that needs its address reloaded, then
2341 ;; there is nothing to prevent reload from using r0 to reload the address.
2342 ;; This reload would clobber the value in r0 we are trying to store.
2343 ;; If we let reload allocate r0, then this problem can never happen.
2344 (define_insn "udivsi3_i1"
2345 [(set (match_operand:SI 0 "register_operand" "=z")
2346 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2347 (clobber (reg:SI T_REG))
2348 (clobber (reg:SI PR_REG))
2349 (clobber (reg:SI R1_REG))
2350 (clobber (reg:SI R4_REG))
2351 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2352 "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2353 "jsr @%1%#"
2354 [(set_attr "type" "sfunc")
2355 (set_attr "needs_delay_slot" "yes")])
2356
2357 ; Since shmedia-nofpu code could be linked against shcompact code, and
2358 ; the udivsi3 libcall has the same name, we must consider all registers
2359 ; clobbered that are in the union of the registers clobbered by the
2360 ; shmedia and the shcompact implementation. Note, if the shcompact
2361 ; implementation actually used shcompact code, we'd need to clobber
2362 ; also r23 and fr23.
2363 (define_insn "udivsi3_i1_media"
2364 [(set (match_operand:SI 0 "register_operand" "=z")
2365 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2366 (clobber (reg:SI T_MEDIA_REG))
2367 (clobber (reg:SI PR_MEDIA_REG))
2368 (clobber (reg:SI R20_REG))
2369 (clobber (reg:SI R21_REG))
2370 (clobber (reg:SI R22_REG))
2371 (clobber (reg:DI TR0_REG))
2372 (clobber (reg:DI TR1_REG))
2373 (clobber (reg:DI TR2_REG))
2374 (use (match_operand 1 "target_reg_operand" "b"))]
2375 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2376 "blink %1, r18"
2377 [(set_attr "type" "sfunc")
2378 (set_attr "needs_delay_slot" "yes")])
2379
2380 (define_expand "udivsi3_i4_media"
2381 [(set (match_dup 3)
2382 (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
2383 (set (match_dup 4)
2384 (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
2385 (set (match_dup 5) (float:DF (match_dup 3)))
2386 (set (match_dup 6) (float:DF (match_dup 4)))
2387 (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
2388 (set (match_dup 8) (fix:DI (match_dup 7)))
2389 (set (match_operand:SI 0 "register_operand" "")
2390 (truncate:SI (match_dup 8)))]
2391 "TARGET_SHMEDIA_FPU"
2392 {
2393 operands[3] = gen_reg_rtx (DImode);
2394 operands[4] = gen_reg_rtx (DImode);
2395 operands[5] = gen_reg_rtx (DFmode);
2396 operands[6] = gen_reg_rtx (DFmode);
2397 operands[7] = gen_reg_rtx (DFmode);
2398 operands[8] = gen_reg_rtx (DImode);
2399 })
2400
2401 (define_insn "udivsi3_i4"
2402 [(set (match_operand:SI 0 "register_operand" "=y")
2403 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2404 (clobber (reg:SI T_REG))
2405 (clobber (reg:SI PR_REG))
2406 (clobber (reg:DF DR0_REG))
2407 (clobber (reg:DF DR2_REG))
2408 (clobber (reg:DF DR4_REG))
2409 (clobber (reg:SI R0_REG))
2410 (clobber (reg:SI R1_REG))
2411 (clobber (reg:SI R4_REG))
2412 (clobber (reg:SI R5_REG))
2413 (clobber (reg:SI FPSCR_STAT_REG))
2414 (use (reg:SI FPSCR_MODES_REG))
2415 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2416 "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2417 "jsr @%1%#"
2418 [(set_attr "type" "sfunc")
2419 (set_attr "fp_mode" "double")
2420 (set_attr "needs_delay_slot" "yes")])
2421
2422 (define_insn "udivsi3_i4_single"
2423 [(set (match_operand:SI 0 "register_operand" "=y")
2424 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2425 (clobber (reg:SI T_REG))
2426 (clobber (reg:SI PR_REG))
2427 (clobber (reg:DF DR0_REG))
2428 (clobber (reg:DF DR2_REG))
2429 (clobber (reg:DF DR4_REG))
2430 (clobber (reg:SI R0_REG))
2431 (clobber (reg:SI R1_REG))
2432 (clobber (reg:SI R4_REG))
2433 (clobber (reg:SI R5_REG))
2434 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2435 "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2436 && TARGET_FPU_SINGLE"
2437 "jsr @%1%#"
2438 [(set_attr "type" "sfunc")
2439 (set_attr "needs_delay_slot" "yes")])
2440
2441 (define_insn "udivsi3_i4_int"
2442 [(set (match_operand:SI 0 "register_operand" "=z")
2443 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2444 (clobber (reg:SI T_REG))
2445 (clobber (reg:SI R1_REG))
2446 (clobber (reg:SI PR_REG))
2447 (clobber (reg:SI MACH_REG))
2448 (clobber (reg:SI MACL_REG))
2449 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2450 "TARGET_SH1"
2451 "jsr @%1%#"
2452 [(set_attr "type" "sfunc")
2453 (set_attr "needs_delay_slot" "yes")])
2454
2455
2456 (define_expand "udivsi3"
2457 [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
2458 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2459 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2460 (parallel [(set (match_operand:SI 0 "register_operand" "")
2461 (udiv:SI (reg:SI R4_REG)
2462 (reg:SI R5_REG)))
2463 (clobber (reg:SI T_REG))
2464 (clobber (reg:SI PR_REG))
2465 (clobber (reg:SI R4_REG))
2466 (use (match_dup 3))])]
2467 ""
2468 {
2469 rtx last;
2470
2471 operands[3] = gen_reg_rtx (Pmode);
2472 /* Emit the move of the address to a pseudo outside of the libcall. */
2473 if (TARGET_DIVIDE_CALL_TABLE)
2474 {
2475 /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
2476 that causes problems when the divide code is supposed to come from a
2477 separate library. Division by zero is undefined, so dividing 1 can be
2478 implemented by comparing with the divisor. */
2479 if (operands[1] == const1_rtx && currently_expanding_to_rtl)
2480 {
2481 rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
2482 emit_insn (gen_cstoresi4 (operands[0], test,
2483 operands[1], operands[2]));
2484 DONE;
2485 }
2486 else if (operands[2] == const0_rtx)
2487 {
2488 emit_move_insn (operands[0], operands[2]);
2489 DONE;
2490 }
2491 function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT);
2492 last = gen_udivsi3_i4_int (operands[0], operands[3]);
2493 }
2494 else if (TARGET_DIVIDE_CALL_FP)
2495 {
2496 function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC);
2497 if (TARGET_FPU_SINGLE)
2498 last = gen_udivsi3_i4_single (operands[0], operands[3]);
2499 else
2500 last = gen_udivsi3_i4 (operands[0], operands[3]);
2501 }
2502 else if (TARGET_SHMEDIA_FPU)
2503 {
2504 operands[1] = force_reg (SImode, operands[1]);
2505 operands[2] = force_reg (SImode, operands[2]);
2506 emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
2507 DONE;
2508 }
2509 else if (TARGET_SH2A)
2510 {
2511 operands[1] = force_reg (SImode, operands[1]);
2512 operands[2] = force_reg (SImode, operands[2]);
2513 emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
2514 DONE;
2515 }
2516 else if (TARGET_SH5)
2517 {
2518 function_symbol (operands[3],
2519 TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3",
2520 SFUNC_STATIC);
2521
2522 if (TARGET_SHMEDIA)
2523 last = gen_udivsi3_i1_media (operands[0], operands[3]);
2524 else if (TARGET_FPU_ANY)
2525 last = gen_udivsi3_i4_single (operands[0], operands[3]);
2526 else
2527 last = gen_udivsi3_i1 (operands[0], operands[3]);
2528 }
2529 else
2530 {
2531 function_symbol (operands[3], "__udivsi3", SFUNC_STATIC);
2532 last = gen_udivsi3_i1 (operands[0], operands[3]);
2533 }
2534 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2535 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2536 emit_insn (last);
2537 DONE;
2538 })
2539
2540 (define_insn "divsi3_sh2a"
2541 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2542 (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
2543 (match_operand:SI 2 "arith_reg_operand" "z")))]
2544 "TARGET_SH2A"
2545 "divs %2,%1"
2546 [(set_attr "type" "arith")
2547 (set_attr "in_delay_slot" "no")])
2548
2549 (define_insn "divsi3_i1"
2550 [(set (match_operand:SI 0 "register_operand" "=z")
2551 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2552 (clobber (reg:SI T_REG))
2553 (clobber (reg:SI PR_REG))
2554 (clobber (reg:SI R1_REG))
2555 (clobber (reg:SI R2_REG))
2556 (clobber (reg:SI R3_REG))
2557 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2558 "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2559 "jsr @%1%#"
2560 [(set_attr "type" "sfunc")
2561 (set_attr "needs_delay_slot" "yes")])
2562
2563 (define_insn "divsi3_i1_media"
2564 [(set (match_operand:SI 0 "register_operand" "=z")
2565 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2566 (clobber (reg:SI T_MEDIA_REG))
2567 (clobber (reg:SI PR_MEDIA_REG))
2568 (clobber (reg:SI R1_REG))
2569 (clobber (reg:SI R20_REG))
2570 (clobber (reg:SI R21_REG))
2571 (clobber (reg:SI TR0_REG))
2572 (use (match_operand 1 "target_reg_operand" "b"))]
2573 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2574 "blink %1, r18"
2575 [(set_attr "type" "sfunc")])
2576
2577 (define_insn "divsi3_media_2"
2578 [(set (match_operand:SI 0 "register_operand" "=z")
2579 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2580 (clobber (reg:SI T_MEDIA_REG))
2581 (clobber (reg:SI PR_MEDIA_REG))
2582 (clobber (reg:SI R1_REG))
2583 (clobber (reg:SI R21_REG))
2584 (clobber (reg:SI TR0_REG))
2585 (use (reg:SI R20_REG))
2586 (use (match_operand 1 "target_reg_operand" "b"))]
2587 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2588 "blink %1, r18"
2589 [(set_attr "type" "sfunc")])
2590
2591 ;; This pattern acts as a placeholder for -mdiv=inv:call to carry
2592 ;; hard reg clobbers and data dependencies that we need when we want
2593 ;; to rematerialize the division into a call.
2594 (define_insn_and_split "divsi_inv_call"
2595 [(set (match_operand:SI 0 "register_operand" "=r")
2596 (div:SI (match_operand:SI 1 "register_operand" "r")
2597 (match_operand:SI 2 "register_operand" "r")))
2598 (clobber (reg:SI R4_REG))
2599 (clobber (reg:SI R5_REG))
2600 (clobber (reg:SI T_MEDIA_REG))
2601 (clobber (reg:SI PR_MEDIA_REG))
2602 (clobber (reg:SI R1_REG))
2603 (clobber (reg:SI R21_REG))
2604 (clobber (reg:SI TR0_REG))
2605 (clobber (reg:SI R20_REG))
2606 (use (match_operand:SI 3 "register_operand" "r"))]
2607 "TARGET_SHMEDIA"
2608 "#"
2609 "&& (reload_in_progress || reload_completed)"
2610 [(set (match_dup 0) (match_dup 3))]
2611 ""
2612 [(set_attr "highpart" "must_split")])
2613
2614 ;; This is the combiner pattern for -mdiv=inv:call .
2615 (define_insn_and_split "*divsi_inv_call_combine"
2616 [(set (match_operand:SI 0 "register_operand" "=z")
2617 (div:SI (match_operand:SI 1 "register_operand" "r")
2618 (match_operand:SI 2 "register_operand" "r")))
2619 (clobber (reg:SI R4_REG))
2620 (clobber (reg:SI R5_REG))
2621 (clobber (reg:SI T_MEDIA_REG))
2622 (clobber (reg:SI PR_MEDIA_REG))
2623 (clobber (reg:SI R1_REG))
2624 (clobber (reg:SI R21_REG))
2625 (clobber (reg:SI TR0_REG))
2626 (clobber (reg:SI R20_REG))
2627 (use (unspec:SI [(match_dup 1)
2628 (match_operand:SI 3 "" "")
2629 (unspec:SI [(match_operand:SI 4 "" "")
2630 (match_dup 3)
2631 (match_operand:DI 5 "" "")]
2632 UNSPEC_DIV_INV_M2)
2633 (match_operand:DI 6 "" "")
2634 (const_int 0)
2635 (const_int 0)]
2636 UNSPEC_DIV_INV_M3))]
2637 "TARGET_SHMEDIA"
2638 "#"
2639 "&& (reload_in_progress || reload_completed)"
2640 [(pc)]
2641 {
2642 const char *name = sh_divsi3_libfunc;
2643 enum sh_function_kind kind = SFUNC_GOT;
2644 rtx sym;
2645
2646 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2647 emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2648 while (TARGET_DIVIDE_INV_CALL2)
2649 {
2650 rtx x = operands[3];
2651
2652 if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2653 break;
2654 x = XVECEXP (x, 0, 0);
2655 name = "__sdivsi3_2";
2656 kind = SFUNC_STATIC;
2657 emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2658 break;
2659 }
2660 sym = function_symbol (NULL, name, kind);
2661 emit_insn (gen_divsi3_media_2 (operands[0], sym));
2662 DONE;
2663 }
2664 [(set_attr "highpart" "must_split")])
2665
2666 (define_expand "divsi3_i4_media"
2667 [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2668 (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2669 (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2670 (set (match_operand:SI 0 "register_operand" "=r")
2671 (fix:SI (match_dup 5)))]
2672 "TARGET_SHMEDIA_FPU"
2673 {
2674 operands[3] = gen_reg_rtx (DFmode);
2675 operands[4] = gen_reg_rtx (DFmode);
2676 operands[5] = gen_reg_rtx (DFmode);
2677 })
2678
2679 (define_insn "divsi3_i4"
2680 [(set (match_operand:SI 0 "register_operand" "=y")
2681 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2682 (clobber (reg:SI PR_REG))
2683 (clobber (reg:DF DR0_REG))
2684 (clobber (reg:DF DR2_REG))
2685 (clobber (reg:SI FPSCR_STAT_REG))
2686 (use (reg:SI FPSCR_MODES_REG))
2687 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2688 "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2689 "jsr @%1%#"
2690 [(set_attr "type" "sfunc")
2691 (set_attr "fp_mode" "double")
2692 (set_attr "needs_delay_slot" "yes")])
2693
2694 (define_insn "divsi3_i4_single"
2695 [(set (match_operand:SI 0 "register_operand" "=y")
2696 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2697 (clobber (reg:SI PR_REG))
2698 (clobber (reg:DF DR0_REG))
2699 (clobber (reg:DF DR2_REG))
2700 (clobber (reg:SI R2_REG))
2701 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2702 "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2703 && TARGET_FPU_SINGLE"
2704 "jsr @%1%#"
2705 [(set_attr "type" "sfunc")
2706 (set_attr "needs_delay_slot" "yes")])
2707
2708 (define_insn "divsi3_i4_int"
2709 [(set (match_operand:SI 0 "register_operand" "=z")
2710 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2711 (clobber (reg:SI T_REG))
2712 (clobber (reg:SI PR_REG))
2713 (clobber (reg:SI R1_REG))
2714 (clobber (reg:SI MACH_REG))
2715 (clobber (reg:SI MACL_REG))
2716 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2717 "TARGET_SH1"
2718 "jsr @%1%#"
2719 [(set_attr "type" "sfunc")
2720 (set_attr "needs_delay_slot" "yes")])
2721
2722 (define_expand "divsi3"
2723 [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2724 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2725 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2726 (parallel [(set (match_operand:SI 0 "register_operand" "")
2727 (div:SI (reg:SI R4_REG)
2728 (reg:SI R5_REG)))
2729 (clobber (reg:SI T_REG))
2730 (clobber (reg:SI PR_REG))
2731 (clobber (reg:SI R1_REG))
2732 (clobber (reg:SI R2_REG))
2733 (clobber (reg:SI R3_REG))
2734 (use (match_dup 3))])]
2735 ""
2736 {
2737 rtx last;
2738
2739 operands[3] = gen_reg_rtx (Pmode);
2740 /* Emit the move of the address to a pseudo outside of the libcall. */
2741 if (TARGET_DIVIDE_CALL_TABLE)
2742 {
2743 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2744 last = gen_divsi3_i4_int (operands[0], operands[3]);
2745 }
2746 else if (TARGET_DIVIDE_CALL_FP)
2747 {
2748 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2749 if (TARGET_FPU_SINGLE)
2750 last = gen_divsi3_i4_single (operands[0], operands[3]);
2751 else
2752 last = gen_divsi3_i4 (operands[0], operands[3]);
2753 }
2754 else if (TARGET_SH2A)
2755 {
2756 operands[1] = force_reg (SImode, operands[1]);
2757 operands[2] = force_reg (SImode, operands[2]);
2758 emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2759 DONE;
2760 }
2761 else if (TARGET_DIVIDE_INV)
2762 {
2763 rtx dividend = operands[1];
2764 rtx divisor = operands[2];
2765 rtx tab_base;
2766 rtx nsb_res = gen_reg_rtx (DImode);
2767 rtx norm64 = gen_reg_rtx (DImode);
2768 rtx tab_ix = gen_reg_rtx (DImode);
2769 rtx norm32 = gen_reg_rtx (SImode);
2770 rtx i92 = force_reg (DImode, GEN_INT (92));
2771 rtx scratch0a = gen_reg_rtx (DImode);
2772 rtx scratch0b = gen_reg_rtx (DImode);
2773 rtx inv0 = gen_reg_rtx (SImode);
2774 rtx scratch1a = gen_reg_rtx (DImode);
2775 rtx scratch1b = gen_reg_rtx (DImode);
2776 rtx shift = gen_reg_rtx (DImode);
2777 rtx i2p27, i43;
2778 rtx inv1 = gen_reg_rtx (SImode);
2779 rtx scratch2a = gen_reg_rtx (DImode);
2780 rtx scratch2b = gen_reg_rtx (SImode);
2781 rtx inv2 = gen_reg_rtx (SImode);
2782 rtx scratch3a = gen_reg_rtx (DImode);
2783 rtx scratch3b = gen_reg_rtx (DImode);
2784 rtx scratch3c = gen_reg_rtx (DImode);
2785 rtx scratch3d = gen_reg_rtx (SImode);
2786 rtx scratch3e = gen_reg_rtx (DImode);
2787 rtx result = gen_reg_rtx (SImode);
2788
2789 if (! arith_reg_or_0_operand (dividend, SImode))
2790 dividend = force_reg (SImode, dividend);
2791 if (! arith_reg_operand (divisor, SImode))
2792 divisor = force_reg (SImode, divisor);
2793 if (flag_pic && Pmode != DImode)
2794 {
2795 tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2796 tab_base = gen_datalabel_ref (tab_base);
2797 tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2798 }
2799 else
2800 {
2801 tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table");
2802 tab_base = gen_datalabel_ref (tab_base);
2803 tab_base = force_reg (DImode, tab_base);
2804 }
2805 if (TARGET_DIVIDE_INV20U)
2806 i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2807 else
2808 i2p27 = GEN_INT (0);
2809 if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2810 i43 = force_reg (DImode, GEN_INT (43));
2811 else
2812 i43 = GEN_INT (0);
2813 emit_insn (gen_nsbdi (nsb_res,
2814 simplify_gen_subreg (DImode, divisor, SImode, 0)));
2815 emit_insn (gen_ashldi3_media (norm64,
2816 gen_rtx_SUBREG (DImode, divisor, 0),
2817 nsb_res));
2818 emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2819 emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2820 emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2821 inv0, scratch0a, scratch0b,
2822 scratch1a, scratch1b));
2823 emit_insn (gen_subdi3 (shift, i92, nsb_res));
2824 emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2825 scratch2a));
2826 emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2827 i2p27, i43,
2828 scratch3a, scratch3b, scratch3c,
2829 scratch2a, scratch2b, scratch3d, scratch3e));
2830 if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2831 emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2832 else if (TARGET_DIVIDE_INV_FP)
2833 emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2834 gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2835 gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2836 gen_reg_rtx (DFmode)));
2837 else
2838 emit_move_insn (operands[0], result);
2839 DONE;
2840 }
2841 else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2842 {
2843 operands[1] = force_reg (SImode, operands[1]);
2844 operands[2] = force_reg (SImode, operands[2]);
2845 emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2846 DONE;
2847 }
2848 else if (TARGET_SH5)
2849 {
2850 if (TARGET_DIVIDE_CALL2)
2851 {
2852 rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2853 tab_base = gen_datalabel_ref (tab_base);
2854 emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2855 }
2856 if (TARGET_FPU_ANY && TARGET_SH1)
2857 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2858 else if (TARGET_DIVIDE_CALL2)
2859 function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC);
2860 else
2861 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2862
2863 if (TARGET_SHMEDIA)
2864 last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2865 (operands[0], operands[3]));
2866 else if (TARGET_FPU_ANY)
2867 last = gen_divsi3_i4_single (operands[0], operands[3]);
2868 else
2869 last = gen_divsi3_i1 (operands[0], operands[3]);
2870 }
2871 else
2872 {
2873 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2874 last = gen_divsi3_i1 (operands[0], operands[3]);
2875 }
2876 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2877 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2878 emit_insn (last);
2879 DONE;
2880 })
2881
2882 ;; operands: scratch, tab_base, tab_ix
2883 ;; These are unspecs because we could generate an indexed addressing mode
2884 ;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2885 ;; confuse reload. See PR27117.
2886 (define_insn "divsi_inv_qitable"
2887 [(set (match_operand:DI 0 "register_operand" "=r")
2888 (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2889 (match_operand:DI 2 "register_operand" "r")]
2890 UNSPEC_DIV_INV_TABLE)))]
2891 "TARGET_SHMEDIA"
2892 "ldx.ub %1, %2, %0"
2893 [(set_attr "type" "load_media")
2894 (set_attr "highpart" "user")])
2895
2896 ;; operands: scratch, tab_base, tab_ix
2897 (define_insn "divsi_inv_hitable"
2898 [(set (match_operand:DI 0 "register_operand" "=r")
2899 (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2900 (match_operand:DI 2 "register_operand" "r")]
2901 UNSPEC_DIV_INV_TABLE)))]
2902 "TARGET_SHMEDIA"
2903 "ldx.w %1, %2, %0"
2904 [(set_attr "type" "load_media")
2905 (set_attr "highpart" "user")])
2906
2907 ;; operands: inv0, tab_base, tab_ix, norm32
2908 ;; scratch equiv in sdivsi3_2: r19, r21
2909 (define_expand "divsi_inv_m0"
2910 [(set (match_operand:SI 0 "register_operand" "=r")
2911 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2912 (match_operand:DI 2 "register_operand" "r")
2913 (match_operand:SI 3 "register_operand" "r")]
2914 UNSPEC_DIV_INV_M0))
2915 (clobber (match_operand:DI 4 "register_operand" "=r"))
2916 (clobber (match_operand:DI 5 "register_operand" "=r"))]
2917 "TARGET_SHMEDIA"
2918 {
2919 /*
2920 tab_base: r20
2921 tab_ix: r21
2922 norm32: r25
2923 ldx.ub r20, r21, r19 // u0.8
2924 shlli r21, 1, r21
2925 muls.l r25, r19, r19 // s2.38
2926 ldx.w r20, r21, r21 // s2.14
2927 shari r19, 24, r19 // truncate to s2.14
2928 sub r21, r19, r19 // some 11 bit inverse in s1.14
2929 */
2930
2931 rtx inv0 = operands[0];
2932 rtx tab_base = operands[1];
2933 rtx tab_ix = operands[2];
2934 rtx norm32 = operands[3];
2935 rtx scratch0 = operands[4];
2936 rtx scratch0_si = gen_lowpart (SImode, scratch0);
2937 rtx scratch1 = operands[5];
2938
2939 emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2940 emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2941 emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2942 emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2943 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2944 emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2945 DONE;
2946 })
2947
2948 ;; operands: inv1, tab_base, tab_ix, norm32
2949 (define_insn_and_split "divsi_inv_m1"
2950 [(set (match_operand:SI 0 "register_operand" "=r")
2951 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2952 (match_operand:DI 2 "register_operand" "r")
2953 (match_operand:SI 3 "register_operand" "r")]
2954 UNSPEC_DIV_INV_M1))
2955 (clobber (match_operand:SI 4 "register_operand" "=r"))
2956 (clobber (match_operand:DI 5 "register_operand" "=r"))
2957 (clobber (match_operand:DI 6 "register_operand" "=r"))
2958 (clobber (match_operand:DI 7 "register_operand" "=r"))
2959 (clobber (match_operand:DI 8 "register_operand" "=r"))]
2960 "TARGET_SHMEDIA"
2961 "#"
2962 "&& !can_create_pseudo_p ()"
2963 [(pc)]
2964 {
2965 /* inv0: r19
2966 muls.l r19, r19, r18 // u0.28
2967 muls.l r25, r18, r18 // s2.58
2968 shlli r19, 45, r0 // multiply by two and convert to s2.58
2969 sub r0, r18, r18
2970 shari r18, 28, r18 // some 18 bit inverse in s1.30
2971 */
2972
2973 rtx inv1 = operands[0];
2974 rtx tab_base = operands[1];
2975 rtx tab_ix = operands[2];
2976 rtx norm32 = operands[3];
2977 rtx inv0 = operands[4];
2978 rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2979 rtx scratch0a = operands[5];
2980 rtx scratch0b = operands[6];
2981 rtx scratch0 = operands[7];
2982 rtx scratch1 = operands[8];
2983 rtx scratch1_si = gen_lowpart (SImode, scratch1);
2984
2985 emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2986 scratch0a, scratch0b));
2987 emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2988 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2989 emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2990 emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2991 emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2992 DONE;
2993 })
2994
2995 ;; operands: inv2, norm32, inv1, i92
2996 (define_insn_and_split "divsi_inv_m2"
2997 [(set (match_operand:SI 0 "register_operand" "=r")
2998 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2999 (match_operand:SI 2 "register_operand" "r")
3000 (match_operand:DI 3 "register_operand" "r")]
3001 UNSPEC_DIV_INV_M2))
3002 (clobber (match_operand:DI 4 "register_operand" "=r"))]
3003 "TARGET_SHMEDIA"
3004 "#"
3005 "&& !can_create_pseudo_p ()"
3006 [(pc)]
3007 {
3008 /*
3009 muls.l r18, r25, r0 // s2.60
3010 shari r0, 16, r0 // s-16.44
3011 sub
3012 muls.l r0, r18, r19 // s-16.74
3013 shari r19, 30, r19 // s-16.44
3014 */
3015 rtx inv2 = operands[0];
3016 rtx norm32 = operands[1];
3017 rtx inv1 = operands[2];
3018 rtx i92 = operands[3];
3019 rtx scratch0 = operands[4];
3020 rtx scratch0_si = gen_lowpart (SImode, scratch0);
3021
3022 emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
3023 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
3024 emit_insn (gen_subdi3 (scratch0, i92, scratch0));
3025 emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
3026 emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
3027 DONE;
3028 })
3029
3030 (define_insn_and_split "divsi_inv_m3"
3031 [(set (match_operand:SI 0 "register_operand" "=r")
3032 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
3033 (match_operand:SI 2 "register_operand" "r")
3034 (match_operand:SI 3 "register_operand" "r")
3035 (match_operand:DI 4 "register_operand" "r")
3036 (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
3037 (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
3038 UNSPEC_DIV_INV_M3))
3039 (clobber (match_operand:DI 7 "register_operand" "=r"))
3040 (clobber (match_operand:DI 8 "register_operand" "=r"))
3041 (clobber (match_operand:DI 9 "register_operand" "=r"))
3042 (clobber (match_operand:DI 10 "register_operand" "=r"))
3043 (clobber (match_operand:SI 11 "register_operand" "=r"))
3044 (clobber (match_operand:SI 12 "register_operand" "=r"))
3045 (clobber (match_operand:DI 13 "register_operand" "=r"))]
3046 "TARGET_SHMEDIA"
3047 "#"
3048 "&& !can_create_pseudo_p ()"
3049 [(pc)]
3050 {
3051 /*
3052 r0: result r1: shift r4: dividend r18: inv1 r19: inv2
3053 r0: scratch0 r19: scratch1 r21: scratch2
3054
3055 muls.l r18, r4, r25 // s32.30
3056 muls.l r19, r4, r19 // s15.30
3057 shari r25, 63, r21
3058 shari r19, 14, r19 // s18.-14
3059 sub r25, r19, r0
3060 shard r0, r1, r0
3061 sub r0, r21, r0
3062 */
3063
3064 rtx result = operands[0];
3065 rtx dividend = operands[1];
3066 rtx inv1 = operands[2];
3067 rtx inv2 = operands[3];
3068 rtx shift = operands[4];
3069 rtx scratch0 = operands[7];
3070 rtx scratch1 = operands[8];
3071 rtx scratch2 = operands[9];
3072
3073 if (satisfies_constraint_N (dividend))
3074 {
3075 emit_move_insn (result, dividend);
3076 DONE;
3077 }
3078
3079 emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
3080 emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
3081 emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
3082 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
3083 emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
3084 emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
3085 emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
3086 DONE;
3087 })
3088
3089 ;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
3090 ;; inv1: tab_base, tab_ix, norm32
3091 ;; inv2: norm32, inv1, i92
3092 (define_insn_and_split "divsi_inv_m1_3"
3093 [(set (match_operand:SI 0 "register_operand" "=r")
3094 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
3095 (unspec:SI [(match_operand:DI 2 "register_operand" "r")
3096 (match_operand:DI 3 "register_operand" "r")
3097 (match_operand:SI 4 "register_operand" "r")]
3098 UNSPEC_DIV_INV_M1)
3099 (unspec:SI [(match_dup 4)
3100 (unspec:SI [(match_dup 2)
3101 (match_dup 3)
3102 (match_dup 4)] UNSPEC_DIV_INV_M1)
3103 (match_operand:SI 5 "" "")]
3104 UNSPEC_DIV_INV_M2)
3105 (match_operand:DI 6 "register_operand" "r")
3106 (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
3107 (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
3108 UNSPEC_DIV_INV_M3))
3109 (clobber (match_operand:DI 9 "register_operand" "=r"))
3110 (clobber (match_operand:DI 10 "register_operand" "=r"))
3111 (clobber (match_operand:DI 11 "register_operand" "=r"))
3112 (clobber (match_operand:DI 12 "register_operand" "=r"))
3113 (clobber (match_operand:SI 13 "register_operand" "=r"))
3114 (clobber (match_operand:SI 14 "register_operand" "=r"))
3115 (clobber (match_operand:DI 15 "register_operand" "=r"))]
3116 "TARGET_SHMEDIA
3117 && (TARGET_DIVIDE_INV_MINLAT
3118 || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
3119 "#"
3120 "&& !can_create_pseudo_p ()"
3121 [(pc)]
3122 {
3123 rtx result = operands[0];
3124 rtx dividend = operands[1];
3125 rtx tab_base = operands[2];
3126 rtx tab_ix = operands[3];
3127 rtx norm32 = operands[4];
3128 /* rtx i92 = operands[5]; */
3129 rtx shift = operands[6];
3130 rtx i2p27 = operands[7];
3131 rtx i43 = operands[8];
3132 rtx scratch0 = operands[9];
3133 rtx scratch0_si = gen_lowpart (SImode, scratch0);
3134 rtx scratch1 = operands[10];
3135 rtx scratch1_si = gen_lowpart (SImode, scratch1);
3136 rtx scratch2 = operands[11];
3137 rtx scratch3 = operands[12];
3138 rtx scratch4 = operands[13];
3139 rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
3140 rtx scratch5 = operands[14];
3141 rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
3142 rtx scratch6 = operands[15];
3143
3144 emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
3145 scratch0, scratch1));
3146 /* inv0 == scratch4 */
3147 if (! TARGET_DIVIDE_INV20U)
3148 {
3149 emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
3150 i2p27 = scratch0;
3151 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
3152 }
3153 else
3154 {
3155 emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
3156 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
3157 }
3158 emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
3159 emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
3160 emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
3161 /* inv1 == scratch4 */
3162
3163 if (TARGET_DIVIDE_INV_MINLAT)
3164 {
3165 emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
3166 emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
3167 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
3168 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
3169 emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
3170 emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
3171 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
3172 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
3173 emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
3174 emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
3175 emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
3176 }
3177 else
3178 {
3179 rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
3180 /* Use separate scratch regs for nsb and sign to allow scheduling. */
3181 emit_insn (gen_nsbdi (scratch6,
3182 simplify_gen_subreg (DImode, dividend, SImode, 0)));
3183 emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
3184 emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
3185 emit_insn (gen_divsi_inv20 (scratch2,
3186 norm32, scratch4, dividend,
3187 scratch6, scratch3, i43,
3188 /* scratch0 may be shared with i2p27. */
3189 scratch0, scratch1, scratch5,
3190 label, label, i2p27));
3191 }
3192 emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
3193 emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
3194 DONE;
3195 })
3196
3197 (define_insn "divsi_inv20"
3198 [(set (match_operand:DI 0 "register_operand" "=&r")
3199 (unspec:DI [(match_operand:SI 1 "register_operand" "r")
3200 (match_operand:SI 2 "register_operand" "r")
3201 (match_operand:SI 3 "register_operand" "r")
3202 (match_operand:DI 4 "register_operand" "r")
3203 (match_operand:DI 5 "register_operand" "r")
3204 (match_operand:DI 6 "register_operand" "r")
3205 (match_operand:DI 12 "register_operand" "r")
3206 (match_operand 10 "target_operand" "b")
3207 (match_operand 11 "immediate_operand" "i")]
3208 UNSPEC_DIV_INV20))
3209 (clobber (match_operand:DI 7 "register_operand" "=&r"))
3210 (clobber (match_operand:DI 8 "register_operand" "=&r"))
3211 (clobber (match_operand:SI 9 "register_operand" "=r"))]
3212 "TARGET_SHMEDIA
3213 && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
3214 {
3215 /* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
3216 %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
3217 %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
3218 %10 label (tr), %11 label (imm)
3219
3220 muls.l inv1, norm32, scratch0 // s2.60
3221 muls.l inv1, dividend, result // s32.30
3222 xor i2p27, result_sign, round_scratch
3223 bge/u dividend_nsb, i43, tr.. (label)
3224 shari scratch0, 16, scratch0 // s-16.44
3225 muls.l sratch0_si, inv1, scratch0 // s-16.74
3226 sub result, round_scratch, result
3227 shari dividend, 14, scratch1 // s19.-14
3228 shari scratch0, 30, scratch0 // s-16.44
3229 muls.l scratch0, scratch1, round_scratch // s15.30
3230 label:
3231 sub result, round_scratch, result */
3232
3233 const bool likely = TARGET_DIVIDE_INV20L;
3234 if (likely)
3235 return
3236 "muls.l %2, %3, %0" "\n"
3237 " xor %12, %5, %7" "\n"
3238 " bge/l %4, %6, %10" "\n"
3239 " muls.l %2, %1, %8" "\n"
3240 " shari %8, 16, %8" "\n"
3241 " muls.l %8, %2, %8" "\n"
3242 " shari %3, 14, %9" "\n"
3243 " shari %8, 30, %8" "\n"
3244 " muls.l %8, %9, %8" "\n"
3245 " sub %0, %8, %0" "\n"
3246 "%11: add %0, %7, %0";
3247 else
3248 return
3249 "muls.l %2, %1, %8" "\n"
3250 " muls.l %2, %3, %0" "\n"
3251 " xor %12, %5, %7" "\n"
3252 " bge/u %4, %6, %10" "\n"
3253 " shari %8, 16, %8" "\n"
3254 " muls.l %8, %2, %8" "\n"
3255 " sub %0, %7, %0" "\n"
3256 " shari %3, 14, %9" "\n"
3257 " shari %8, 30, %8" "\n"
3258 " muls.l %8, %9, %7" "\n"
3259 "%11: sub %0, %7, %0";
3260 })
3261
3262 (define_insn_and_split "divsi_inv_fp"
3263 [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
3264 (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
3265 (match_operand:SI 2 "register_operand" "rf")))
3266 (use (match_operand:SI 3 "general_movsrc_operand" "r"))
3267 (clobber (match_operand:SI 4 "register_operand" "=r"))
3268 (clobber (match_operand:SI 5 "register_operand" "=r"))
3269 (clobber (match_operand:DF 6 "register_operand" "=r"))
3270 (clobber (match_operand:DF 7 "register_operand" "=r"))
3271 (clobber (match_operand:DF 8 "register_operand" "=r"))]
3272 "TARGET_SHMEDIA_FPU"
3273 "#"
3274 "&& (reload_in_progress || reload_completed)"
3275 [(set (match_dup 0) (match_dup 3))]
3276 ""
3277 [(set_attr "highpart" "must_split")])
3278
3279 ;; If a matching group of divide-by-inverse instructions is in the same
3280 ;; basic block after gcse & loop optimizations, we want to transform them
3281 ;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
3282 (define_insn_and_split "*divsi_inv_fp_combine"
3283 [(set (match_operand:SI 0 "register_operand" "=f")
3284 (div:SI (match_operand:SI 1 "register_operand" "f")
3285 (match_operand:SI 2 "register_operand" "f")))
3286 (use (unspec:SI [(match_dup 1)
3287 (match_operand:SI 3 "" "")
3288 (unspec:SI [(match_operand:SI 4 "" "")
3289 (match_dup 3)
3290 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
3291 (match_operand:DI 6 "" "")
3292 (const_int 0)
3293 (const_int 0)] UNSPEC_DIV_INV_M3))
3294 (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
3295 (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
3296 (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
3297 (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
3298 (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
3299 "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
3300 "#"
3301 "&& 1"
3302 [(set (match_dup 9) (float:DF (match_dup 1)))
3303 (set (match_dup 10) (float:DF (match_dup 2)))
3304 (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
3305 (set (match_dup 8)
3306 (fix:SI (match_dup 11)))
3307 (set (match_dup 0) (match_dup 8))]
3308 {
3309 if (! fp_arith_reg_operand (operands[1], SImode))
3310 {
3311 emit_move_insn (operands[7], operands[1]);
3312 operands[1] = operands[7];
3313 }
3314 if (! fp_arith_reg_operand (operands[2], SImode))
3315 {
3316 emit_move_insn (operands[8], operands[2]);
3317 operands[2] = operands[8];
3318 }
3319 }
3320 [(set_attr "highpart" "must_split")])
3321 \f
3322 ;; -------------------------------------------------------------------------
3323 ;; Multiplication instructions
3324 ;; -------------------------------------------------------------------------
3325
3326 (define_insn "umulhisi3_i"
3327 [(set (reg:SI MACL_REG)
3328 (mult:SI (zero_extend:SI
3329 (match_operand:HI 0 "arith_reg_operand" "r"))
3330 (zero_extend:SI
3331 (match_operand:HI 1 "arith_reg_operand" "r"))))]
3332 "TARGET_SH1"
3333 "mulu.w %1,%0"
3334 [(set_attr "type" "smpy")])
3335
3336 (define_insn "mulhisi3_i"
3337 [(set (reg:SI MACL_REG)
3338 (mult:SI (sign_extend:SI
3339 (match_operand:HI 0 "arith_reg_operand" "r"))
3340 (sign_extend:SI
3341 (match_operand:HI 1 "arith_reg_operand" "r"))))]
3342 "TARGET_SH1"
3343 "muls.w %1,%0"
3344 [(set_attr "type" "smpy")])
3345
3346 (define_expand "mulhisi3"
3347 [(set (reg:SI MACL_REG)
3348 (mult:SI (sign_extend:SI
3349 (match_operand:HI 1 "arith_reg_operand" ""))
3350 (sign_extend:SI
3351 (match_operand:HI 2 "arith_reg_operand" ""))))
3352 (set (match_operand:SI 0 "arith_reg_operand" "")
3353 (reg:SI MACL_REG))]
3354 "TARGET_SH1"
3355 {
3356 rtx_insn *insn;
3357 rtx macl;
3358
3359 macl = gen_rtx_REG (SImode, MACL_REG);
3360 start_sequence ();
3361 emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
3362 insn = get_insns ();
3363 end_sequence ();
3364 /* expand_binop can't find a suitable code in umul_widen_optab to
3365 make a REG_EQUAL note from, so make one here.
3366 See also smulsi3_highpart.
3367 ??? Alternatively, we could put this at the calling site of expand_binop,
3368 i.e. expand_expr. */
3369 /* Use emit_libcall_block for loop invariant code motion and to make
3370 a REG_EQUAL note. */
3371 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3372
3373 DONE;
3374 })
3375
3376 (define_expand "umulhisi3"
3377 [(set (reg:SI MACL_REG)
3378 (mult:SI (zero_extend:SI
3379 (match_operand:HI 1 "arith_reg_operand" ""))
3380 (zero_extend:SI
3381 (match_operand:HI 2 "arith_reg_operand" ""))))
3382 (set (match_operand:SI 0 "arith_reg_operand" "")
3383 (reg:SI MACL_REG))]
3384 "TARGET_SH1"
3385 {
3386 rtx_insn *insn;
3387 rtx macl;
3388
3389 macl = gen_rtx_REG (SImode, MACL_REG);
3390 start_sequence ();
3391 emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
3392 insn = get_insns ();
3393 end_sequence ();
3394 /* expand_binop can't find a suitable code in umul_widen_optab to
3395 make a REG_EQUAL note from, so make one here.
3396 See also smulsi3_highpart.
3397 ??? Alternatively, we could put this at the calling site of expand_binop,
3398 i.e. expand_expr. */
3399 /* Use emit_libcall_block for loop invariant code motion and to make
3400 a REG_EQUAL note. */
3401 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3402
3403 DONE;
3404 })
3405
3406 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
3407 ;; a call to a routine which clobbers known registers.
3408 (define_insn ""
3409 [(set (match_operand:SI 1 "register_operand" "=z")
3410 (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
3411 (clobber (reg:SI MACL_REG))
3412 (clobber (reg:SI T_REG))
3413 (clobber (reg:SI PR_REG))
3414 (clobber (reg:SI R3_REG))
3415 (clobber (reg:SI R2_REG))
3416 (clobber (reg:SI R1_REG))
3417 (use (match_operand:SI 0 "arith_reg_operand" "r"))]
3418 "TARGET_SH1"
3419 "jsr @%0%#"
3420 [(set_attr "type" "sfunc")
3421 (set_attr "needs_delay_slot" "yes")])
3422
3423 (define_expand "mulsi3_call"
3424 [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
3425 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
3426 (parallel[(set (match_operand:SI 0 "register_operand" "")
3427 (mult:SI (reg:SI R4_REG)
3428 (reg:SI R5_REG)))
3429 (clobber (reg:SI MACL_REG))
3430 (clobber (reg:SI T_REG))
3431 (clobber (reg:SI PR_REG))
3432 (clobber (reg:SI R3_REG))
3433 (clobber (reg:SI R2_REG))
3434 (clobber (reg:SI R1_REG))
3435 (use (match_operand:SI 3 "register_operand" ""))])]
3436 "TARGET_SH1"
3437 "")
3438
3439 (define_insn "mul_r"
3440 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3441 (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
3442 (match_operand:SI 2 "arith_reg_operand" "z")))]
3443 "TARGET_SH2A"
3444 "mulr %2,%0"
3445 [(set_attr "type" "dmpy")])
3446
3447 (define_insn "mul_l"
3448 [(set (reg:SI MACL_REG)
3449 (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
3450 (match_operand:SI 1 "arith_reg_operand" "r")))]
3451 "TARGET_SH2"
3452 "mul.l %1,%0"
3453 [(set_attr "type" "dmpy")])
3454
3455 (define_expand "mulsi3"
3456 [(set (reg:SI MACL_REG)
3457 (mult:SI (match_operand:SI 1 "arith_reg_operand" "")
3458 (match_operand:SI 2 "arith_reg_operand" "")))
3459 (set (match_operand:SI 0 "arith_reg_operand" "")
3460 (reg:SI MACL_REG))]
3461 "TARGET_SH1"
3462 {
3463 if (!TARGET_SH2)
3464 {
3465 /* The address must be set outside the libcall,
3466 since it goes into a pseudo. */
3467 rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC);
3468 rtx addr = force_reg (SImode, sym);
3469 rtx insns = gen_mulsi3_call (operands[0], operands[1],
3470 operands[2], addr);
3471 emit_insn (insns);
3472 }
3473 else
3474 {
3475 rtx macl = gen_rtx_REG (SImode, MACL_REG);
3476
3477 emit_insn (gen_mul_l (operands[1], operands[2]));
3478 /* consec_sets_giv can only recognize the first insn that sets a
3479 giv as the giv insn. So we must tag this also with a REG_EQUAL
3480 note. */
3481 emit_insn (gen_movsi_i ((operands[0]), macl));
3482 }
3483 DONE;
3484 })
3485
3486 (define_insn "mulsidi3_i"
3487 [(set (reg:SI MACH_REG)
3488 (truncate:SI
3489 (lshiftrt:DI
3490 (mult:DI
3491 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3492 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3493 (const_int 32))))
3494 (set (reg:SI MACL_REG)
3495 (mult:SI (match_dup 0)
3496 (match_dup 1)))]
3497 "TARGET_SH2"
3498 "dmuls.l %1,%0"
3499 [(set_attr "type" "dmpy")])
3500
3501 (define_expand "mulsidi3"
3502 [(set (match_operand:DI 0 "arith_reg_dest" "")
3503 (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3504 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3505 "TARGET_SH2 || TARGET_SHMEDIA"
3506 {
3507 if (TARGET_SH2)
3508 {
3509 emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2]));
3510 DONE;
3511 }
3512 })
3513
3514 (define_insn "mulsidi3_media"
3515 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3516 (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3517 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3518 "TARGET_SHMEDIA"
3519 "muls.l %1, %2, %0"
3520 [(set_attr "type" "dmpy_media")
3521 (set_attr "highpart" "ignore")])
3522
3523 (define_insn_and_split "mulsidi3_compact"
3524 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3525 (mult:DI
3526 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3527 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3528 (clobber (reg:SI MACH_REG))
3529 (clobber (reg:SI MACL_REG))]
3530 "TARGET_SH2"
3531 "#"
3532 "&& 1"
3533 [(const_int 0)]
3534 {
3535 rtx low_dst = gen_lowpart (SImode, operands[0]);
3536 rtx high_dst = gen_highpart (SImode, operands[0]);
3537
3538 emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
3539
3540 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3541 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3542 /* We need something to tag the possible REG_EQUAL notes on to. */
3543 emit_move_insn (operands[0], operands[0]);
3544 DONE;
3545 })
3546
3547 (define_insn "umulsidi3_i"
3548 [(set (reg:SI MACH_REG)
3549 (truncate:SI
3550 (lshiftrt:DI
3551 (mult:DI
3552 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3553 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3554 (const_int 32))))
3555 (set (reg:SI MACL_REG)
3556 (mult:SI (match_dup 0)
3557 (match_dup 1)))]
3558 "TARGET_SH2"
3559 "dmulu.l %1,%0"
3560 [(set_attr "type" "dmpy")])
3561
3562 (define_expand "umulsidi3"
3563 [(set (match_operand:DI 0 "arith_reg_dest" "")
3564 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3565 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3566 "TARGET_SH2 || TARGET_SHMEDIA"
3567 {
3568 if (TARGET_SH2)
3569 {
3570 emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2]));
3571 DONE;
3572 }
3573 })
3574
3575 (define_insn "umulsidi3_media"
3576 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3577 (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3578 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3579 "TARGET_SHMEDIA"
3580 "mulu.l %1, %2, %0"
3581 [(set_attr "type" "dmpy_media")
3582 (set_attr "highpart" "ignore")])
3583
3584 (define_insn_and_split "umulsidi3_compact"
3585 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3586 (mult:DI
3587 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3588 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3589 (clobber (reg:SI MACH_REG))
3590 (clobber (reg:SI MACL_REG))]
3591 "TARGET_SH2"
3592 "#"
3593 "&& 1"
3594 [(const_int 0)]
3595 {
3596 rtx low_dst = gen_lowpart (SImode, operands[0]);
3597 rtx high_dst = gen_highpart (SImode, operands[0]);
3598
3599 emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
3600
3601 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3602 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3603 /* We need something to tag the possible REG_EQUAL notes on to. */
3604 emit_move_insn (operands[0], operands[0]);
3605 DONE;
3606 })
3607
3608 (define_insn "smulsi3_highpart_i"
3609 [(set (reg:SI MACH_REG)
3610 (truncate:SI
3611 (lshiftrt:DI
3612 (mult:DI
3613 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3614 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3615 (const_int 32))))
3616 (clobber (reg:SI MACL_REG))]
3617 "TARGET_SH2"
3618 "dmuls.l %1,%0"
3619 [(set_attr "type" "dmpy")])
3620
3621 (define_expand "smulsi3_highpart"
3622 [(parallel
3623 [(set (reg:SI MACH_REG)
3624 (truncate:SI
3625 (lshiftrt:DI
3626 (mult:DI
3627 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3628 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3629 (const_int 32))))
3630 (clobber (reg:SI MACL_REG))])
3631 (set (match_operand:SI 0 "arith_reg_operand" "")
3632 (reg:SI MACH_REG))]
3633 "TARGET_SH2"
3634 {
3635 rtx_insn *insn;
3636 rtx mach;
3637
3638 mach = gen_rtx_REG (SImode, MACH_REG);
3639 start_sequence ();
3640 emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3641 insn = get_insns ();
3642 end_sequence ();
3643 /* expand_binop can't find a suitable code in mul_highpart_optab to
3644 make a REG_EQUAL note from, so make one here.
3645 See also {,u}mulhisi.
3646 ??? Alternatively, we could put this at the calling site of expand_binop,
3647 i.e. expand_mult_highpart. */
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], mach, SET_SRC (single_set (insn)));
3651
3652 DONE;
3653 })
3654
3655 (define_insn "umulsi3_highpart_i"
3656 [(set (reg:SI MACH_REG)
3657 (truncate:SI
3658 (lshiftrt:DI
3659 (mult:DI
3660 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3661 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3662 (const_int 32))))
3663 (clobber (reg:SI MACL_REG))]
3664 "TARGET_SH2"
3665 "dmulu.l %1,%0"
3666 [(set_attr "type" "dmpy")])
3667
3668 (define_expand "umulsi3_highpart"
3669 [(parallel
3670 [(set (reg:SI MACH_REG)
3671 (truncate:SI
3672 (lshiftrt:DI
3673 (mult:DI
3674 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3675 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3676 (const_int 32))))
3677 (clobber (reg:SI MACL_REG))])
3678 (set (match_operand:SI 0 "arith_reg_operand" "")
3679 (reg:SI MACH_REG))]
3680 "TARGET_SH2"
3681 {
3682 rtx_insn *insn;
3683 rtx mach;
3684
3685 mach = gen_rtx_REG (SImode, MACH_REG);
3686 start_sequence ();
3687 emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3688 insn = get_insns ();
3689 end_sequence ();
3690 /* Use emit_libcall_block for loop invariant code motion and to make
3691 a REG_EQUAL note. */
3692 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3693
3694 DONE;
3695 })
3696
3697 (define_insn_and_split "muldi3"
3698 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3699 (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3700 (match_operand:DI 2 "arith_reg_operand" "r")))
3701 (clobber (match_scratch:DI 3 "=&r"))
3702 (clobber (match_scratch:DI 4 "=r"))]
3703 "TARGET_SHMEDIA"
3704 "#"
3705 "reload_completed"
3706 [(const_int 0)]
3707 {
3708 rtx op3_v2si, op2_v2si;
3709
3710 op3_v2si = operands[3];
3711 if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3712 {
3713 op3_v2si = XEXP (op3_v2si, 0);
3714 op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3715 }
3716 op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3717 op2_v2si = operands[2];
3718 if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3719 {
3720 op2_v2si = XEXP (op2_v2si, 0);
3721 op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3722 }
3723 op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3724 emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3725 emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3726 emit_insn (gen_umulsidi3_media (operands[4],
3727 sh_gen_truncate (SImode, operands[1], 0),
3728 sh_gen_truncate (SImode, operands[2], 0)));
3729 emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3730 emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3731 emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3732 emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3733 DONE;
3734 })
3735 \f
3736 ;; -------------------------------------------------------------------------
3737 ;; Logical operations
3738 ;; -------------------------------------------------------------------------
3739
3740 (define_expand "andsi3"
3741 [(set (match_operand:SI 0 "arith_reg_operand" "")
3742 (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3743 (match_operand:SI 2 "logical_and_operand" "")))]
3744 ""
3745 {
3746 /* If it is possible to turn the and insn into a zero extension
3747 already, redundant zero extensions will be folded, which results
3748 in better code.
3749 Ideally the splitter of *andsi_compact would be enough, if redundant
3750 zero extensions were detected after the combine pass, which does not
3751 happen at the moment. */
3752 if (TARGET_SH1)
3753 {
3754 if (satisfies_constraint_Jmb (operands[2]))
3755 {
3756 emit_insn (gen_zero_extendqisi2 (operands[0],
3757 gen_lowpart (QImode, operands[1])));
3758 DONE;
3759 }
3760 else if (satisfies_constraint_Jmw (operands[2]))
3761 {
3762 emit_insn (gen_zero_extendhisi2 (operands[0],
3763 gen_lowpart (HImode, operands[1])));
3764 DONE;
3765 }
3766 }
3767 })
3768
3769 (define_insn_and_split "*andsi_compact"
3770 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r")
3771 (and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0")
3772 (match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))]
3773 "TARGET_SH1"
3774 "@
3775 extu.b %1,%0
3776 extu.w %1,%0
3777 and %2,%0
3778 and %2,%0"
3779 "&& 1"
3780 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
3781 {
3782 if (satisfies_constraint_Jmb (operands[2]))
3783 operands[1] = gen_lowpart (QImode, operands[1]);
3784 else if (satisfies_constraint_Jmw (operands[2]))
3785 operands[1] = gen_lowpart (HImode, operands[1]);
3786 else
3787 FAIL;
3788 }
3789 [(set_attr "type" "arith")])
3790
3791 (define_insn "*andsi3_media"
3792 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3793 (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3794 (match_operand:SI 2 "logical_operand" "r,I10")))]
3795 "TARGET_SHMEDIA"
3796 "@
3797 and %1, %2, %0
3798 andi %1, %2, %0"
3799 [(set_attr "type" "arith_media")])
3800
3801 (define_insn "*andsi3_bclr"
3802 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3803 (and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3804 (match_operand:SI 2 "const_int_operand" "Psz")))]
3805 "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
3806 "bclr %W2,%0"
3807 [(set_attr "type" "arith")])
3808
3809 (define_insn_and_split "anddi3"
3810 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3811 (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3812 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
3813 "TARGET_SHMEDIA"
3814 "@
3815 and %1, %2, %0
3816 andi %1, %2, %0
3817 #"
3818 "reload_completed
3819 && ! logical_operand (operands[2], DImode)"
3820 [(const_int 0)]
3821 {
3822 if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3823 emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3824 else
3825 emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3826 DONE;
3827 }
3828 [(set_attr "type" "arith_media")])
3829
3830 (define_insn "andcsi3"
3831 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3832 (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3833 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3834 "TARGET_SHMEDIA"
3835 "andc %1,%2,%0"
3836 [(set_attr "type" "arith_media")])
3837
3838 (define_insn "andcdi3"
3839 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3840 (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3841 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3842 "TARGET_SHMEDIA"
3843 "andc %1,%2,%0"
3844 [(set_attr "type" "arith_media")])
3845
3846 (define_expand "iorsi3"
3847 [(set (match_operand:SI 0 "arith_reg_operand" "")
3848 (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3849 (match_operand:SI 2 "logical_operand" "")))]
3850 ""
3851 "")
3852
3853 (define_insn "*iorsi3_compact"
3854 [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3855 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3856 (match_operand:SI 2 "logical_operand" "r,K08")))]
3857 "TARGET_SH1
3858 && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
3859 "or %2,%0"
3860 [(set_attr "type" "arith")])
3861
3862 (define_insn "*iorsi3_media"
3863 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3864 (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3865 (match_operand:SI 2 "logical_operand" "r,I10")))]
3866 "TARGET_SHMEDIA"
3867 "@
3868 or %1, %2, %0
3869 ori %1, %2, %0"
3870 [(set_attr "type" "arith_media")])
3871
3872 (define_insn "*iorsi3_bset"
3873 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3874 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3875 (match_operand:SI 2 "const_int_operand" "Pso")))]
3876 "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
3877 "bset %V2,%0"
3878 [(set_attr "type" "arith")])
3879
3880 (define_insn "iordi3"
3881 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3882 (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3883 (match_operand:DI 2 "logical_operand" "r,I10")))]
3884 "TARGET_SHMEDIA"
3885 "@
3886 or %1, %2, %0
3887 ori %1, %2, %0"
3888 [(set_attr "type" "arith_media")])
3889
3890 (define_insn_and_split "*logical_sidi3"
3891 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3892 (sign_extend:DI (match_operator:SI 3 "logical_operator"
3893 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3894 (match_operand:SI 2 "logical_operand" "r,I10")])))]
3895 "TARGET_SHMEDIA"
3896 "#"
3897 "&& reload_completed"
3898 [(set (match_dup 0) (match_dup 3))]
3899 {
3900 operands[3]
3901 = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3902 simplify_gen_subreg (DImode, operands[1], SImode, 0),
3903 simplify_gen_subreg (DImode, operands[2], SImode, 0));
3904 })
3905
3906 (define_insn_and_split "*logical_sidisi3"
3907 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3908 (truncate:SI (sign_extend:DI
3909 (match_operator:SI 3 "logical_operator"
3910 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3911 (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3912 "TARGET_SHMEDIA"
3913 "#"
3914 "&& 1"
3915 [(set (match_dup 0) (match_dup 3))])
3916
3917 (define_insn_and_split "*logical_sidi3_2"
3918 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3919 (sign_extend:DI (truncate:SI (sign_extend:DI
3920 (match_operator:SI 3 "logical_operator"
3921 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3922 (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3923 "TARGET_SHMEDIA"
3924 "#"
3925 "&& 1"
3926 [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3927
3928 (define_expand "xorsi3"
3929 [(set (match_operand:SI 0 "arith_reg_operand" "")
3930 (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3931 (match_operand:SI 2 "xor_operand" "")))]
3932 ""
3933 "")
3934
3935 (define_insn "*xorsi3_compact"
3936 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3937 (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3938 (match_operand:SI 2 "logical_operand" "K08,r")))]
3939 "TARGET_SH1"
3940 "xor %2,%0"
3941 [(set_attr "type" "arith")])
3942
3943 ;; The *logical_op_t pattern helps combine eliminating sign/zero extensions
3944 ;; of results where one of the inputs is a T bit store. Notice that this
3945 ;; pattern must not match during reload. If reload picks this pattern it
3946 ;; will be impossible to split it afterwards.
3947 (define_insn_and_split "*logical_op_t"
3948 [(set (match_operand:SI 0 "arith_reg_dest")
3949 (match_operator:SI 3 "logical_operator"
3950 [(match_operand:SI 1 "arith_reg_operand")
3951 (match_operand:SI 2 "t_reg_operand")]))]
3952 "TARGET_SH1 && can_create_pseudo_p ()"
3953 "#"
3954 "&& 1"
3955 [(set (match_dup 4) (reg:SI T_REG))
3956 (set (match_dup 0) (match_dup 3))]
3957 {
3958 operands[4] = gen_reg_rtx (SImode);
3959 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
3960 operands[1], operands[4]);
3961 })
3962
3963 (define_insn "*xorsi3_media"
3964 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3965 (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3966 (match_operand:SI 2 "xor_operand" "r,I06")))]
3967 "TARGET_SHMEDIA"
3968 "@
3969 xor %1, %2, %0
3970 xori %1, %2, %0"
3971 [(set_attr "type" "arith_media")])
3972
3973 (define_insn "xordi3"
3974 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3975 (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3976 (match_operand:DI 2 "xor_operand" "r,I06")))]
3977 "TARGET_SHMEDIA"
3978 "@
3979 xor %1, %2, %0
3980 xori %1, %2, %0"
3981 [(set_attr "type" "arith_media")])
3982
3983 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3984 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
3985 (define_split
3986 [(set (match_operand:DI 0 "arith_reg_dest" "")
3987 (sign_extend:DI (match_operator 4 "binary_logical_operator"
3988 [(match_operand 1 "any_register_operand" "")
3989 (match_operand 2 "any_register_operand" "")])))]
3990 "TARGET_SHMEDIA"
3991 [(set (match_dup 5) (match_dup 4))
3992 (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3993 {
3994 enum machine_mode inmode = GET_MODE (operands[1]);
3995 int offset = 0;
3996
3997 if (GET_CODE (operands[0]) == SUBREG)
3998 {
3999 offset = SUBREG_BYTE (operands[0]);
4000 operands[0] = SUBREG_REG (operands[0]);
4001 }
4002 gcc_assert (REG_P (operands[0]));
4003 if (TARGET_BIG_ENDIAN)
4004 offset += 8 - GET_MODE_SIZE (inmode);
4005 operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
4006 })
4007 \f
4008 ;; -------------------------------------------------------------------------
4009 ;; Shifts and rotates
4010 ;; -------------------------------------------------------------------------
4011
4012 (define_expand "rotldi3"
4013 [(set (match_operand:DI 0 "arith_reg_dest" "")
4014 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "")
4015 (match_operand:HI 2 "mextr_bit_offset" "")))]
4016 "TARGET_SHMEDIA"
4017 {
4018 if (! mextr_bit_offset (operands[2], HImode))
4019 FAIL;
4020 })
4021
4022 (define_insn "rotldi3_mextr"
4023 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4024 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
4025 (match_operand:HI 2 "mextr_bit_offset" "i")))]
4026 "TARGET_SHMEDIA"
4027 {
4028 static char templ[16];
4029 sprintf (templ, "mextr%d %%1,%%1,%%0",
4030 8 - (int) (INTVAL (operands[2]) >> 3));
4031 return templ;
4032 }
4033 [(set_attr "type" "arith_media")])
4034
4035 (define_expand "rotrdi3"
4036 [(set (match_operand:DI 0 "arith_reg_dest" "")
4037 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "")
4038 (match_operand:HI 2 "mextr_bit_offset" "")))]
4039 "TARGET_SHMEDIA"
4040 {
4041 if (! mextr_bit_offset (operands[2], HImode))
4042 FAIL;
4043 })
4044
4045 (define_insn "rotrdi3_mextr"
4046 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4047 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
4048 (match_operand:HI 2 "mextr_bit_offset" "i")))]
4049 "TARGET_SHMEDIA"
4050 {
4051 static char templ[16];
4052 sprintf (templ, "mextr%d %%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3);
4053 return templ;
4054 }
4055 [(set_attr "type" "arith_media")])
4056
4057 (define_split
4058 [(set (match_operand:DI 0 "arith_reg_dest" "")
4059 (ior:DI (zero_extend:DI (mem:QI (match_operand 1
4060 "ua_address_operand" "")))
4061 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
4062 (const_int 8))))
4063 (clobber (match_operand:DI 3 "register_operand" ""))]
4064 "TARGET_SHMEDIA"
4065 [(match_dup 4) (match_dup 5)]
4066 {
4067 operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
4068 (operands[3], operands[1]));
4069 operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
4070 GEN_INT (56), GEN_INT (8));
4071 })
4072
4073 (define_expand "rotrsi3"
4074 [(set (match_operand:SI 0 "arith_reg_dest")
4075 (rotatert:SI (match_operand:SI 1 "arith_reg_operand")
4076 (match_operand:SI 2 "const_int_operand")))]
4077 "TARGET_SH1"
4078 {
4079 HOST_WIDE_INT ival = INTVAL (operands[2]);
4080 if (ival == 1)
4081 {
4082 emit_insn (gen_rotrsi3_1 (operands[0], operands[1]));
4083 DONE;
4084 }
4085
4086 FAIL;
4087 })
4088
4089 (define_insn "rotrsi3_1"
4090 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4091 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
4092 (const_int 1)))
4093 (set (reg:SI T_REG)
4094 (and:SI (match_dup 1) (const_int 1)))]
4095 "TARGET_SH1"
4096 "rotr %0"
4097 [(set_attr "type" "arith")])
4098
4099 ;; A slimplified version of rotr for combine.
4100 (define_insn "*rotrsi3_1"
4101 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4102 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
4103 (const_int 1)))
4104 (clobber (reg:SI T_REG))]
4105 "TARGET_SH1"
4106 "rotr %0"
4107 [(set_attr "type" "arith")])
4108
4109 (define_insn "rotlsi3_1"
4110 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4111 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4112 (const_int 1)))
4113 (set (reg:SI T_REG)
4114 (lshiftrt:SI (match_dup 1) (const_int 31)))]
4115 "TARGET_SH1"
4116 "rotl %0"
4117 [(set_attr "type" "arith")])
4118
4119 ;; A simplified version of rotl for combine.
4120 (define_insn "*rotlsi3_1"
4121 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4122 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4123 (const_int 1)))
4124 (clobber (reg:SI T_REG))]
4125 "TARGET_SH1"
4126 "rotl %0"
4127 [(set_attr "type" "arith")])
4128
4129 (define_insn "rotlsi3_31"
4130 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4131 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4132 (const_int 31)))
4133 (clobber (reg:SI T_REG))]
4134 "TARGET_SH1"
4135 "rotr %0"
4136 [(set_attr "type" "arith")])
4137
4138 (define_insn "rotlsi3_16"
4139 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4140 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
4141 (const_int 16)))]
4142 "TARGET_SH1"
4143 "swap.w %1,%0"
4144 [(set_attr "type" "arith")])
4145
4146 (define_expand "rotlsi3"
4147 [(set (match_operand:SI 0 "arith_reg_dest")
4148 (rotate:SI (match_operand:SI 1 "arith_reg_operand")
4149 (match_operand:SI 2 "const_int_operand")))]
4150 "TARGET_SH1"
4151 {
4152 static const char rot_tab[] = {
4153 000, 000, 000, 000, 000, 000, 010, 001,
4154 001, 001, 011, 013, 003, 003, 003, 003,
4155 003, 003, 003, 003, 003, 013, 012, 002,
4156 002, 002, 010, 000, 000, 000, 000, 000,
4157 };
4158
4159 int count = INTVAL (operands[2]);
4160 int choice = rot_tab[count];
4161 if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
4162 FAIL;
4163 choice &= 7;
4164 switch (choice)
4165 {
4166 case 0:
4167 emit_move_insn (operands[0], operands[1]);
4168 count -= (count & 16) * 2;
4169 break;
4170 case 3:
4171 emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
4172 count -= 16;
4173 break;
4174 case 1:
4175 case 2:
4176 {
4177 rtx parts[2];
4178 parts[0] = gen_reg_rtx (SImode);
4179 parts[1] = gen_reg_rtx (SImode);
4180 emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
4181 emit_move_insn (parts[choice-1], operands[1]);
4182 emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
4183 emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
4184 emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
4185 count = (count & ~16) - 8;
4186 }
4187 }
4188
4189 for (; count > 0; count--)
4190 emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
4191 for (; count < 0; count++)
4192 emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4193
4194 DONE;
4195 })
4196
4197 (define_insn "rotlhi3_8"
4198 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4199 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
4200 (const_int 8)))]
4201 "TARGET_SH1"
4202 "swap.b %1,%0"
4203 [(set_attr "type" "arith")])
4204
4205 (define_expand "rotlhi3"
4206 [(set (match_operand:HI 0 "arith_reg_operand")
4207 (rotate:HI (match_operand:HI 1 "arith_reg_operand")
4208 (match_operand:HI 2 "const_int_operand")))]
4209 "TARGET_SH1"
4210 {
4211 if (INTVAL (operands[2]) != 8)
4212 FAIL;
4213 })
4214
4215 ;; The rotcr and rotcl insns are used primarily in DImode shifts by one.
4216 ;; They can also be used to implement things like
4217 ;; bool t = a == b;
4218 ;; int x0 = (y >> 1) | (t << 31); // rotcr
4219 ;; int x1 = (y << 1) | t; // rotcl
4220 (define_insn "rotcr"
4221 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4222 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4223 (const_int 1))
4224 (ashift:SI (match_operand:SI 2 "t_reg_operand")
4225 (const_int 31))))
4226 (set (reg:SI T_REG)
4227 (and:SI (match_dup 1) (const_int 1)))]
4228 "TARGET_SH1"
4229 "rotcr %0"
4230 [(set_attr "type" "arith")])
4231
4232 (define_insn "rotcl"
4233 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4234 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4235 (const_int 1))
4236 (match_operand:SI 2 "t_reg_operand")))
4237 (set (reg:SI T_REG)
4238 (lshiftrt:SI (match_dup 1) (const_int 31)))]
4239 "TARGET_SH1"
4240 "rotcl %0"
4241 [(set_attr "type" "arith")])
4242
4243 ;; Simplified rotcr version for combine, which allows arbitrary shift
4244 ;; amounts for the reg. If the shift amount is '1' rotcr can be used
4245 ;; directly. Otherwise we have to insert a shift in between.
4246 (define_insn_and_split "*rotcr"
4247 [(set (match_operand:SI 0 "arith_reg_dest")
4248 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4249 (match_operand:SI 2 "const_int_operand"))
4250 (ashift:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4251 (const_int 31))))
4252 (clobber (reg:SI T_REG))]
4253 "TARGET_SH1"
4254 "#"
4255 "&& can_create_pseudo_p ()"
4256 [(const_int 0)]
4257 {
4258 if (INTVAL (operands[2]) > 1)
4259 {
4260 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4261 rtx prev_set_t_insn = NULL_RTX;
4262 rtx tmp_t_reg = NULL_RTX;
4263
4264 /* If we're going to emit a shift sequence that clobbers the T_REG,
4265 try to find the previous insn that sets the T_REG and emit the
4266 shift insn before that insn, to remove the T_REG dependency.
4267 If the insn that sets the T_REG cannot be found, store the T_REG
4268 in a temporary reg and restore it after the shift. */
4269 if (sh_lshrsi_clobbers_t_reg_p (shift_count)
4270 && ! sh_dynamicalize_shift_p (shift_count))
4271 {
4272 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4273
4274 /* Skip the nott insn, which was probably inserted by the splitter
4275 of *rotcr_neg_t. Don't use one of the recog functions
4276 here during insn splitting, since that causes problems in later
4277 passes. */
4278 if (prev_set_t_insn != NULL_RTX)
4279 {
4280 rtx pat = PATTERN (prev_set_t_insn);
4281 if (GET_CODE (pat) == SET
4282 && t_reg_operand (XEXP (pat, 0), SImode)
4283 && negt_reg_operand (XEXP (pat, 1), SImode))
4284 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4285 }
4286
4287 if (! (prev_set_t_insn != NULL_RTX
4288 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4289 && ! reg_referenced_p (get_t_reg_rtx (),
4290 PATTERN (prev_set_t_insn))))
4291 {
4292 prev_set_t_insn = NULL_RTX;
4293 tmp_t_reg = gen_reg_rtx (SImode);
4294 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4295 }
4296 }
4297
4298 rtx shift_result = gen_reg_rtx (SImode);
4299 rtx shift_insn = gen_lshrsi3 (shift_result, operands[1], shift_count);
4300 operands[1] = shift_result;
4301
4302 /* Emit the shift insn before the insn that sets T_REG, if possible. */
4303 if (prev_set_t_insn != NULL_RTX)
4304 emit_insn_before (shift_insn, prev_set_t_insn);
4305 else
4306 emit_insn (shift_insn);
4307
4308 /* Restore T_REG if it has been saved before. */
4309 if (tmp_t_reg != NULL_RTX)
4310 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4311 }
4312
4313 /* For the rotcr insn to work, operands[3] must be in T_REG.
4314 If it is not we can get it there by shifting it right one bit.
4315 In this case T_REG is not an input for this insn, thus we don't have to
4316 pay attention as of where to insert the shlr insn. */
4317 if (! t_reg_operand (operands[3], SImode))
4318 {
4319 /* We don't care about the shifted result here, only the T_REG. */
4320 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4321 operands[3] = get_t_reg_rtx ();
4322 }
4323
4324 emit_insn (gen_rotcr (operands[0], operands[1], operands[3]));
4325 DONE;
4326 })
4327
4328 ;; If combine tries the same as above but with swapped operands, split
4329 ;; it so that it will try the pattern above.
4330 (define_split
4331 [(set (match_operand:SI 0 "arith_reg_dest")
4332 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4333 (const_int 31))
4334 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4335 (match_operand:SI 3 "const_int_operand"))))]
4336 "TARGET_SH1 && can_create_pseudo_p ()"
4337 [(parallel [(set (match_dup 0)
4338 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4339 (ashift:SI (match_dup 1) (const_int 31))))
4340 (clobber (reg:SI T_REG))])])
4341
4342 ;; Basically the same as the rotcr pattern above, but for rotcl.
4343 ;; FIXME: Fold copy pasted split code for rotcr and rotcl.
4344 (define_insn_and_split "*rotcl"
4345 [(set (match_operand:SI 0 "arith_reg_dest")
4346 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4347 (match_operand:SI 2 "const_int_operand"))
4348 (and:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4349 (const_int 1))))
4350 (clobber (reg:SI T_REG))]
4351 "TARGET_SH1"
4352 "#"
4353 "&& can_create_pseudo_p ()"
4354 [(const_int 0)]
4355 {
4356 gcc_assert (INTVAL (operands[2]) > 0);
4357
4358 if (INTVAL (operands[2]) > 1)
4359 {
4360 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4361 rtx prev_set_t_insn = NULL_RTX;
4362 rtx tmp_t_reg = NULL_RTX;
4363
4364 /* If we're going to emit a shift sequence that clobbers the T_REG,
4365 try to find the previous insn that sets the T_REG and emit the
4366 shift insn before that insn, to remove the T_REG dependency.
4367 If the insn that sets the T_REG cannot be found, store the T_REG
4368 in a temporary reg and restore it after the shift. */
4369 if (sh_ashlsi_clobbers_t_reg_p (shift_count)
4370 && ! sh_dynamicalize_shift_p (shift_count))
4371 {
4372 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4373
4374 /* Skip the nott insn, which was probably inserted by the splitter
4375 of *rotcl_neg_t. Don't use one of the recog functions
4376 here during insn splitting, since that causes problems in later
4377 passes. */
4378 if (prev_set_t_insn != NULL_RTX)
4379 {
4380 rtx pat = PATTERN (prev_set_t_insn);
4381 if (GET_CODE (pat) == SET
4382 && t_reg_operand (XEXP (pat, 0), SImode)
4383 && negt_reg_operand (XEXP (pat, 1), SImode))
4384 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4385 }
4386
4387 if (! (prev_set_t_insn != NULL_RTX
4388 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4389 && ! reg_referenced_p (get_t_reg_rtx (),
4390 PATTERN (prev_set_t_insn))))
4391 {
4392 prev_set_t_insn = NULL_RTX;
4393 tmp_t_reg = gen_reg_rtx (SImode);
4394 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4395 }
4396 }
4397
4398 rtx shift_result = gen_reg_rtx (SImode);
4399 rtx shift_insn = gen_ashlsi3 (shift_result, operands[1], shift_count);
4400 operands[1] = shift_result;
4401
4402 /* Emit the shift insn before the insn that sets T_REG, if possible. */
4403 if (prev_set_t_insn != NULL_RTX)
4404 emit_insn_before (shift_insn, prev_set_t_insn);
4405 else
4406 emit_insn (shift_insn);
4407
4408 /* Restore T_REG if it has been saved before. */
4409 if (tmp_t_reg != NULL_RTX)
4410 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4411 }
4412
4413 /* For the rotcl insn to work, operands[3] must be in T_REG.
4414 If it is not we can get it there by shifting it right one bit.
4415 In this case T_REG is not an input for this insn, thus we don't have to
4416 pay attention as of where to insert the shlr insn. */
4417 if (! t_reg_operand (operands[3], SImode))
4418 {
4419 /* We don't care about the shifted result here, only the T_REG. */
4420 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4421 operands[3] = get_t_reg_rtx ();
4422 }
4423
4424 emit_insn (gen_rotcl (operands[0], operands[1], operands[3]));
4425 DONE;
4426 })
4427
4428 ;; rotcl combine pattern variations
4429 (define_insn_and_split "*rotcl"
4430 [(set (match_operand:SI 0 "arith_reg_dest")
4431 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4432 (match_operand:SI 2 "const_int_operand"))
4433 (match_operand:SI 3 "t_reg_operand")))
4434 (clobber (reg:SI T_REG))]
4435 "TARGET_SH1"
4436 "#"
4437 "&& can_create_pseudo_p ()"
4438 [(parallel [(set (match_dup 0)
4439 (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4440 (and:SI (match_dup 3) (const_int 1))))
4441 (clobber (reg:SI T_REG))])])
4442
4443 (define_insn_and_split "*rotcl"
4444 [(set (match_operand:SI 0 "arith_reg_dest")
4445 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4446 (const_int 1))
4447 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4448 (match_operand:SI 3 "const_int_operand"))))
4449 (clobber (reg:SI T_REG))]
4450 "TARGET_SH1"
4451 "#"
4452 "&& can_create_pseudo_p ()"
4453 [(parallel [(set (match_dup 0)
4454 (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4455 (and:SI (match_dup 1) (const_int 1))))
4456 (clobber (reg:SI T_REG))])])
4457
4458 (define_insn_and_split "*rotcl"
4459 [(set (match_operand:SI 0 "arith_reg_dest")
4460 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4461 (match_operand:SI 2 "const_int_operand"))
4462 (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4463 (const_int 31))))
4464 (clobber (reg:SI T_REG))]
4465 "TARGET_SH1"
4466 "#"
4467 "&& can_create_pseudo_p ()"
4468 [(parallel [(set (match_dup 0)
4469 (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4470 (and:SI (reg:SI T_REG) (const_int 1))))
4471 (clobber (reg:SI T_REG))])]
4472 {
4473 /* We don't care about the result of the left shift, only the T_REG. */
4474 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4475 })
4476
4477 (define_insn_and_split "*rotcl"
4478 [(set (match_operand:SI 0 "arith_reg_dest")
4479 (ior:SI (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4480 (const_int 31))
4481 (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4482 (match_operand:SI 2 "const_int_operand"))))
4483 (clobber (reg:SI T_REG))]
4484 "TARGET_SH1"
4485 "#"
4486 "&& can_create_pseudo_p ()"
4487 [(parallel [(set (match_dup 0)
4488 (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4489 (and:SI (reg:SI T_REG) (const_int 1))))
4490 (clobber (reg:SI T_REG))])]
4491 {
4492 /* We don't care about the result of the left shift, only the T_REG. */
4493 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4494 })
4495
4496 ;; rotcr combine bridge pattern which will make combine try out more
4497 ;; complex patterns.
4498 (define_insn_and_split "*rotcr"
4499 [(set (match_operand:SI 0 "arith_reg_dest")
4500 (ashift:SI (match_operand:SI 1 "t_reg_operand") (const_int 31)))]
4501 "TARGET_SH1"
4502 "#"
4503 "&& 1"
4504 [(set (match_dup 0) (match_dup 1))
4505 (parallel [(set (match_dup 0)
4506 (ior:SI (lshiftrt:SI (match_dup 0) (const_int 1))
4507 (ashift:SI (match_dup 1) (const_int 31))))
4508 (set (reg:SI T_REG)
4509 (and:SI (match_dup 0) (const_int 1)))])])
4510
4511 (define_insn_and_split "*rotcr"
4512 [(set (match_operand:SI 0 "arith_reg_dest")
4513 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
4514 (const_int -2147483648)) ;; 0xffffffff80000000
4515 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4516 (const_int 1))))
4517 (clobber (reg:SI T_REG))]
4518 "TARGET_SH1"
4519 "#"
4520 "&& can_create_pseudo_p ()"
4521 [(const_int 0)]
4522 {
4523 rtx tmp = gen_reg_rtx (SImode);
4524 emit_insn (gen_shll (tmp, operands[1]));
4525 emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ()));
4526 DONE;
4527 })
4528
4529 ;; rotcr combine patterns for rotating in the negated T_REG value.
4530 (define_insn_and_split "*rotcr_neg_t"
4531 [(set (match_operand:SI 0 "arith_reg_dest")
4532 (ior:SI (match_operand:SI 1 "negt_reg_shl31_operand")
4533 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4534 (match_operand:SI 3 "const_int_operand"))))
4535 (clobber (reg:SI T_REG))]
4536 "TARGET_SH1"
4537 "#"
4538 "&& can_create_pseudo_p ()"
4539 [(parallel [(set (match_dup 0)
4540 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4541 (ashift:SI (reg:SI T_REG) (const_int 31))))
4542 (clobber (reg:SI T_REG))])]
4543 {
4544 emit_insn (gen_nott (get_t_reg_rtx ()));
4545 })
4546
4547 (define_insn_and_split "*rotcr_neg_t"
4548 [(set (match_operand:SI 0 "arith_reg_dest")
4549 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4550 (match_operand:SI 2 "const_int_operand"))
4551 (match_operand:SI 3 "negt_reg_shl31_operand")))
4552 (clobber (reg:SI T_REG))]
4553 "TARGET_SH1"
4554 "#"
4555 "&& can_create_pseudo_p ()"
4556 [(parallel [(set (match_dup 0)
4557 (ior:SI (lshiftrt:SI (match_dup 1) (match_dup 2))
4558 (ashift:SI (reg:SI T_REG) (const_int 31))))
4559 (clobber (reg:SI T_REG))])]
4560 {
4561 emit_insn (gen_nott (get_t_reg_rtx ()));
4562 })
4563
4564 ;; rotcl combine patterns for rotating in the negated T_REG value.
4565 ;; For some strange reason these have to be specified as splits which combine
4566 ;; will pick up. If they are specified as insn_and_split like the
4567 ;; *rotcr_neg_t patterns above, combine would recognize them successfully
4568 ;; but not emit them on non-SH2A targets.
4569 (define_split
4570 [(set (match_operand:SI 0 "arith_reg_dest")
4571 (ior:SI (match_operand:SI 1 "negt_reg_operand")
4572 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4573 (match_operand:SI 3 "const_int_operand"))))]
4574 "TARGET_SH1"
4575 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4576 (parallel [(set (match_dup 0)
4577 (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4578 (and:SI (reg:SI T_REG) (const_int 1))))
4579 (clobber (reg:SI T_REG))])])
4580
4581 (define_split
4582 [(set (match_operand:SI 0 "arith_reg_dest")
4583 (ior:SI (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4584 (match_operand:SI 3 "const_int_operand"))
4585 (match_operand:SI 1 "negt_reg_operand")))]
4586 "TARGET_SH1"
4587 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4588 (parallel [(set (match_dup 0)
4589 (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4590 (and:SI (reg:SI T_REG) (const_int 1))))
4591 (clobber (reg:SI T_REG))])])
4592
4593 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4594 ;; SImode shift left
4595
4596 (define_expand "ashlsi3"
4597 [(set (match_operand:SI 0 "arith_reg_operand" "")
4598 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
4599 (match_operand:SI 2 "shift_count_operand" "")))]
4600 ""
4601 {
4602 if (TARGET_SHMEDIA)
4603 {
4604 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
4605 {
4606 operands[2] = GEN_INT (-INTVAL (operands[2]));
4607 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
4608 DONE;
4609 }
4610 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
4611 DONE;
4612 }
4613 if (TARGET_DYNSHIFT
4614 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
4615 operands[2] = force_reg (SImode, operands[2]);
4616
4617 /* If the ashlsi3_* insn is going to clobber the T_REG it must be
4618 expanded here. */
4619 if (CONST_INT_P (operands[2])
4620 && sh_ashlsi_clobbers_t_reg_p (operands[2])
4621 && ! sh_dynamicalize_shift_p (operands[2]))
4622 {
4623 emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1],
4624 operands[2]));
4625 DONE;
4626 }
4627
4628 /* Expand a library call for the dynamic shift. */
4629 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
4630 {
4631 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
4632 rtx funcaddr = gen_reg_rtx (Pmode);
4633 function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC);
4634 emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr));
4635
4636 DONE;
4637 }
4638 })
4639
4640 (define_insn "ashlsi3_k"
4641 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4642 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
4643 (match_operand:SI 2 "p27_shift_count_operand" "M,P27")))]
4644 "TARGET_SH1"
4645 "@
4646 add %0,%0
4647 shll%O2 %0"
4648 [(set_attr "type" "arith")])
4649
4650 (define_insn_and_split "ashlsi3_d"
4651 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4652 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4653 (match_operand:SI 2 "shift_count_operand" "r")))]
4654 "TARGET_DYNSHIFT"
4655 "shld %2,%0"
4656 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
4657 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4658 [(const_int 0)]
4659 {
4660 if (satisfies_constraint_P27 (operands[2]))
4661 {
4662 emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2]));
4663 DONE;
4664 }
4665 else if (! satisfies_constraint_P27 (operands[2]))
4666 {
4667 /* This must happen before reload, otherwise the constant will be moved
4668 into a register due to the "r" constraint, after which this split
4669 cannot be done anymore.
4670 Unfortunately the move insn will not always be eliminated.
4671 Also, here we must not create a shift sequence that clobbers the
4672 T_REG. */
4673 emit_move_insn (operands[0], operands[1]);
4674 gen_shifty_op (ASHIFT, operands);
4675 DONE;
4676 }
4677
4678 FAIL;
4679 }
4680 [(set_attr "type" "dyn_shift")])
4681
4682 ;; If dynamic shifts are not available use a library function.
4683 ;; By specifying the pattern we reduce the number of call clobbered regs.
4684 ;; In order to make combine understand the truncation of the shift amount
4685 ;; operand we have to allow it to use pseudo regs for the shift operands.
4686 (define_insn "ashlsi3_d_call"
4687 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
4688 (ashift:SI (reg:SI R4_REG)
4689 (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
4690 (const_int 31))))
4691 (use (match_operand:SI 2 "arith_reg_operand" "r"))
4692 (clobber (reg:SI T_REG))
4693 (clobber (reg:SI PR_REG))]
4694 "TARGET_SH1 && !TARGET_DYNSHIFT"
4695 "jsr @%2%#"
4696 [(set_attr "type" "sfunc")
4697 (set_attr "needs_delay_slot" "yes")])
4698
4699 (define_insn_and_split "ashlsi3_n"
4700 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4701 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4702 (match_operand:SI 2 "not_p27_shift_count_operand" "")))]
4703 "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4704 "#"
4705 "&& (reload_completed
4706 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4707 [(const_int 0)]
4708 {
4709 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4710 {
4711 /* If this pattern was picked and dynamic shifts are supported, switch
4712 to dynamic shift pattern before reload. */
4713 operands[2] = force_reg (SImode, operands[2]);
4714 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4715 }
4716 else
4717 gen_shifty_op (ASHIFT, operands);
4718
4719 DONE;
4720 })
4721
4722 (define_insn_and_split "ashlsi3_n_clobbers_t"
4723 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4724 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4725 (match_operand:SI 2 "not_p27_shift_count_operand" "")))
4726 (clobber (reg:SI T_REG))]
4727 "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])"
4728 "#"
4729 "&& (reload_completed || INTVAL (operands[2]) == 31
4730 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4731 [(const_int 0)]
4732 {
4733 if (INTVAL (operands[2]) == 31)
4734 {
4735 /* If the shift amount is 31 we split into a different sequence before
4736 reload so that it gets a chance to allocate R0 for the sequence.
4737 If it fails to do so (due to pressure on R0), it will take one insn
4738 more for the and. */
4739 emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx));
4740 emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4741 }
4742 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4743 {
4744 /* If this pattern was picked and dynamic shifts are supported, switch
4745 to dynamic shift pattern before reload. */
4746 operands[2] = force_reg (SImode, operands[2]);
4747 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4748 }
4749 else
4750 gen_shifty_op (ASHIFT, operands);
4751
4752 DONE;
4753 })
4754
4755 (define_insn "shll"
4756 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4757 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
4758 (set (reg:SI T_REG)
4759 (lt:SI (match_dup 1) (const_int 0)))]
4760 "TARGET_SH1"
4761 "shll %0"
4762 [(set_attr "type" "arith")])
4763
4764 (define_insn "*ashlsi_c_void"
4765 [(set (reg:SI T_REG)
4766 (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
4767 (clobber (match_scratch:SI 1 "=0"))]
4768 "TARGET_SH1 && cse_not_expected"
4769 "shll %0"
4770 [(set_attr "type" "arith")])
4771
4772 (define_peephole2
4773 [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
4774 (set (reg:SI T_REG)
4775 (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
4776 "TARGET_SH1
4777 && peep2_reg_dead_p (2, operands[0])
4778 && peep2_reg_dead_p (2, operands[1])"
4779 [(const_int 0)]
4780 {
4781 emit_insn (gen_shll (operands[1], operands[1]));
4782 DONE;
4783 })
4784
4785 (define_insn "ashlsi3_media"
4786 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4787 (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
4788 (match_operand:SI 2 "shift_count_operand" "r,n")))]
4789 "TARGET_SHMEDIA"
4790 "@
4791 shlld.l %1, %2, %0
4792 shlli.l %1, %2, %0"
4793 [(set_attr "type" "arith_media")
4794 (set_attr "highpart" "ignore")])
4795
4796 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4797 ;; HImode shift left
4798
4799 (define_expand "ashlhi3"
4800 [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
4801 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
4802 (match_operand:SI 2 "nonmemory_operand" "")))
4803 (clobber (reg:SI T_REG))])]
4804 "TARGET_SH1"
4805 {
4806 if (!CONST_INT_P (operands[2]))
4807 FAIL;
4808 /* It may be possible to call gen_ashlhi3 directly with more generic
4809 operands. Make sure operands[1] is a HImode register here. */
4810 if (!arith_reg_operand (operands[1], HImode))
4811 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4812 })
4813
4814 (define_insn "ashlhi3_k"
4815 [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4816 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
4817 (match_operand:HI 2 "const_int_operand" "M,P27")))]
4818 "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
4819 "@
4820 add %0,%0
4821 shll%O2 %0"
4822 [(set_attr "type" "arith")])
4823
4824 (define_insn_and_split "*ashlhi3_n"
4825 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4826 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
4827 (match_operand:HI 2 "const_int_operand" "n")))
4828 (clobber (reg:SI T_REG))]
4829 "TARGET_SH1"
4830 "#"
4831 "&& reload_completed"
4832 [(use (reg:SI R0_REG))]
4833 {
4834 gen_shifty_hi_op (ASHIFT, operands);
4835 DONE;
4836 })
4837
4838 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4839 ;; DImode shift left
4840
4841 (define_expand "ashldi3"
4842 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4843 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
4844 (match_operand:DI 2 "immediate_operand" "")))
4845 (clobber (reg:SI T_REG))])]
4846 ""
4847 {
4848 if (TARGET_SHMEDIA)
4849 {
4850 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
4851 {
4852 operands[2] = GEN_INT (-INTVAL (operands[2]));
4853 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4854 DONE;
4855 }
4856 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
4857 DONE;
4858 }
4859 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
4860 {
4861 emit_insn (gen_ashldi3_k (operands[0], operands[1]));
4862 DONE;
4863 }
4864 else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32)
4865 {
4866 emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
4867 DONE;
4868 }
4869 else
4870 FAIL;
4871 })
4872
4873 ;; Expander for DImode shift left with SImode operations.
4874 (define_expand "ashldi3_std"
4875 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4876 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4877 (match_operand:DI 2 "const_int_operand" "n")))]
4878 "TARGET_SH1 && INTVAL (operands[2]) < 32"
4879 {
4880 rtx low_src = gen_lowpart (SImode, operands[1]);
4881 rtx high_src = gen_highpart (SImode, operands[1]);
4882 rtx dst = gen_reg_rtx (DImode);
4883 rtx low_dst = gen_lowpart (SImode, dst);
4884 rtx high_dst = gen_highpart (SImode, dst);
4885 rtx tmp0 = gen_reg_rtx (SImode);
4886 rtx tmp1 = gen_reg_rtx (SImode);
4887
4888 emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
4889 emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));
4890 emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));
4891 emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
4892 emit_move_insn (operands[0], dst);
4893 DONE;
4894 })
4895
4896 (define_insn_and_split "ashldi3_k"
4897 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4898 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
4899 (const_int 1)))
4900 (clobber (reg:SI T_REG))]
4901 "TARGET_SH1"
4902 "#"
4903 "&& reload_completed"
4904 [(const_int 0)]
4905 {
4906 rtx high = gen_highpart (SImode, operands[0]);
4907 rtx low = gen_lowpart (SImode, operands[0]);
4908 emit_insn (gen_shll (low, low));
4909 emit_insn (gen_rotcl (high, high, get_t_reg_rtx ()));
4910 DONE;
4911 })
4912
4913 (define_insn "ashldi3_media"
4914 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4915 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4916 (match_operand:DI 2 "shift_count_operand" "r,n")))]
4917 "TARGET_SHMEDIA"
4918 "@
4919 shlld %1, %2, %0
4920 shlli %1, %2, %0"
4921 [(set_attr "type" "arith_media")])
4922
4923 (define_insn "*ashldisi3_media"
4924 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4925 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4926 (match_operand:DI 2 "const_int_operand" "n")))]
4927 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4928 "shlli.l %1, %2, %0"
4929 [(set_attr "type" "arith_media")
4930 (set_attr "highpart" "ignore")])
4931
4932 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4933 ;; SImode arithmetic shift right
4934 ;;
4935 ;; We can't do HImode right shifts correctly unless we start out with an
4936 ;; explicit zero / sign extension; doing that would result in worse overall
4937 ;; code, so just let the machine independent code widen the mode.
4938 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
4939
4940 (define_expand "ashrsi3"
4941 [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
4942 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
4943 (match_operand:SI 2 "nonmemory_operand" "")))
4944 (clobber (reg:SI T_REG))])]
4945 ""
4946 {
4947 if (TARGET_SHMEDIA)
4948 {
4949 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
4950 {
4951 operands[2] = GEN_INT (-INTVAL (operands[2]));
4952 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
4953 DONE;
4954 }
4955 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
4956 DONE;
4957 }
4958 if (expand_ashiftrt (operands))
4959 DONE;
4960 else
4961 FAIL;
4962 })
4963
4964 (define_insn "shar"
4965 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4966 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4967 (const_int 1)))
4968 (set (reg:SI T_REG)
4969 (and:SI (match_dup 1) (const_int 1)))]
4970 "TARGET_SH1"
4971 "shar %0"
4972 [(set_attr "type" "arith")])
4973
4974 (define_insn "ashrsi3_k"
4975 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4976 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4977 (match_operand:SI 2 "const_int_operand" "M")))
4978 (clobber (reg:SI T_REG))]
4979 "TARGET_SH1 && INTVAL (operands[2]) == 1"
4980 "shar %0"
4981 [(set_attr "type" "arith")])
4982
4983 (define_insn_and_split "ashrsi2_16"
4984 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4985 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
4986 (const_int 16)))]
4987 "TARGET_SH1"
4988 "#"
4989 "&& 1"
4990 [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
4991 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
4992 {
4993 operands[2] = gen_lowpart (HImode, operands[0]);
4994 })
4995
4996 (define_insn_and_split "ashrsi2_31"
4997 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4998 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4999 (const_int 31)))
5000 (clobber (reg:SI T_REG))]
5001 "TARGET_SH1"
5002 "#"
5003 "&& 1"
5004 [(const_int 0)]
5005 {
5006 emit_insn (gen_shll (operands[0], operands[1]));
5007 emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
5008 DONE;
5009 })
5010
5011 (define_insn "ashrsi3_d"
5012 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5013 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5014 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
5015 "TARGET_DYNSHIFT"
5016 "shad %2,%0"
5017 [(set_attr "type" "dyn_shift")])
5018
5019 (define_insn "ashrsi3_n"
5020 [(set (reg:SI R4_REG)
5021 (ashiftrt:SI (reg:SI R4_REG)
5022 (match_operand:SI 0 "const_int_operand" "i")))
5023 (clobber (reg:SI T_REG))
5024 (clobber (reg:SI PR_REG))
5025 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
5026 "TARGET_SH1"
5027 "jsr @%1%#"
5028 [(set_attr "type" "sfunc")
5029 (set_attr "needs_delay_slot" "yes")])
5030
5031 (define_insn "ashrsi3_media"
5032 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5033 (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5034 (match_operand:SI 2 "shift_count_operand" "r,n")))]
5035 "TARGET_SHMEDIA"
5036 "@
5037 shard.l %1, %2, %0
5038 shari.l %1, %2, %0"
5039 [(set_attr "type" "arith_media")
5040 (set_attr "highpart" "ignore")])
5041
5042 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5043 ;; DImode arithmetic shift right
5044
5045 (define_expand "ashrdi3"
5046 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5047 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
5048 (match_operand:DI 2 "immediate_operand" "")))
5049 (clobber (reg:SI T_REG))])]
5050 ""
5051 {
5052 if (TARGET_SHMEDIA)
5053 {
5054 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5055 {
5056 operands[2] = GEN_INT (-INTVAL (operands[2]));
5057 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
5058 DONE;
5059 }
5060 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
5061 DONE;
5062 }
5063 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5064 FAIL;
5065 })
5066
5067 (define_insn_and_split "ashrdi3_k"
5068 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5069 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5070 (const_int 1)))
5071 (clobber (reg:SI T_REG))]
5072 "TARGET_SH1"
5073 "#"
5074 "&& reload_completed"
5075 [(const_int 0)]
5076 {
5077 rtx high = gen_highpart (SImode, operands[0]);
5078 rtx low = gen_lowpart (SImode, operands[0]);
5079 emit_insn (gen_shar (high, high));
5080 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5081 DONE;
5082 })
5083
5084 (define_insn "ashrdi3_media"
5085 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5086 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5087 (match_operand:DI 2 "shift_count_operand" "r,n")))]
5088 "TARGET_SHMEDIA
5089 && (arith_reg_dest (operands[0], DImode)
5090 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
5091 "@
5092 shard %1, %2, %0
5093 shari %1, %2, %0"
5094 [(set_attr "type" "arith_media")])
5095
5096 (define_insn "*ashrdisi3_media"
5097 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5098 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5099 (match_operand:DI 2 "const_int_operand" "n")))]
5100 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5101 "shari.l %1, %2, %0"
5102 [(set_attr "type" "arith_media")
5103 (set_attr "highpart" "ignore")])
5104
5105 (define_insn "ashrdisi3_media_high"
5106 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5107 (truncate:SI
5108 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5109 (match_operand:DI 2 "const_int_operand" "n"))))]
5110 "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
5111 "shari %1, %2, %0"
5112 [(set_attr "type" "arith_media")])
5113
5114 (define_insn "ashrdisi3_media_opaque"
5115 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5116 (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
5117 (match_operand:DI 2 "const_int_operand" "n")]
5118 UNSPEC_ASHIFTRT))]
5119 "TARGET_SHMEDIA"
5120 "shari %1, %2, %0"
5121 [(set_attr "type" "arith_media")])
5122
5123 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5124 ;; SImode logical shift right
5125
5126 (define_expand "lshrsi3"
5127 [(set (match_operand:SI 0 "arith_reg_dest" "")
5128 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
5129 (match_operand:SI 2 "shift_count_operand" "")))]
5130 ""
5131 {
5132 if (TARGET_SHMEDIA)
5133 {
5134 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5135 {
5136 operands[2] = GEN_INT (-INTVAL (operands[2]));
5137 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
5138 DONE;
5139 }
5140 emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
5141 DONE;
5142 }
5143
5144 /* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn
5145 here, otherwise the pattern will never match due to the shift amount reg
5146 negation. */
5147 if (TARGET_DYNSHIFT
5148 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
5149 {
5150 rtx neg_count = force_reg (SImode,
5151 gen_int_mode (- INTVAL (operands[2]), SImode));
5152 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
5153 DONE;
5154 }
5155
5156 if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2]))
5157 {
5158 rtx neg_count = gen_reg_rtx (SImode);
5159 emit_insn (gen_negsi2 (neg_count, operands[2]));
5160 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
5161 DONE;
5162 }
5163
5164 /* If the lshrsi3_* insn is going to clobber the T_REG it must be
5165 expanded here. */
5166 if (CONST_INT_P (operands[2])
5167 && sh_lshrsi_clobbers_t_reg_p (operands[2])
5168 && ! sh_dynamicalize_shift_p (operands[2]))
5169 {
5170 emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1],
5171 operands[2]));
5172 DONE;
5173 }
5174
5175 /* Expand a library call for the dynamic shift. */
5176 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
5177 {
5178 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
5179 rtx funcaddr = gen_reg_rtx (Pmode);
5180 function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC);
5181 emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr));
5182 DONE;
5183 }
5184 })
5185
5186 (define_insn "lshrsi3_k"
5187 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5188 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5189 (match_operand:SI 2 "p27_rshift_count_operand" "P27")))]
5190 "TARGET_SH1"
5191 "shlr%O2 %0"
5192 [(set_attr "type" "arith")])
5193
5194 (define_insn_and_split "lshrsi3_d"
5195 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5196 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5197 (neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))]
5198 "TARGET_DYNSHIFT"
5199 "shld %2,%0"
5200 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
5201 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5202 [(const_int 0)]
5203 {
5204 if (satisfies_constraint_P27 (operands[2]))
5205 {
5206 /* This will not be done for a shift amount of 1, because it would
5207 clobber the T_REG. */
5208 emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2]));
5209 DONE;
5210 }
5211 else if (! satisfies_constraint_P27 (operands[2]))
5212 {
5213 /* This must happen before reload, otherwise the constant will be moved
5214 into a register due to the "r" constraint, after which this split
5215 cannot be done anymore.
5216 Unfortunately the move insn will not always be eliminated.
5217 Also, here we must not create a shift sequence that clobbers the
5218 T_REG. */
5219 emit_move_insn (operands[0], operands[1]);
5220 gen_shifty_op (LSHIFTRT, operands);
5221 DONE;
5222 }
5223
5224 FAIL;
5225 }
5226 [(set_attr "type" "dyn_shift")])
5227
5228 ;; If dynamic shifts are not available use a library function.
5229 ;; By specifying the pattern we reduce the number of call clobbered regs.
5230 ;; In order to make combine understand the truncation of the shift amount
5231 ;; operand we have to allow it to use pseudo regs for the shift operands.
5232 (define_insn "lshrsi3_d_call"
5233 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
5234 (lshiftrt:SI (reg:SI R4_REG)
5235 (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
5236 (const_int 31))))
5237 (use (match_operand:SI 2 "arith_reg_operand" "r"))
5238 (clobber (reg:SI T_REG))
5239 (clobber (reg:SI PR_REG))]
5240 "TARGET_SH1 && !TARGET_DYNSHIFT"
5241 "jsr @%2%#"
5242 [(set_attr "type" "sfunc")
5243 (set_attr "needs_delay_slot" "yes")])
5244
5245 (define_insn_and_split "lshrsi3_n"
5246 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5247 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5248 (match_operand:SI 2 "not_p27_rshift_count_operand")))]
5249 "TARGET_SH1 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5250 "#"
5251 "&& (reload_completed
5252 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5253 [(const_int 0)]
5254 {
5255 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5256 {
5257 /* If this pattern was picked and dynamic shifts are supported, switch
5258 to dynamic shift pattern before reload. */
5259 operands[2] = force_reg (SImode,
5260 gen_int_mode (- INTVAL (operands[2]), SImode));
5261 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5262 }
5263 else
5264 gen_shifty_op (LSHIFTRT, operands);
5265
5266 DONE;
5267 })
5268
5269 ;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of
5270 ;; the shlr pattern.
5271 (define_insn_and_split "lshrsi3_n_clobbers_t"
5272 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5273 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5274 (match_operand:SI 2 "not_p27_rshift_count_operand")))
5275 (clobber (reg:SI T_REG))]
5276 "TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])"
5277 "#"
5278 "&& (reload_completed || INTVAL (operands[2]) == 31
5279 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5280 [(const_int 0)]
5281 {
5282 if (INTVAL (operands[2]) == 31)
5283 {
5284 emit_insn (gen_shll (operands[0], operands[1]));
5285 emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
5286 }
5287 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5288 {
5289 /* If this pattern was picked and dynamic shifts are supported, switch
5290 to dynamic shift pattern before reload. */
5291 operands[2] = force_reg (SImode,
5292 gen_int_mode (- INTVAL (operands[2]), SImode));
5293 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5294 }
5295 else
5296 gen_shifty_op (LSHIFTRT, operands);
5297
5298 DONE;
5299 })
5300
5301 (define_insn "shlr"
5302 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5303 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5304 (const_int 1)))
5305 (set (reg:SI T_REG)
5306 (and:SI (match_dup 1) (const_int 1)))]
5307 "TARGET_SH1"
5308 "shlr %0"
5309 [(set_attr "type" "arith")])
5310
5311 (define_insn "lshrsi3_media"
5312 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5313 (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5314 (match_operand:SI 2 "shift_count_operand" "r,n")))]
5315 "TARGET_SHMEDIA"
5316 "@
5317 shlrd.l %1, %2, %0
5318 shlri.l %1, %2, %0"
5319 [(set_attr "type" "arith_media")
5320 (set_attr "highpart" "ignore")])
5321
5322 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5323 ;; DImode logical shift right
5324
5325 (define_expand "lshrdi3"
5326 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5327 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
5328 (match_operand:DI 2 "immediate_operand" "")))
5329 (clobber (reg:SI T_REG))])]
5330 ""
5331 {
5332 if (TARGET_SHMEDIA)
5333 {
5334 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5335 {
5336 operands[2] = GEN_INT (-INTVAL (operands[2]));
5337 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
5338 DONE;
5339 }
5340 emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
5341 DONE;
5342 }
5343 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5344 FAIL;
5345 })
5346
5347 (define_insn_and_split "lshrdi3_k"
5348 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5349 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5350 (const_int 1)))
5351 (clobber (reg:SI T_REG))]
5352 "TARGET_SH1"
5353 "#"
5354 "&& reload_completed"
5355 [(const_int 0)]
5356 {
5357 rtx high = gen_highpart (SImode, operands[0]);
5358 rtx low = gen_lowpart (SImode, operands[0]);
5359 emit_insn (gen_shlr (high, high));
5360 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5361 DONE;
5362 })
5363
5364 (define_insn "lshrdi3_media"
5365 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5366 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5367 (match_operand:DI 2 "shift_count_operand" "r,n")))]
5368 "TARGET_SHMEDIA
5369 && (arith_reg_dest (operands[0], DImode)
5370 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
5371 "@
5372 shlrd %1, %2, %0
5373 shlri %1, %2, %0"
5374 [(set_attr "type" "arith_media")])
5375
5376 (define_insn "*lshrdisi3_media"
5377 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5378 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5379 (match_operand:DI 2 "const_int_operand" "n")))]
5380 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5381 "shlri.l %1, %2, %0"
5382 [(set_attr "type" "arith_media")
5383 (set_attr "highpart" "ignore")])
5384
5385 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5386 ;; Combined left/right shifts
5387
5388 (define_split
5389 [(set (match_operand:SI 0 "register_operand" "")
5390 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5391 (match_operand:SI 2 "const_int_operand" ""))
5392 (match_operand:SI 3 "const_int_operand" "")))]
5393 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5394 [(use (reg:SI R0_REG))]
5395 {
5396 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5397 FAIL;
5398 DONE;
5399 })
5400
5401 (define_split
5402 [(set (match_operand:SI 0 "register_operand" "")
5403 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5404 (match_operand:SI 2 "const_int_operand" ""))
5405 (match_operand:SI 3 "const_int_operand" "")))
5406 (clobber (reg:SI T_REG))]
5407 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5408 [(use (reg:SI R0_REG))]
5409 {
5410 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5411 FAIL;
5412 DONE;
5413 })
5414
5415 (define_insn ""
5416 [(set (match_operand:SI 0 "register_operand" "=r")
5417 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5418 (match_operand:SI 2 "const_int_operand" "n"))
5419 (match_operand:SI 3 "const_int_operand" "n")))
5420 (clobber (reg:SI T_REG))]
5421 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
5422 "#"
5423 [(set (attr "length")
5424 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5425 (const_string "4")
5426 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5427 (const_string "6")
5428 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5429 (const_string "8")
5430 (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
5431 (const_string "10")
5432 (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
5433 (const_string "12")
5434 (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
5435 (const_string "14")
5436 (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
5437 (const_string "16")]
5438 (const_string "18")))
5439 (set_attr "type" "arith")])
5440
5441 (define_insn ""
5442 [(set (match_operand:SI 0 "register_operand" "=z")
5443 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5444 (match_operand:SI 2 "const_int_operand" "n"))
5445 (match_operand:SI 3 "const_int_operand" "n")))
5446 (clobber (reg:SI T_REG))]
5447 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
5448 "#"
5449 [(set (attr "length")
5450 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5451 (const_string "4")
5452 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5453 (const_string "6")
5454 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5455 (const_string "8")]
5456 (const_string "10")))
5457 (set_attr "type" "arith")])
5458
5459 ;; shift left / and combination with a scratch register: The combine pass
5460 ;; does not accept the individual instructions, even though they are
5461 ;; cheap. But it needs a precise description so that it is usable after
5462 ;; reload.
5463 (define_insn "and_shl_scratch"
5464 [(set (match_operand:SI 0 "register_operand" "=r,&r")
5465 (lshiftrt:SI
5466 (ashift:SI
5467 (and:SI
5468 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
5469 (match_operand:SI 2 "const_int_operand" "N,n"))
5470 (match_operand:SI 3 "" "0,r"))
5471 (match_operand:SI 4 "const_int_operand" "n,n"))
5472 (match_operand:SI 5 "const_int_operand" "n,n")))
5473 (clobber (reg:SI T_REG))]
5474 "TARGET_SH1"
5475 "#"
5476 [(set (attr "length")
5477 (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
5478 (const_string "4")
5479 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
5480 (const_string "6")
5481 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
5482 (const_string "8")
5483 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
5484 (const_string "10")]
5485 (const_string "12")))
5486 (set_attr "type" "arith")])
5487
5488 (define_split
5489 [(set (match_operand:SI 0 "register_operand" "")
5490 (lshiftrt:SI
5491 (ashift:SI
5492 (and:SI
5493 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
5494 (match_operand:SI 2 "const_int_operand" ""))
5495 (match_operand:SI 3 "register_operand" ""))
5496 (match_operand:SI 4 "const_int_operand" ""))
5497 (match_operand:SI 5 "const_int_operand" "")))
5498 (clobber (reg:SI T_REG))]
5499 "TARGET_SH1"
5500 [(use (reg:SI R0_REG))]
5501 {
5502 rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
5503
5504 if (INTVAL (operands[2]))
5505 {
5506 gen_shifty_op (LSHIFTRT, operands);
5507 }
5508 emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
5509 operands[2] = operands[4];
5510 gen_shifty_op (ASHIFT, operands);
5511 if (INTVAL (operands[5]))
5512 {
5513 operands[2] = operands[5];
5514 gen_shifty_op (LSHIFTRT, operands);
5515 }
5516 DONE;
5517 })
5518
5519 ;; signed left/right shift combination.
5520 (define_split
5521 [(set (match_operand:SI 0 "register_operand" "")
5522 (sign_extract:SI
5523 (ashift:SI (match_operand:SI 1 "register_operand" "")
5524 (match_operand:SI 2 "const_int_operand" ""))
5525 (match_operand:SI 3 "const_int_operand" "")
5526 (const_int 0)))
5527 (clobber (reg:SI T_REG))]
5528 "TARGET_SH1"
5529 [(use (reg:SI R0_REG))]
5530 {
5531 if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1]))
5532 FAIL;
5533 DONE;
5534 })
5535
5536 (define_insn "shl_sext_ext"
5537 [(set (match_operand:SI 0 "register_operand" "=r")
5538 (sign_extract:SI
5539 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5540 (match_operand:SI 2 "const_int_operand" "n"))
5541 (match_operand:SI 3 "const_int_operand" "n")
5542 (const_int 0)))
5543 (clobber (reg:SI T_REG))]
5544 "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
5545 "#"
5546 [(set (attr "length")
5547 (cond [(match_test "shl_sext_length (insn)")
5548 (const_string "2")
5549 (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
5550 (const_string "4")
5551 (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5552 (const_string "6")
5553 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5554 (const_string "8")
5555 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5556 (const_string "10")
5557 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5558 (const_string "12")
5559 (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
5560 (const_string "14")
5561 (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
5562 (const_string "16")]
5563 (const_string "18")))
5564 (set_attr "type" "arith")])
5565
5566 (define_insn "shl_sext_sub"
5567 [(set (match_operand:SI 0 "register_operand" "=z")
5568 (sign_extract:SI
5569 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5570 (match_operand:SI 2 "const_int_operand" "n"))
5571 (match_operand:SI 3 "const_int_operand" "n")
5572 (const_int 0)))
5573 (clobber (reg:SI T_REG))]
5574 "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
5575 "#"
5576 [(set (attr "length")
5577 (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5578 (const_string "6")
5579 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5580 (const_string "8")
5581 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5582 (const_string "10")
5583 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5584 (const_string "12")]
5585 (const_string "14")))
5586 (set_attr "type" "arith")])
5587
5588 ;; The xtrct_left and xtrct_right patterns are used in expansions of DImode
5589 ;; shifts by 16, and allow the xtrct instruction to be generated from C
5590 ;; source.
5591 (define_insn "xtrct_left"
5592 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5593 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5594 (const_int 16))
5595 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
5596 (const_int 16))))]
5597 "TARGET_SH1"
5598 "xtrct %1,%0"
5599 [(set_attr "type" "arith")])
5600
5601 (define_insn "xtrct_right"
5602 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5603 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5604 (const_int 16))
5605 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
5606 (const_int 16))))]
5607 "TARGET_SH1"
5608 "xtrct %2,%0"
5609 [(set_attr "type" "arith")])
5610
5611 ;; -------------------------------------------------------------------------
5612 ;; Unary arithmetic
5613 ;; -------------------------------------------------------------------------
5614
5615 (define_insn "negc"
5616 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5617 (neg:SI (plus:SI (reg:SI T_REG)
5618 (match_operand:SI 1 "arith_reg_operand" "r"))))
5619 (set (reg:SI T_REG)
5620 (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
5621 (const_int 0)))]
5622 "TARGET_SH1"
5623 "negc %1,%0"
5624 [(set_attr "type" "arith")])
5625
5626 ;; A simplified version of the negc insn, where the exact value of the
5627 ;; T bit doesn't matter. This is easier for combine to pick up.
5628 ;; Notice that '0 - x - 1' is the same as '~x', thus we don't specify
5629 ;; extra patterns for this case.
5630 (define_insn "*negc"
5631 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5632 (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5633 (match_operand:SI 2 "t_reg_operand" "")))
5634 (clobber (reg:SI T_REG))]
5635 "TARGET_SH1"
5636 "negc %1,%0"
5637 [(set_attr "type" "arith")])
5638
5639 (define_insn "*negdi_media"
5640 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5641 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
5642 "TARGET_SHMEDIA"
5643 "sub r63, %1, %0"
5644 [(set_attr "type" "arith_media")])
5645
5646 ;; Don't split into individual negc insns immediately so that neg:DI (abs:DI)
5647 ;; can be combined.
5648 (define_expand "negdi2"
5649 [(parallel [(set (match_operand:DI 0 "arith_reg_dest")
5650 (neg:DI (match_operand:DI 1 "arith_reg_operand")))
5651 (clobber (reg:SI T_REG))])]
5652 "TARGET_SH1")
5653
5654 (define_insn_and_split "*negdi2"
5655 [(set (match_operand:DI 0 "arith_reg_dest")
5656 (neg:DI (match_operand:DI 1 "arith_reg_operand")))
5657 (clobber (reg:SI T_REG))]
5658 "TARGET_SH1"
5659 "#"
5660 "&& can_create_pseudo_p ()"
5661 [(const_int 0)]
5662 {
5663 emit_insn (gen_clrt ());
5664 emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
5665 gen_lowpart (SImode, operands[1])));
5666 emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
5667 gen_highpart (SImode, operands[1])));
5668 DONE;
5669 })
5670
5671 (define_insn "negsi2"
5672 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5673 (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5674 "TARGET_SH1"
5675 "neg %1,%0"
5676 [(set_attr "type" "arith")])
5677
5678 (define_insn_and_split "one_cmplsi2"
5679 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5680 (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5681 "TARGET_SH1"
5682 "not %1,%0"
5683 "&& can_create_pseudo_p ()"
5684 [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0)))
5685 (set (match_dup 0) (reg:SI T_REG))]
5686 {
5687 /* PR 54685
5688 If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following
5689 sequence:
5690
5691 (set (reg0) (not:SI (reg0) (reg1)))
5692 (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31)))
5693 (clobber (reg:SI T_REG))])
5694
5695 ... match and combine the sequence manually in the split pass after the
5696 combine pass. Notice that combine does try the target pattern of this
5697 split, but if the pattern is added it interferes with other patterns, in
5698 particular with the div0s comparisons.
5699 This could also be done with a peephole but doing it here before register
5700 allocation can save one temporary.
5701 When we're here, the not:SI pattern obviously has been matched already
5702 and we only have to see whether the following insn is the left shift. */
5703
5704 rtx i = next_nonnote_insn_bb (curr_insn);
5705 if (i == NULL_RTX || !NONJUMP_INSN_P (i))
5706 FAIL;
5707
5708 rtx p = PATTERN (i);
5709 if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2)
5710 FAIL;
5711
5712 rtx p0 = XVECEXP (p, 0, 0);
5713 rtx p1 = XVECEXP (p, 0, 1);
5714
5715 if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31))) */
5716 GET_CODE (p0) == SET
5717 && GET_CODE (XEXP (p0, 1)) == LSHIFTRT
5718 && REG_P (XEXP (XEXP (p0, 1), 0))
5719 && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0])
5720 && CONST_INT_P (XEXP (XEXP (p0, 1), 1))
5721 && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31
5722
5723 /* (clobber (reg:SI T_REG)) */
5724 && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0))
5725 && REGNO (XEXP (p1, 0)) == T_REG)
5726 {
5727 operands[0] = XEXP (p0, 0);
5728 set_insn_deleted (i);
5729 }
5730 else
5731 FAIL;
5732 }
5733 [(set_attr "type" "arith")])
5734
5735 (define_expand "one_cmpldi2"
5736 [(set (match_operand:DI 0 "arith_reg_dest" "")
5737 (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
5738 (const_int -1)))]
5739 "TARGET_SHMEDIA" "")
5740
5741 (define_expand "abs<mode>2"
5742 [(parallel [(set (match_operand:SIDI 0 "arith_reg_dest")
5743 (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
5744 (clobber (reg:SI T_REG))])]
5745 "TARGET_SH1")
5746
5747 (define_insn_and_split "*abs<mode>2"
5748 [(set (match_operand:SIDI 0 "arith_reg_dest")
5749 (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
5750 (clobber (reg:SI T_REG))]
5751 "TARGET_SH1"
5752 "#"
5753 "&& can_create_pseudo_p ()"
5754 [(const_int 0)]
5755 {
5756 if (<MODE>mode == SImode)
5757 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5758 else
5759 {
5760 rtx high_src = gen_highpart (SImode, operands[1]);
5761 emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5762 }
5763
5764 emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
5765 const1_rtx));
5766 DONE;
5767 })
5768
5769 (define_insn_and_split "*negabs<mode>2"
5770 [(set (match_operand:SIDI 0 "arith_reg_dest")
5771 (neg:SIDI (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))))
5772 (clobber (reg:SI T_REG))]
5773 "TARGET_SH1"
5774 "#"
5775 "&& can_create_pseudo_p ()"
5776 [(const_int 0)]
5777 {
5778 if (<MODE>mode == SImode)
5779 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5780 else
5781 {
5782 rtx high_src = gen_highpart (SImode, operands[1]);
5783 emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5784 }
5785
5786 emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
5787 const0_rtx));
5788 DONE;
5789 })
5790
5791 ;; The SH4 202 can do zero-offset branches without pipeline stalls.
5792 ;; This can be used as some kind of conditional execution, which is useful
5793 ;; for abs.
5794 ;; Actually the instruction scheduling should decide whether to use a
5795 ;; zero-offset branch or not for any generic case involving a single
5796 ;; instruction on SH4 202.
5797 (define_insn_and_split "negsi_cond"
5798 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5799 (if_then_else
5800 (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand" "M,N"))
5801 (match_operand:SI 1 "arith_reg_operand" "0,0")
5802 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
5803 "TARGET_SH1 && TARGET_ZDCBRANCH"
5804 {
5805 static const char* alt[] =
5806 {
5807 "bt 0f" "\n"
5808 " neg %2,%0" "\n"
5809 "0:",
5810
5811 "bf 0f" "\n"
5812 " neg %2,%0" "\n"
5813 "0:"
5814 };
5815 return alt[which_alternative];
5816 }
5817 "TARGET_SH1 && ! TARGET_ZDCBRANCH"
5818 [(const_int 0)]
5819 {
5820 rtx skip_neg_label = gen_label_rtx ();
5821
5822 emit_move_insn (operands[0], operands[1]);
5823
5824 emit_jump_insn (INTVAL (operands[3])
5825 ? gen_branch_true (skip_neg_label)
5826 : gen_branch_false (skip_neg_label));
5827
5828 emit_label_after (skip_neg_label,
5829 emit_insn (gen_negsi2 (operands[0], operands[1])));
5830 DONE;
5831 }
5832 [(set_attr "type" "arith") ;; poor approximation
5833 (set_attr "length" "4")])
5834
5835 (define_insn_and_split "negdi_cond"
5836 [(set (match_operand:DI 0 "arith_reg_dest")
5837 (if_then_else
5838 (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand"))
5839 (match_operand:DI 1 "arith_reg_operand")
5840 (neg:DI (match_operand:DI 2 "arith_reg_operand"))))
5841 (clobber (reg:SI T_REG))]
5842 "TARGET_SH1"
5843 "#"
5844 "&& can_create_pseudo_p ()"
5845 [(const_int 0)]
5846 {
5847 rtx skip_neg_label = gen_label_rtx ();
5848
5849 emit_move_insn (operands[0], operands[1]);
5850
5851 emit_jump_insn (INTVAL (operands[3])
5852 ? gen_branch_true (skip_neg_label)
5853 : gen_branch_false (skip_neg_label));
5854
5855 if (!INTVAL (operands[3]))
5856 emit_insn (gen_clrt ());
5857
5858 emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
5859 gen_lowpart (SImode, operands[1])));
5860 emit_label_after (skip_neg_label,
5861 emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
5862 gen_highpart (SImode, operands[1]))));
5863 DONE;
5864 })
5865
5866 (define_expand "bswapsi2"
5867 [(set (match_operand:SI 0 "arith_reg_dest" "")
5868 (bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))]
5869 "TARGET_SH1"
5870 {
5871 if (! can_create_pseudo_p ())
5872 FAIL;
5873 else
5874 {
5875 rtx tmp0 = gen_reg_rtx (SImode);
5876 rtx tmp1 = gen_reg_rtx (SImode);
5877
5878 emit_insn (gen_swapbsi2 (tmp0, operands[1]));
5879 emit_insn (gen_rotlsi3_16 (tmp1, tmp0));
5880 emit_insn (gen_swapbsi2 (operands[0], tmp1));
5881 DONE;
5882 }
5883 })
5884
5885 (define_insn "swapbsi2"
5886 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5887 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
5888 (const_int 4294901760))
5889 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5890 (const_int 65280))
5891 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5892 (const_int 255)))))]
5893 "TARGET_SH1"
5894 "swap.b %1,%0"
5895 [(set_attr "type" "arith")])
5896
5897 ;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying
5898 ;; partial byte swap expressions such as...
5899 ;; ((x & 0xFF) << 8) | ((x >> 8) & 0xFF).
5900 ;; ...which are currently not handled by the tree optimizers.
5901 ;; The combine pass will not initially try to combine the full expression,
5902 ;; but only some sub-expressions. In such a case the *swapbisi2_and_shl8
5903 ;; pattern acts as an intermediate pattern that will eventually lead combine
5904 ;; to the swapbsi2 pattern above.
5905 ;; As a side effect this also improves code that does (x & 0xFF) << 8
5906 ;; or (x << 8) & 0xFF00.
5907 (define_insn_and_split "*swapbisi2_and_shl8"
5908 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5909 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5910 (const_int 8))
5911 (const_int 65280))
5912 (match_operand:SI 2 "arith_reg_operand" "r")))]
5913 "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5914 "#"
5915 "&& can_create_pseudo_p ()"
5916 [(const_int 0)]
5917 {
5918 rtx tmp0 = gen_reg_rtx (SImode);
5919 rtx tmp1 = gen_reg_rtx (SImode);
5920
5921 emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1])));
5922 emit_insn (gen_swapbsi2 (tmp1, tmp0));
5923 emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2]));
5924 DONE;
5925 })
5926
5927 ;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another
5928 ;; intermediate pattern that will help the combine pass arriving at swapbsi2.
5929 (define_insn_and_split "*swapbhisi2"
5930 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5931 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5932 (const_int 8))
5933 (const_int 65280))
5934 (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))]
5935 "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5936 "#"
5937 "&& can_create_pseudo_p ()"
5938 [(const_int 0)]
5939 {
5940 rtx tmp = gen_reg_rtx (SImode);
5941
5942 emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1])));
5943 emit_insn (gen_swapbsi2 (operands[0], tmp));
5944 DONE;
5945 })
5946
5947 ;; In some cases the swapbsi2 pattern might leave a sequence such as...
5948 ;; swap.b r4,r4
5949 ;; mov r4,r0
5950 ;;
5951 ;; which can be simplified to...
5952 ;; swap.b r4,r0
5953 (define_peephole2
5954 [(set (match_operand:SI 0 "arith_reg_dest" "")
5955 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5956 (const_int 4294901760))
5957 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5958 (const_int 65280))
5959 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5960 (const_int 255)))))
5961 (set (match_operand:SI 2 "arith_reg_dest" "")
5962 (match_dup 0))]
5963 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
5964 [(set (match_dup 2)
5965 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5966 (const_int 4294901760))
5967 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5968 (const_int 65280))
5969 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5970 (const_int 255)))))])
5971 \f
5972 ;; -------------------------------------------------------------------------
5973 ;; Zero extension instructions
5974 ;; -------------------------------------------------------------------------
5975
5976 (define_insn "zero_extendsidi2"
5977 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5978 (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
5979 "TARGET_SHMEDIA"
5980 "addz.l %1, r63, %0"
5981 [(set_attr "type" "arith_media")
5982 (set_attr "highpart" "extend")])
5983
5984 (define_insn "zero_extendhidi2"
5985 [(set (match_operand:DI 0 "register_operand" "=r,r")
5986 (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5987 "TARGET_SHMEDIA"
5988 "@
5989 #
5990 ld%M1.uw %m1, %0"
5991 [(set_attr "type" "*,load_media")
5992 (set (attr "highpart")
5993 (cond [(match_test "sh_contains_memref_p (insn)")
5994 (const_string "user")]
5995 (const_string "ignore")))])
5996
5997 (define_split
5998 [(set (match_operand:DI 0 "register_operand" "")
5999 (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
6000 "TARGET_SHMEDIA && reload_completed"
6001 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
6002 (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
6003 {
6004 if (GET_CODE (operands[1]) == TRUNCATE)
6005 operands[1] = XEXP (operands[1], 0);
6006 })
6007
6008 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
6009 ;; reload the entire truncate expression.
6010 (define_insn_and_split "*loaddi_trunc"
6011 [(set (match_operand 0 "any_register_operand" "=r")
6012 (truncate (match_operand:DI 1 "memory_operand" "m")))]
6013 "TARGET_SHMEDIA && reload_completed"
6014 "#"
6015 "TARGET_SHMEDIA && reload_completed"
6016 [(set (match_dup 0) (match_dup 1))]
6017 {
6018 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6019 })
6020
6021 (define_insn "zero_extendqidi2"
6022 [(set (match_operand:DI 0 "register_operand" "=r,r")
6023 (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6024 "TARGET_SHMEDIA"
6025 "@
6026 andi %1, 255, %0
6027 ld%M1.ub %m1, %0"
6028 [(set_attr "type" "arith_media,load_media")
6029 (set (attr "highpart")
6030 (cond [(match_test "sh_contains_memref_p (insn)")
6031 (const_string "user")]
6032 (const_string "ignore")))])
6033
6034 (define_expand "zero_extend<mode>si2"
6035 [(set (match_operand:SI 0 "arith_reg_dest")
6036 (zero_extend:SI (match_operand:QIHI 1 "zero_extend_operand")))])
6037
6038 (define_insn_and_split "*zero_extend<mode>si2_compact"
6039 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6040 (zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
6041 "TARGET_SH1"
6042 "extu.<bw> %1,%0"
6043 "&& can_create_pseudo_p ()"
6044 [(set (match_dup 0) (match_dup 2))]
6045 {
6046 /* Sometimes combine fails to combine a T bit or negated T bit store to a
6047 reg with a following zero extension. In the split pass after combine,
6048 try to figure out how the extended reg was set. If it originated from
6049 the T bit we can replace the zero extension with a reg move, which will
6050 be eliminated. Notice that this also helps the *cbranch_t splitter when
6051 it tries to post-combine tests and conditional branches, as it does not
6052 check for zero extensions. */
6053 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
6054 if (operands[2] == NULL_RTX)
6055 FAIL;
6056 }
6057 [(set_attr "type" "arith")])
6058
6059 (define_insn "*zero_extendhisi2_media"
6060 [(set (match_operand:SI 0 "register_operand" "=r,r")
6061 (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6062 "TARGET_SHMEDIA"
6063 "@
6064 #
6065 ld%M1.uw %m1, %0"
6066 [(set_attr "type" "arith_media,load_media")
6067 (set (attr "highpart")
6068 (cond [(match_test "sh_contains_memref_p (insn)")
6069 (const_string "user")]
6070 (const_string "ignore")))])
6071
6072 (define_split
6073 [(set (match_operand:SI 0 "register_operand" "")
6074 (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6075 "TARGET_SHMEDIA && reload_completed"
6076 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6077 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
6078 {
6079 rtx op1 = operands[1];
6080
6081 if (GET_CODE (op1) == TRUNCATE)
6082 op1 = XEXP (op1, 0);
6083 operands[2]
6084 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6085 subreg_lowpart_offset (SImode, GET_MODE (op1)));
6086 })
6087
6088 (define_insn "*zero_extendqisi2_media"
6089 [(set (match_operand:SI 0 "register_operand" "=r,r")
6090 (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6091 "TARGET_SHMEDIA"
6092 "@
6093 andi %1, 255, %0
6094 ld%M1.ub %m1, %0"
6095 [(set_attr "type" "arith_media,load_media")
6096 (set (attr "highpart")
6097 (cond [(match_test "sh_contains_memref_p (insn)")
6098 (const_string "user")]
6099 (const_string "ignore")))])
6100
6101 (define_insn "zero_extendqihi2"
6102 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6103 (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6104 "TARGET_SH1"
6105 "extu.b %1,%0"
6106 [(set_attr "type" "arith")])
6107
6108 ;; SH2A supports two zero extending load instructions: movu.b and movu.w.
6109 ;; They could also be used for simple memory addresses like @Rn by setting
6110 ;; the displacement value to zero. However, doing so too early results in
6111 ;; missed opportunities for other optimizations such as post-inc or index
6112 ;; addressing loads.
6113 ;; Although the 'zero_extend_movu_operand' predicate does not allow simple
6114 ;; register addresses (an address without a displacement, index, post-inc),
6115 ;; zero-displacement addresses might be generated during reload, wich are
6116 ;; simplified to simple register addresses in turn. Thus, we have to
6117 ;; provide the Sdd and Sra alternatives in the patterns.
6118 (define_insn "*zero_extend<mode>si2_disp_mem"
6119 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
6120 (zero_extend:SI
6121 (match_operand:QIHI 1 "zero_extend_movu_operand" "Sdd,Sra")))]
6122 "TARGET_SH2A"
6123 "@
6124 movu.<bw> %1,%0
6125 movu.<bw> @(0,%t1),%0"
6126 [(set_attr "type" "load")
6127 (set_attr "length" "4")])
6128
6129 ;; Convert the zero extending loads in sequences such as:
6130 ;; movu.b @(1,r5),r0 movu.w @(2,r5),r0
6131 ;; mov.b r0,@(1,r4) mov.b r0,@(1,r4)
6132 ;;
6133 ;; back to sign extending loads like:
6134 ;; mov.b @(1,r5),r0 mov.w @(2,r5),r0
6135 ;; mov.b r0,@(1,r4) mov.b r0,@(1,r4)
6136 ;;
6137 ;; if the extension type is irrelevant. The sign extending mov.{b|w} insn
6138 ;; is only 2 bytes in size if the displacement is {K04|K05}.
6139 ;; If the displacement is greater it doesn't matter, so we convert anyways.
6140 (define_peephole2
6141 [(set (match_operand:SI 0 "arith_reg_dest" "")
6142 (zero_extend:SI (match_operand 1 "displacement_mem_operand" "")))
6143 (set (match_operand 2 "nonimmediate_operand" "")
6144 (match_operand 3 "arith_reg_operand" ""))]
6145 "TARGET_SH2A
6146 && REGNO (operands[0]) == REGNO (operands[3])
6147 && peep2_reg_dead_p (2, operands[0])
6148 && GET_MODE_SIZE (GET_MODE (operands[2]))
6149 <= GET_MODE_SIZE (GET_MODE (operands[1]))"
6150 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
6151 (set (match_dup 2) (match_dup 3))])
6152
6153 ;; Fold sequences such as
6154 ;; mov.b @r3,r7
6155 ;; extu.b r7,r7
6156 ;; into
6157 ;; movu.b @(0,r3),r7
6158 ;; This does not reduce the code size but the number of instructions is
6159 ;; halved, which results in faster code.
6160 (define_peephole2
6161 [(set (match_operand:SI 0 "arith_reg_dest" "")
6162 (sign_extend:SI (match_operand 1 "simple_mem_operand" "")))
6163 (set (match_operand:SI 2 "arith_reg_dest" "")
6164 (zero_extend:SI (match_operand 3 "arith_reg_operand" "")))]
6165 "TARGET_SH2A
6166 && GET_MODE (operands[1]) == GET_MODE (operands[3])
6167 && (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode)
6168 && REGNO (operands[0]) == REGNO (operands[3])
6169 && (REGNO (operands[2]) == REGNO (operands[0])
6170 || peep2_reg_dead_p (2, operands[0]))"
6171 [(set (match_dup 2) (zero_extend:SI (match_dup 4)))]
6172 {
6173 operands[4]
6174 = replace_equiv_address (operands[1],
6175 gen_rtx_PLUS (SImode, XEXP (operands[1], 0),
6176 const0_rtx));
6177 })
6178
6179 ;; -------------------------------------------------------------------------
6180 ;; Sign extension instructions
6181 ;; -------------------------------------------------------------------------
6182
6183 ;; ??? This should be a define expand.
6184 ;; ??? Or perhaps it should be dropped?
6185
6186 ;; convert_move generates good code for SH[1-4].
6187 (define_insn "extendsidi2"
6188 [(set (match_operand:DI 0 "register_operand" "=r,r,r")
6189 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
6190 "TARGET_SHMEDIA"
6191 "@
6192 add.l %1, r63, %0
6193 ld%M1.l %m1, %0
6194 fmov.sl %1, %0"
6195 [(set_attr "type" "arith_media,load_media,fpconv_media")
6196 (set (attr "highpart")
6197 (cond [(match_test "sh_contains_memref_p (insn)")
6198 (const_string "user")]
6199 (const_string "extend")))])
6200
6201 (define_insn "extendhidi2"
6202 [(set (match_operand:DI 0 "register_operand" "=r,r")
6203 (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6204 "TARGET_SHMEDIA"
6205 "@
6206 #
6207 ld%M1.w %m1, %0"
6208 [(set_attr "type" "*,load_media")
6209 (set (attr "highpart")
6210 (cond [(match_test "sh_contains_memref_p (insn)")
6211 (const_string "user")]
6212 (const_string "ignore")))])
6213
6214 (define_split
6215 [(set (match_operand:DI 0 "register_operand" "")
6216 (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
6217 "TARGET_SHMEDIA && reload_completed"
6218 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
6219 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
6220 {
6221 if (GET_CODE (operands[1]) == TRUNCATE)
6222 operands[1] = XEXP (operands[1], 0);
6223 })
6224
6225 (define_insn "extendqidi2"
6226 [(set (match_operand:DI 0 "register_operand" "=r,r")
6227 (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6228 "TARGET_SHMEDIA"
6229 "@
6230 #
6231 ld%M1.b %m1, %0"
6232 [(set_attr "type" "*,load_media")
6233 (set (attr "highpart")
6234 (cond [(match_test "sh_contains_memref_p (insn)")
6235 (const_string "user")]
6236 (const_string "ignore")))])
6237
6238 (define_split
6239 [(set (match_operand:DI 0 "register_operand" "")
6240 (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
6241 "TARGET_SHMEDIA && reload_completed"
6242 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
6243 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
6244 {
6245 if (GET_CODE (operands[1]) == TRUNCATE)
6246 operands[1] = XEXP (operands[1], 0);
6247 })
6248
6249 (define_expand "extend<mode>si2"
6250 [(set (match_operand:SI 0 "arith_reg_dest")
6251 (sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))])
6252
6253 (define_insn "*extendhisi2_media"
6254 [(set (match_operand:SI 0 "register_operand" "=r,r")
6255 (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6256 "TARGET_SHMEDIA"
6257 "@
6258 #
6259 ld%M1.w %m1, %0"
6260 [(set_attr "type" "arith_media,load_media")
6261 (set (attr "highpart")
6262 (cond [(match_test "sh_contains_memref_p (insn)")
6263 (const_string "user")]
6264 (const_string "ignore")))])
6265
6266 (define_split
6267 [(set (match_operand:SI 0 "register_operand" "")
6268 (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6269 "TARGET_SHMEDIA && reload_completed"
6270 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6271 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
6272 {
6273 rtx op1 = operands[1];
6274 if (GET_CODE (op1) == TRUNCATE)
6275 op1 = XEXP (op1, 0);
6276 operands[2]
6277 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6278 subreg_lowpart_offset (SImode, GET_MODE (op1)));
6279 })
6280
6281 (define_insn_and_split "*extend<mode>si2_compact_reg"
6282 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6283 (sign_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
6284 "TARGET_SH1"
6285 "exts.<bw> %1,%0"
6286 "&& can_create_pseudo_p ()"
6287 [(set (match_dup 0) (match_dup 2))]
6288 {
6289 /* Sometimes combine fails to combine a T bit or negated T bit store to a
6290 reg with a following sign extension. In the split pass after combine,
6291 try to figure the extended reg was set. If it originated from the T
6292 bit we can replace the sign extension with a reg move, which will be
6293 eliminated. */
6294 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
6295 if (operands[2] == NULL_RTX)
6296 FAIL;
6297 }
6298 [(set_attr "type" "arith")])
6299
6300 ;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute.
6301 ;; See movqi insns.
6302 (define_insn "*extend<mode>si2_compact_mem_disp"
6303 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
6304 (sign_extend:SI
6305 (mem:QIHI
6306 (plus:SI
6307 (match_operand:SI 1 "arith_reg_operand" "%r,r")
6308 (match_operand:SI 2 "const_int_operand" "<disp04>,N")))))]
6309 "TARGET_SH1 && ! TARGET_SH2A
6310 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
6311 "@
6312 mov.<bw> @(%O2,%1),%0
6313 mov.<bw> @%1,%0"
6314 [(set_attr "type" "load")])
6315
6316 (define_insn "*extend<mode>si2_compact_mem_disp"
6317 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
6318 (sign_extend:SI
6319 (mem:QIHI
6320 (plus:SI
6321 (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6322 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>")))))]
6323 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
6324 "@
6325 mov.<bw> @(%O2,%1),%0
6326 mov.<bw> @%1,%0
6327 mov.<bw> @(%O2,%1),%0"
6328 [(set_attr "type" "load")
6329 (set_attr "length" "2,2,4")])
6330
6331 ;; The *_snd patterns will take care of other QImode/HImode addressing
6332 ;; modes than displacement addressing. They must be defined _after_ the
6333 ;; displacement addressing patterns. Otherwise the displacement addressing
6334 ;; patterns will not be picked.
6335 (define_insn "*extend<mode>si2_compact_snd"
6336 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6337 (sign_extend:SI
6338 (match_operand:QIHI 1 "movsrc_no_disp_mem_operand" "Snd")))]
6339 "TARGET_SH1"
6340 "mov.<bw> %1,%0"
6341 [(set_attr "type" "load")])
6342
6343 (define_insn "*extendqisi2_media"
6344 [(set (match_operand:SI 0 "register_operand" "=r,r")
6345 (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6346 "TARGET_SHMEDIA"
6347 "@
6348 #
6349 ld%M1.b %m1, %0"
6350 [(set_attr "type" "arith_media,load_media")
6351 (set (attr "highpart")
6352 (cond [(match_test "sh_contains_memref_p (insn)")
6353 (const_string "user")]
6354 (const_string "ignore")))])
6355
6356 (define_split
6357 [(set (match_operand:SI 0 "register_operand" "")
6358 (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
6359 "TARGET_SHMEDIA && reload_completed"
6360 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
6361 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
6362 {
6363 rtx op1 = operands[1];
6364 if (GET_CODE (op1) == TRUNCATE)
6365 op1 = XEXP (op1, 0);
6366 operands[2]
6367 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6368 subreg_lowpart_offset (SImode, GET_MODE (op1)));
6369 })
6370
6371 (define_expand "extendqihi2"
6372 [(set (match_operand:HI 0 "arith_reg_dest" "")
6373 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "")))]
6374 ""
6375 "")
6376
6377 (define_insn "*extendqihi2_compact_reg"
6378 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6379 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6380 "TARGET_SH1"
6381 "exts.b %1,%0"
6382 [(set_attr "type" "arith")])
6383
6384 ;; It would seem useful to combine the truncXi patterns into the movXi
6385 ;; patterns, but unary operators are ignored when matching constraints,
6386 ;; so we need separate patterns.
6387 (define_insn "truncdisi2"
6388 [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
6389 (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
6390 "TARGET_SHMEDIA"
6391 "@
6392 add.l %1, r63, %0
6393 st%M0.l %m0, %1
6394 fst%M0.s %m0, %T1
6395 fmov.ls %1, %0
6396 fmov.sl %T1, %0
6397 fmov.s %T1, %0"
6398 [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,
6399 fpconv_media,fmove_media")
6400 (set (attr "highpart")
6401 (cond [(match_test "sh_contains_memref_p (insn)")
6402 (const_string "user")]
6403 (const_string "extend")))])
6404
6405 (define_insn "truncdihi2"
6406 [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
6407 (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
6408 "TARGET_SHMEDIA"
6409 {
6410 static const char* alt[] =
6411 {
6412 "shlli %1,48,%0" "\n"
6413 " shlri %0,48,%0",
6414
6415 "st%M0.w %m0, %1"
6416 };
6417 return alt[which_alternative];
6418 }
6419 [(set_attr "type" "arith_media,store_media")
6420 (set_attr "length" "8,4")
6421 (set (attr "highpart")
6422 (cond [(match_test "sh_contains_memref_p (insn)")
6423 (const_string "user")]
6424 (const_string "extend")))])
6425
6426 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
6427 ; Because we use zero extension, we can't provide signed QImode compares
6428 ; using a simple compare or conditional branch insn.
6429 (define_insn "truncdiqi2"
6430 [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
6431 (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
6432 "TARGET_SHMEDIA"
6433 "@
6434 andi %1, 255, %0
6435 st%M0.b %m0, %1"
6436 [(set_attr "type" "arith_media,store")
6437 (set (attr "highpart")
6438 (cond [(match_test "sh_contains_memref_p (insn)")
6439 (const_string "user")]
6440 (const_string "extend")))])
6441
6442 ;; -------------------------------------------------------------------------
6443 ;; Move instructions
6444 ;; -------------------------------------------------------------------------
6445
6446 ;; define push and pop so it is easy for sh.c
6447 ;; We can't use push and pop on SHcompact because the stack must always
6448 ;; be 8-byte aligned.
6449 (define_expand "push"
6450 [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
6451 (match_operand:SI 0 "register_operand" "r,l,x"))]
6452 "TARGET_SH1 && ! TARGET_SH5"
6453 "")
6454
6455 (define_expand "pop"
6456 [(set (match_operand:SI 0 "register_operand" "=r,l,x")
6457 (mem:SI (post_inc:SI (reg:SI SP_REG))))]
6458 "TARGET_SH1 && ! TARGET_SH5"
6459 "")
6460
6461 (define_expand "push_e"
6462 [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
6463 (match_operand:SF 0 "" ""))
6464 (use (reg:SI FPSCR_MODES_REG))
6465 (clobber (scratch:SI))])]
6466 "TARGET_SH1 && ! TARGET_SH5"
6467 "")
6468
6469 (define_insn "push_fpul"
6470 [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
6471 "TARGET_SH2E && ! TARGET_SH5"
6472 "sts.l fpul,@-r15"
6473 [(set_attr "type" "fstore")
6474 (set_attr "late_fp_use" "yes")
6475 (set_attr "hit_stack" "yes")])
6476
6477 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
6478 ;; so use that.
6479 (define_expand "push_4"
6480 [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
6481 (match_operand:DF 0 "" ""))
6482 (use (reg:SI FPSCR_MODES_REG))
6483 (clobber (scratch:SI))])]
6484 "TARGET_SH1 && ! TARGET_SH5"
6485 "")
6486
6487 (define_expand "pop_e"
6488 [(parallel [(set (match_operand:SF 0 "" "")
6489 (mem:SF (post_inc:SI (reg:SI SP_REG))))
6490 (use (reg:SI FPSCR_MODES_REG))
6491 (clobber (scratch:SI))])]
6492 "TARGET_SH1 && ! TARGET_SH5"
6493 "")
6494
6495 (define_insn "pop_fpul"
6496 [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
6497 "TARGET_SH2E && ! TARGET_SH5"
6498 "lds.l @r15+,fpul"
6499 [(set_attr "type" "load")
6500 (set_attr "hit_stack" "yes")])
6501
6502 (define_expand "pop_4"
6503 [(parallel [(set (match_operand:DF 0 "" "")
6504 (mem:DF (post_inc:SI (reg:SI SP_REG))))
6505 (use (reg:SI FPSCR_MODES_REG))
6506 (clobber (scratch:SI))])]
6507 "TARGET_SH1 && ! TARGET_SH5"
6508 "")
6509
6510 (define_expand "push_fpscr"
6511 [(const_int 0)]
6512 "TARGET_SH2E"
6513 {
6514 add_reg_note (
6515 emit_insn (
6516 gen_sts_fpscr (
6517 gen_frame_mem (SImode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx)))),
6518 REG_INC, stack_pointer_rtx);
6519 DONE;
6520 })
6521
6522 (define_expand "pop_fpscr"
6523 [(const_int 0)]
6524 "TARGET_SH2E"
6525 {
6526 add_reg_note (
6527 emit_insn (
6528 gen_lds_fpscr (
6529 gen_frame_mem (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx)))),
6530 REG_INC, stack_pointer_rtx);
6531 DONE;
6532 })
6533
6534 ;; The clrt and sett patterns can happen as the result of optimization and
6535 ;; insn expansion.
6536 ;; Comparisons might get simplified to a move of zero or 1 into the T reg.
6537 ;; In this case they might not disappear completely, because the T reg is
6538 ;; a fixed hard reg.
6539 ;; When DImode operations that use the T reg as carry/borrow are split into
6540 ;; individual SImode operations, the T reg is usually cleared before the
6541 ;; first SImode insn.
6542 (define_insn "clrt"
6543 [(set (reg:SI T_REG) (const_int 0))]
6544 "TARGET_SH1"
6545 "clrt"
6546 [(set_attr "type" "mt_group")])
6547
6548 (define_insn "sett"
6549 [(set (reg:SI T_REG) (const_int 1))]
6550 "TARGET_SH1"
6551 "sett"
6552 [(set_attr "type" "mt_group")])
6553
6554 ;; Use the combine pass to transform sequences such as
6555 ;; mov r5,r0
6556 ;; add #1,r0
6557 ;; shll2 r0
6558 ;; mov.l @(r0,r4),r0
6559 ;; into
6560 ;; shll2 r5
6561 ;; add r4,r5
6562 ;; mov.l @(4,r5),r0
6563 ;;
6564 ;; See also PR 39423.
6565 ;; Notice that these patterns have a T_REG clobber, because the shift
6566 ;; sequence that will be split out might clobber the T_REG. Ideally, the
6567 ;; clobber would be added conditionally, depending on the result of
6568 ;; sh_ashlsi_clobbers_t_reg_p. When splitting out the shifts we must go
6569 ;; through the ashlsi3 expander in order to get the right shift insn --
6570 ;; a T_REG clobbering or non-clobbering shift sequence or dynamic shift.
6571 ;; FIXME: Combine never tries this kind of patterns for DImode.
6572 (define_insn_and_split "*movsi_index_disp_load"
6573 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6574 (match_operand:SI 1 "mem_index_disp_operand" "m"))
6575 (clobber (reg:SI T_REG))]
6576 "TARGET_SH1"
6577 "#"
6578 "&& can_create_pseudo_p ()"
6579 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6580 (set (match_dup 0) (match_dup 7))]
6581 {
6582 rtx mem = operands[1];
6583 rtx plus0_rtx = XEXP (mem, 0);
6584 rtx plus1_rtx = XEXP (plus0_rtx, 0);
6585 rtx mult_rtx = XEXP (plus1_rtx, 0);
6586
6587 operands[1] = XEXP (mult_rtx, 0);
6588 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6589 operands[3] = XEXP (plus1_rtx, 1);
6590 operands[4] = XEXP (plus0_rtx, 1);
6591 operands[5] = gen_reg_rtx (SImode);
6592 operands[6] = gen_reg_rtx (SImode);
6593 operands[7] =
6594 replace_equiv_address (mem,
6595 gen_rtx_PLUS (SImode, operands[6], operands[4]));
6596
6597 emit_insn (gen_ashlsi3 (operands[5], operands[1], operands[2]));
6598 })
6599
6600 (define_insn_and_split "*movhi_index_disp_load"
6601 [(set (match_operand:SI 0 "arith_reg_dest")
6602 (SZ_EXTEND:SI (match_operand:HI 1 "mem_index_disp_operand")))
6603 (clobber (reg:SI T_REG))]
6604 "TARGET_SH1"
6605 "#"
6606 "&& can_create_pseudo_p ()"
6607 [(const_int 0)]
6608 {
6609 rtx mem = operands[1];
6610 rtx plus0_rtx = XEXP (mem, 0);
6611 rtx plus1_rtx = XEXP (plus0_rtx, 0);
6612 rtx mult_rtx = XEXP (plus1_rtx, 0);
6613
6614 rtx op_1 = XEXP (mult_rtx, 0);
6615 rtx op_2 = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6616 rtx op_3 = XEXP (plus1_rtx, 1);
6617 rtx op_4 = XEXP (plus0_rtx, 1);
6618 rtx op_5 = gen_reg_rtx (SImode);
6619 rtx op_6 = gen_reg_rtx (SImode);
6620 rtx op_7 = replace_equiv_address (mem, gen_rtx_PLUS (SImode, op_6, op_4));
6621
6622 emit_insn (gen_ashlsi3 (op_5, op_1, op_2));
6623 emit_insn (gen_addsi3 (op_6, op_5, op_3));
6624
6625 if (<CODE> == SIGN_EXTEND)
6626 {
6627 emit_insn (gen_extendhisi2 (operands[0], op_7));
6628 DONE;
6629 }
6630 else if (<CODE> == ZERO_EXTEND)
6631 {
6632 /* On SH2A the movu.w insn can be used for zero extending loads. */
6633 if (TARGET_SH2A)
6634 emit_insn (gen_zero_extendhisi2 (operands[0], op_7));
6635 else
6636 {
6637 emit_insn (gen_extendhisi2 (operands[0], op_7));
6638 emit_insn (gen_zero_extendhisi2 (operands[0],
6639 gen_lowpart (HImode, operands[0])));
6640 }
6641 DONE;
6642 }
6643 else
6644 FAIL;
6645 })
6646
6647 (define_insn_and_split "*mov<mode>_index_disp_store"
6648 [(set (match_operand:HISI 0 "mem_index_disp_operand" "=m")
6649 (match_operand:HISI 1 "arith_reg_operand" "r"))
6650 (clobber (reg:SI T_REG))]
6651 "TARGET_SH1"
6652 "#"
6653 "&& can_create_pseudo_p ()"
6654 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6655 (set (match_dup 7) (match_dup 1))]
6656 {
6657 rtx mem = operands[0];
6658 rtx plus0_rtx = XEXP (mem, 0);
6659 rtx plus1_rtx = XEXP (plus0_rtx, 0);
6660 rtx mult_rtx = XEXP (plus1_rtx, 0);
6661
6662 operands[0] = XEXP (mult_rtx, 0);
6663 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6664 operands[3] = XEXP (plus1_rtx, 1);
6665 operands[4] = XEXP (plus0_rtx, 1);
6666 operands[5] = gen_reg_rtx (SImode);
6667 operands[6] = gen_reg_rtx (SImode);
6668 operands[7] =
6669 replace_equiv_address (mem,
6670 gen_rtx_PLUS (SImode, operands[6], operands[4]));
6671
6672 emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2]));
6673 })
6674
6675 ;; t/r must come after r/r, lest reload will try to reload stuff like
6676 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
6677 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
6678 (define_insn "movsi_i"
6679 [(set (match_operand:SI 0 "general_movdst_operand"
6680 "=r,r,r,r,r,r,m,<,<,x,l,x,l,r")
6681 (match_operand:SI 1 "general_movsrc_operand"
6682 "Q,r,I08,mr,x,l,r,x,l,r,r,>,>,i"))]
6683 "TARGET_SH1
6684 && ! TARGET_SH2E
6685 && ! TARGET_SH2A
6686 && (register_operand (operands[0], SImode)
6687 || register_operand (operands[1], SImode))"
6688 "@
6689 mov.l %1,%0
6690 mov %1,%0
6691 mov %1,%0
6692 mov.l %1,%0
6693 sts %1,%0
6694 sts %1,%0
6695 mov.l %1,%0
6696 sts.l %1,%0
6697 sts.l %1,%0
6698 lds %1,%0
6699 lds %1,%0
6700 lds.l %1,%0
6701 lds.l %1,%0
6702 fake %1,%0"
6703 [(set_attr "type" "pcload_si,move,movi8,load_si,mac_gp,prget,store,mac_mem,
6704 pstore,gp_mac,prset,mem_mac,pload,pcload_si")
6705 (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
6706
6707 ;; t/r must come after r/r, lest reload will try to reload stuff like
6708 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
6709 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
6710 ;; will require a reload.
6711 ;; ??? We can't include f/f because we need the proper FPSCR setting when
6712 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
6713 (define_insn "movsi_ie"
6714 [(set (match_operand:SI 0 "general_movdst_operand"
6715 "=r,r,r,r,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
6716 (match_operand:SI 1 "general_movsrc_operand"
6717 "Q,r,I08,I20,I28,mr,x,l,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
6718 "(TARGET_SH2E || TARGET_SH2A)
6719 && ((register_operand (operands[0], SImode)
6720 && !fpscr_operand (operands[0], SImode))
6721 || (register_operand (operands[1], SImode)
6722 && !fpscr_operand (operands[1], SImode)))"
6723 "@
6724 mov.l %1,%0
6725 mov %1,%0
6726 mov %1,%0
6727 movi20 %1,%0
6728 movi20s %1,%0
6729 mov.l %1,%0
6730 sts %1,%0
6731 sts %1,%0
6732 mov.l %1,%0
6733 sts.l %1,%0
6734 sts.l %1,%0
6735 lds %1,%0
6736 lds %1,%0
6737 lds.l %1,%0
6738 lds.l %1,%0
6739 lds.l %1,%0
6740 sts.l %1,%0
6741 fake %1,%0
6742 lds %1,%0
6743 sts %1,%0
6744 fsts fpul,%0
6745 flds %1,fpul
6746 fmov %1,%0
6747 ! move optimized away"
6748 [(set_attr "type" "pcload_si,move,movi8,move,move,load_si,mac_gp,prget,store,
6749 mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore,
6750 pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
6751 (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
6752 (set_attr_alternative "length"
6753 [(const_int 2)
6754 (const_int 2)
6755 (const_int 2)
6756 (const_int 4)
6757 (const_int 4)
6758 (if_then_else
6759 (match_test "TARGET_SH2A")
6760 (const_int 4) (const_int 2))
6761 (const_int 2)
6762 (const_int 2)
6763 (if_then_else
6764 (match_test "TARGET_SH2A")
6765 (const_int 4) (const_int 2))
6766 (const_int 2)
6767 (const_int 2)
6768 (const_int 2)
6769 (const_int 2)
6770 (const_int 2)
6771 (const_int 2)
6772 (const_int 2)
6773 (const_int 2)
6774 (const_int 2)
6775 (const_int 2)
6776 (const_int 2)
6777 (const_int 2)
6778 (const_int 2)
6779 (const_int 2)
6780 (const_int 0)])])
6781
6782 (define_insn "movsi_i_lowpart"
6783 [(set (strict_low_part
6784 (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
6785 (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,r,i"))]
6786 "TARGET_SH1
6787 && (register_operand (operands[0], SImode)
6788 || register_operand (operands[1], SImode))"
6789 "@
6790 mov.l %1,%0
6791 mov %1,%0
6792 mov %1,%0
6793 mov.l %1,%0
6794 sts %1,%0
6795 sts %1,%0
6796 mov.l %1,%0
6797 fake %1,%0"
6798 [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,store,pcload")])
6799
6800 (define_insn_and_split "load_ra"
6801 [(set (match_operand:SI 0 "general_movdst_operand" "")
6802 (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
6803 "TARGET_SH1"
6804 "#"
6805 "&& ! currently_expanding_to_rtl"
6806 [(set (match_dup 0) (match_dup 1))]
6807 {
6808 if (TARGET_SHCOMPACT && crtl->saves_all_registers)
6809 operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
6810 })
6811
6812 ;; The '?'s in the following constraints may not reflect the time taken
6813 ;; to perform the move. They are there to discourage the use of floating-
6814 ;; point registers for storing integer values.
6815 (define_insn "*movsi_media"
6816 [(set (match_operand:SI 0 "general_movdst_operand"
6817 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
6818 (match_operand:SI 1 "general_movsrc_operand"
6819 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
6820 "TARGET_SHMEDIA_FPU
6821 && (register_operand (operands[0], SImode)
6822 || sh_register_operand (operands[1], SImode)
6823 || GET_CODE (operands[1]) == TRUNCATE)"
6824 "@
6825 add.l %1, r63, %0
6826 movi %1, %0
6827 #
6828 ld%M1.l %m1, %0
6829 st%M0.l %m0, %N1
6830 fld%M1.s %m1, %0
6831 fst%M0.s %m0, %1
6832 fmov.ls %N1, %0
6833 fmov.sl %1, %0
6834 fmov.s %1, %0
6835 ptabs %1, %0
6836 gettr %1, %0
6837 pt %1, %0"
6838 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
6839 fload_media,fstore_media,fload_media,fpconv_media,
6840 fmove_media,ptabs_media,gettr_media,pt_media")
6841 (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
6842 (set (attr "highpart")
6843 (cond [(match_test "sh_contains_memref_p (insn)")
6844 (const_string "user")]
6845 (const_string "ignore")))])
6846
6847 (define_insn "*movsi_media_nofpu"
6848 [(set (match_operand:SI 0 "general_movdst_operand"
6849 "=r,r,r,r,m,*b,r,*b")
6850 (match_operand:SI 1 "general_movsrc_operand"
6851 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
6852 "TARGET_SHMEDIA
6853 && (register_operand (operands[0], SImode)
6854 || sh_register_operand (operands[1], SImode)
6855 || GET_CODE (operands[1]) == TRUNCATE)"
6856 "@
6857 add.l %1, r63, %0
6858 movi %1, %0
6859 #
6860 ld%M1.l %m1, %0
6861 st%M0.l %m0, %N1
6862 ptabs %1, %0
6863 gettr %1, %0
6864 pt %1, %0"
6865 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
6866 ptabs_media,gettr_media,pt_media")
6867 (set_attr "length" "4,4,8,4,4,4,4,12")
6868 (set (attr "highpart")
6869 (cond [(match_test "sh_contains_memref_p (insn)")
6870 (const_string "user")]
6871 (const_string "ignore")))])
6872
6873 (define_expand "movsi_const"
6874 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6875 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6876 (const_int 16)] UNSPEC_EXTRACT_S16)))
6877 (set (match_dup 0)
6878 (ior:SI (ashift:SI (match_dup 0) (const_int 16))
6879 (const:SI (unspec:SI [(match_dup 1)
6880 (const_int 0)] UNSPEC_EXTRACT_U16))))]
6881 "TARGET_SHMEDIA && reload_completed
6882 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6883 {
6884 if (GET_CODE (operands[1]) == LABEL_REF
6885 && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
6886 LABEL_NUSES (XEXP (operands[1], 0)) += 2;
6887 else if (GOTOFF_P (operands[1]))
6888 {
6889 rtx unspec = XEXP (operands[1], 0);
6890
6891 if (! UNSPEC_GOTOFF_P (unspec))
6892 {
6893 unspec = XEXP (unspec, 0);
6894 if (! UNSPEC_GOTOFF_P (unspec))
6895 abort ();
6896 }
6897 if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
6898 && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
6899 LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
6900 }
6901 })
6902
6903 (define_expand "movsi_const_16bit"
6904 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6905 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6906 (const_int 0)] UNSPEC_EXTRACT_S16)))]
6907 "TARGET_SHMEDIA && flag_pic && reload_completed
6908 && GET_CODE (operands[1]) == SYMBOL_REF"
6909 "")
6910
6911 (define_split
6912 [(set (match_operand:SI 0 "arith_reg_dest" "")
6913 (match_operand:SI 1 "immediate_operand" ""))]
6914 "TARGET_SHMEDIA && reload_completed
6915 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6916 [(const_int 0)]
6917 {
6918 rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
6919
6920 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
6921
6922 DONE;
6923 })
6924
6925 (define_split
6926 [(set (match_operand:SI 0 "register_operand" "")
6927 (match_operand:SI 1 "immediate_operand" ""))]
6928 "TARGET_SHMEDIA && reload_completed
6929 && ((CONST_INT_P (operands[1])
6930 && ! satisfies_constraint_I16 (operands[1]))
6931 || GET_CODE (operands[1]) == CONST_DOUBLE)"
6932 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
6933
6934 (define_expand "movsi"
6935 [(set (match_operand:SI 0 "general_movdst_operand" "")
6936 (match_operand:SI 1 "general_movsrc_operand" ""))]
6937 ""
6938 {
6939 prepare_move_operands (operands, SImode);
6940 })
6941
6942 (define_expand "ic_invalidate_line"
6943 [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
6944 (match_dup 1)] UNSPEC_ICACHE)
6945 (clobber (scratch:SI))])]
6946 "TARGET_HARD_SH4 || TARGET_SH5"
6947 {
6948 if (TARGET_SHMEDIA)
6949 {
6950 emit_insn (gen_ic_invalidate_line_media (operands[0]));
6951 DONE;
6952 }
6953 else if (TARGET_SHCOMPACT)
6954 {
6955 operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC);
6956 operands[1] = force_reg (Pmode, operands[1]);
6957 emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
6958 DONE;
6959 }
6960 else if (TARGET_SH4A || TARGET_SH4_300)
6961 {
6962 emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
6963 DONE;
6964 }
6965 operands[0] = force_reg (Pmode, operands[0]);
6966 operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
6967 Pmode)));
6968 })
6969
6970 ;; The address %0 is assumed to be 4-aligned at least. Thus, by ORing
6971 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
6972 ;; the requirement *1*00 for associative address writes. The alignment of
6973 ;; %0 implies that its least significant bit is cleared,
6974 ;; thus we clear the V bit of a matching entry if there is one.
6975 (define_insn "ic_invalidate_line_i"
6976 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
6977 (match_operand:SI 1 "register_operand" "r")]
6978 UNSPEC_ICACHE)
6979 (clobber (match_scratch:SI 2 "=&r"))]
6980 "TARGET_HARD_SH4"
6981 {
6982 return "ocbwb @%0" "\n"
6983 " extu.w %0,%2" "\n"
6984 " or %1,%2" "\n"
6985 " mov.l %0,@%2";
6986 }
6987 [(set_attr "length" "8")
6988 (set_attr "type" "cwb")])
6989
6990 (define_insn "ic_invalidate_line_sh4a"
6991 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
6992 UNSPEC_ICACHE)]
6993 "TARGET_SH4A || TARGET_SH4_300"
6994 {
6995 return "ocbwb @%0" "\n"
6996 " synco" "\n"
6997 " icbi @%0";
6998 }
6999 [(set_attr "length" "16") ;; FIXME: Why 16 and not 6? Looks like typo.
7000 (set_attr "type" "cwb")])
7001
7002 ;; ??? could make arg 0 an offsettable memory operand to allow to save
7003 ;; an add in the code that calculates the address.
7004 (define_insn "ic_invalidate_line_media"
7005 [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
7006 UNSPEC_ICACHE)]
7007 "TARGET_SHMEDIA"
7008 {
7009 return "ocbwb %0,0" "\n"
7010 " synco" "\n"
7011 " icbi %0,0" "\n"
7012 " synci";
7013 }
7014 [(set_attr "length" "16")
7015 (set_attr "type" "invalidate_line_media")])
7016
7017 (define_insn "ic_invalidate_line_compact"
7018 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
7019 (match_operand:SI 1 "register_operand" "r")]
7020 UNSPEC_ICACHE)
7021 (clobber (reg:SI PR_REG))]
7022 "TARGET_SHCOMPACT"
7023 "jsr @%1%#"
7024 [(set_attr "type" "sfunc")
7025 (set_attr "needs_delay_slot" "yes")])
7026
7027 (define_expand "initialize_trampoline"
7028 [(match_operand:SI 0 "" "")
7029 (match_operand:SI 1 "" "")
7030 (match_operand:SI 2 "" "")]
7031 "TARGET_SHCOMPACT"
7032 {
7033 rtx sfun, tramp;
7034
7035 tramp = force_reg (Pmode, operands[0]);
7036 sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline",
7037 SFUNC_STATIC));
7038 emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
7039 emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
7040
7041 emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
7042 DONE;
7043 })
7044
7045 (define_insn "initialize_trampoline_compact"
7046 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
7047 (match_operand:SI 1 "register_operand" "r")
7048 (reg:SI R2_REG) (reg:SI R3_REG)]
7049 UNSPEC_INIT_TRAMP)
7050
7051 (clobber (reg:SI PR_REG))]
7052 "TARGET_SHCOMPACT"
7053 "jsr @%1%#"
7054 [(set_attr "type" "sfunc")
7055 (set_attr "needs_delay_slot" "yes")])
7056
7057 (define_expand "mov<mode>"
7058 [(set (match_operand:QIHI 0 "general_movdst_operand")
7059 (match_operand:QIHI 1 "general_movsrc_operand"))]
7060 ""
7061 {
7062 if (can_create_pseudo_p () && CONST_INT_P (operands[1])
7063 && REG_P (operands[0]) && REGNO (operands[0]) != R0_REG)
7064 {
7065 rtx reg = gen_reg_rtx(SImode);
7066 emit_move_insn (reg, operands[1]);
7067 operands[1] = gen_lowpart (<MODE>mode, reg);
7068 }
7069
7070 prepare_move_operands (operands, <MODE>mode);
7071 })
7072
7073 ;; Specifying the displacement addressing load / store patterns separately
7074 ;; before the generic movqi / movhi pattern allows controlling the order
7075 ;; in which load / store insns are selected in a more fine grained way.
7076 ;; FIXME: The non-SH2A and SH2A variants should be combined by adding
7077 ;; "enabled" attribute as it is done in other targets.
7078 (define_insn "*mov<mode>_store_mem_disp04"
7079 [(set (mem:QIHI
7080 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
7081 (match_operand:SI 1 "const_int_operand" "<disp04>,N")))
7082 (match_operand:QIHI 2 "arith_reg_operand" "z,r"))]
7083 "TARGET_SH1 && sh_legitimate_index_p (<MODE>mode, operands[1], false, true)"
7084 "@
7085 mov.<bw> %2,@(%O1,%0)
7086 mov.<bw> %2,@%0"
7087 [(set_attr "type" "store")])
7088
7089 (define_insn "*mov<mode>_store_mem_disp12"
7090 [(set (mem:QIHI
7091 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
7092 (match_operand:SI 1 "const_int_operand" "<disp12>")))
7093 (match_operand:QIHI 2 "arith_reg_operand" "r"))]
7094 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[1], true, true)"
7095 "mov.<bw> %2,@(%O1,%0)"
7096 [(set_attr "type" "store")
7097 (set_attr "length" "4")])
7098
7099 (define_insn "*mov<mode>_load_mem_disp04"
7100 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r")
7101 (mem:QIHI
7102 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
7103 (match_operand:SI 2 "const_int_operand" "<disp04>,N"))))]
7104 "TARGET_SH1 && ! TARGET_SH2A
7105 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
7106 "@
7107 mov.<bw> @(%O2,%1),%0
7108 mov.<bw> @%1,%0"
7109 [(set_attr "type" "load")])
7110
7111 (define_insn "*mov<mode>_load_mem_disp12"
7112 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r,r")
7113 (mem:QIHI
7114 (plus:SI
7115 (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
7116 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>"))))]
7117 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
7118 "@
7119 mov.<bw> @(%O2,%1),%0
7120 mov.<bw> @%1,%0
7121 mov.<bw> @(%O2,%1),%0"
7122 [(set_attr "type" "load")
7123 (set_attr "length" "2,2,4")])
7124
7125 ;; The order of the constraint alternatives is important here.
7126 ;; Q/r has to come first, otherwise PC relative loads might wrongly get
7127 ;; placed into delay slots. Since there is no QImode PC relative load, the
7128 ;; Q constraint and general_movsrc_operand will reject it for QImode.
7129 ;; The Snd alternatives should come before Sdd in order to avoid a preference
7130 ;; of using r0 als the register operand for addressing modes other than
7131 ;; displacement addressing.
7132 ;; The Sdd alternatives allow only r0 as register operand, even though on
7133 ;; SH2A any register could be allowed by switching to a 32 bit insn.
7134 ;; Generally sticking to the r0 is preferrable, since it generates smaller
7135 ;; code. Obvious r0 reloads can then be eliminated with a peephole on SH2A.
7136 (define_insn "*mov<mode>"
7137 [(set (match_operand:QIHI 0 "general_movdst_operand"
7138 "=r,r,r,Snd,r, Sdd,z, r,l")
7139 (match_operand:QIHI 1 "general_movsrc_operand"
7140 "Q,r,i,r, Snd,z, Sdd,l,r"))]
7141 "TARGET_SH1
7142 && (arith_reg_operand (operands[0], <MODE>mode)
7143 || arith_reg_operand (operands[1], <MODE>mode))"
7144 "@
7145 mov.<bw> %1,%0
7146 mov %1,%0
7147 mov %1,%0
7148 mov.<bw> %1,%0
7149 mov.<bw> %1,%0
7150 mov.<bw> %1,%0
7151 mov.<bw> %1,%0
7152 sts %1,%0
7153 lds %1,%0"
7154 [(set_attr "type" "pcload,move,movi8,store,load,store,load,prget,prset")
7155 (set (attr "length")
7156 (cond [(and (match_operand 0 "displacement_mem_operand")
7157 (not (match_operand 0 "short_displacement_mem_operand")))
7158 (const_int 4)
7159 (and (match_operand 1 "displacement_mem_operand")
7160 (not (match_operand 1 "short_displacement_mem_operand")))
7161 (const_int 4)]
7162 (const_int 2)))])
7163
7164 (define_insn "*movqi_media"
7165 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
7166 (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
7167 "TARGET_SHMEDIA
7168 && (arith_reg_operand (operands[0], QImode)
7169 || extend_reg_or_0_operand (operands[1], QImode))"
7170 "@
7171 add.l %1, r63, %0
7172 movi %1, %0
7173 ld%M1.ub %m1, %0
7174 st%M0.b %m0, %N1"
7175 [(set_attr "type" "arith_media,arith_media,load_media,store_media")
7176 (set (attr "highpart")
7177 (cond [(match_test "sh_contains_memref_p (insn)")
7178 (const_string "user")]
7179 (const_string "ignore")))])
7180
7181 (define_expand "reload_inqi"
7182 [(set (match_operand:SI 2 "" "=&r")
7183 (match_operand:QI 1 "inqhi_operand" ""))
7184 (set (match_operand:QI 0 "arith_reg_operand" "=r")
7185 (truncate:QI (match_dup 3)))]
7186 "TARGET_SHMEDIA"
7187 {
7188 rtx inner = XEXP (operands[1], 0);
7189 int regno = REGNO (inner);
7190
7191 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
7192 operands[1] = gen_rtx_REG (SImode, regno);
7193 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7194 })
7195
7196 (define_insn "*movhi_media"
7197 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m")
7198 (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
7199 "TARGET_SHMEDIA
7200 && (arith_reg_operand (operands[0], HImode)
7201 || arith_reg_or_0_operand (operands[1], HImode))"
7202 "@
7203 add.l %1, r63, %0
7204 movi %1, %0
7205 #
7206 ld%M1.w %m1, %0
7207 st%M0.w %m0, %N1"
7208 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
7209 (set (attr "highpart")
7210 (cond [(match_test "sh_contains_memref_p (insn)")
7211 (const_string "user")]
7212 (const_string "ignore")))])
7213
7214 (define_split
7215 [(set (match_operand:HI 0 "register_operand" "")
7216 (match_operand:HI 1 "immediate_operand" ""))]
7217 "TARGET_SHMEDIA && reload_completed
7218 && ! satisfies_constraint_I16 (operands[1])"
7219 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
7220
7221 (define_expand "reload_inhi"
7222 [(set (match_operand:SI 2 "" "=&r")
7223 (match_operand:HI 1 "inqhi_operand" ""))
7224 (set (match_operand:HI 0 "arith_reg_operand" "=r")
7225 (truncate:HI (match_dup 3)))]
7226 "TARGET_SHMEDIA"
7227 {
7228 rtx inner = XEXP (operands[1], 0);
7229 int regno = REGNO (inner);
7230
7231 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
7232 operands[1] = gen_rtx_REG (SImode, regno);
7233 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7234 })
7235
7236 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
7237 ;; compiled with -m2 -ml -O3 -funroll-loops
7238 (define_insn "*movdi_i"
7239 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
7240 (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
7241 "TARGET_SH1
7242 && (arith_reg_operand (operands[0], DImode)
7243 || arith_reg_operand (operands[1], DImode))"
7244 {
7245 return output_movedouble (insn, operands, DImode);
7246 }
7247 [(set_attr "length" "4")
7248 (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
7249
7250 ;; If the output is a register and the input is memory or a register, we have
7251 ;; to be careful and see which word needs to be loaded first.
7252 (define_split
7253 [(set (match_operand:DI 0 "general_movdst_operand" "")
7254 (match_operand:DI 1 "general_movsrc_operand" ""))]
7255 "TARGET_SH1 && reload_completed"
7256 [(set (match_dup 2) (match_dup 3))
7257 (set (match_dup 4) (match_dup 5))]
7258 {
7259 int regno;
7260
7261 if ((MEM_P (operands[0])
7262 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
7263 || (MEM_P (operands[1])
7264 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7265 FAIL;
7266
7267 switch (GET_CODE (operands[0]))
7268 {
7269 case REG:
7270 regno = REGNO (operands[0]);
7271 break;
7272 case SUBREG:
7273 regno = subreg_regno (operands[0]);
7274 break;
7275 case MEM:
7276 regno = -1;
7277 break;
7278 default:
7279 gcc_unreachable ();
7280 }
7281
7282 if (regno == -1
7283 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
7284 {
7285 operands[2] = operand_subword (operands[0], 0, 0, DImode);
7286 operands[3] = operand_subword (operands[1], 0, 0, DImode);
7287 operands[4] = operand_subword (operands[0], 1, 0, DImode);
7288 operands[5] = operand_subword (operands[1], 1, 0, DImode);
7289 }
7290 else
7291 {
7292 operands[2] = operand_subword (operands[0], 1, 0, DImode);
7293 operands[3] = operand_subword (operands[1], 1, 0, DImode);
7294 operands[4] = operand_subword (operands[0], 0, 0, DImode);
7295 operands[5] = operand_subword (operands[1], 0, 0, DImode);
7296 }
7297
7298 if (operands[2] == 0 || operands[3] == 0
7299 || operands[4] == 0 || operands[5] == 0)
7300 FAIL;
7301 })
7302
7303 ;; The '?'s in the following constraints may not reflect the time taken
7304 ;; to perform the move. They are there to discourage the use of floating-
7305 ;; point registers for storing integer values.
7306 (define_insn "*movdi_media"
7307 [(set (match_operand:DI 0 "general_movdst_operand"
7308 "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
7309 (match_operand:DI 1 "general_movsrc_operand"
7310 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
7311 "TARGET_SHMEDIA_FPU
7312 && (register_operand (operands[0], DImode)
7313 || sh_register_operand (operands[1], DImode))"
7314 "@
7315 add %1, r63, %0
7316 movi %1, %0
7317 #
7318 ld%M1.q %m1, %0
7319 st%M0.q %m0, %N1
7320 fld%M1.d %m1, %0
7321 fst%M0.d %m0, %1
7322 fmov.qd %N1, %0
7323 fmov.dq %1, %0
7324 fmov.d %1, %0
7325 ptabs %1, %0
7326 gettr %1, %0
7327 pt %1, %0"
7328 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7329 fload_media,fstore_media,fload_media,dfpconv_media,
7330 fmove_media,ptabs_media,gettr_media,pt_media")
7331 (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
7332
7333 (define_insn "*movdi_media_nofpu"
7334 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
7335 (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
7336 "TARGET_SHMEDIA
7337 && (register_operand (operands[0], DImode)
7338 || sh_register_operand (operands[1], DImode))"
7339 "@
7340 add %1, r63, %0
7341 movi %1, %0
7342 #
7343 ld%M1.q %m1, %0
7344 st%M0.q %m0, %N1
7345 ptabs %1, %0
7346 gettr %1, %0
7347 pt %1, %0"
7348 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7349 ptabs_media,gettr_media,pt_media")
7350 (set_attr "length" "4,4,16,4,4,4,4,*")])
7351
7352 (define_insn "*movdi_media_I16"
7353 [(set (match_operand:DI 0 "ext_dest_operand" "=r")
7354 (match_operand:DI 1 "const_int_operand" "I16"))]
7355 "TARGET_SHMEDIA && reload_completed"
7356 "movi %1, %0"
7357 [(set_attr "type" "arith_media")
7358 (set_attr "length" "4")])
7359
7360 (define_split
7361 [(set (match_operand:DI 0 "arith_reg_dest" "")
7362 (match_operand:DI 1 "immediate_operand" ""))]
7363 "TARGET_SHMEDIA && reload_completed
7364 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7365 [(set (match_dup 0) (match_dup 1))]
7366 {
7367 rtx insn;
7368
7369 if (TARGET_SHMEDIA64)
7370 insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
7371 else
7372 insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
7373
7374 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
7375
7376 DONE;
7377 })
7378
7379 (define_expand "movdi_const"
7380 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7381 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7382 (const_int 48)] UNSPEC_EXTRACT_S16)))
7383 (set (match_dup 0)
7384 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7385 (const:DI (unspec:DI [(match_dup 1)
7386 (const_int 32)] UNSPEC_EXTRACT_U16))))
7387 (set (match_dup 0)
7388 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7389 (const:DI (unspec:DI [(match_dup 1)
7390 (const_int 16)] UNSPEC_EXTRACT_U16))))
7391 (set (match_dup 0)
7392 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7393 (const:DI (unspec:DI [(match_dup 1)
7394 (const_int 0)] UNSPEC_EXTRACT_U16))))]
7395 "TARGET_SHMEDIA64 && reload_completed
7396 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7397 {
7398 sh_mark_label (operands[1], 4);
7399 })
7400
7401 (define_expand "movdi_const_32bit"
7402 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7403 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7404 (const_int 16)] UNSPEC_EXTRACT_S16)))
7405 (set (match_dup 0)
7406 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7407 (const:DI (unspec:DI [(match_dup 1)
7408 (const_int 0)] UNSPEC_EXTRACT_U16))))]
7409 "TARGET_SHMEDIA32 && reload_completed
7410 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7411 {
7412 sh_mark_label (operands[1], 2);
7413 })
7414
7415 (define_expand "movdi_const_16bit"
7416 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7417 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7418 (const_int 0)] UNSPEC_EXTRACT_S16)))]
7419 "TARGET_SHMEDIA && flag_pic && reload_completed
7420 && GET_CODE (operands[1]) == SYMBOL_REF"
7421 "")
7422
7423 (define_split
7424 [(set (match_operand:DI 0 "ext_dest_operand" "")
7425 (match_operand:DI 1 "immediate_operand" ""))]
7426 "TARGET_SHMEDIA && reload_completed
7427 && CONST_INT_P (operands[1])
7428 && ! satisfies_constraint_I16 (operands[1])"
7429 [(set (match_dup 0) (match_dup 2))
7430 (match_dup 1)]
7431 {
7432 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
7433 unsigned HOST_WIDE_INT low = val;
7434 unsigned HOST_WIDE_INT high = val;
7435 unsigned HOST_WIDE_INT sign;
7436 unsigned HOST_WIDE_INT val2 = val ^ (val-1);
7437
7438 /* Zero-extend the 16 least-significant bits. */
7439 low &= 0xffff;
7440
7441 /* Arithmetic shift right the word by 16 bits. */
7442 high >>= 16;
7443 if (GET_CODE (operands[0]) == SUBREG
7444 && GET_MODE (SUBREG_REG (operands[0])) == SImode)
7445 {
7446 high &= 0xffff;
7447 high ^= 0x8000;
7448 high -= 0x8000;
7449 }
7450 else
7451 {
7452 sign = 1;
7453 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7454 high ^= sign;
7455 high -= sign;
7456 }
7457 do
7458 {
7459 /* If we can't generate the constant with a two-insn movi / shori
7460 sequence, try some other strategies. */
7461 if (! CONST_OK_FOR_I16 (high))
7462 {
7463 /* Try constant load / left shift. We know VAL != 0. */
7464 val2 = val ^ (val-1);
7465 if (val2 > 0x1ffff)
7466 {
7467 int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
7468
7469 if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
7470 || (! CONST_OK_FOR_I16 (high >> 16)
7471 && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
7472 {
7473 val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
7474 operands[1] = gen_ashldi3_media (operands[0], operands[0],
7475 GEN_INT (trailing_zeroes));
7476 break;
7477 }
7478 }
7479 /* Try constant load / right shift. */
7480 val2 = (val >> 15) + 1;
7481 if (val2 == (val2 & -val2))
7482 {
7483 int shift = 49 - exact_log2 (val2);
7484
7485 val2 = trunc_int_for_mode (val << shift, DImode);
7486 if (CONST_OK_FOR_I16 (val2))
7487 {
7488 operands[1] = gen_lshrdi3_media (operands[0], operands[0],
7489 GEN_INT (shift));
7490 break;
7491 }
7492 }
7493 /* Try mperm.w . */
7494 val2 = val & 0xffff;
7495 if ((val >> 16 & 0xffff) == val2
7496 && (val >> 32 & 0xffff) == val2
7497 && (val >> 48 & 0xffff) == val2)
7498 {
7499 val2 = (HOST_WIDE_INT) val >> 48;
7500 operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
7501 operands[1] = gen_mperm_w0 (operands[1], operands[1]);
7502 break;
7503 }
7504 /* Try movi / mshflo.l */
7505 val2 = (HOST_WIDE_INT) val >> 32;
7506 if (val2 == ((unsigned HOST_WIDE_INT)
7507 trunc_int_for_mode (val, SImode)))
7508 {
7509 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7510 operands[0]);
7511 break;
7512 }
7513 /* Try movi / mshflo.l w/ r63. */
7514 val2 = val + ((HOST_WIDE_INT) -1 << 32);
7515 if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
7516 {
7517 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7518 const0_rtx);
7519 break;
7520 }
7521 }
7522 val2 = high;
7523 operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
7524 }
7525 while (0);
7526 operands[2] = GEN_INT (val2);
7527 })
7528
7529 (define_split
7530 [(set (match_operand:DI 0 "ext_dest_operand" "")
7531 (match_operand:DI 1 "immediate_operand" ""))]
7532 "TARGET_SHMEDIA && reload_completed
7533 && GET_CODE (operands[1]) == CONST_DOUBLE"
7534 [(set (match_dup 0) (match_dup 2))
7535 (set (match_dup 0)
7536 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
7537 {
7538 unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
7539 unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
7540 unsigned HOST_WIDE_INT val = low;
7541 unsigned HOST_WIDE_INT sign;
7542
7543 /* Zero-extend the 16 least-significant bits. */
7544 val &= 0xffff;
7545 operands[1] = GEN_INT (val);
7546
7547 /* Arithmetic shift right the double-word by 16 bits. */
7548 low >>= 16;
7549 low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
7550 high >>= 16;
7551 sign = 1;
7552 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7553 high ^= sign;
7554 high -= sign;
7555
7556 /* This will only be true if high is a sign-extension of low, i.e.,
7557 it must be either 0 or (unsigned)-1, and be zero iff the
7558 most-significant bit of low is set. */
7559 if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
7560 operands[2] = GEN_INT (low);
7561 else
7562 operands[2] = immed_double_const (low, high, DImode);
7563 })
7564
7565 (define_insn "shori_media"
7566 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
7567 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
7568 (const_int 16))
7569 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
7570 "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
7571 "@
7572 shori %u2, %0
7573 #"
7574 [(set_attr "type" "arith_media,*")])
7575
7576 (define_insn "*shori_media_si"
7577 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
7578 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
7579 (const_int 16))
7580 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
7581 "TARGET_SHMEDIA"
7582 "shori %u2, %0")
7583
7584 (define_expand "movdi"
7585 [(set (match_operand:DI 0 "general_movdst_operand" "")
7586 (match_operand:DI 1 "general_movsrc_operand" ""))]
7587 ""
7588 {
7589 prepare_move_operands (operands, DImode);
7590 })
7591
7592 (define_insn "movdf_media"
7593 [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
7594 (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
7595 "TARGET_SHMEDIA_FPU
7596 && (register_operand (operands[0], DFmode)
7597 || sh_register_operand (operands[1], DFmode))"
7598 "@
7599 fmov.d %1, %0
7600 fmov.qd %N1, %0
7601 fmov.dq %1, %0
7602 add %1, r63, %0
7603 #
7604 fld%M1.d %m1, %0
7605 fst%M0.d %m0, %1
7606 ld%M1.q %m1, %0
7607 st%M0.q %m0, %N1"
7608 [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,
7609 fload_media,fstore_media,load_media,store_media")])
7610
7611 (define_insn "movdf_media_nofpu"
7612 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7613 (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
7614 "TARGET_SHMEDIA
7615 && (register_operand (operands[0], DFmode)
7616 || sh_register_operand (operands[1], DFmode))"
7617 "@
7618 add %1, r63, %0
7619 #
7620 ld%M1.q %m1, %0
7621 st%M0.q %m0, %N1"
7622 [(set_attr "type" "arith_media,*,load_media,store_media")])
7623
7624 (define_split
7625 [(set (match_operand:DF 0 "arith_reg_dest" "")
7626 (match_operand:DF 1 "immediate_operand" ""))]
7627 "TARGET_SHMEDIA && reload_completed"
7628 [(set (match_dup 3) (match_dup 2))]
7629 {
7630 int endian = WORDS_BIG_ENDIAN ? 1 : 0;
7631 long values[2];
7632 REAL_VALUE_TYPE value;
7633
7634 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
7635 REAL_VALUE_TO_TARGET_DOUBLE (value, values);
7636
7637 if (HOST_BITS_PER_WIDE_INT >= 64)
7638 operands[2] = immed_double_const ((unsigned long) values[endian]
7639 | ((HOST_WIDE_INT) values[1 - endian]
7640 << 32), 0, DImode);
7641 else
7642 {
7643 gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
7644 operands[2] = immed_double_const (values[endian], values[1 - endian],
7645 DImode);
7646 }
7647
7648 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
7649 })
7650
7651 ;; FIXME: This should be a define_insn_and_split.
7652 (define_insn "movdf_k"
7653 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7654 (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
7655 "TARGET_SH1
7656 && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
7657 /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
7658 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
7659 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
7660 && (arith_reg_operand (operands[0], DFmode)
7661 || arith_reg_operand (operands[1], DFmode))"
7662 {
7663 return output_movedouble (insn, operands, DFmode);
7664 }
7665 [(set_attr "length" "4")
7666 (set_attr "type" "move,pcload,load,store")])
7667
7668 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
7669 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
7670 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
7671 ;; the d/m/c/X alternative, which is split later into single-precision
7672 ;; instructions. And when not optimizing, no splits are done before fixing
7673 ;; up pcloads, so we need usable length information for that.
7674 (define_insn "movdf_i4"
7675 [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
7676 (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
7677 (use (reg:SI FPSCR_MODES_REG))
7678 (clobber (match_scratch:SI 2 "=X,X,&z,X,X,X,X,X,X,X"))]
7679 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
7680 && (arith_reg_operand (operands[0], DFmode)
7681 || arith_reg_operand (operands[1], DFmode))"
7682 {
7683 switch (which_alternative)
7684 {
7685 case 0:
7686 if (TARGET_FMOVD)
7687 return "fmov %1,%0";
7688 else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
7689 return "fmov %R1,%R0" "\n"
7690 " fmov %S1,%S0";
7691 else
7692 return "fmov %S1,%S0" "\n"
7693 " fmov %R1,%R0";
7694 case 3:
7695 case 4:
7696 return "fmov.d %1,%0";
7697 default:
7698 return "#";
7699 }
7700 }
7701 [(set_attr_alternative "length"
7702 [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
7703 (const_int 4)
7704 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7705 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7706 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7707 (const_int 4)
7708 (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
7709 ;; We can't use 4-byte push/pop on SHcompact, so we have to
7710 ;; increment or decrement r15 explicitly.
7711 (if_then_else
7712 (match_test "TARGET_SHCOMPACT")
7713 (const_int 10) (const_int 8))
7714 (if_then_else
7715 (match_test "TARGET_SHCOMPACT")
7716 (const_int 10) (const_int 8))])
7717 (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
7718 (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
7719 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
7720 (const_string "double")
7721 (const_string "none")))])
7722
7723 ;; Moving DFmode between fp/general registers through memory
7724 ;; (the top of the stack) is faster than moving through fpul even for
7725 ;; little endian. Because the type of an instruction is important for its
7726 ;; scheduling, it is beneficial to split these operations, rather than
7727 ;; emitting them in one single chunk, even if this will expose a stack
7728 ;; use that will prevent scheduling of other stack accesses beyond this
7729 ;; instruction.
7730 (define_split
7731 [(set (match_operand:DF 0 "register_operand")
7732 (match_operand:DF 1 "register_operand"))
7733 (use (reg:SI FPSCR_MODES_REG))
7734 (clobber (match_scratch:SI 2))]
7735 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
7736 && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
7737 [(const_int 0)]
7738 {
7739 rtx insn, tos;
7740
7741 if (TARGET_SH5 && true_regnum (operands[1]) < 16)
7742 {
7743 emit_move_insn (stack_pointer_rtx,
7744 plus_constant (Pmode, stack_pointer_rtx, -8));
7745 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
7746 }
7747 else
7748 tos = gen_tmp_stack_mem (DFmode,
7749 gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
7750 insn = emit_insn (gen_movdf_i4 (tos, operands[1]));
7751 if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
7752 add_reg_note (insn, REG_INC, stack_pointer_rtx);
7753 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
7754 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
7755 else
7756 tos = gen_tmp_stack_mem (DFmode,
7757 gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
7758 insn = emit_insn (gen_movdf_i4 (operands[0], tos));
7759 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
7760 emit_move_insn (stack_pointer_rtx,
7761 plus_constant (Pmode, stack_pointer_rtx, 8));
7762 else
7763 add_reg_note (insn, REG_INC, stack_pointer_rtx);
7764 DONE;
7765 })
7766
7767 ;; local-alloc sometimes allocates scratch registers even when not required,
7768 ;; so we must be prepared to handle these.
7769
7770 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
7771 (define_split
7772 [(set (match_operand:DF 0 "general_movdst_operand" "")
7773 (match_operand:DF 1 "general_movsrc_operand" ""))
7774 (use (reg:SI FPSCR_MODES_REG))
7775 (clobber (match_scratch:SI 2))]
7776 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
7777 && reload_completed
7778 && true_regnum (operands[0]) < 16
7779 && true_regnum (operands[1]) < 16"
7780 [(set (match_dup 0) (match_dup 1))]
7781 {
7782 /* If this was a reg <-> mem operation with base + index reg addressing,
7783 we have to handle this in a special way. */
7784 rtx mem = operands[0];
7785 int store_p = 1;
7786 if (! memory_operand (mem, DFmode))
7787 {
7788 mem = operands[1];
7789 store_p = 0;
7790 }
7791 if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
7792 mem = SUBREG_REG (mem);
7793 if (MEM_P (mem))
7794 {
7795 rtx addr = XEXP (mem, 0);
7796 if (GET_CODE (addr) == PLUS
7797 && REG_P (XEXP (addr, 0))
7798 && REG_P (XEXP (addr, 1)))
7799 {
7800 int offset;
7801 rtx reg0 = gen_rtx_REG (Pmode, 0);
7802 rtx regop = operands[store_p], word0 ,word1;
7803
7804 if (GET_CODE (regop) == SUBREG)
7805 alter_subreg (&regop, true);
7806 if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
7807 offset = 2;
7808 else
7809 offset = 4;
7810 mem = copy_rtx (mem);
7811 PUT_MODE (mem, SImode);
7812 word0 = gen_rtx_SUBREG (SImode, regop, 0);
7813 alter_subreg (&word0, true);
7814 word1 = gen_rtx_SUBREG (SImode, regop, 4);
7815 alter_subreg (&word1, true);
7816 if (store_p || ! refers_to_regno_p (REGNO (word0),
7817 REGNO (word0) + 1, addr, 0))
7818 {
7819 emit_insn (store_p
7820 ? gen_movsi_ie (mem, word0)
7821 : gen_movsi_ie (word0, mem));
7822 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7823 mem = copy_rtx (mem);
7824 emit_insn (store_p
7825 ? gen_movsi_ie (mem, word1)
7826 : gen_movsi_ie (word1, mem));
7827 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7828 }
7829 else
7830 {
7831 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7832 emit_insn (gen_movsi_ie (word1, mem));
7833 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7834 mem = copy_rtx (mem);
7835 emit_insn (gen_movsi_ie (word0, mem));
7836 }
7837 DONE;
7838 }
7839 }
7840 })
7841
7842 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
7843 (define_split
7844 [(set (match_operand:DF 0 "register_operand" "")
7845 (match_operand:DF 1 "memory_operand" ""))
7846 (use (reg:SI FPSCR_MODES_REG))
7847 (clobber (reg:SI R0_REG))]
7848 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
7849 [(parallel [(set (match_dup 0) (match_dup 1))
7850 (use (reg:SI FPSCR_MODES_REG))
7851 (clobber (scratch:SI))])]
7852 "")
7853
7854 (define_expand "reload_indf__frn"
7855 [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
7856 (match_operand:DF 1 "immediate_operand" "FQ"))
7857 (use (reg:SI FPSCR_MODES_REG))
7858 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
7859 "TARGET_SH1"
7860 "")
7861
7862 (define_expand "reload_outdf__RnFRm"
7863 [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
7864 (match_operand:DF 1 "register_operand" "af,r"))
7865 (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
7866 "TARGET_SH1"
7867 "")
7868
7869 ;; Simplify no-op moves.
7870 (define_split
7871 [(set (match_operand:SF 0 "register_operand" "")
7872 (match_operand:SF 1 "register_operand" ""))
7873 (use (reg:SI FPSCR_MODES_REG))
7874 (clobber (match_scratch:SI 2))]
7875 "TARGET_SH2E && reload_completed
7876 && true_regnum (operands[0]) == true_regnum (operands[1])"
7877 [(set (match_dup 0) (match_dup 0))]
7878 "")
7879
7880 ;; fmovd substitute post-reload splits
7881 (define_split
7882 [(set (match_operand:DF 0 "register_operand" "")
7883 (match_operand:DF 1 "register_operand" ""))
7884 (use (reg:SI FPSCR_MODES_REG))
7885 (clobber (match_scratch:SI 2))]
7886 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
7887 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7888 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
7889 [(const_int 0)]
7890 {
7891 int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
7892 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
7893 gen_rtx_REG (SFmode, src)));
7894 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
7895 gen_rtx_REG (SFmode, src + 1)));
7896 DONE;
7897 })
7898
7899 (define_split
7900 [(set (match_operand:DF 0 "register_operand" "")
7901 (mem:DF (match_operand:SI 1 "register_operand" "")))
7902 (use (reg:SI FPSCR_MODES_REG))
7903 (clobber (match_scratch:SI 2))]
7904 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7905 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7906 && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
7907 [(const_int 0)]
7908 {
7909 int regno = true_regnum (operands[0]);
7910 rtx insn;
7911 rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
7912 rtx mem2
7913 = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
7914 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
7915 regno + SH_REG_MSW_OFFSET),
7916 mem2));
7917 add_reg_note (insn, REG_INC, operands[1]);
7918 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
7919 regno + SH_REG_LSW_OFFSET),
7920 change_address (mem, SFmode, NULL_RTX)));
7921 DONE;
7922 })
7923
7924 (define_split
7925 [(set (match_operand:DF 0 "register_operand" "")
7926 (match_operand:DF 1 "memory_operand" ""))
7927 (use (reg:SI FPSCR_MODES_REG))
7928 (clobber (match_scratch:SI 2))]
7929 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7930 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
7931 [(const_int 0)]
7932 {
7933 int regno = true_regnum (operands[0]);
7934 rtx addr, insn;
7935 rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
7936 rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
7937 rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
7938
7939 operands[1] = copy_rtx (mem2);
7940 addr = XEXP (mem2, 0);
7941
7942 switch (GET_CODE (addr))
7943 {
7944 case REG:
7945 /* This is complicated. If the register is an arithmetic register
7946 we can just fall through to the REG+DISP case below. Otherwise
7947 we have to use a combination of POST_INC and REG addressing... */
7948 if (! arith_reg_operand (operands[1], SFmode))
7949 {
7950 XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
7951 insn = emit_insn (gen_movsf_ie (reg0, mem2));
7952 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7953
7954 emit_insn (gen_movsf_ie (reg1, operands[1]));
7955
7956 /* If we have modified the stack pointer, the value that we have
7957 read with post-increment might be modified by an interrupt,
7958 so write it back. */
7959 if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
7960 emit_insn (gen_push_e (reg0));
7961 else
7962 emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0),
7963 GEN_INT (-4)));
7964 break;
7965 }
7966 /* Fall through. */
7967
7968 case PLUS:
7969 emit_insn (gen_movsf_ie (reg0, operands[1]));
7970 operands[1] = copy_rtx (operands[1]);
7971 XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4);
7972 emit_insn (gen_movsf_ie (reg1, operands[1]));
7973 break;
7974
7975 case POST_INC:
7976 insn = emit_insn (gen_movsf_ie (reg0, operands[1]));
7977 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7978
7979 insn = emit_insn (gen_movsf_ie (reg1, operands[1]));
7980 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7981 break;
7982
7983 default:
7984 debug_rtx (addr);
7985 gcc_unreachable ();
7986 }
7987
7988 DONE;
7989 })
7990
7991 (define_split
7992 [(set (match_operand:DF 0 "memory_operand" "")
7993 (match_operand:DF 1 "register_operand" ""))
7994 (use (reg:SI FPSCR_MODES_REG))
7995 (clobber (match_scratch:SI 2))]
7996 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7997 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
7998 [(const_int 0)]
7999 {
8000 int regno = true_regnum (operands[1]);
8001 rtx insn, addr;
8002 rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
8003 rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
8004
8005 operands[0] = copy_rtx (operands[0]);
8006 PUT_MODE (operands[0], SFmode);
8007 addr = XEXP (operands[0], 0);
8008
8009 switch (GET_CODE (addr))
8010 {
8011 case REG:
8012 /* This is complicated. If the register is an arithmetic register
8013 we can just fall through to the REG+DISP case below. Otherwise
8014 we have to use a combination of REG and PRE_DEC addressing... */
8015 if (! arith_reg_operand (operands[0], SFmode))
8016 {
8017 emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
8018 emit_insn (gen_movsf_ie (operands[0], reg1));
8019
8020 operands[0] = copy_rtx (operands[0]);
8021 XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
8022
8023 insn = emit_insn (gen_movsf_ie (operands[0], reg0));
8024 add_reg_note (insn, REG_INC, XEXP (addr, 0));
8025 break;
8026 }
8027 /* Fall through. */
8028
8029 case PLUS:
8030 /* Since REG+DISP addressing has already been decided upon by gcc
8031 we can rely upon it having chosen an arithmetic register as the
8032 register component of the address. Just emit the lower numbered
8033 register first, to the lower address, then the higher numbered
8034 register to the higher address. */
8035 emit_insn (gen_movsf_ie (operands[0], reg0));
8036
8037 operands[0] = copy_rtx (operands[0]);
8038 XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4);
8039
8040 emit_insn (gen_movsf_ie (operands[0], reg1));
8041 break;
8042
8043 case PRE_DEC:
8044 /* This is easy. Output the word to go to the higher address
8045 first (ie the word in the higher numbered register) then the
8046 word to go to the lower address. */
8047
8048 insn = emit_insn (gen_movsf_ie (operands[0], reg1));
8049 add_reg_note (insn, REG_INC, XEXP (addr, 0));
8050
8051 insn = emit_insn (gen_movsf_ie (operands[0], reg0));
8052 add_reg_note (insn, REG_INC, XEXP (addr, 0));
8053 break;
8054
8055 default:
8056 /* FAIL; */
8057 debug_rtx (addr);
8058 gcc_unreachable ();
8059 }
8060
8061 DONE;
8062 })
8063
8064 ;; If the output is a register and the input is memory or a register, we have
8065 ;; to be careful and see which word needs to be loaded first.
8066 (define_split
8067 [(set (match_operand:DF 0 "general_movdst_operand" "")
8068 (match_operand:DF 1 "general_movsrc_operand" ""))]
8069 "TARGET_SH1 && reload_completed"
8070 [(set (match_dup 2) (match_dup 3))
8071 (set (match_dup 4) (match_dup 5))]
8072 {
8073 int regno;
8074
8075 if ((MEM_P (operands[0])
8076 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
8077 || (MEM_P (operands[1])
8078 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
8079 FAIL;
8080
8081 switch (GET_CODE (operands[0]))
8082 {
8083 case REG:
8084 regno = REGNO (operands[0]);
8085 break;
8086 case SUBREG:
8087 regno = subreg_regno (operands[0]);
8088 break;
8089 case MEM:
8090 regno = -1;
8091 break;
8092 default:
8093 gcc_unreachable ();
8094 }
8095
8096 if (regno == -1
8097 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
8098 {
8099 operands[2] = operand_subword (operands[0], 0, 0, DFmode);
8100 operands[3] = operand_subword (operands[1], 0, 0, DFmode);
8101 operands[4] = operand_subword (operands[0], 1, 0, DFmode);
8102 operands[5] = operand_subword (operands[1], 1, 0, DFmode);
8103 }
8104 else
8105 {
8106 operands[2] = operand_subword (operands[0], 1, 0, DFmode);
8107 operands[3] = operand_subword (operands[1], 1, 0, DFmode);
8108 operands[4] = operand_subword (operands[0], 0, 0, DFmode);
8109 operands[5] = operand_subword (operands[1], 0, 0, DFmode);
8110 }
8111
8112 if (operands[2] == 0 || operands[3] == 0
8113 || operands[4] == 0 || operands[5] == 0)
8114 FAIL;
8115 })
8116
8117 (define_expand "movdf"
8118 [(set (match_operand:DF 0 "general_movdst_operand" "")
8119 (match_operand:DF 1 "general_movsrc_operand" ""))]
8120 ""
8121 {
8122 prepare_move_operands (operands, DFmode);
8123 if (TARGET_SHMEDIA)
8124 {
8125 if (TARGET_SHMEDIA_FPU)
8126 emit_insn (gen_movdf_media (operands[0], operands[1]));
8127 else
8128 emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
8129 DONE;
8130 }
8131 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
8132 {
8133 emit_insn (gen_movdf_i4 (operands[0], operands[1]));
8134 DONE;
8135 }
8136 })
8137
8138 ;;This is incompatible with the way gcc uses subregs.
8139 ;;(define_insn "movv2sf_i"
8140 ;; [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
8141 ;; (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
8142 ;; "TARGET_SHMEDIA_FPU
8143 ;; && (fp_arith_reg_operand (operands[0], V2SFmode)
8144 ;; || fp_arith_reg_operand (operands[1], V2SFmode))"
8145 ;; "@
8146 ;; #
8147 ;; fld%M1.p %m1, %0
8148 ;; fst%M0.p %m0, %1"
8149 ;; [(set_attr "type" "*,fload_media,fstore_media")])
8150 (define_insn_and_split "movv2sf_i"
8151 [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
8152 (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
8153 "TARGET_SHMEDIA_FPU"
8154 "#"
8155 "TARGET_SHMEDIA_FPU && reload_completed"
8156 [(set (match_dup 0) (match_dup 1))]
8157 {
8158 operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
8159 operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
8160 })
8161
8162 (define_expand "movv2sf"
8163 [(set (match_operand:V2SF 0 "general_movdst_operand" "")
8164 (match_operand:V2SF 1 "nonimmediate_operand" ""))]
8165 "TARGET_SHMEDIA_FPU"
8166 {
8167 prepare_move_operands (operands, V2SFmode);
8168 })
8169
8170 (define_expand "addv2sf3"
8171 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8172 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8173 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8174 "TARGET_SHMEDIA_FPU"
8175 {
8176 sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
8177 DONE;
8178 })
8179
8180 (define_expand "subv2sf3"
8181 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8182 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8183 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8184 "TARGET_SHMEDIA_FPU"
8185 {
8186 sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
8187 DONE;
8188 })
8189
8190 (define_expand "mulv2sf3"
8191 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8192 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8193 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8194 "TARGET_SHMEDIA_FPU"
8195 {
8196 sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
8197 DONE;
8198 })
8199
8200 (define_expand "divv2sf3"
8201 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8202 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8203 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8204 "TARGET_SHMEDIA_FPU"
8205 {
8206 sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
8207 DONE;
8208 })
8209
8210 (define_insn_and_split "*movv4sf_i"
8211 [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
8212 (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
8213 "TARGET_SHMEDIA_FPU"
8214 "#"
8215 "&& reload_completed"
8216 [(const_int 0)]
8217 {
8218 for (int i = 0; i < 4/2; i++)
8219 {
8220 rtx x, y;
8221
8222 if (MEM_P (operands[0]))
8223 x = adjust_address (operands[0], V2SFmode,
8224 i * GET_MODE_SIZE (V2SFmode));
8225 else
8226 x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
8227
8228 if (MEM_P (operands[1]))
8229 y = adjust_address (operands[1], V2SFmode,
8230 i * GET_MODE_SIZE (V2SFmode));
8231 else
8232 y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
8233
8234 emit_insn (gen_movv2sf_i (x, y));
8235 }
8236
8237 DONE;
8238 }
8239 [(set_attr "length" "8")])
8240
8241 (define_expand "movv4sf"
8242 [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
8243 (match_operand:V4SF 1 "general_operand" ""))]
8244 "TARGET_SHMEDIA_FPU"
8245 {
8246 prepare_move_operands (operands, V4SFmode);
8247 })
8248
8249 (define_insn_and_split "*movv16sf_i"
8250 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8251 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8252 "TARGET_SHMEDIA_FPU"
8253 "#"
8254 "&& reload_completed"
8255 [(const_int 0)]
8256 {
8257 for (int i = 0; i < 16/2; i++)
8258 {
8259 rtx x, y;
8260
8261 if (MEM_P (operands[0]))
8262 x = adjust_address (operands[0], V2SFmode,
8263 i * GET_MODE_SIZE (V2SFmode));
8264 else
8265 {
8266 x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
8267 alter_subreg (&x, true);
8268 }
8269
8270 if (MEM_P (operands[1]))
8271 y = adjust_address (operands[1], V2SFmode,
8272 i * GET_MODE_SIZE (V2SFmode));
8273 else
8274 {
8275 y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
8276 alter_subreg (&y, true);
8277 }
8278
8279 emit_insn (gen_movv2sf_i (x, y));
8280 }
8281
8282 DONE;
8283 }
8284 [(set_attr "length" "32")])
8285
8286 (define_expand "movv16sf"
8287 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8288 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8289 "TARGET_SHMEDIA_FPU"
8290 {
8291 prepare_move_operands (operands, V16SFmode);
8292 })
8293
8294 (define_insn "movsf_media"
8295 [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
8296 (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
8297 "TARGET_SHMEDIA_FPU
8298 && (register_operand (operands[0], SFmode)
8299 || sh_register_operand (operands[1], SFmode))"
8300 "@
8301 fmov.s %1, %0
8302 fmov.ls %N1, %0
8303 fmov.sl %1, %0
8304 add.l %1, r63, %0
8305 #
8306 fld%M1.s %m1, %0
8307 fst%M0.s %m0, %1
8308 ld%M1.l %m1, %0
8309 st%M0.l %m0, %N1"
8310 [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
8311 (set (attr "highpart")
8312 (cond [(match_test "sh_contains_memref_p (insn)")
8313 (const_string "user")]
8314 (const_string "ignore")))])
8315
8316 (define_insn "movsf_media_nofpu"
8317 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
8318 (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
8319 "TARGET_SHMEDIA
8320 && (register_operand (operands[0], SFmode)
8321 || sh_register_operand (operands[1], SFmode))"
8322 "@
8323 add.l %1, r63, %0
8324 #
8325 ld%M1.l %m1, %0
8326 st%M0.l %m0, %N1"
8327 [(set_attr "type" "arith_media,*,load_media,store_media")
8328 (set (attr "highpart")
8329 (cond [(match_test "sh_contains_memref_p (insn)")
8330 (const_string "user")]
8331 (const_string "ignore")))])
8332
8333 (define_split
8334 [(set (match_operand:SF 0 "arith_reg_dest" "")
8335 (match_operand:SF 1 "immediate_operand" ""))]
8336 "TARGET_SHMEDIA && reload_completed
8337 && ! FP_REGISTER_P (true_regnum (operands[0]))"
8338 [(set (match_dup 3) (match_dup 2))]
8339 {
8340 long values;
8341 REAL_VALUE_TYPE value;
8342
8343 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
8344 REAL_VALUE_TO_TARGET_SINGLE (value, values);
8345 operands[2] = GEN_INT (values);
8346
8347 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
8348 })
8349
8350 (define_insn "movsf_i"
8351 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
8352 (match_operand:SF 1 "general_movsrc_operand" "r,G,FQ,mr,r,r,l"))]
8353 "TARGET_SH1
8354 && (! TARGET_SH2E
8355 /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
8356 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
8357 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
8358 && (arith_reg_operand (operands[0], SFmode)
8359 || arith_reg_operand (operands[1], SFmode))"
8360 "@
8361 mov %1,%0
8362 mov #0,%0
8363 mov.l %1,%0
8364 mov.l %1,%0
8365 mov.l %1,%0
8366 lds %1,%0
8367 sts %1,%0"
8368 [(set_attr "type" "move,move,pcload,load,store,move,move")])
8369
8370 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
8371 ;; update_flow_info would not know where to put REG_EQUAL notes
8372 ;; when the destination changes mode.
8373 (define_insn "movsf_ie"
8374 [(set (match_operand:SF 0 "general_movdst_operand"
8375 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
8376 (match_operand:SF 1 "general_movsrc_operand"
8377 "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
8378 (use (reg:SI FPSCR_MODES_REG))
8379 (clobber (match_scratch:SI 2 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
8380 "TARGET_SH2E
8381 && (arith_reg_operand (operands[0], SFmode) || fpul_operand (operands[0], SFmode)
8382 || arith_reg_operand (operands[1], SFmode) || fpul_operand (operands[1], SFmode)
8383 || arith_reg_operand (operands[2], SImode))"
8384 "@
8385 fmov %1,%0
8386 mov %1,%0
8387 fldi0 %0
8388 fldi1 %0
8389 #
8390 fmov.s %1,%0
8391 fmov.s %1,%0
8392 mov.l %1,%0
8393 mov.l %1,%0
8394 mov.l %1,%0
8395 fsts fpul,%0
8396 flds %1,fpul
8397 lds.l %1,%0
8398 #
8399 sts %1,%0
8400 lds %1,%0
8401 sts.l %1,%0
8402 lds.l %1,%0
8403 ! move optimized away"
8404 [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,
8405 store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
8406 (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
8407 (set_attr_alternative "length"
8408 [(const_int 2)
8409 (const_int 2)
8410 (const_int 2)
8411 (const_int 2)
8412 (const_int 4)
8413 (if_then_else
8414 (match_test "TARGET_SH2A")
8415 (const_int 4) (const_int 2))
8416 (if_then_else
8417 (match_test "TARGET_SH2A")
8418 (const_int 4) (const_int 2))
8419 (const_int 2)
8420 (if_then_else
8421 (match_test "TARGET_SH2A")
8422 (const_int 4) (const_int 2))
8423 (if_then_else
8424 (match_test "TARGET_SH2A")
8425 (const_int 4) (const_int 2))
8426 (const_int 2)
8427 (const_int 2)
8428 (const_int 2)
8429 (const_int 4)
8430 (const_int 2)
8431 (const_int 2)
8432 (const_int 2)
8433 (const_int 2)
8434 (const_int 0)])
8435 (set_attr_alternative "fp_mode"
8436 [(if_then_else (eq_attr "fmovd" "yes")
8437 (const_string "single") (const_string "none"))
8438 (const_string "none")
8439 (const_string "single")
8440 (const_string "single")
8441 (const_string "none")
8442 (if_then_else (eq_attr "fmovd" "yes")
8443 (const_string "single") (const_string "none"))
8444 (if_then_else (eq_attr "fmovd" "yes")
8445 (const_string "single") (const_string "none"))
8446 (const_string "none")
8447 (const_string "none")
8448 (const_string "none")
8449 (const_string "none")
8450 (const_string "none")
8451 (const_string "none")
8452 (const_string "none")
8453 (const_string "none")
8454 (const_string "none")
8455 (const_string "none")
8456 (const_string "none")
8457 (const_string "none")])])
8458
8459 (define_split
8460 [(set (match_operand:SF 0 "register_operand" "")
8461 (match_operand:SF 1 "register_operand" ""))
8462 (use (reg:SI FPSCR_MODES_REG))
8463 (clobber (reg:SI FPUL_REG))]
8464 "TARGET_SH1"
8465 [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
8466 (use (reg:SI FPSCR_MODES_REG))
8467 (clobber (scratch:SI))])
8468 (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
8469 (use (reg:SI FPSCR_MODES_REG))
8470 (clobber (scratch:SI))])]
8471 "")
8472
8473 (define_expand "movsf"
8474 [(set (match_operand:SF 0 "general_movdst_operand" "")
8475 (match_operand:SF 1 "general_movsrc_operand" ""))]
8476 ""
8477 {
8478 prepare_move_operands (operands, SFmode);
8479 if (TARGET_SHMEDIA)
8480 {
8481 if (TARGET_SHMEDIA_FPU)
8482 emit_insn (gen_movsf_media (operands[0], operands[1]));
8483 else
8484 emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
8485 DONE;
8486 }
8487 if (TARGET_SH2E)
8488 {
8489 emit_insn (gen_movsf_ie (operands[0], operands[1]));
8490 DONE;
8491 }
8492 })
8493
8494 (define_insn "mov_nop"
8495 [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
8496 "TARGET_SH2E"
8497 ""
8498 [(set_attr "length" "0")
8499 (set_attr "type" "nil")])
8500
8501 (define_expand "reload_insf__frn"
8502 [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
8503 (match_operand:SF 1 "immediate_operand" "FQ"))
8504 (use (reg:SI FPSCR_MODES_REG))
8505 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8506 "TARGET_SH1"
8507 "")
8508
8509 (define_expand "reload_insi__i_fpul"
8510 [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
8511 (match_operand:SI 1 "immediate_operand" "i"))
8512 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8513 "TARGET_SH1"
8514 "")
8515
8516 (define_expand "ptabs"
8517 [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
8518 "TARGET_SHMEDIA"
8519 {
8520 if (!TARGET_PT_FIXED)
8521 {
8522 rtx eq = operands[1];
8523
8524 /* ??? For canonical RTL we really should remove any CONST from EQ
8525 before wrapping it in the AND, and finally wrap the EQ into a
8526 const if is constant. However, for reload we must expose the
8527 input register or symbolic constant, and we can't have
8528 different insn structures outside of the operands for different
8529 alternatives of the same pattern. */
8530 eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
8531 GEN_INT (3));
8532 operands[1]
8533 = (gen_rtx_IF_THEN_ELSE
8534 (PDImode,
8535 eq,
8536 gen_rtx_MEM (PDImode, operands[1]),
8537 gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
8538 PDImode, operands[1])));
8539 }
8540 })
8541
8542 ;; expanded by ptabs expander.
8543 (define_insn "*extendsipdi_media"
8544 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8545 (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
8546 "r,Csy")
8547 (const_int 3))
8548 (const_int 3))
8549 (mem:PDI (match_dup 1))
8550 (sign_extend:PDI (match_dup 1))))]
8551 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8552 "@
8553 ptabs %1, %0
8554 pt %1, %0"
8555 [(set_attr "type" "ptabs_media,pt_media")
8556 (set_attr "length" "4,*")])
8557
8558 (define_insn "*truncdipdi_media"
8559 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8560 (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
8561 "r,Csy")
8562 (const_int 3))
8563 (const_int 3))
8564 (mem:PDI (match_dup 1))
8565 (truncate:PDI (match_dup 1))))]
8566 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8567 "@
8568 ptabs %1, %0
8569 pt %1, %0"
8570 [(set_attr "type" "ptabs_media,pt_media")
8571 (set_attr "length" "4,*")])
8572
8573 (define_insn "*movsi_y"
8574 [(set (match_operand:SI 0 "register_operand" "=y,y")
8575 (match_operand:SI 1 "immediate_operand" "Qi,I08"))
8576 (clobber (match_scratch:SI 2 "=&z,r"))]
8577 "TARGET_SH2E
8578 && (reload_in_progress || reload_completed)"
8579 "#"
8580 [(set_attr "length" "4")
8581 (set_attr "type" "pcload,move")])
8582
8583 (define_split
8584 [(set (match_operand:SI 0 "register_operand" "")
8585 (match_operand:SI 1 "immediate_operand" ""))
8586 (clobber (match_operand:SI 2 "register_operand" ""))]
8587 "TARGET_SH1"
8588 [(set (match_dup 2) (match_dup 1))
8589 (set (match_dup 0) (match_dup 2))]
8590 "")
8591 \f
8592 ;; ------------------------------------------------------------------------
8593 ;; Define the real conditional branch instructions.
8594 ;; ------------------------------------------------------------------------
8595
8596 (define_expand "branch_true"
8597 [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
8598 (label_ref (match_operand 0))
8599 (pc)))]
8600 "TARGET_SH1")
8601
8602 (define_expand "branch_false"
8603 [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8604 (label_ref (match_operand 0))
8605 (pc)))]
8606 "TARGET_SH1")
8607
8608 (define_insn_and_split "*cbranch_t"
8609 [(set (pc) (if_then_else (match_operand 1 "cbranch_treg_value")
8610 (label_ref (match_operand 0))
8611 (pc)))]
8612 "TARGET_SH1"
8613 {
8614 return output_branch (sh_eval_treg_value (operands[1]), insn, operands);
8615 }
8616 "&& 1"
8617 [(const_int 0)]
8618 {
8619 /* Try to canonicalize the branch condition if it is not one of:
8620 (ne (reg:SI T_REG) (const_int 0))
8621 (eq (reg:SI T_REG) (const_int 0))
8622
8623 Instead of splitting out a new insn, we modify the current insn's
8624 operands as needed. This preserves things such as REG_DEAD notes. */
8625
8626 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
8627 && REG_P (XEXP (operands[1], 0)) && REGNO (XEXP (operands[1], 0)) == T_REG
8628 && XEXP (operands[1], 1) == const0_rtx)
8629 DONE;
8630
8631 int branch_cond = sh_eval_treg_value (operands[1]);
8632 rtx new_cond_rtx = NULL_RTX;
8633
8634 if (branch_cond == 0)
8635 new_cond_rtx = gen_rtx_EQ (VOIDmode, get_t_reg_rtx (), const0_rtx);
8636 else if (branch_cond == 1)
8637 new_cond_rtx = gen_rtx_NE (VOIDmode, get_t_reg_rtx (), const0_rtx);
8638
8639 if (new_cond_rtx != NULL_RTX)
8640 validate_change (curr_insn, &XEXP (XEXP (PATTERN (curr_insn), 1), 0),
8641 new_cond_rtx, false);
8642 DONE;
8643 }
8644 [(set_attr "type" "cbranch")])
8645
8646 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
8647 ;; which destination is too far away.
8648 ;; The const_int_operand is distinct for each branch target; it avoids
8649 ;; unwanted matches with redundant_insn.
8650 (define_insn "block_branch_redirect"
8651 [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
8652 "TARGET_SH1"
8653 ""
8654 [(set_attr "length" "0")])
8655
8656 ;; This one has the additional purpose to record a possible scratch register
8657 ;; for the following branch.
8658 ;; ??? Unfortunately, just setting the scratch register is not good enough,
8659 ;; because the insn then might be deemed dead and deleted. And we can't
8660 ;; make the use in the jump insn explicit because that would disable
8661 ;; delay slot scheduling from the target.
8662 (define_insn "indirect_jump_scratch"
8663 [(set (match_operand:SI 0 "register_operand" "=r")
8664 (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
8665 (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
8666 "TARGET_SH1"
8667 ""
8668 [(set_attr "length" "0")])
8669
8670 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
8671 ;; being pulled into the delay slot of a condbranch that has been made to
8672 ;; jump around the unconditional jump because it was out of range.
8673 (define_insn "stuff_delay_slot"
8674 [(set (pc)
8675 (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
8676 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
8677 "TARGET_SH1"
8678 ""
8679 [(set_attr "length" "0")
8680 (set_attr "cond_delay_slot" "yes")])
8681 \f
8682 ;; Conditional branch insns
8683
8684 (define_expand "cbranchint4_media"
8685 [(set (pc)
8686 (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
8687 [(match_operand 1 "" "")
8688 (match_operand 2 "" "")])
8689 (match_operand 3 "" "")
8690 (pc)))]
8691 "TARGET_SHMEDIA"
8692 {
8693 enum machine_mode mode = GET_MODE (operands[1]);
8694 if (mode == VOIDmode)
8695 mode = GET_MODE (operands[2]);
8696 if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
8697 {
8698 operands[1] = force_reg (mode, operands[1]);
8699 if (CONSTANT_P (operands[2])
8700 && (! satisfies_constraint_I06 (operands[2])))
8701 operands[2] = force_reg (mode, operands[2]);
8702 }
8703 else
8704 {
8705 if (operands[1] != const0_rtx)
8706 operands[1] = force_reg (mode, operands[1]);
8707 if (operands[2] != const0_rtx)
8708 operands[2] = force_reg (mode, operands[2]);
8709 }
8710 switch (GET_CODE (operands[0]))
8711 {
8712 case LEU:
8713 case LE:
8714 case LTU:
8715 case LT:
8716 operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
8717 VOIDmode, operands[2], operands[1]);
8718 operands[1] = XEXP (operands[0], 0);
8719 operands[2] = XEXP (operands[0], 1);
8720 break;
8721 default:
8722 operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
8723 VOIDmode, operands[1], operands[2]);
8724 break;
8725 }
8726 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
8727 })
8728
8729 (define_expand "cbranchfp4_media"
8730 [(set (pc)
8731 (if_then_else (match_operator 0 "sh_float_comparison_operator"
8732 [(match_operand 1 "" "")
8733 (match_operand 2 "" "")])
8734 (match_operand 3 "" "")
8735 (pc)))]
8736 "TARGET_SHMEDIA"
8737 {
8738 rtx tmp = gen_reg_rtx (SImode);
8739 rtx cmp;
8740 if (GET_CODE (operands[0]) == NE)
8741 cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
8742 else
8743 cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
8744 operands[1], operands[2]);
8745
8746 emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
8747
8748 if (GET_CODE (cmp) == GET_CODE (operands[0]))
8749 operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
8750 else
8751 operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
8752 operands[1] = tmp;
8753 operands[2] = const0_rtx;
8754 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
8755 })
8756
8757 (define_insn "*beq_media_i"
8758 [(set (pc)
8759 (if_then_else (match_operator 3 "equality_comparison_operator"
8760 [(match_operand:DI 1 "arith_reg_operand" "r,r")
8761 (match_operand:DI 2 "arith_operand" "r,I06")])
8762 (match_operand 0 "target_operand" "b,b")
8763 (pc)))]
8764 "TARGET_SHMEDIA"
8765 "@
8766 b%o3%' %1, %2, %0%>
8767 b%o3i%' %1, %2, %0%>"
8768 [(set_attr "type" "cbranch_media")])
8769
8770 (define_insn "*beq_media_i32"
8771 [(set (pc)
8772 (if_then_else (match_operator 3 "equality_comparison_operator"
8773 [(match_operand:SI 1 "arith_reg_operand" "r,r")
8774 (match_operand:SI 2 "arith_operand" "r,I06")])
8775 (match_operand 0 "target_operand" "b,b")
8776 (pc)))]
8777 "TARGET_SHMEDIA"
8778 "@
8779 b%o3%' %1, %2, %0%>
8780 b%o3i%' %1, %2, %0%>"
8781 [(set_attr "type" "cbranch_media")])
8782
8783 (define_insn "*bgt_media_i"
8784 [(set (pc)
8785 (if_then_else (match_operator 3 "greater_comparison_operator"
8786 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8787 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
8788 (match_operand 0 "target_operand" "b")
8789 (pc)))]
8790 "TARGET_SHMEDIA"
8791 "b%o3%' %N1, %N2, %0%>"
8792 [(set_attr "type" "cbranch_media")])
8793
8794 (define_insn "*bgt_media_i32"
8795 [(set (pc)
8796 (if_then_else (match_operator 3 "greater_comparison_operator"
8797 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8798 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8799 (match_operand 0 "target_operand" "b")
8800 (pc)))]
8801 "TARGET_SHMEDIA"
8802 "b%o3%' %N1, %N2, %0%>"
8803 [(set_attr "type" "cbranch_media")])
8804
8805 ;; These are only needed to make invert_jump() happy - otherwise, jump
8806 ;; optimization will be silently disabled.
8807 (define_insn "*blt_media_i"
8808 [(set (pc)
8809 (if_then_else (match_operator 3 "less_comparison_operator"
8810 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8811 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
8812 (match_operand 0 "target_operand" "b")
8813 (pc)))]
8814 "TARGET_SHMEDIA"
8815 "b%o3%' %N2, %N1, %0%>"
8816 [(set_attr "type" "cbranch_media")])
8817
8818 (define_insn "*blt_media_i32"
8819 [(set (pc)
8820 (if_then_else (match_operator 3 "less_comparison_operator"
8821 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8822 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8823 (match_operand 0 "target_operand" "b")
8824 (pc)))]
8825 "TARGET_SHMEDIA"
8826 "b%o3%' %N2, %N1, %0%>"
8827 [(set_attr "type" "cbranch_media")])
8828
8829 ;; combiner splitter for test-and-branch on single bit in register. This
8830 ;; is endian dependent because the non-paradoxical subreg looks different
8831 ;; on big endian.
8832 (define_split
8833 [(set (pc)
8834 (if_then_else
8835 (match_operator 3 "equality_comparison_operator"
8836 [(subreg:SI
8837 (zero_extract:DI
8838 (subreg:DI (match_operand:SI 1 "extend_reg_operand" "") 0)
8839 (const_int 1)
8840 (match_operand 2 "const_int_operand" "")) 0)
8841 (const_int 0)])
8842 (match_operand 0 "target_operand" "")
8843 (pc)))
8844 (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
8845 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
8846 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
8847 (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
8848 {
8849 operands[5] = GEN_INT (31 - INTVAL (operands[2]));
8850 operands[6] = (GET_CODE (operands[3]) == EQ
8851 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
8852 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
8853 })
8854
8855 ; operand 0 is the loop count pseudo register
8856 ; operand 1 is the label to jump to at the top of the loop
8857 (define_expand "doloop_end"
8858 [(parallel [(set (pc)
8859 (if_then_else (ne:SI (match_operand:SI 0 "" "")
8860 (const_int 1))
8861 (label_ref (match_operand 1 "" ""))
8862 (pc)))
8863 (set (match_dup 0)
8864 (plus:SI (match_dup 0) (const_int -1)))
8865 (clobber (reg:SI T_REG))])]
8866 "TARGET_SH2"
8867 {
8868 if (GET_MODE (operands[0]) != SImode)
8869 FAIL;
8870 emit_jump_insn (gen_doloop_end_split (operands[0], operands[1], operands[0]));
8871 DONE;
8872 })
8873
8874 (define_insn_and_split "doloop_end_split"
8875 [(set (pc)
8876 (if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0")
8877 (const_int 1))
8878 (label_ref (match_operand 1 "" ""))
8879 (pc)))
8880 (set (match_operand:SI 0 "arith_reg_dest" "=r")
8881 (plus:SI (match_dup 2) (const_int -1)))
8882 (clobber (reg:SI T_REG))]
8883 "TARGET_SH2"
8884 "#"
8885 ""
8886 [(parallel [(set (reg:SI T_REG)
8887 (eq:SI (match_dup 2) (const_int 1)))
8888 (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
8889 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8890 (label_ref (match_dup 1))
8891 (pc)))]
8892 ""
8893 [(set_attr "type" "cbranch")])
8894 \f
8895 ;; ------------------------------------------------------------------------
8896 ;; Jump and linkage insns
8897 ;; ------------------------------------------------------------------------
8898
8899 (define_insn "jump_compact"
8900 [(set (pc)
8901 (label_ref (match_operand 0 "" "")))]
8902 "TARGET_SH1 && !CROSSING_JUMP_P (insn)"
8903 {
8904 /* The length is 16 if the delay slot is unfilled. */
8905 if (get_attr_length(insn) > 4)
8906 return output_far_jump(insn, operands[0]);
8907 else
8908 return "bra %l0%#";
8909 }
8910 [(set_attr "type" "jump")
8911 (set_attr "needs_delay_slot" "yes")])
8912
8913 ;; ??? It would be much saner to explicitly use the scratch register
8914 ;; in the jump insn, and have indirect_jump_scratch only set it,
8915 ;; but fill_simple_delay_slots would refuse to do delay slot filling
8916 ;; from the target then, as it uses simplejump_p.
8917 ;;(define_insn "jump_compact_far"
8918 ;; [(set (pc)
8919 ;; (label_ref (match_operand 0 "" "")))
8920 ;; (use (match_operand 1 "register_operand" "r")]
8921 ;; "TARGET_SH1"
8922 ;; "* return output_far_jump(insn, operands[0], operands[1]);"
8923 ;; [(set_attr "type" "jump")
8924 ;; (set_attr "needs_delay_slot" "yes")])
8925
8926 (define_insn "jump_media"
8927 [(set (pc)
8928 (match_operand 0 "target_operand" "b"))]
8929 "TARGET_SHMEDIA"
8930 "blink %0, r63%>"
8931 [(set_attr "type" "jump_media")])
8932
8933 (define_expand "jump"
8934 [(set (pc)
8935 (label_ref (match_operand 0 "" "")))]
8936 ""
8937 {
8938 if (TARGET_SH1)
8939 emit_jump_insn (gen_jump_compact (operands[0]));
8940 else if (TARGET_SHMEDIA)
8941 {
8942 if (reload_in_progress || reload_completed)
8943 FAIL;
8944 emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode, operands[0])));
8945 }
8946 DONE;
8947 })
8948
8949 (define_insn "force_mode_for_call"
8950 [(use (reg:SI FPSCR_MODES_REG))]
8951 "TARGET_SHCOMPACT"
8952 ""
8953 [(set_attr "length" "0")
8954 (set (attr "fp_mode")
8955 (if_then_else (eq_attr "fpu_single" "yes")
8956 (const_string "single") (const_string "double")))])
8957
8958 (define_insn "calli"
8959 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8960 (match_operand 1 "" ""))
8961 (use (reg:SI FPSCR_MODES_REG))
8962 (clobber (reg:SI PR_REG))]
8963 "TARGET_SH1"
8964 {
8965 if (TARGET_SH2A && (dbr_sequence_length () == 0))
8966 return "jsr/n @%0";
8967 else
8968 return "jsr @%0%#";
8969 }
8970 [(set_attr "type" "call")
8971 (set (attr "fp_mode")
8972 (if_then_else (eq_attr "fpu_single" "yes")
8973 (const_string "single") (const_string "double")))
8974 (set_attr "needs_delay_slot" "yes")
8975 (set_attr "fp_set" "unknown")])
8976
8977 ;; This is TBR relative jump instruction for SH2A architecture.
8978 ;; Its use is enabled by assigning an attribute "function_vector"
8979 ;; and the vector number to a function during its declaration.
8980 (define_insn "calli_tbr_rel"
8981 [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
8982 (match_operand 1 "" ""))
8983 (use (reg:SI FPSCR_MODES_REG))
8984 (clobber (reg:SI PR_REG))]
8985 "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
8986 {
8987 unsigned HOST_WIDE_INT vect_num;
8988 vect_num = sh2a_get_function_vector_number (operands[0]);
8989 operands[2] = GEN_INT (vect_num * 4);
8990
8991 return "jsr/n @@(%O2,tbr)";
8992 }
8993 [(set_attr "type" "call")
8994 (set (attr "fp_mode")
8995 (if_then_else (eq_attr "fpu_single" "yes")
8996 (const_string "single") (const_string "double")))
8997 (set_attr "needs_delay_slot" "no")
8998 (set_attr "fp_set" "unknown")])
8999
9000 ;; This is a pc-rel call, using bsrf, for use with PIC.
9001 (define_insn "calli_pcrel"
9002 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9003 (match_operand 1 "" ""))
9004 (use (reg:SI FPSCR_MODES_REG))
9005 (use (reg:SI PIC_REG))
9006 (use (match_operand 2 "" ""))
9007 (clobber (reg:SI PR_REG))]
9008 "TARGET_SH2"
9009 {
9010 return "bsrf %0" "\n"
9011 "%O2:%#";
9012 }
9013 [(set_attr "type" "call")
9014 (set (attr "fp_mode")
9015 (if_then_else (eq_attr "fpu_single" "yes")
9016 (const_string "single") (const_string "double")))
9017 (set_attr "needs_delay_slot" "yes")
9018 (set_attr "fp_set" "unknown")])
9019
9020 (define_insn_and_split "call_pcrel"
9021 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
9022 (match_operand 1 "" ""))
9023 (use (reg:SI FPSCR_MODES_REG))
9024 (use (reg:SI PIC_REG))
9025 (clobber (reg:SI PR_REG))
9026 (clobber (match_scratch:SI 2 "=r"))]
9027 "TARGET_SH2"
9028 "#"
9029 "reload_completed"
9030 [(const_int 0)]
9031 {
9032 rtx lab = PATTERN (gen_call_site ());
9033
9034 if (SYMBOL_REF_LOCAL_P (operands[0]))
9035 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
9036 else
9037 emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
9038 emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
9039 DONE;
9040 }
9041 [(set_attr "type" "call")
9042 (set (attr "fp_mode")
9043 (if_then_else (eq_attr "fpu_single" "yes")
9044 (const_string "single") (const_string "double")))
9045 (set_attr "needs_delay_slot" "yes")
9046 (set_attr "fp_set" "unknown")])
9047
9048 (define_insn "call_compact"
9049 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9050 (match_operand 1 "" ""))
9051 (match_operand 2 "immediate_operand" "n")
9052 (use (reg:SI R0_REG))
9053 (use (reg:SI R1_REG))
9054 (use (reg:SI FPSCR_MODES_REG))
9055 (clobber (reg:SI PR_REG))]
9056 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9057 "jsr @%0%#"
9058 [(set_attr "type" "call")
9059 (set (attr "fp_mode")
9060 (if_then_else (eq_attr "fpu_single" "yes")
9061 (const_string "single") (const_string "double")))
9062 (set_attr "needs_delay_slot" "yes")])
9063
9064 (define_insn "call_compact_rettramp"
9065 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9066 (match_operand 1 "" ""))
9067 (match_operand 2 "immediate_operand" "n")
9068 (use (reg:SI R0_REG))
9069 (use (reg:SI R1_REG))
9070 (use (reg:SI FPSCR_MODES_REG))
9071 (clobber (reg:SI R10_REG))
9072 (clobber (reg:SI PR_REG))]
9073 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9074 "jsr @%0%#"
9075 [(set_attr "type" "call")
9076 (set (attr "fp_mode")
9077 (if_then_else (eq_attr "fpu_single" "yes")
9078 (const_string "single") (const_string "double")))
9079 (set_attr "needs_delay_slot" "yes")])
9080
9081 (define_insn "call_media"
9082 [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
9083 (match_operand 1 "" ""))
9084 (clobber (reg:DI PR_MEDIA_REG))]
9085 "TARGET_SHMEDIA"
9086 "blink %0, r18"
9087 [(set_attr "type" "jump_media")])
9088
9089 (define_insn "call_valuei"
9090 [(set (match_operand 0 "" "=rf")
9091 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9092 (match_operand 2 "" "")))
9093 (use (reg:SI FPSCR_MODES_REG))
9094 (clobber (reg:SI PR_REG))]
9095 "TARGET_SH1"
9096 {
9097 if (TARGET_SH2A && (dbr_sequence_length () == 0))
9098 return "jsr/n @%1";
9099 else
9100 return "jsr @%1%#";
9101 }
9102 [(set_attr "type" "call")
9103 (set (attr "fp_mode")
9104 (if_then_else (eq_attr "fpu_single" "yes")
9105 (const_string "single") (const_string "double")))
9106 (set_attr "needs_delay_slot" "yes")
9107 (set_attr "fp_set" "unknown")])
9108
9109 ;; This is TBR relative jump instruction for SH2A architecture.
9110 ;; Its use is enabled by assigning an attribute "function_vector"
9111 ;; and the vector number to a function during its declaration.
9112 (define_insn "call_valuei_tbr_rel"
9113 [(set (match_operand 0 "" "=rf")
9114 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9115 (match_operand 2 "" "")))
9116 (use (reg:SI FPSCR_MODES_REG))
9117 (clobber (reg:SI PR_REG))]
9118 "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
9119 {
9120 unsigned HOST_WIDE_INT vect_num;
9121 vect_num = sh2a_get_function_vector_number (operands[1]);
9122 operands[3] = GEN_INT (vect_num * 4);
9123
9124 return "jsr/n @@(%O3,tbr)";
9125 }
9126 [(set_attr "type" "call")
9127 (set (attr "fp_mode")
9128 (if_then_else (eq_attr "fpu_single" "yes")
9129 (const_string "single") (const_string "double")))
9130 (set_attr "needs_delay_slot" "no")
9131 (set_attr "fp_set" "unknown")])
9132
9133 (define_insn "call_valuei_pcrel"
9134 [(set (match_operand 0 "" "=rf")
9135 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9136 (match_operand 2 "" "")))
9137 (use (reg:SI FPSCR_MODES_REG))
9138 (use (reg:SI PIC_REG))
9139 (use (match_operand 3 "" ""))
9140 (clobber (reg:SI PR_REG))]
9141 "TARGET_SH2"
9142 {
9143 return "bsrf %1" "\n"
9144 "%O3:%#";
9145 }
9146 [(set_attr "type" "call")
9147 (set (attr "fp_mode")
9148 (if_then_else (eq_attr "fpu_single" "yes")
9149 (const_string "single") (const_string "double")))
9150 (set_attr "needs_delay_slot" "yes")
9151 (set_attr "fp_set" "unknown")])
9152
9153 (define_insn_and_split "call_value_pcrel"
9154 [(set (match_operand 0 "" "=rf")
9155 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9156 (match_operand 2 "" "")))
9157 (use (reg:SI FPSCR_MODES_REG))
9158 (use (reg:SI PIC_REG))
9159 (clobber (reg:SI PR_REG))
9160 (clobber (match_scratch:SI 3 "=r"))]
9161 "TARGET_SH2"
9162 "#"
9163 "reload_completed"
9164 [(const_int 0)]
9165 {
9166 rtx lab = PATTERN (gen_call_site ());
9167
9168 if (SYMBOL_REF_LOCAL_P (operands[1]))
9169 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
9170 else
9171 emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
9172 emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
9173 operands[2], copy_rtx (lab)));
9174 DONE;
9175 }
9176 [(set_attr "type" "call")
9177 (set (attr "fp_mode")
9178 (if_then_else (eq_attr "fpu_single" "yes")
9179 (const_string "single") (const_string "double")))
9180 (set_attr "needs_delay_slot" "yes")
9181 (set_attr "fp_set" "unknown")])
9182
9183 (define_insn "call_value_compact"
9184 [(set (match_operand 0 "" "=rf")
9185 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9186 (match_operand 2 "" "")))
9187 (match_operand 3 "immediate_operand" "n")
9188 (use (reg:SI R0_REG))
9189 (use (reg:SI R1_REG))
9190 (use (reg:SI FPSCR_MODES_REG))
9191 (clobber (reg:SI PR_REG))]
9192 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9193 "jsr @%1%#"
9194 [(set_attr "type" "call")
9195 (set (attr "fp_mode")
9196 (if_then_else (eq_attr "fpu_single" "yes")
9197 (const_string "single") (const_string "double")))
9198 (set_attr "needs_delay_slot" "yes")])
9199
9200 (define_insn "call_value_compact_rettramp"
9201 [(set (match_operand 0 "" "=rf")
9202 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9203 (match_operand 2 "" "")))
9204 (match_operand 3 "immediate_operand" "n")
9205 (use (reg:SI R0_REG))
9206 (use (reg:SI R1_REG))
9207 (use (reg:SI FPSCR_MODES_REG))
9208 (clobber (reg:SI R10_REG))
9209 (clobber (reg:SI PR_REG))]
9210 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9211 "jsr @%1%#"
9212 [(set_attr "type" "call")
9213 (set (attr "fp_mode")
9214 (if_then_else (eq_attr "fpu_single" "yes")
9215 (const_string "single") (const_string "double")))
9216 (set_attr "needs_delay_slot" "yes")])
9217
9218 (define_insn "call_value_media"
9219 [(set (match_operand 0 "" "=rf")
9220 (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
9221 (match_operand 2 "" "")))
9222 (clobber (reg:DI PR_MEDIA_REG))]
9223 "TARGET_SHMEDIA"
9224 "blink %1, r18"
9225 [(set_attr "type" "jump_media")])
9226
9227 (define_expand "call"
9228 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9229 (match_operand 1 "" ""))
9230 (match_operand 2 "" "")
9231 (use (reg:SI FPSCR_MODES_REG))
9232 (clobber (reg:SI PR_REG))])]
9233 ""
9234 {
9235 if (TARGET_SHMEDIA)
9236 {
9237 operands[0] = shmedia_prepare_call_address (operands[0], 0);
9238 emit_call_insn (gen_call_media (operands[0], operands[1]));
9239 DONE;
9240 }
9241 else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
9242 {
9243 rtx cookie_rtx = operands[2];
9244 long cookie = INTVAL (cookie_rtx);
9245 rtx func = XEXP (operands[0], 0);
9246 rtx r0, r1;
9247
9248 if (flag_pic)
9249 {
9250 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9251 {
9252 rtx reg = gen_reg_rtx (Pmode);
9253
9254 emit_insn (gen_symGOTPLT2reg (reg, func));
9255 func = reg;
9256 }
9257 else
9258 func = legitimize_pic_address (func, Pmode, 0);
9259 }
9260
9261 r0 = gen_rtx_REG (SImode, R0_REG);
9262 r1 = gen_rtx_REG (SImode, R1_REG);
9263
9264 /* Since such a call function may use all call-clobbered
9265 registers, we force a mode switch earlier, so that we don't
9266 run out of registers when adjusting fpscr for the call. */
9267 emit_insn (gen_force_mode_for_call ());
9268
9269 operands[0]
9270 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9271 operands[0] = force_reg (SImode, operands[0]);
9272
9273 emit_move_insn (r0, func);
9274 emit_move_insn (r1, cookie_rtx);
9275
9276 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9277 emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
9278 operands[2]));
9279 else
9280 emit_call_insn (gen_call_compact (operands[0], operands[1],
9281 operands[2]));
9282
9283 DONE;
9284 }
9285 else if (TARGET_SHCOMPACT && flag_pic
9286 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9287 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9288 {
9289 rtx reg = gen_reg_rtx (Pmode);
9290
9291 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
9292 XEXP (operands[0], 0) = reg;
9293 }
9294 if (!flag_pic && TARGET_SH2A
9295 && MEM_P (operands[0])
9296 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9297 {
9298 if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
9299 {
9300 emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
9301 operands[1]));
9302 DONE;
9303 }
9304 }
9305 if (flag_pic && TARGET_SH2
9306 && MEM_P (operands[0])
9307 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9308 {
9309 emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
9310 DONE;
9311 }
9312 else
9313 {
9314 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9315 operands[1] = operands[2];
9316 }
9317
9318 emit_call_insn (gen_calli (operands[0], operands[1]));
9319 DONE;
9320 })
9321
9322 (define_insn "call_pop_compact"
9323 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9324 (match_operand 1 "" ""))
9325 (match_operand 2 "immediate_operand" "n")
9326 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9327 (match_operand 3 "immediate_operand" "n")))
9328 (use (reg:SI R0_REG))
9329 (use (reg:SI R1_REG))
9330 (use (reg:SI FPSCR_MODES_REG))
9331 (clobber (reg:SI PR_REG))]
9332 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9333 "jsr @%0%#"
9334 [(set_attr "type" "call")
9335 (set (attr "fp_mode")
9336 (if_then_else (eq_attr "fpu_single" "yes")
9337 (const_string "single") (const_string "double")))
9338 (set_attr "needs_delay_slot" "yes")])
9339
9340 (define_insn "call_pop_compact_rettramp"
9341 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9342 (match_operand 1 "" ""))
9343 (match_operand 2 "immediate_operand" "n")
9344 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9345 (match_operand 3 "immediate_operand" "n")))
9346 (use (reg:SI R0_REG))
9347 (use (reg:SI R1_REG))
9348 (use (reg:SI FPSCR_MODES_REG))
9349 (clobber (reg:SI R10_REG))
9350 (clobber (reg:SI PR_REG))]
9351 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9352 "jsr @%0%#"
9353 [(set_attr "type" "call")
9354 (set (attr "fp_mode")
9355 (if_then_else (eq_attr "fpu_single" "yes")
9356 (const_string "single") (const_string "double")))
9357 (set_attr "needs_delay_slot" "yes")])
9358
9359 (define_expand "call_pop"
9360 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9361 (match_operand 1 "" ""))
9362 (match_operand 2 "" "")
9363 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9364 (match_operand 3 "" "")))])]
9365 "TARGET_SHCOMPACT"
9366 {
9367 rtx cookie_rtx;
9368 long cookie;
9369 rtx func;
9370 rtx r0, r1;
9371
9372 gcc_assert (operands[2] && INTVAL (operands[2]));
9373 cookie_rtx = operands[2];
9374 cookie = INTVAL (cookie_rtx);
9375 func = XEXP (operands[0], 0);
9376
9377 if (flag_pic)
9378 {
9379 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9380 {
9381 rtx reg = gen_reg_rtx (Pmode);
9382 emit_insn (gen_symGOTPLT2reg (reg, func));
9383 func = reg;
9384 }
9385 else
9386 func = legitimize_pic_address (func, Pmode, 0);
9387 }
9388
9389 r0 = gen_rtx_REG (SImode, R0_REG);
9390 r1 = gen_rtx_REG (SImode, R1_REG);
9391
9392 /* Since such a call function may use all call-clobbered
9393 registers, we force a mode switch earlier, so that we don't
9394 run out of registers when adjusting fpscr for the call. */
9395 emit_insn (gen_force_mode_for_call ());
9396
9397 operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9398 SFUNC_GOT);
9399 operands[0] = force_reg (SImode, operands[0]);
9400
9401 emit_move_insn (r0, func);
9402 emit_move_insn (r1, cookie_rtx);
9403
9404 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9405 emit_call_insn (gen_call_pop_compact_rettramp
9406 (operands[0], operands[1], operands[2], operands[3]));
9407 else
9408 emit_call_insn (gen_call_pop_compact
9409 (operands[0], operands[1], operands[2], operands[3]));
9410
9411 DONE;
9412 })
9413
9414 (define_expand "call_value"
9415 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9416 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9417 (match_operand 2 "" "")))
9418 (match_operand 3 "" "")
9419 (use (reg:SI FPSCR_MODES_REG))
9420 (clobber (reg:SI PR_REG))])]
9421 ""
9422 {
9423 if (TARGET_SHMEDIA)
9424 {
9425 operands[1] = shmedia_prepare_call_address (operands[1], 0);
9426 emit_call_insn (gen_call_value_media (operands[0], operands[1],
9427 operands[2]));
9428 DONE;
9429 }
9430 else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
9431 {
9432 rtx cookie_rtx = operands[3];
9433 long cookie = INTVAL (cookie_rtx);
9434 rtx func = XEXP (operands[1], 0);
9435 rtx r0, r1;
9436
9437 if (flag_pic)
9438 {
9439 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9440 {
9441 rtx reg = gen_reg_rtx (Pmode);
9442
9443 emit_insn (gen_symGOTPLT2reg (reg, func));
9444 func = reg;
9445 }
9446 else
9447 func = legitimize_pic_address (func, Pmode, 0);
9448 }
9449
9450 r0 = gen_rtx_REG (SImode, R0_REG);
9451 r1 = gen_rtx_REG (SImode, R1_REG);
9452
9453 /* Since such a call function may use all call-clobbered
9454 registers, we force a mode switch earlier, so that we don't
9455 run out of registers when adjusting fpscr for the call. */
9456 emit_insn (gen_force_mode_for_call ());
9457
9458 operands[1]
9459 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9460 operands[1] = force_reg (SImode, operands[1]);
9461
9462 emit_move_insn (r0, func);
9463 emit_move_insn (r1, cookie_rtx);
9464
9465 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9466 emit_call_insn (gen_call_value_compact_rettramp (operands[0],
9467 operands[1],
9468 operands[2],
9469 operands[3]));
9470 else
9471 emit_call_insn (gen_call_value_compact (operands[0], operands[1],
9472 operands[2], operands[3]));
9473
9474 DONE;
9475 }
9476 else if (TARGET_SHCOMPACT && flag_pic
9477 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9478 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9479 {
9480 rtx reg = gen_reg_rtx (Pmode);
9481
9482 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
9483 XEXP (operands[1], 0) = reg;
9484 }
9485 if (!flag_pic && TARGET_SH2A
9486 && MEM_P (operands[1])
9487 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9488 {
9489 if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
9490 {
9491 emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
9492 XEXP (operands[1], 0), operands[2]));
9493 DONE;
9494 }
9495 }
9496 if (flag_pic && TARGET_SH2
9497 && MEM_P (operands[1])
9498 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9499 {
9500 emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
9501 operands[2]));
9502 DONE;
9503 }
9504 else
9505 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9506
9507 emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
9508 DONE;
9509 })
9510
9511 (define_insn "sibcalli"
9512 [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
9513 (match_operand 1 "" ""))
9514 (use (reg:SI FPSCR_MODES_REG))
9515 (return)]
9516 "TARGET_SH1"
9517 "jmp @%0%#"
9518 [(set_attr "needs_delay_slot" "yes")
9519 (set (attr "fp_mode")
9520 (if_then_else (eq_attr "fpu_single" "yes")
9521 (const_string "single") (const_string "double")))
9522 (set_attr "type" "jump_ind")])
9523
9524 (define_insn "sibcalli_pcrel"
9525 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
9526 (match_operand 1 "" ""))
9527 (use (match_operand 2 "" ""))
9528 (use (reg:SI FPSCR_MODES_REG))
9529 (return)]
9530 "TARGET_SH2"
9531 {
9532 return "braf %0" "\n"
9533 "%O2:%#";
9534 }
9535 [(set_attr "needs_delay_slot" "yes")
9536 (set (attr "fp_mode")
9537 (if_then_else (eq_attr "fpu_single" "yes")
9538 (const_string "single") (const_string "double")))
9539 (set_attr "type" "jump_ind")])
9540
9541 ;; This uses an unspec to describe that the symbol_ref is very close.
9542 (define_insn "sibcalli_thunk"
9543 [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
9544 UNSPEC_THUNK))
9545 (match_operand 1 "" ""))
9546 (use (reg:SI FPSCR_MODES_REG))
9547 (return)]
9548 "TARGET_SH1"
9549 "bra %O0"
9550 [(set_attr "needs_delay_slot" "yes")
9551 (set (attr "fp_mode")
9552 (if_then_else (eq_attr "fpu_single" "yes")
9553 (const_string "single") (const_string "double")))
9554 (set_attr "type" "jump")
9555 (set_attr "length" "2")])
9556
9557 (define_insn_and_split "sibcall_pcrel"
9558 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
9559 (match_operand 1 "" ""))
9560 (use (reg:SI FPSCR_MODES_REG))
9561 (clobber (match_scratch:SI 2 "=k"))
9562 (return)]
9563 "TARGET_SH2"
9564 "#"
9565 "reload_completed"
9566 [(const_int 0)]
9567 {
9568 rtx lab = PATTERN (gen_call_site ());
9569 rtx call_insn;
9570
9571 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
9572 call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
9573 copy_rtx (lab)));
9574 SIBLING_CALL_P (call_insn) = 1;
9575 DONE;
9576 }
9577 [(set_attr "needs_delay_slot" "yes")
9578 (set (attr "fp_mode")
9579 (if_then_else (eq_attr "fpu_single" "yes")
9580 (const_string "single") (const_string "double")))
9581 (set_attr "type" "jump_ind")])
9582
9583 (define_insn "sibcall_compact"
9584 [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
9585 (match_operand 1 "" ""))
9586 (return)
9587 (use (match_operand:SI 2 "register_operand" "z,x"))
9588 (use (reg:SI R1_REG))
9589 (use (reg:SI FPSCR_MODES_REG))
9590 ;; We want to make sure the `x' above will only match MACH_REG
9591 ;; because sibcall_epilogue may clobber MACL_REG.
9592 (clobber (reg:SI MACL_REG))]
9593 "TARGET_SHCOMPACT"
9594 {
9595 static const char* alt[] =
9596 {
9597 "jmp @%0%#",
9598
9599 "jmp @%0" "\n"
9600 " sts %2,r0"
9601 };
9602 return alt[which_alternative];
9603 }
9604 [(set_attr "needs_delay_slot" "yes,no")
9605 (set_attr "length" "2,4")
9606 (set (attr "fp_mode") (const_string "single"))
9607 (set_attr "type" "jump_ind")])
9608
9609 (define_insn "sibcall_media"
9610 [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
9611 (match_operand 1 "" ""))
9612 (use (reg:SI PR_MEDIA_REG))
9613 (return)]
9614 "TARGET_SHMEDIA"
9615 "blink %0, r63"
9616 [(set_attr "type" "jump_media")])
9617
9618 (define_expand "sibcall"
9619 [(parallel
9620 [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9621 (match_operand 1 "" ""))
9622 (match_operand 2 "" "")
9623 (use (reg:SI FPSCR_MODES_REG))
9624 (return)])]
9625 ""
9626 {
9627 if (TARGET_SHMEDIA)
9628 {
9629 operands[0] = shmedia_prepare_call_address (operands[0], 1);
9630 emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
9631 DONE;
9632 }
9633 else if (TARGET_SHCOMPACT && operands[2]
9634 && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9635 {
9636 rtx cookie_rtx = operands[2];
9637 long cookie = INTVAL (cookie_rtx);
9638 rtx func = XEXP (operands[0], 0);
9639 rtx mach, r1;
9640
9641 if (flag_pic)
9642 {
9643 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9644 {
9645 rtx reg = gen_reg_rtx (Pmode);
9646
9647 emit_insn (gen_symGOT2reg (reg, func));
9648 func = reg;
9649 }
9650 else
9651 func = legitimize_pic_address (func, Pmode, 0);
9652 }
9653
9654 /* FIXME: if we could tell whether all argument registers are
9655 already taken, we could decide whether to force the use of
9656 MACH_REG or to stick to R0_REG. Unfortunately, there's no
9657 simple way to tell. We could use the CALL_COOKIE, but we
9658 can't currently tell a register used for regular argument
9659 passing from one that is unused. If we leave it up to reload
9660 to decide which register to use, it seems to always choose
9661 R0_REG, which leaves no available registers in SIBCALL_REGS
9662 to hold the address of the trampoline. */
9663 mach = gen_rtx_REG (SImode, MACH_REG);
9664 r1 = gen_rtx_REG (SImode, R1_REG);
9665
9666 /* Since such a call function may use all call-clobbered
9667 registers, we force a mode switch earlier, so that we don't
9668 run out of registers when adjusting fpscr for the call. */
9669 emit_insn (gen_force_mode_for_call ());
9670
9671 operands[0]
9672 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9673 operands[0] = force_reg (SImode, operands[0]);
9674
9675 /* We don't need a return trampoline, since the callee will
9676 return directly to the upper caller. */
9677 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9678 {
9679 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9680 cookie_rtx = GEN_INT (cookie);
9681 }
9682
9683 emit_move_insn (mach, func);
9684 emit_move_insn (r1, cookie_rtx);
9685
9686 emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
9687 DONE;
9688 }
9689 else if (TARGET_SHCOMPACT && flag_pic
9690 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9691 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9692 {
9693 rtx reg = gen_reg_rtx (Pmode);
9694
9695 emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
9696 XEXP (operands[0], 0) = reg;
9697 }
9698 if (flag_pic && TARGET_SH2
9699 && MEM_P (operands[0])
9700 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9701 /* The PLT needs the PIC register, but the epilogue would have
9702 to restore it, so we can only use PC-relative PIC calls for
9703 static functions. */
9704 && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9705 {
9706 emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
9707 DONE;
9708 }
9709 else
9710 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9711
9712 emit_call_insn (gen_sibcalli (operands[0], operands[1]));
9713 DONE;
9714 })
9715
9716 (define_insn "sibcall_valuei"
9717 [(set (match_operand 0 "" "=rf")
9718 (call (mem:SI (match_operand:SI 1 "register_operand" "k"))
9719 (match_operand 2 "" "")))
9720 (use (reg:SI FPSCR_MODES_REG))
9721 (return)]
9722 "TARGET_SH1"
9723 "jmp @%1%#"
9724 [(set_attr "needs_delay_slot" "yes")
9725 (set (attr "fp_mode")
9726 (if_then_else (eq_attr "fpu_single" "yes")
9727 (const_string "single") (const_string "double")))
9728 (set_attr "type" "jump_ind")])
9729
9730 (define_insn "sibcall_valuei_pcrel"
9731 [(set (match_operand 0 "" "=rf")
9732 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
9733 (match_operand 2 "" "")))
9734 (use (match_operand 3 "" ""))
9735 (use (reg:SI FPSCR_MODES_REG))
9736 (return)]
9737 "TARGET_SH2"
9738 {
9739 return "braf %1" "\n"
9740 "%O3:%#";
9741 }
9742 [(set_attr "needs_delay_slot" "yes")
9743 (set (attr "fp_mode")
9744 (if_then_else (eq_attr "fpu_single" "yes")
9745 (const_string "single") (const_string "double")))
9746 (set_attr "type" "jump_ind")])
9747
9748 (define_insn_and_split "sibcall_value_pcrel"
9749 [(set (match_operand 0 "" "=rf")
9750 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9751 (match_operand 2 "" "")))
9752 (use (reg:SI FPSCR_MODES_REG))
9753 (clobber (match_scratch:SI 3 "=k"))
9754 (return)]
9755 "TARGET_SH2"
9756 "#"
9757 "reload_completed"
9758 [(const_int 0)]
9759 {
9760 rtx lab = PATTERN (gen_call_site ());
9761 rtx call_insn;
9762
9763 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
9764 call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
9765 operands[3],
9766 operands[2],
9767 copy_rtx (lab)));
9768 SIBLING_CALL_P (call_insn) = 1;
9769 DONE;
9770 }
9771 [(set_attr "needs_delay_slot" "yes")
9772 (set (attr "fp_mode")
9773 (if_then_else (eq_attr "fpu_single" "yes")
9774 (const_string "single") (const_string "double")))
9775 (set_attr "type" "jump_ind")])
9776
9777 (define_insn "sibcall_value_compact"
9778 [(set (match_operand 0 "" "=rf,rf")
9779 (call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
9780 (match_operand 2 "" "")))
9781 (return)
9782 (use (match_operand:SI 3 "register_operand" "z,x"))
9783 (use (reg:SI R1_REG))
9784 (use (reg:SI FPSCR_MODES_REG))
9785 ;; We want to make sure the `x' above will only match MACH_REG
9786 ;; because sibcall_epilogue may clobber MACL_REG.
9787 (clobber (reg:SI MACL_REG))]
9788 "TARGET_SHCOMPACT"
9789 {
9790 static const char* alt[] =
9791 {
9792 "jmp @%1%#",
9793
9794 "jmp @%1" "\n"
9795 " sts %3,r0"
9796 };
9797 return alt[which_alternative];
9798 }
9799 [(set_attr "needs_delay_slot" "yes,no")
9800 (set_attr "length" "2,4")
9801 (set (attr "fp_mode") (const_string "single"))
9802 (set_attr "type" "jump_ind")])
9803
9804 (define_insn "sibcall_value_media"
9805 [(set (match_operand 0 "" "=rf")
9806 (call (mem:DI (match_operand 1 "target_reg_operand" "k"))
9807 (match_operand 2 "" "")))
9808 (use (reg:SI PR_MEDIA_REG))
9809 (return)]
9810 "TARGET_SHMEDIA"
9811 "blink %1, r63"
9812 [(set_attr "type" "jump_media")])
9813
9814 (define_expand "sibcall_value"
9815 [(parallel
9816 [(set (match_operand 0 "arith_reg_operand" "")
9817 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9818 (match_operand 2 "" "")))
9819 (match_operand 3 "" "")
9820 (use (reg:SI FPSCR_MODES_REG))
9821 (return)])]
9822 ""
9823 {
9824 if (TARGET_SHMEDIA)
9825 {
9826 operands[1] = shmedia_prepare_call_address (operands[1], 1);
9827 emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
9828 operands[2]));
9829 DONE;
9830 }
9831 else if (TARGET_SHCOMPACT && operands[3]
9832 && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9833 {
9834 rtx cookie_rtx = operands[3];
9835 long cookie = INTVAL (cookie_rtx);
9836 rtx func = XEXP (operands[1], 0);
9837 rtx mach, r1;
9838
9839 if (flag_pic)
9840 {
9841 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9842 {
9843 rtx reg = gen_reg_rtx (Pmode);
9844
9845 emit_insn (gen_symGOT2reg (reg, func));
9846 func = reg;
9847 }
9848 else
9849 func = legitimize_pic_address (func, Pmode, 0);
9850 }
9851
9852 /* FIXME: if we could tell whether all argument registers are
9853 already taken, we could decide whether to force the use of
9854 MACH_REG or to stick to R0_REG. Unfortunately, there's no
9855 simple way to tell. We could use the CALL_COOKIE, but we
9856 can't currently tell a register used for regular argument
9857 passing from one that is unused. If we leave it up to reload
9858 to decide which register to use, it seems to always choose
9859 R0_REG, which leaves no available registers in SIBCALL_REGS
9860 to hold the address of the trampoline. */
9861 mach = gen_rtx_REG (SImode, MACH_REG);
9862 r1 = gen_rtx_REG (SImode, R1_REG);
9863
9864 /* Since such a call function may use all call-clobbered
9865 registers, we force a mode switch earlier, so that we don't
9866 run out of registers when adjusting fpscr for the call. */
9867 emit_insn (gen_force_mode_for_call ());
9868
9869 operands[1]
9870 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9871 operands[1] = force_reg (SImode, operands[1]);
9872
9873 /* We don't need a return trampoline, since the callee will
9874 return directly to the upper caller. */
9875 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9876 {
9877 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9878 cookie_rtx = GEN_INT (cookie);
9879 }
9880
9881 emit_move_insn (mach, func);
9882 emit_move_insn (r1, cookie_rtx);
9883
9884 emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
9885 operands[2], mach));
9886 DONE;
9887 }
9888 else if (TARGET_SHCOMPACT && flag_pic
9889 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9890 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9891 {
9892 rtx reg = gen_reg_rtx (Pmode);
9893
9894 emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
9895 XEXP (operands[1], 0) = reg;
9896 }
9897 if (flag_pic && TARGET_SH2
9898 && MEM_P (operands[1])
9899 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9900 /* The PLT needs the PIC register, but the epilogue would have
9901 to restore it, so we can only use PC-relative PIC calls for
9902 static functions. */
9903 && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9904 {
9905 emit_call_insn (gen_sibcall_value_pcrel (operands[0],
9906 XEXP (operands[1], 0),
9907 operands[2]));
9908 DONE;
9909 }
9910 else
9911 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9912
9913 emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
9914 DONE;
9915 })
9916
9917 (define_insn "call_value_pop_compact"
9918 [(set (match_operand 0 "" "=rf")
9919 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9920 (match_operand 2 "" "")))
9921 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9922 (match_operand 4 "immediate_operand" "n")))
9923 (match_operand 3 "immediate_operand" "n")
9924 (use (reg:SI R0_REG))
9925 (use (reg:SI R1_REG))
9926 (use (reg:SI FPSCR_MODES_REG))
9927 (clobber (reg:SI PR_REG))]
9928 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9929 "jsr @%1%#"
9930 [(set_attr "type" "call")
9931 (set (attr "fp_mode")
9932 (if_then_else (eq_attr "fpu_single" "yes")
9933 (const_string "single") (const_string "double")))
9934 (set_attr "needs_delay_slot" "yes")])
9935
9936 (define_insn "call_value_pop_compact_rettramp"
9937 [(set (match_operand 0 "" "=rf")
9938 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9939 (match_operand 2 "" "")))
9940 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9941 (match_operand 4 "immediate_operand" "n")))
9942 (match_operand 3 "immediate_operand" "n")
9943 (use (reg:SI R0_REG))
9944 (use (reg:SI R1_REG))
9945 (use (reg:SI FPSCR_MODES_REG))
9946 (clobber (reg:SI R10_REG))
9947 (clobber (reg:SI PR_REG))]
9948 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9949 "jsr @%1%#"
9950 [(set_attr "type" "call")
9951 (set (attr "fp_mode")
9952 (if_then_else (eq_attr "fpu_single" "yes")
9953 (const_string "single") (const_string "double")))
9954 (set_attr "needs_delay_slot" "yes")])
9955
9956 (define_expand "call_value_pop"
9957 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9958 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9959 (match_operand 2 "" "")))
9960 (match_operand 3 "" "")
9961 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9962 (match_operand 4 "" "")))])]
9963 "TARGET_SHCOMPACT"
9964 {
9965 rtx cookie_rtx;
9966 long cookie;
9967 rtx func;
9968 rtx r0, r1;
9969
9970 gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
9971 cookie_rtx = operands[3];
9972 cookie = INTVAL (cookie_rtx);
9973 func = XEXP (operands[1], 0);
9974
9975 if (flag_pic)
9976 {
9977 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9978 {
9979 rtx reg = gen_reg_rtx (Pmode);
9980
9981 emit_insn (gen_symGOTPLT2reg (reg, func));
9982 func = reg;
9983 }
9984 else
9985 func = legitimize_pic_address (func, Pmode, 0);
9986 }
9987
9988 r0 = gen_rtx_REG (SImode, R0_REG);
9989 r1 = gen_rtx_REG (SImode, R1_REG);
9990
9991 /* Since such a call function may use all call-clobbered
9992 registers, we force a mode switch earlier, so that we don't
9993 run out of registers when adjusting fpscr for the call. */
9994 emit_insn (gen_force_mode_for_call ());
9995
9996 operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9997 SFUNC_GOT);
9998 operands[1] = force_reg (SImode, operands[1]);
9999
10000 emit_move_insn (r0, func);
10001 emit_move_insn (r1, cookie_rtx);
10002
10003 if (cookie & CALL_COOKIE_RET_TRAMP (1))
10004 emit_call_insn (gen_call_value_pop_compact_rettramp
10005 (operands[0], operands[1], operands[2],
10006 operands[3], operands[4]));
10007 else
10008 emit_call_insn (gen_call_value_pop_compact
10009 (operands[0], operands[1], operands[2],
10010 operands[3], operands[4]));
10011
10012 DONE;
10013 })
10014
10015 (define_expand "sibcall_epilogue"
10016 [(return)]
10017 ""
10018 {
10019 sh_expand_epilogue (true);
10020 if (TARGET_SHCOMPACT)
10021 {
10022 rtx_insn *insn;
10023 rtx set;
10024
10025 /* If epilogue clobbers r0, preserve it in macl. */
10026 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
10027 if ((set = single_set (insn))
10028 && REG_P (SET_DEST (set))
10029 && REGNO (SET_DEST (set)) == R0_REG)
10030 {
10031 rtx r0 = gen_rtx_REG (SImode, R0_REG);
10032 rtx tmp = gen_rtx_REG (SImode, MACL_REG);
10033
10034 /* We can't tell at this point whether the sibcall is a
10035 sibcall_compact and, if it is, whether it uses r0 or
10036 mach as operand 2, so let the instructions that
10037 preserve r0 be optimized away if r0 turns out to be
10038 dead. */
10039 emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
10040 emit_move_insn (r0, tmp);
10041 break;
10042 }
10043 }
10044 DONE;
10045 })
10046
10047 (define_insn "indirect_jump_compact"
10048 [(set (pc)
10049 (match_operand:SI 0 "arith_reg_operand" "r"))]
10050 "TARGET_SH1"
10051 "jmp @%0%#"
10052 [(set_attr "needs_delay_slot" "yes")
10053 (set_attr "type" "jump_ind")])
10054
10055 (define_expand "indirect_jump"
10056 [(set (pc)
10057 (match_operand 0 "register_operand" ""))]
10058 ""
10059 {
10060 if (GET_MODE (operands[0]) != Pmode)
10061 operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
10062 })
10063
10064 ;; The use of operand 1 / 2 helps us distinguish case table jumps
10065 ;; which can be present in structured code from indirect jumps which can not
10066 ;; be present in structured code. This allows -fprofile-arcs to work.
10067
10068 ;; For SH1 processors.
10069 (define_insn "casesi_jump_1"
10070 [(set (pc)
10071 (match_operand:SI 0 "register_operand" "r"))
10072 (use (label_ref (match_operand 1 "" "")))]
10073 "TARGET_SH1"
10074 "jmp @%0%#"
10075 [(set_attr "needs_delay_slot" "yes")
10076 (set_attr "type" "jump_ind")])
10077
10078 ;; For all later processors.
10079 (define_insn "casesi_jump_2"
10080 [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
10081 (label_ref (match_operand 1 "" ""))))
10082 (use (label_ref (match_operand 2 "" "")))]
10083 "TARGET_SH2
10084 && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
10085 "braf %0%#"
10086 [(set_attr "needs_delay_slot" "yes")
10087 (set_attr "type" "jump_ind")])
10088
10089 (define_insn "casesi_jump_media"
10090 [(set (pc) (match_operand 0 "target_reg_operand" "b"))
10091 (use (label_ref (match_operand 1 "" "")))]
10092 "TARGET_SHMEDIA"
10093 "blink %0, r63"
10094 [(set_attr "type" "jump_media")])
10095
10096 ;; Call subroutine returning any type.
10097 ;; ??? This probably doesn't work.
10098 (define_expand "untyped_call"
10099 [(parallel [(call (match_operand 0 "" "")
10100 (const_int 0))
10101 (match_operand 1 "" "")
10102 (match_operand 2 "" "")])]
10103 "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
10104 {
10105 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
10106
10107 for (int i = 0; i < XVECLEN (operands[2], 0); i++)
10108 {
10109 rtx set = XVECEXP (operands[2], 0, i);
10110 emit_move_insn (SET_DEST (set), SET_SRC (set));
10111 }
10112
10113 /* The optimizer does not know that the call sets the function value
10114 registers we stored in the result block. We avoid problems by
10115 claiming that all hard registers are used and clobbered at this
10116 point. */
10117 emit_insn (gen_blockage ());
10118
10119 DONE;
10120 })
10121 \f
10122 ;; ------------------------------------------------------------------------
10123 ;; Misc insns
10124 ;; ------------------------------------------------------------------------
10125
10126 (define_insn "dect"
10127 [(set (reg:SI T_REG)
10128 (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
10129 (set (match_operand:SI 0 "arith_reg_dest" "=r")
10130 (plus:SI (match_dup 1) (const_int -1)))]
10131 "TARGET_SH2"
10132 "dt %0"
10133 [(set_attr "type" "arith")])
10134
10135 (define_insn "nop"
10136 [(const_int 0)]
10137 ""
10138 "nop")
10139
10140 ;; Load address of a label. This is only generated by the casesi expand,
10141 ;; and by machine_dependent_reorg (fixing up fp moves).
10142 ;; This must use unspec, because this only works for labels that are
10143 ;; within range.
10144 (define_insn "mova"
10145 [(set (reg:SI R0_REG)
10146 (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
10147 "TARGET_SH1"
10148 "mova %O0,r0"
10149 [(set_attr "in_delay_slot" "no")
10150 (set_attr "type" "arith")])
10151
10152 ;; machine_dependent_reorg will make this a `mova'.
10153 (define_insn "mova_const"
10154 [(set (reg:SI R0_REG)
10155 (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
10156 "TARGET_SH1"
10157 "#"
10158 [(set_attr "in_delay_slot" "no")
10159 (set_attr "type" "arith")])
10160
10161 (define_expand "GOTaddr2picreg"
10162 [(set (reg:SI R0_REG)
10163 (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
10164 UNSPEC_MOVA))
10165 (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
10166 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
10167 ""
10168 {
10169 if (TARGET_VXWORKS_RTP)
10170 {
10171 rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
10172 rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
10173 emit_insn (gen_vxworks_picreg (gott_base, gott_index));
10174 DONE;
10175 }
10176
10177 operands[0] = gen_rtx_REG (Pmode, PIC_REG);
10178 operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
10179
10180 if (TARGET_SHMEDIA)
10181 {
10182 rtx tr = gen_rtx_REG (Pmode, TR0_REG);
10183 rtx pic = operands[0];
10184 rtx lab = PATTERN (gen_call_site ());
10185 rtx insn, equiv;
10186
10187 equiv = operands[1];
10188 operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
10189 UNSPEC_PCREL_SYMOFF);
10190 operands[1] = gen_rtx_CONST (Pmode, operands[1]);
10191
10192 if (Pmode == SImode)
10193 {
10194 emit_insn (gen_movsi_const (pic, operands[1]));
10195 emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
10196 }
10197 else
10198 {
10199 emit_insn (gen_movdi_const (pic, operands[1]));
10200 emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
10201 }
10202
10203 insn = emit_move_insn (operands[0], tr);
10204
10205 set_unique_reg_note (insn, REG_EQUAL, equiv);
10206
10207 DONE;
10208 }
10209 })
10210
10211 ;; A helper for GOTaddr2picreg to finish up the initialization of the
10212 ;; PIC register.
10213 (define_expand "vxworks_picreg"
10214 [(set (reg:SI PIC_REG)
10215 (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
10216 (set (reg:SI R0_REG)
10217 (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
10218 (set (reg:SI PIC_REG)
10219 (mem:SI (reg:SI PIC_REG)))
10220 (set (reg:SI PIC_REG)
10221 (mem:SI (plus:SI (reg:SI PIC_REG)
10222 (reg:SI R0_REG))))]
10223 "TARGET_VXWORKS_RTP")
10224
10225 (define_insn "*ptb"
10226 [(set (match_operand 0 "target_reg_operand" "=b")
10227 (const (unspec [(match_operand 1 "" "Csy")]
10228 UNSPEC_DATALABEL)))]
10229 "TARGET_SHMEDIA && flag_pic
10230 && satisfies_constraint_Csy (operands[1])"
10231 "ptb/u datalabel %1, %0"
10232 [(set_attr "type" "ptabs_media")
10233 (set_attr "length" "*")])
10234
10235 (define_insn "ptrel_si"
10236 [(set (match_operand:SI 0 "target_reg_operand" "=b")
10237 (plus:SI (match_operand:SI 1 "register_operand" "r")
10238 (pc)))
10239 (match_operand:SI 2 "" "")]
10240 "TARGET_SHMEDIA"
10241 "%O2: ptrel/u %1, %0"
10242 [(set_attr "type" "ptabs_media")])
10243
10244 (define_insn "ptrel_di"
10245 [(set (match_operand:DI 0 "target_reg_operand" "=b")
10246 (plus:DI (match_operand:DI 1 "register_operand" "r")
10247 (pc)))
10248 (match_operand:DI 2 "" "")]
10249 "TARGET_SHMEDIA"
10250 "%O2: ptrel/u %1, %0"
10251 [(set_attr "type" "ptabs_media")])
10252
10253 (define_expand "builtin_setjmp_receiver"
10254 [(match_operand 0 "" "")]
10255 "flag_pic"
10256 {
10257 emit_insn (gen_GOTaddr2picreg ());
10258 DONE;
10259 })
10260
10261 (define_expand "call_site"
10262 [(unspec [(match_dup 0)] UNSPEC_CALLER)]
10263 "TARGET_SH1"
10264 {
10265 static HOST_WIDE_INT i = 0;
10266 operands[0] = GEN_INT (i);
10267 i++;
10268 })
10269
10270 ;; op0 = op1 + r12 but hide it before reload completed. See the comment
10271 ;; in symGOT_load expand.
10272 (define_insn_and_split "chk_guard_add"
10273 [(set (match_operand:SI 0 "register_operand" "=&r")
10274 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
10275 (reg:SI PIC_REG)]
10276 UNSPEC_CHKADD))]
10277 "TARGET_SH1"
10278 "#"
10279 "TARGET_SH1 && reload_completed"
10280 [(set (match_dup 0) (reg:SI PIC_REG))
10281 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
10282 ""
10283 [(set_attr "type" "arith")])
10284
10285 (define_expand "sym_label2reg"
10286 [(set (match_operand:SI 0 "" "")
10287 (const:SI (unspec:SI [(match_operand:SI 1 "" "")
10288 (const (plus:SI (match_operand:SI 2 "" "")
10289 (const_int 2)))]
10290 UNSPEC_SYMOFF)))]
10291 "TARGET_SH1" "")
10292
10293 (define_expand "symGOT_load"
10294 [(set (match_dup 2) (match_operand 1 "" ""))
10295 (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
10296 (set (match_operand 0 "" "") (mem (match_dup 3)))]
10297 ""
10298 {
10299 rtx mem;
10300
10301 operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10302 operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10303
10304 if (TARGET_SHMEDIA)
10305 {
10306 rtx reg = operands[2];
10307
10308 if (Pmode == DImode)
10309 {
10310 if (flag_pic > 1)
10311 emit_insn (gen_movdi_const_32bit (reg, operands[1]));
10312 else
10313 emit_insn (gen_movdi_const_16bit (reg, operands[1]));
10314 }
10315 else
10316 {
10317 if (flag_pic > 1)
10318 emit_insn (gen_movsi_const (reg, operands[1]));
10319 else
10320 emit_insn (gen_movsi_const_16bit (reg, operands[1]));
10321 }
10322 }
10323 else
10324 emit_move_insn (operands[2], operands[1]);
10325
10326 /* When stack protector inserts codes after the result is set to
10327 R0, @(rX, r12) will cause a spill failure for R0. Use a unspec
10328 insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
10329 when rX is a GOT address for the guard symbol. Ugly but doesn't
10330 matter because this is a rare situation. */
10331 if (!TARGET_SHMEDIA
10332 && flag_stack_protect
10333 && GET_CODE (operands[1]) == CONST
10334 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
10335 && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
10336 && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
10337 "__stack_chk_guard") == 0)
10338 emit_insn (gen_chk_guard_add (operands[3], operands[2]));
10339 else
10340 emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
10341 gen_rtx_REG (Pmode, PIC_REG)));
10342
10343 /* N.B. This is not constant for a GOTPLT relocation. */
10344 mem = gen_rtx_MEM (Pmode, operands[3]);
10345 MEM_NOTRAP_P (mem) = 1;
10346 /* ??? Should we have a special alias set for the GOT? */
10347 emit_move_insn (operands[0], mem);
10348
10349 DONE;
10350 })
10351
10352 (define_expand "sym2GOT"
10353 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
10354 ""
10355 "")
10356
10357 (define_expand "symGOT2reg"
10358 [(match_operand 0 "" "") (match_operand 1 "" "")]
10359 ""
10360 {
10361 rtx gotsym, insn;
10362
10363 gotsym = gen_sym2GOT (operands[1]);
10364 PUT_MODE (gotsym, Pmode);
10365 insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
10366
10367 MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
10368
10369 DONE;
10370 })
10371
10372 (define_expand "symGOTPLT2reg"
10373 [(match_operand 0 "" "") (match_operand 1 "" "")]
10374 ""
10375 {
10376 rtx pltsym = gen_rtx_CONST (Pmode,
10377 gen_rtx_UNSPEC (Pmode,
10378 gen_rtvec (1, operands[1]),
10379 UNSPEC_GOTPLT));
10380 emit_insn (gen_symGOT_load (operands[0], pltsym));
10381 DONE;
10382 })
10383
10384 (define_expand "sym2GOTOFF"
10385 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
10386 ""
10387 "")
10388
10389 (define_expand "symGOTOFF2reg"
10390 [(match_operand 0 "" "") (match_operand 1 "" "")]
10391 ""
10392 {
10393 rtx gotoffsym, insn;
10394 rtx t = (!can_create_pseudo_p ()
10395 ? operands[0]
10396 : gen_reg_rtx (GET_MODE (operands[0])));
10397
10398 gotoffsym = gen_sym2GOTOFF (operands[1]);
10399 PUT_MODE (gotoffsym, Pmode);
10400 emit_move_insn (t, gotoffsym);
10401 insn = emit_move_insn (operands[0],
10402 gen_rtx_PLUS (Pmode, t,
10403 gen_rtx_REG (Pmode, PIC_REG)));
10404
10405 set_unique_reg_note (insn, REG_EQUAL, operands[1]);
10406
10407 DONE;
10408 })
10409
10410 (define_expand "symPLT_label2reg"
10411 [(set (match_operand:SI 0 "" "")
10412 (const:SI
10413 (unspec:SI
10414 [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
10415 (const:SI (plus:SI (match_operand:SI 2 "" "")
10416 (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
10417 ;; Even though the PIC register is not really used by the call
10418 ;; sequence in which this is expanded, the PLT code assumes the PIC
10419 ;; register is set, so we must not skip its initialization. Since
10420 ;; we only use this expand as part of calling sequences, and never
10421 ;; to take the address of a function, this is the best point to
10422 ;; insert the (use). Using the PLT to take the address of a
10423 ;; function would be wrong, not only because the PLT entry could
10424 ;; then be called from a function that doesn't initialize the PIC
10425 ;; register to the proper GOT, but also because pointers to the
10426 ;; same function might not compare equal, should they be set by
10427 ;; different shared libraries.
10428 (use (reg:SI PIC_REG))]
10429 "TARGET_SH1"
10430 "")
10431
10432 (define_expand "sym2PIC"
10433 [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
10434 ""
10435 "")
10436
10437 ;; -------------------------------------------------------------------------
10438 ;; TLS code generation.
10439
10440 ;; FIXME: The multi-insn asm blocks should be converted to use
10441 ;; define_insn_and_split.
10442 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
10443 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
10444 ;; for details.
10445
10446 (define_insn "tls_global_dynamic"
10447 [(set (match_operand:SI 0 "register_operand" "=&z")
10448 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10449 UNSPEC_TLSGD))
10450 (const_int 0)))
10451 (use (reg:SI FPSCR_MODES_REG))
10452 (use (reg:SI PIC_REG))
10453 (clobber (reg:SI PR_REG))
10454 (clobber (scratch:SI))]
10455 "TARGET_SH1"
10456 {
10457 return "mov.l 1f,r4" "\n"
10458 " mova 2f,r0" "\n"
10459 " mov.l 2f,r1" "\n"
10460 " add r0,r1" "\n"
10461 " jsr @r1" "\n"
10462 " add r12,r4" "\n"
10463 " bra 3f" "\n"
10464 " nop" "\n"
10465 " .align 2" "\n"
10466 "1: .long %a1@TLSGD" "\n"
10467 "2: .long __tls_get_addr@PLT" "\n"
10468 "3:";
10469 }
10470 [(set_attr "type" "tls_load")
10471 (set_attr "length" "26")])
10472
10473 (define_insn "tls_local_dynamic"
10474 [(set (match_operand:SI 0 "register_operand" "=&z")
10475 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10476 UNSPEC_TLSLDM))
10477 (const_int 0)))
10478 (use (reg:SI FPSCR_MODES_REG))
10479 (use (reg:SI PIC_REG))
10480 (clobber (reg:SI PR_REG))
10481 (clobber (scratch:SI))]
10482 "TARGET_SH1"
10483 {
10484 return "mov.l 1f,r4" "\n"
10485 " mova 2f,r0" "\n"
10486 " mov.l 2f,r1" "\n"
10487 " add r0,r1" "\n"
10488 " jsr @r1" "\n"
10489 " add r12,r4" "\n"
10490 " bra 3f" "\n"
10491 " nop" "\n"
10492 " .align 2" "\n"
10493 "1: .long %a1@TLSLDM" "\n"
10494 "2: .long __tls_get_addr@PLT" "\n"
10495 "3:";
10496 }
10497 [(set_attr "type" "tls_load")
10498 (set_attr "length" "26")])
10499
10500 (define_expand "sym2DTPOFF"
10501 [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
10502 ""
10503 "")
10504
10505 (define_expand "symDTPOFF2reg"
10506 [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
10507 ""
10508 {
10509 rtx dtpoffsym;
10510 rtx t = (!can_create_pseudo_p ()
10511 ? operands[0]
10512 : gen_reg_rtx (GET_MODE (operands[0])));
10513
10514 dtpoffsym = gen_sym2DTPOFF (operands[1]);
10515 PUT_MODE (dtpoffsym, Pmode);
10516 emit_move_insn (t, dtpoffsym);
10517 emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
10518 DONE;
10519 })
10520
10521 (define_expand "sym2GOTTPOFF"
10522 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
10523 ""
10524 "")
10525
10526 (define_insn "tls_initial_exec"
10527 [(set (match_operand:SI 0 "register_operand" "=&r")
10528 (unspec:SI [(match_operand:SI 1 "" "")]
10529 UNSPEC_TLSIE))
10530 (use (reg:SI GBR_REG))
10531 (use (reg:SI PIC_REG))
10532 (clobber (reg:SI R0_REG))]
10533 ""
10534 {
10535 return "mov.l 1f,r0" "\n"
10536 " stc gbr,%0" "\n"
10537 " mov.l @(r0,r12),r0" "\n"
10538 " bra 2f" "\n"
10539 " add r0,%0" "\n"
10540 " .align 2" "\n"
10541 "1: .long %a1" "\n"
10542 "2:";
10543 }
10544 [(set_attr "type" "tls_load")
10545 (set_attr "length" "16")])
10546
10547 (define_expand "sym2TPOFF"
10548 [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
10549 ""
10550 "")
10551
10552 (define_expand "symTPOFF2reg"
10553 [(match_operand 0 "" "") (match_operand 1 "" "")]
10554 ""
10555 {
10556 rtx tpoffsym;
10557
10558 tpoffsym = gen_sym2TPOFF (operands[1]);
10559 PUT_MODE (tpoffsym, Pmode);
10560 emit_move_insn (operands[0], tpoffsym);
10561 DONE;
10562 })
10563
10564 ;;------------------------------------------------------------------------------
10565 ;; Thread pointer getter and setter.
10566 ;;
10567 ;; On SH the thread pointer is kept in the GBR.
10568 ;; These patterns are usually expanded from the respective built-in functions.
10569 (define_expand "get_thread_pointersi"
10570 [(set (match_operand:SI 0 "register_operand") (reg:SI GBR_REG))]
10571 "TARGET_SH1")
10572
10573 ;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses.
10574 (define_insn "store_gbr"
10575 [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))]
10576 ""
10577 "stc gbr,%0"
10578 [(set_attr "type" "tls_load")])
10579
10580 (define_expand "set_thread_pointersi"
10581 [(set (reg:SI GBR_REG)
10582 (unspec_volatile:SI [(match_operand:SI 0 "register_operand")]
10583 UNSPECV_GBR))]
10584 "TARGET_SH1")
10585
10586 (define_insn "load_gbr"
10587 [(set (reg:SI GBR_REG)
10588 (unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
10589 UNSPECV_GBR))]
10590 "TARGET_SH1"
10591 "ldc %0,gbr"
10592 [(set_attr "type" "move")])
10593
10594 ;;------------------------------------------------------------------------------
10595 ;; Thread pointer relative memory loads and stores.
10596 ;;
10597 ;; On SH there are GBR displacement address modes which can be utilized to
10598 ;; access memory behind the thread pointer.
10599 ;; Since we do not allow using GBR for general purpose memory accesses, these
10600 ;; GBR addressing modes are formed by the combine pass.
10601 ;; This could be done with fewer patterns than below by using a mem predicate
10602 ;; for the GBR mem, but then reload would try to reload addresses with a
10603 ;; zero displacement for some strange reason.
10604
10605 (define_insn "*mov<mode>_gbr_load"
10606 [(set (match_operand:QIHISI 0 "register_operand" "=z")
10607 (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10608 (match_operand:QIHISI 1 "gbr_displacement"))))]
10609 "TARGET_SH1"
10610 "mov.<bwl> @(%O1,gbr),%0"
10611 [(set_attr "type" "load")])
10612
10613 (define_insn "*mov<mode>_gbr_load"
10614 [(set (match_operand:QIHISI 0 "register_operand" "=z")
10615 (mem:QIHISI (reg:SI GBR_REG)))]
10616 "TARGET_SH1"
10617 "mov.<bwl> @(0,gbr),%0"
10618 [(set_attr "type" "load")])
10619
10620 (define_insn "*mov<mode>_gbr_load"
10621 [(set (match_operand:SI 0 "register_operand" "=z")
10622 (sign_extend:SI
10623 (mem:QIHI (plus:SI (reg:SI GBR_REG)
10624 (match_operand:QIHI 1 "gbr_displacement")))))]
10625 "TARGET_SH1"
10626 "mov.<bw> @(%O1,gbr),%0"
10627 [(set_attr "type" "load")])
10628
10629 (define_insn "*mov<mode>_gbr_load"
10630 [(set (match_operand:SI 0 "register_operand" "=z")
10631 (sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))]
10632 "TARGET_SH1"
10633 "mov.<bw> @(0,gbr),%0"
10634 [(set_attr "type" "load")])
10635
10636 (define_insn "*mov<mode>_gbr_store"
10637 [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10638 (match_operand:QIHISI 0 "gbr_displacement")))
10639 (match_operand:QIHISI 1 "register_operand" "z"))]
10640 "TARGET_SH1"
10641 "mov.<bwl> %1,@(%O0,gbr)"
10642 [(set_attr "type" "store")])
10643
10644 (define_insn "*mov<mode>_gbr_store"
10645 [(set (mem:QIHISI (reg:SI GBR_REG))
10646 (match_operand:QIHISI 0 "register_operand" "z"))]
10647 "TARGET_SH1"
10648 "mov.<bwl> %0,@(0,gbr)"
10649 [(set_attr "type" "store")])
10650
10651 ;; DImode memory accesses have to be split in two SImode accesses.
10652 ;; Split them before reload, so that it gets a better chance to figure out
10653 ;; how to deal with the R0 restriction for the individual SImode accesses.
10654 ;; Do not match this insn during or after reload because it can't be split
10655 ;; afterwards.
10656 (define_insn_and_split "*movdi_gbr_load"
10657 [(set (match_operand:DI 0 "register_operand")
10658 (match_operand:DI 1 "gbr_address_mem"))]
10659 "TARGET_SH1 && can_create_pseudo_p ()"
10660 "#"
10661 "&& 1"
10662 [(set (match_dup 3) (match_dup 5))
10663 (set (match_dup 4) (match_dup 6))]
10664 {
10665 /* Swap low/high part load order on little endian, so that the result reg
10666 of the second load can be used better. */
10667 int off = TARGET_LITTLE_ENDIAN ? 1 : 0;
10668 operands[3 + off] = gen_lowpart (SImode, operands[0]);
10669 operands[5 + off] = gen_lowpart (SImode, operands[1]);
10670 operands[4 - off] = gen_highpart (SImode, operands[0]);
10671 operands[6 - off] = gen_highpart (SImode, operands[1]);
10672 })
10673
10674 (define_insn_and_split "*movdi_gbr_store"
10675 [(set (match_operand:DI 0 "gbr_address_mem")
10676 (match_operand:DI 1 "register_operand"))]
10677 "TARGET_SH1 && can_create_pseudo_p ()"
10678 "#"
10679 "&& 1"
10680 [(set (match_dup 3) (match_dup 5))
10681 (set (match_dup 4) (match_dup 6))]
10682 {
10683 /* Swap low/high part store order on big endian, so that stores of function
10684 call results can save a reg copy. */
10685 int off = TARGET_LITTLE_ENDIAN ? 0 : 1;
10686 operands[3 + off] = gen_lowpart (SImode, operands[0]);
10687 operands[5 + off] = gen_lowpart (SImode, operands[1]);
10688 operands[4 - off] = gen_highpart (SImode, operands[0]);
10689 operands[6 - off] = gen_highpart (SImode, operands[1]);
10690 })
10691
10692 ;; Sometimes memory accesses do not get combined with the store_gbr insn,
10693 ;; in particular when the displacements are in the range of the regular move
10694 ;; insns. Thus, in the first split pass after the combine pass we search
10695 ;; for missed opportunities and try to fix them up ourselves.
10696 ;; If an equivalent GBR address can be determined the load / store is split
10697 ;; into one of the GBR load / store patterns.
10698 ;; All of that must happen before reload (GBR address modes use R0 as the
10699 ;; other operand) and there's no point of doing it if the GBR is not
10700 ;; referenced in a function at all.
10701 (define_split
10702 [(set (match_operand:QIHISIDI 0 "register_operand")
10703 (match_operand:QIHISIDI 1 "memory_operand"))]
10704 "TARGET_SH1 && !reload_in_progress && !reload_completed
10705 && df_regs_ever_live_p (GBR_REG)"
10706 [(set (match_dup 0) (match_dup 1))]
10707 {
10708 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10709 if (gbr_mem != NULL_RTX)
10710 operands[1] = replace_equiv_address (operands[1], gbr_mem);
10711 else
10712 FAIL;
10713 })
10714
10715 (define_split
10716 [(set (match_operand:SI 0 "register_operand")
10717 (sign_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10718 "TARGET_SH1 && !reload_in_progress && !reload_completed
10719 && df_regs_ever_live_p (GBR_REG)"
10720 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
10721 {
10722 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10723 if (gbr_mem != NULL_RTX)
10724 operands[1] = replace_equiv_address (operands[1], gbr_mem);
10725 else
10726 FAIL;
10727 })
10728
10729 ;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads.
10730 ;; Split those so that a GBR load can be used.
10731 (define_split
10732 [(set (match_operand:SI 0 "register_operand")
10733 (zero_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10734 "TARGET_SH2A && !reload_in_progress && !reload_completed
10735 && df_regs_ever_live_p (GBR_REG)"
10736 [(set (match_dup 2) (match_dup 1))
10737 (set (match_dup 0) (zero_extend:SI (match_dup 2)))]
10738 {
10739 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10740 if (gbr_mem != NULL_RTX)
10741 {
10742 operands[2] = gen_reg_rtx (GET_MODE (operands[1]));
10743 operands[1] = replace_equiv_address (operands[1], gbr_mem);
10744 }
10745 else
10746 FAIL;
10747 })
10748
10749 (define_split
10750 [(set (match_operand:QIHISIDI 0 "memory_operand")
10751 (match_operand:QIHISIDI 1 "register_operand"))]
10752 "TARGET_SH1 && !reload_in_progress && !reload_completed
10753 && df_regs_ever_live_p (GBR_REG)"
10754 [(set (match_dup 0) (match_dup 1))]
10755 {
10756 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]);
10757 if (gbr_mem != NULL_RTX)
10758 operands[0] = replace_equiv_address (operands[0], gbr_mem);
10759 else
10760 FAIL;
10761 })
10762
10763 ;;------------------------------------------------------------------------------
10764 ;; case instruction for switch statements.
10765
10766 ;; operand 0 is index
10767 ;; operand 1 is the minimum bound
10768 ;; operand 2 is the maximum bound - minimum bound + 1
10769 ;; operand 3 is CODE_LABEL for the table;
10770 ;; operand 4 is the CODE_LABEL to go to if index out of range.
10771 (define_expand "casesi"
10772 [(match_operand:SI 0 "arith_reg_operand" "")
10773 (match_operand:SI 1 "arith_reg_operand" "")
10774 (match_operand:SI 2 "arith_reg_operand" "")
10775 (match_operand 3 "" "") (match_operand 4 "" "")]
10776 ""
10777 {
10778 rtx reg = gen_reg_rtx (SImode);
10779 rtx reg2 = gen_reg_rtx (SImode);
10780 if (TARGET_SHMEDIA)
10781 {
10782 rtx reg = gen_reg_rtx (DImode);
10783 rtx reg2 = gen_reg_rtx (DImode);
10784 rtx reg3 = gen_reg_rtx (Pmode);
10785 rtx reg4 = gen_reg_rtx (Pmode);
10786 rtx reg5 = gen_reg_rtx (Pmode);
10787 rtx load, test;
10788
10789 operands[0] = convert_modes (DImode, SImode, operands[0], 0);
10790 operands[1] = convert_modes (DImode, SImode, operands[1], 0);
10791 operands[2] = convert_modes (DImode, SImode, operands[2], 1);
10792
10793 test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
10794 emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0],
10795 operands[4]));
10796 emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
10797 test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
10798 emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
10799 emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
10800 emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
10801 (Pmode, operands[3])));
10802 /* Messy: can we subreg to clean this up? */
10803 if (Pmode == DImode)
10804 load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
10805 else
10806 load = gen_casesi_load_media (reg4,
10807 gen_rtx_SUBREG (DImode, reg3, 0),
10808 reg2, operands[3]);
10809 PUT_MODE (SET_SRC (load), Pmode);
10810 emit_insn (load);
10811 /* ??? The following add could be eliminated if we used ptrel. */
10812 emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
10813 emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
10814 emit_barrier ();
10815 DONE;
10816 }
10817 operands[1] = copy_to_mode_reg (SImode, operands[1]);
10818 operands[2] = copy_to_mode_reg (SImode, operands[2]);
10819 /* If optimizing, casesi_worker depends on the mode of the instruction
10820 before label it 'uses' - operands[3]. */
10821 emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
10822 reg));
10823 emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
10824 if (TARGET_SH2)
10825 emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
10826 else
10827 emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
10828 /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
10829 operands[3], but to lab. We will fix this up in
10830 machine_dependent_reorg. */
10831 emit_barrier ();
10832 DONE;
10833 })
10834
10835 (define_expand "casesi_0"
10836 [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
10837 (set (match_dup 4) (minus:SI (match_dup 4)
10838 (match_operand:SI 1 "arith_operand" "")))
10839 (set (reg:SI T_REG)
10840 (gtu:SI (match_dup 4)
10841 (match_operand:SI 2 "arith_reg_operand" "")))
10842 (set (pc)
10843 (if_then_else (ne (reg:SI T_REG)
10844 (const_int 0))
10845 (label_ref (match_operand 3 "" ""))
10846 (pc)))]
10847 "TARGET_SH1"
10848 "")
10849
10850 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
10851 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
10852 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
10853 (define_insn "casesi_worker_0"
10854 [(set (match_operand:SI 0 "register_operand" "=r,r")
10855 (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
10856 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10857 (clobber (match_scratch:SI 3 "=X,1"))
10858 (clobber (match_scratch:SI 4 "=&z,z"))]
10859 "TARGET_SH1"
10860 "#")
10861
10862 (define_split
10863 [(set (match_operand:SI 0 "register_operand" "")
10864 (unspec:SI [(match_operand:SI 1 "register_operand" "")
10865 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10866 (clobber (match_scratch:SI 3 ""))
10867 (clobber (match_scratch:SI 4 ""))]
10868 "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
10869 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
10870 (parallel [(set (match_dup 0)
10871 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10872 (label_ref (match_dup 2))] UNSPEC_CASESI))
10873 (clobber (match_dup 3))])
10874 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
10875 {
10876 if (GET_CODE (operands[2]) == CODE_LABEL)
10877 LABEL_NUSES (operands[2])++;
10878 })
10879
10880 (define_split
10881 [(set (match_operand:SI 0 "register_operand" "")
10882 (unspec:SI [(match_operand:SI 1 "register_operand" "")
10883 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10884 (clobber (match_scratch:SI 3 ""))
10885 (clobber (match_scratch:SI 4 ""))]
10886 "TARGET_SH2 && reload_completed"
10887 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
10888 (parallel [(set (match_dup 0)
10889 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10890 (label_ref (match_dup 2))] UNSPEC_CASESI))
10891 (clobber (match_dup 3))])]
10892 {
10893 if (GET_CODE (operands[2]) == CODE_LABEL)
10894 LABEL_NUSES (operands[2])++;
10895 })
10896
10897 (define_insn "casesi_worker_1"
10898 [(set (match_operand:SI 0 "register_operand" "=r,r")
10899 (unspec:SI [(reg:SI R0_REG)
10900 (match_operand:SI 1 "register_operand" "0,r")
10901 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10902 (clobber (match_scratch:SI 3 "=X,1"))]
10903 "TARGET_SH1"
10904 {
10905 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2])));
10906
10907 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10908
10909 switch (GET_MODE (diff_vec))
10910 {
10911 case SImode:
10912 return "shll2 %1" "\n"
10913 " mov.l @(r0,%1),%0";
10914 case HImode:
10915 return "add %1,%1" "\n"
10916 " mov.w @(r0,%1),%0";
10917 case QImode:
10918 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10919 return "mov.b @(r0,%1),%0" "\n"
10920 " extu.b %0,%0";
10921 else
10922 return "mov.b @(r0,%1),%0";
10923
10924 default:
10925 gcc_unreachable ();
10926 }
10927 }
10928 [(set_attr "length" "4")])
10929
10930 (define_insn "casesi_worker_2"
10931 [(set (match_operand:SI 0 "register_operand" "=r,r")
10932 (unspec:SI [(reg:SI R0_REG)
10933 (match_operand:SI 1 "register_operand" "0,r")
10934 (label_ref (match_operand 2 "" ""))
10935 (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
10936 (clobber (match_operand:SI 4 "" "=X,1"))]
10937 "TARGET_SH2 && reload_completed && flag_pic"
10938 {
10939 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2])));
10940 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10941
10942 switch (GET_MODE (diff_vec))
10943 {
10944 case SImode:
10945 return "shll2 %1" "\n"
10946 " add r0,%1" "\n"
10947 " mova %O3,r0" "\n"
10948 " mov.l @(r0,%1),%0";
10949 case HImode:
10950 return "add %1,%1" "\n"
10951 " add r0,%1" "\n"
10952 " mova %O3,r0" "\n"
10953 " mov.w @(r0,%1),%0";
10954 case QImode:
10955 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10956 return "add r0,%1" "\n"
10957 " mova %O3,r0" "\n"
10958 " mov.b @(r0,%1),%0" "\n"
10959 " extu.b %0,%0";
10960 else
10961 return "add r0,%1" "\n"
10962 " mova %O3,r0" "\n"
10963 " mov.b @(r0,%1),%0";
10964 default:
10965 gcc_unreachable ();
10966 }
10967 }
10968 [(set_attr "length" "8")])
10969
10970 (define_insn "casesi_shift_media"
10971 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10972 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
10973 (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
10974 UNSPEC_CASESI)))]
10975 "TARGET_SHMEDIA"
10976 {
10977 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2])));
10978
10979 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10980
10981 switch (GET_MODE (diff_vec))
10982 {
10983 case SImode:
10984 return "shlli %1, 2, %0";
10985 case HImode:
10986 return "shlli %1, 1, %0";
10987 case QImode:
10988 if (rtx_equal_p (operands[0], operands[1]))
10989 return "";
10990 return "add %1, r63, %0";
10991 default:
10992 gcc_unreachable ();
10993 }
10994 }
10995 [(set_attr "type" "arith_media")])
10996
10997 (define_insn "casesi_load_media"
10998 [(set (match_operand 0 "any_arith_reg_dest" "=r")
10999 (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
11000 (match_operand:DI 2 "arith_reg_operand" "r")
11001 (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
11002 "TARGET_SHMEDIA"
11003 {
11004 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[3])));
11005
11006 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
11007
11008 switch (GET_MODE (diff_vec))
11009 {
11010 case SImode:
11011 return "ldx.l %1, %2, %0";
11012 case HImode:
11013 #if 0
11014 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
11015 return "ldx.uw %1, %2, %0";
11016 #endif
11017 return "ldx.w %1, %2, %0";
11018 case QImode:
11019 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
11020 return "ldx.ub %1, %2, %0";
11021 return "ldx.b %1, %2, %0";
11022 default:
11023 gcc_unreachable ();
11024 }
11025 }
11026 [(set_attr "type" "load_media")])
11027
11028 (define_expand "simple_return"
11029 [(simple_return)]
11030 "sh_can_use_simple_return_p ()")
11031
11032 (define_expand "return"
11033 [(return)]
11034 "reload_completed && epilogue_completed"
11035 {
11036 if (TARGET_SHMEDIA)
11037 {
11038 emit_jump_insn (gen_return_media ());
11039 DONE;
11040 }
11041
11042 if (TARGET_SHCOMPACT
11043 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
11044 {
11045 emit_jump_insn (gen_shcompact_return_tramp ());
11046 DONE;
11047 }
11048 })
11049
11050 (define_insn "*<code>_i"
11051 [(any_return)]
11052 "TARGET_SH1 && ! (TARGET_SHCOMPACT
11053 && (crtl->args.info.call_cookie
11054 & CALL_COOKIE_RET_TRAMP (1)))
11055 && reload_completed
11056 && ! sh_cfun_trap_exit_p ()"
11057 {
11058 if (TARGET_SH2A && (dbr_sequence_length () == 0)
11059 && !current_function_interrupt)
11060 return "rts/n";
11061 else
11062 return "%@ %#";
11063 }
11064 [(set_attr "type" "return")
11065 (set_attr "needs_delay_slot" "yes")])
11066
11067 ;; trapa has no delay slot.
11068 (define_insn "*return_trapa"
11069 [(return)]
11070 "TARGET_SH1 && !TARGET_SHCOMPACT
11071 && reload_completed"
11072 "%@"
11073 [(set_attr "type" "return")])
11074
11075 (define_expand "shcompact_return_tramp"
11076 [(return)]
11077 "TARGET_SHCOMPACT
11078 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
11079 {
11080 rtx reg = gen_rtx_REG (Pmode, R0_REG);
11081
11082 function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC);
11083 emit_jump_insn (gen_shcompact_return_tramp_i ());
11084 DONE;
11085 })
11086
11087 (define_insn "shcompact_return_tramp_i"
11088 [(parallel [(return) (use (reg:SI R0_REG))])]
11089 "TARGET_SHCOMPACT
11090 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
11091 "jmp @r0%#"
11092 [(set_attr "type" "jump_ind")
11093 (set_attr "needs_delay_slot" "yes")])
11094
11095 (define_insn "return_media_i"
11096 [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
11097 "TARGET_SHMEDIA && reload_completed"
11098 "blink %0, r63"
11099 [(set_attr "type" "jump_media")])
11100
11101 (define_insn "return_media_rte"
11102 [(return)]
11103 "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
11104 "rte"
11105 [(set_attr "type" "jump_media")])
11106
11107 (define_expand "return_media"
11108 [(return)]
11109 "TARGET_SHMEDIA && reload_completed"
11110 {
11111 int tr_regno = sh_media_register_for_return ();
11112 rtx tr;
11113
11114 if (current_function_interrupt)
11115 {
11116 emit_jump_insn (gen_return_media_rte ());
11117 DONE;
11118 }
11119 if (tr_regno < 0)
11120 {
11121 rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
11122
11123 gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
11124 tr_regno = TR0_REG;
11125 tr = gen_rtx_REG (Pmode, tr_regno);
11126 emit_move_insn (tr, r18);
11127 }
11128 else
11129 tr = gen_rtx_REG (Pmode, tr_regno);
11130
11131 emit_jump_insn (gen_return_media_i (tr));
11132 DONE;
11133 })
11134
11135 (define_insn "shcompact_preserve_incoming_args"
11136 [(set (match_operand:SI 0 "register_operand" "+r")
11137 (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
11138 "TARGET_SHCOMPACT"
11139 ""
11140 [(set_attr "length" "0")])
11141
11142 (define_insn "shcompact_incoming_args"
11143 [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
11144 (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
11145 (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
11146 (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
11147 (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
11148 (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
11149 (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
11150 (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
11151 (set (mem:BLK (reg:SI MACL_REG))
11152 (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
11153 (use (reg:SI R0_REG))
11154 (clobber (reg:SI R0_REG))
11155 (clobber (reg:SI MACL_REG))
11156 (clobber (reg:SI MACH_REG))
11157 (clobber (reg:SI PR_REG))]
11158 "TARGET_SHCOMPACT"
11159 "jsr @r0%#"
11160 [(set_attr "needs_delay_slot" "yes")])
11161
11162 (define_insn "shmedia_save_restore_regs_compact"
11163 [(set (reg:SI SP_REG)
11164 (plus:SI (reg:SI SP_REG)
11165 (match_operand:SI 0 "immediate_operand" "i")))
11166 (use (reg:SI R0_REG))
11167 (clobber (reg:SI PR_REG))]
11168 "TARGET_SHCOMPACT
11169 && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
11170 || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
11171 "jsr @r0%#"
11172 [(set_attr "needs_delay_slot" "yes")])
11173
11174 (define_expand "prologue"
11175 [(const_int 0)]
11176 ""
11177 {
11178 sh_expand_prologue ();
11179 DONE;
11180 })
11181
11182 (define_expand "epilogue"
11183 [(return)]
11184 ""
11185 {
11186 sh_expand_epilogue (false);
11187 if (TARGET_SHMEDIA
11188 || (TARGET_SHCOMPACT
11189 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))))
11190 {
11191 emit_jump_insn (gen_return ());
11192 DONE;
11193 }
11194 })
11195
11196 (define_expand "eh_return"
11197 [(use (match_operand 0 "register_operand" ""))]
11198 ""
11199 {
11200 rtx ra = operands[0];
11201
11202 if (TARGET_SHMEDIA64)
11203 emit_insn (gen_eh_set_ra_di (ra));
11204 else
11205 emit_insn (gen_eh_set_ra_si (ra));
11206
11207 DONE;
11208 })
11209
11210 ;; Clobber the return address on the stack. We can't expand this
11211 ;; until we know where it will be put in the stack frame.
11212
11213 (define_insn "eh_set_ra_si"
11214 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
11215 UNSPECV_EH_RETURN)
11216 (clobber (match_scratch:SI 1 "=&r"))]
11217 "! TARGET_SHMEDIA64"
11218 "#")
11219
11220 (define_insn "eh_set_ra_di"
11221 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
11222 UNSPECV_EH_RETURN)
11223 (clobber (match_scratch:DI 1 "=&r"))]
11224 "TARGET_SHMEDIA64"
11225 "#")
11226
11227 (define_split
11228 [(unspec_volatile [(match_operand 0 "register_operand" "")]
11229 UNSPECV_EH_RETURN)
11230 (clobber (match_scratch 1 ""))]
11231 "reload_completed"
11232 [(const_int 0)]
11233 {
11234 sh_set_return_address (operands[0], operands[1]);
11235 DONE;
11236 })
11237
11238 (define_insn "blockage"
11239 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
11240 ""
11241 ""
11242 [(set_attr "length" "0")])
11243 \f
11244 ;; Define movml instructions for SH2A target. Currently they are
11245 ;; used to push and pop all banked registers only.
11246
11247 (define_insn "movml_push_banked"
11248 [(set (match_operand:SI 0 "register_operand" "=r")
11249 (plus (match_dup 0) (const_int -32)))
11250 (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
11251 (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
11252 (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
11253 (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
11254 (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
11255 (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
11256 (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
11257 (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
11258 "TARGET_SH2A && REGNO (operands[0]) == 15"
11259 "movml.l r7,@-r15"
11260 [(set_attr "in_delay_slot" "no")])
11261
11262 (define_insn "movml_pop_banked"
11263 [(set (match_operand:SI 0 "register_operand" "=r")
11264 (plus (match_dup 0) (const_int 32)))
11265 (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
11266 (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
11267 (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
11268 (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
11269 (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
11270 (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
11271 (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
11272 (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
11273 "TARGET_SH2A && REGNO (operands[0]) == 15"
11274 "movml.l @r15+,r7"
11275 [(set_attr "in_delay_slot" "no")])
11276 \f
11277 ;; ------------------------------------------------------------------------
11278 ;; Scc instructions
11279 ;; ------------------------------------------------------------------------
11280
11281 (define_insn "movt"
11282 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11283 (match_operand:SI 1 "t_reg_operand"))]
11284 "TARGET_SH1"
11285 "movt %0"
11286 [(set_attr "type" "arith")])
11287
11288 (define_insn "movrt"
11289 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11290 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11291 "TARGET_SH2A"
11292 "movrt %0"
11293 [(set_attr "type" "arith")])
11294
11295 (define_expand "cstore4_media"
11296 [(set (match_operand:SI 0 "register_operand" "=r")
11297 (match_operator:SI 1 "sh_float_comparison_operator"
11298 [(match_operand 2 "logical_operand" "")
11299 (match_operand 3 "cmp_operand" "")]))]
11300 "TARGET_SHMEDIA"
11301 {
11302 enum machine_mode mode = GET_MODE (operands[2]);
11303 enum rtx_code code = GET_CODE (operands[1]);
11304 bool invert, swap;
11305 if (mode == VOIDmode)
11306 mode = GET_MODE (operands[3]);
11307 if (operands[2] == const0_rtx)
11308 {
11309 if (code == EQ || code == NE)
11310 operands[2] = operands[3], operands[3] = const0_rtx;
11311 }
11312 else
11313 operands[2] = force_reg (mode, operands[2]);
11314 if (operands[3] != const0_rtx)
11315 operands[3] = force_reg (mode, operands[3]);
11316
11317 switch (code)
11318 {
11319 case GEU:
11320 case GE:
11321 swap = invert = !FLOAT_MODE_P (mode);
11322 break;
11323
11324 case LEU:
11325 case LE:
11326 swap = FLOAT_MODE_P (mode), invert = !swap;
11327 break;
11328
11329 case LTU:
11330 case LT:
11331 swap = true, invert = false;
11332 break;
11333
11334 case GTU:
11335 case GT:
11336 case EQ:
11337 case UNORDERED:
11338 swap = invert = false;
11339 break;
11340
11341 case NE:
11342 swap = invert = true;
11343 break;
11344
11345 default:
11346 gcc_unreachable ();
11347 }
11348
11349 if (swap)
11350 {
11351 rtx tem = operands[2];
11352 operands[2] = operands[3];
11353 operands[3] = tem;
11354 code = swap_condition (code);
11355 }
11356
11357 if (invert)
11358 {
11359 rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
11360 code = reverse_condition (code);
11361 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11362 emit_insn (gen_cstore4_media (tem, operands[1],
11363 operands[2], operands[3]));
11364 code = EQ;
11365 operands[2] = tem;
11366 operands[3] = const0_rtx;
11367 }
11368
11369 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11370 })
11371
11372 (define_expand "cstoresi4"
11373 [(set (match_operand:SI 0 "register_operand" "=r")
11374 (match_operator:SI 1 "comparison_operator"
11375 [(match_operand:SI 2 "cmpsi_operand" "")
11376 (match_operand:SI 3 "arith_operand" "")]))]
11377 "TARGET_SH1 || TARGET_SHMEDIA"
11378 {
11379 if (TARGET_SHMEDIA)
11380 {
11381 emit_insn (gen_cstore4_media (operands[0], operands[1],
11382 operands[2], operands[3]));
11383 DONE;
11384 }
11385
11386 if (sh_expand_t_scc (operands))
11387 DONE;
11388
11389 if (! currently_expanding_to_rtl)
11390 FAIL;
11391
11392 sh_emit_compare_and_set (operands, SImode);
11393 DONE;
11394 })
11395
11396 (define_expand "cstoredi4"
11397 [(set (match_operand:SI 0 "register_operand" "=r")
11398 (match_operator:SI 1 "comparison_operator"
11399 [(match_operand:DI 2 "arith_operand" "")
11400 (match_operand:DI 3 "arith_operand" "")]))]
11401 "TARGET_SH2 || TARGET_SHMEDIA"
11402 {
11403 if (TARGET_SHMEDIA)
11404 {
11405 emit_insn (gen_cstore4_media (operands[0], operands[1],
11406 operands[2], operands[3]));
11407 DONE;
11408 }
11409
11410 if (sh_expand_t_scc (operands))
11411 DONE;
11412
11413 if (! currently_expanding_to_rtl)
11414 FAIL;
11415
11416 sh_emit_compare_and_set (operands, DImode);
11417 DONE;
11418 })
11419
11420 ;; Move the complement of the T reg to a reg.
11421 ;; On SH2A the movrt insn can be used.
11422 ;; On anything else than SH2A this has to be done with multiple instructions.
11423 ;; One obvious way would be:
11424 ;; cmp/eq ...
11425 ;; movt r0
11426 ;; xor #1,r0
11427 ;;
11428 ;; However, this puts pressure on r0 in most cases and thus the following is
11429 ;; more appealing:
11430 ;; cmp/eq ...
11431 ;; mov #-1,temp
11432 ;; negc temp,dest
11433 ;;
11434 ;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
11435 ;; becomes a one instruction operation. Moreover, care must be taken that
11436 ;; the insn can still be combined with inverted compare and branch code
11437 ;; around it. On the other hand, if a function returns the complement of
11438 ;; a previous comparison result in the T bit, the xor #1,r0 approach might
11439 ;; lead to better code.
11440 (define_expand "movnegt"
11441 [(set (match_operand:SI 0 "arith_reg_dest" "")
11442 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11443 "TARGET_SH1"
11444 {
11445 if (TARGET_SH2A)
11446 emit_insn (gen_movrt (operands[0], operands[1]));
11447 else
11448 {
11449 rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
11450 emit_insn (gen_movrt_negc (operands[0], operands[1], val));
11451 }
11452 DONE;
11453 })
11454
11455 (define_insn "movrt_negc"
11456 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11457 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11458 (set (reg:SI T_REG) (const_int 1))
11459 (use (match_operand:SI 2 "arith_reg_operand" "r"))]
11460 "TARGET_SH1"
11461 "negc %2,%0"
11462 [(set_attr "type" "arith")])
11463
11464 ;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the
11465 ;; pattern can be used by the combine pass. Using a scratch reg for the
11466 ;; -1 constant results in slightly better register allocations compared to
11467 ;; generating a pseudo reg before reload.
11468 (define_insn_and_split "*movrt_negc"
11469 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11470 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11471 (clobber (match_scratch:SI 2 "=r"))
11472 (clobber (reg:SI T_REG))]
11473 "TARGET_SH1 && ! TARGET_SH2A"
11474 "#"
11475 "&& reload_completed"
11476 [(set (match_dup 2) (const_int -1))
11477 (parallel
11478 [(set (match_dup 0) (xor:SI (match_dup 1) (const_int 1)))
11479 (set (reg:SI T_REG) (const_int 1))
11480 (use (match_dup 2))])])
11481
11482 ;; Store the negated T bit in a reg using r0 and xor. This one doesn't
11483 ;; clobber the T bit, which is useful when storing the T bit and the
11484 ;; negated T bit in parallel. On SH2A the movrt insn can be used for that.
11485 ;; Usually we don't want this insn to be matched, except for cases where the
11486 ;; T bit clobber is really not appreciated. Hence the extra use on T_REG.
11487 (define_insn_and_split "movrt_xor"
11488 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
11489 (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
11490 (use (reg:SI T_REG))]
11491 "TARGET_SH1 && !TARGET_SH2A"
11492 "#"
11493 "&& reload_completed"
11494 [(set (match_dup 0) (reg:SI T_REG))
11495 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))])
11496
11497 ;; Store the T bit and the negated T bit in two regs in parallel. There is
11498 ;; no real insn to do that, but specifying this pattern will give combine
11499 ;; some opportunities.
11500 (define_insn_and_split "*movt_movrt"
11501 [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11502 (match_operand:SI 1 "negt_reg_operand"))
11503 (set (match_operand:SI 2 "arith_reg_dest")
11504 (match_operand:SI 3 "t_reg_operand"))])]
11505 "TARGET_SH1"
11506 "#"
11507 "&& 1"
11508 [(const_int 0)]
11509 {
11510 rtx i = TARGET_SH2A
11511 ? gen_movrt (operands[0], get_t_reg_rtx ())
11512 : gen_movrt_xor (operands[0], get_t_reg_rtx ());
11513
11514 emit_insn (i);
11515 emit_insn (gen_movt (operands[2], get_t_reg_rtx ()));
11516 DONE;
11517 })
11518
11519 (define_insn_and_split "*movt_movrt"
11520 [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11521 (match_operand:SI 1 "t_reg_operand"))
11522 (set (match_operand:SI 2 "arith_reg_dest")
11523 (match_operand:SI 3 "negt_reg_operand"))])]
11524 "TARGET_SH1"
11525 "#"
11526 "&& 1"
11527 [(parallel [(set (match_dup 2) (match_dup 3))
11528 (set (match_dup 0) (match_dup 1))])])
11529
11530 ;; Use negc to store the T bit in a MSB of a reg in the following way:
11531 ;; T = 1: 0x80000000 -> reg
11532 ;; T = 0: 0x7FFFFFFF -> reg
11533 ;; This works because 0 - 0x80000000 = 0x80000000.
11534 ;;
11535 ;; This insn must not match again after it has been split into the constant
11536 ;; load and negc. This is accomplished by the special negc insn that
11537 ;; has a use on the operand.
11538 (define_insn_and_split "*mov_t_msb_neg"
11539 [(set (match_operand:SI 0 "arith_reg_dest")
11540 (minus:SI (const_int -2147483648) ;; 0x80000000
11541 (match_operand 1 "t_reg_operand")))
11542 (clobber (reg:SI T_REG))]
11543 "TARGET_SH1"
11544 "#"
11545 "&& can_create_pseudo_p ()"
11546 [(set (match_dup 2) (const_int -2147483648))
11547 (parallel [(set (match_dup 0) (minus:SI (neg:SI (match_dup 2))
11548 (reg:SI T_REG)))
11549 (clobber (reg:SI T_REG))
11550 (use (match_dup 2))])]
11551 {
11552 operands[2] = gen_reg_rtx (SImode);
11553 })
11554
11555 (define_insn "*mov_t_msb_neg_negc"
11556 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11557 (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
11558 (match_operand:SI 2 "t_reg_operand")))
11559 (clobber (reg:SI T_REG))
11560 (use (match_dup 1))]
11561 "TARGET_SH1"
11562 "negc %1,%0"
11563 [(set_attr "type" "arith")])
11564
11565 ;; These are essentially the same as above, but with the inverted T bit.
11566 ;; Combine recognizes the split patterns, but does not take them sometimes
11567 ;; if the T_REG clobber is specified. Instead it tries to split out the
11568 ;; T bit negation. Since these splits are supposed to be taken only by
11569 ;; combine, it will see the T_REG clobber of the *mov_t_msb_neg insn, so this
11570 ;; should be fine.
11571 (define_split
11572 [(set (match_operand:SI 0 "arith_reg_dest")
11573 (plus:SI (match_operand 1 "negt_reg_operand")
11574 (const_int 2147483647)))] ;; 0x7fffffff
11575 "TARGET_SH1 && can_create_pseudo_p ()"
11576 [(parallel [(set (match_dup 0)
11577 (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11578 (clobber (reg:SI T_REG))])])
11579
11580 (define_split
11581 [(set (match_operand:SI 0 "arith_reg_dest")
11582 (if_then_else:SI (match_operand 1 "t_reg_operand")
11583 (const_int 2147483647) ;; 0x7fffffff
11584 (const_int -2147483648)))] ;; 0x80000000
11585 "TARGET_SH1 && can_create_pseudo_p ()"
11586 [(parallel [(set (match_dup 0)
11587 (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11588 (clobber (reg:SI T_REG))])])
11589
11590 ;; The *negnegt pattern helps the combine pass to figure out how to fold
11591 ;; an explicit double T bit negation.
11592 (define_insn_and_split "*negnegt"
11593 [(set (reg:SI T_REG)
11594 (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
11595 "TARGET_SH1"
11596 "#"
11597 ""
11598 [(const_int 0)])
11599
11600 ;; Store T bit as all zeros or ones in a reg.
11601 (define_insn "mov_neg_si_t"
11602 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11603 (neg:SI (match_operand 1 "t_reg_operand" "")))]
11604 "TARGET_SH1"
11605 "subc %0,%0"
11606 [(set_attr "type" "arith")])
11607
11608 ;; Store negated T bit as all zeros or ones in a reg.
11609 ;; Use the following sequence:
11610 ;; subc Rn,Rn ! Rn = Rn - Rn - T; T = T
11611 ;; not Rn,Rn ! Rn = 0 - Rn
11612 (define_split
11613 [(set (match_operand:SI 0 "arith_reg_dest" "")
11614 (neg:SI (match_operand 1 "negt_reg_operand" "")))]
11615 "TARGET_SH1"
11616 [(set (match_dup 0) (neg:SI (reg:SI T_REG)))
11617 (set (match_dup 0) (not:SI (match_dup 0)))])
11618
11619 ;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
11620 (define_insn_and_split "*movtt"
11621 [(set (reg:SI T_REG)
11622 (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
11623 "TARGET_SH1"
11624 "#"
11625 ""
11626 [(const_int 0)])
11627
11628 ;; Invert the T bit.
11629 ;; On SH2A we can use the nott insn. On anything else this must be done with
11630 ;; multiple insns like:
11631 ;; movt Rn
11632 ;; tst Rn,Rn
11633 ;; This requires an additional pseudo. The SH specific sh_treg_combine RTL
11634 ;; pass will look for this insn. Disallow using it if pseudos can't be
11635 ;; created.
11636 (define_insn_and_split "nott"
11637 [(set (reg:SI T_REG)
11638 (xor:SI (match_operand:SI 0 "t_reg_operand") (const_int 1)))]
11639 "TARGET_SH2A || (TARGET_SH1 && can_create_pseudo_p ())"
11640 {
11641 gcc_assert (TARGET_SH2A);
11642 return "nott";
11643 }
11644 "! TARGET_SH2A && can_create_pseudo_p ()"
11645 [(set (match_dup 0) (reg:SI T_REG))
11646 (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
11647 {
11648 operands[0] = gen_reg_rtx (SImode);
11649 })
11650
11651 ;; Store T bit as MSB in a reg.
11652 ;; T = 0: 0x00000000 -> reg
11653 ;; T = 1: 0x80000000 -> reg
11654 (define_insn_and_split "*movt_msb"
11655 [(set (match_operand:SI 0 "arith_reg_dest")
11656 (mult:SI (match_operand:SI 1 "t_reg_operand")
11657 (const_int -2147483648))) ;; 0xffffffff80000000
11658 (clobber (reg:SI T_REG))]
11659 "TARGET_SH1"
11660 "#"
11661 "&& 1"
11662 [(set (match_dup 0) (ashift:SI (reg:SI T_REG) (const_int 31)))])
11663
11664 ;; Store inverted T bit as MSB in a reg.
11665 ;; T = 0: 0x80000000 -> reg
11666 ;; T = 1: 0x00000000 -> reg
11667 ;; On SH2A we can get away without clobbering the T_REG using the movrt insn.
11668 ;; On non SH2A we resort to the following sequence:
11669 ;; movt Rn
11670 ;; tst Rn,Rn
11671 ;; rotcr Rn
11672 ;; The T bit value will be modified during the sequence, but the rotcr insn
11673 ;; will restore its original value.
11674 (define_insn_and_split "*negt_msb"
11675 [(set (match_operand:SI 0 "arith_reg_dest")
11676 (match_operand:SI 1 "negt_reg_shl31_operand"))]
11677 "TARGET_SH1"
11678 "#"
11679 "&& can_create_pseudo_p ()"
11680 [(const_int 0)]
11681 {
11682 rtx tmp = gen_reg_rtx (SImode);
11683
11684 if (TARGET_SH2A)
11685 {
11686 emit_insn (gen_movrt (tmp, get_t_reg_rtx ()));
11687 emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx));
11688 }
11689 else
11690 {
11691 emit_move_insn (tmp, get_t_reg_rtx ());
11692 emit_insn (gen_cmpeqsi_t (tmp, const0_rtx));
11693 emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ()));
11694 }
11695 DONE;
11696 })
11697
11698 ;; The *cset_zero patterns convert optimizations such as
11699 ;; "if (test) x = 0;"
11700 ;; to
11701 ;; "x &= -(test == 0);"
11702 ;; back to conditional branch sequences if zero-displacement branches
11703 ;; are enabled.
11704 ;; FIXME: These patterns can be removed when conditional execution patterns
11705 ;; are implemented, since ifcvt will not perform these optimizations if
11706 ;; conditional execution is supported.
11707 (define_insn "*cset_zero"
11708 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11709 (and:SI (plus:SI (match_operand:SI 1 "t_reg_operand")
11710 (const_int -1))
11711 (match_operand:SI 2 "arith_reg_operand" "0")))]
11712 "TARGET_SH1 && TARGET_ZDCBRANCH"
11713 {
11714 return "bf 0f" "\n"
11715 " mov #0,%0" "\n"
11716 "0:";
11717 }
11718 [(set_attr "type" "arith") ;; poor approximation
11719 (set_attr "length" "4")])
11720
11721 (define_insn "*cset_zero"
11722 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11723 (if_then_else:SI (match_operand:SI 1 "cbranch_treg_value")
11724 (match_operand:SI 2 "arith_reg_operand" "0")
11725 (const_int 0)))]
11726 "TARGET_SH1 && TARGET_ZDCBRANCH"
11727 {
11728 int tval = sh_eval_treg_value (operands[1]);
11729 if (tval == true)
11730 return "bt 0f" "\n"
11731 " mov #0,%0" "\n"
11732 "0:";
11733 else if (tval == false)
11734 return "bf 0f" "\n"
11735 " mov #0,%0" "\n"
11736 "0:";
11737 else
11738 gcc_unreachable ();
11739 }
11740 [(set_attr "type" "arith") ;; poor approximation
11741 (set_attr "length" "4")])
11742
11743 (define_expand "cstoresf4"
11744 [(set (match_operand:SI 0 "register_operand" "=r")
11745 (match_operator:SI 1 "sh_float_comparison_operator"
11746 [(match_operand:SF 2 "arith_operand" "")
11747 (match_operand:SF 3 "arith_operand" "")]))]
11748 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11749 {
11750 if (TARGET_SHMEDIA)
11751 {
11752 emit_insn (gen_cstore4_media (operands[0], operands[1],
11753 operands[2], operands[3]));
11754 DONE;
11755 }
11756
11757 if (! currently_expanding_to_rtl)
11758 FAIL;
11759
11760 sh_emit_compare_and_set (operands, SFmode);
11761 DONE;
11762 })
11763
11764 (define_expand "cstoredf4"
11765 [(set (match_operand:SI 0 "register_operand" "=r")
11766 (match_operator:SI 1 "sh_float_comparison_operator"
11767 [(match_operand:DF 2 "arith_operand" "")
11768 (match_operand:DF 3 "arith_operand" "")]))]
11769 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11770 {
11771 if (TARGET_SHMEDIA)
11772 {
11773 emit_insn (gen_cstore4_media (operands[0], operands[1],
11774 operands[2], operands[3]));
11775 DONE;
11776 }
11777
11778 if (! currently_expanding_to_rtl)
11779 FAIL;
11780
11781 sh_emit_compare_and_set (operands, DFmode);
11782 DONE;
11783 })
11784
11785 ;; -------------------------------------------------------------------------
11786 ;; Instructions to cope with inline literal tables
11787 ;; -------------------------------------------------------------------------
11788
11789 ;; 2 byte integer in line
11790 (define_insn "consttable_2"
11791 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11792 (match_operand 1 "" "")]
11793 UNSPECV_CONST2)]
11794 ""
11795 {
11796 if (operands[1] != const0_rtx)
11797 assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
11798 return "";
11799 }
11800 [(set_attr "length" "2")
11801 (set_attr "in_delay_slot" "no")])
11802
11803 ;; 4 byte integer in line
11804 (define_insn "consttable_4"
11805 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11806 (match_operand 1 "" "")]
11807 UNSPECV_CONST4)]
11808 ""
11809 {
11810 if (operands[1] != const0_rtx)
11811 {
11812 assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
11813 mark_symbol_refs_as_used (operands[0]);
11814 }
11815 return "";
11816 }
11817 [(set_attr "length" "4")
11818 (set_attr "in_delay_slot" "no")])
11819
11820 ;; 8 byte integer in line
11821 (define_insn "consttable_8"
11822 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11823 (match_operand 1 "" "")]
11824 UNSPECV_CONST8)]
11825 ""
11826 {
11827 if (operands[1] != const0_rtx)
11828 assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
11829 return "";
11830 }
11831 [(set_attr "length" "8")
11832 (set_attr "in_delay_slot" "no")])
11833
11834 ;; 4 byte floating point
11835 (define_insn "consttable_sf"
11836 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
11837 (match_operand 1 "" "")]
11838 UNSPECV_CONST4)]
11839 ""
11840 {
11841 if (operands[1] != const0_rtx)
11842 {
11843 REAL_VALUE_TYPE d;
11844 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11845 assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
11846 }
11847 return "";
11848 }
11849 [(set_attr "length" "4")
11850 (set_attr "in_delay_slot" "no")])
11851
11852 ;; 8 byte floating point
11853 (define_insn "consttable_df"
11854 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
11855 (match_operand 1 "" "")]
11856 UNSPECV_CONST8)]
11857 ""
11858 {
11859 if (operands[1] != const0_rtx)
11860 {
11861 REAL_VALUE_TYPE d;
11862 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11863 assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
11864 }
11865 return "";
11866 }
11867 [(set_attr "length" "8")
11868 (set_attr "in_delay_slot" "no")])
11869
11870 ;; Alignment is needed for some constant tables; it may also be added for
11871 ;; Instructions at the start of loops, or after unconditional branches.
11872 ;; ??? We would get more accurate lengths if we did instruction
11873 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
11874 ;; here is too conservative.
11875
11876 ;; align to a two byte boundary
11877 (define_expand "align_2"
11878 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
11879 ""
11880 "")
11881
11882 ;; Align to a four byte boundary.
11883 ;; align_4 and align_log are instructions for the starts of loops, or
11884 ;; after unconditional branches, which may take up extra room.
11885 (define_expand "align_4"
11886 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
11887 ""
11888 "")
11889
11890 ;; Align to a cache line boundary.
11891 (define_insn "align_log"
11892 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
11893 ""
11894 ""
11895 [(set_attr "length" "0")
11896 (set_attr "in_delay_slot" "no")])
11897
11898 ;; Emitted at the end of the literal table, used to emit the
11899 ;; 32bit branch labels if needed.
11900 (define_insn "consttable_end"
11901 [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
11902 ""
11903 {
11904 return output_jump_label_table ();
11905 }
11906 [(set_attr "in_delay_slot" "no")])
11907
11908 ;; Emitted at the end of the window in the literal table.
11909 (define_insn "consttable_window_end"
11910 [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
11911 ""
11912 ""
11913 [(set_attr "length" "0")
11914 (set_attr "in_delay_slot" "no")])
11915
11916 ;; -------------------------------------------------------------------------
11917 ;; Minimum / maximum operations.
11918 ;; -------------------------------------------------------------------------
11919
11920 ;; The SH2A clips.b and clips.w insns do a signed min-max function. If smin
11921 ;; and smax standard name patterns are defined, they will be used during
11922 ;; initial expansion and combine will then be able to form the actual min-max
11923 ;; pattern.
11924 ;; The clips.b and clips.w set the SR.CS bit if the value in the register is
11925 ;; clipped, but there is currently no way of making use of this information.
11926 ;; The only way to read or reset the SR.CS bit is by accessing the SR.
11927 (define_expand "<code>si3"
11928 [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11929 (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand")
11930 (match_operand 2 "const_int_operand")))
11931 (clobber (reg:SI T_REG))])]
11932 "TARGET_SH2A"
11933 {
11934 /* Force the comparison value into a register, because greater-than
11935 comparisons can work only on registers. Combine will be able to pick up
11936 the constant value from the REG_EQUAL note when trying to form a min-max
11937 pattern. */
11938 operands[2] = force_reg (SImode, operands[2]);
11939 })
11940
11941 ;; Convert
11942 ;; smax (smin (...))
11943 ;; to
11944 ;; smin (smax (...))
11945 (define_insn_and_split "*clips"
11946 [(set (match_operand:SI 0 "arith_reg_dest")
11947 (smax:SI (smin:SI (match_operand:SI 1 "arith_reg_operand")
11948 (match_operand 2 "clips_max_const_int"))
11949 (match_operand 3 "clips_min_const_int")))]
11950 "TARGET_SH2A"
11951 "#"
11952 "&& 1"
11953 [(set (match_dup 0)
11954 (smin:SI (smax:SI (match_dup 1) (match_dup 3)) (match_dup 2)))])
11955
11956 (define_insn "*clips"
11957 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11958 (smin:SI (smax:SI (match_operand:SI 1 "arith_reg_operand" "0")
11959 (match_operand 2 "clips_min_const_int"))
11960 (match_operand 3 "clips_max_const_int")))]
11961 "TARGET_SH2A"
11962 {
11963 if (INTVAL (operands[3]) == 127)
11964 return "clips.b %0";
11965 else if (INTVAL (operands[3]) == 32767)
11966 return "clips.w %0";
11967 else
11968 gcc_unreachable ();
11969 }
11970 [(set_attr "type" "arith")])
11971
11972 ;; If the expanded smin or smax patterns were not combined, split them into
11973 ;; a compare and branch sequence, because there are no real smin or smax
11974 ;; insns.
11975 (define_insn_and_split "*<code>si3"
11976 [(set (match_operand:SI 0 "arith_reg_dest")
11977 (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand")
11978 (match_operand:SI 2 "arith_reg_or_0_or_1_operand")))
11979 (clobber (reg:SI T_REG))]
11980 "TARGET_SH2A && can_create_pseudo_p ()"
11981 "#"
11982 "&& 1"
11983 [(const_int 0)]
11984 {
11985 rtx skip_label = gen_label_rtx ();
11986 emit_move_insn (operands[0], operands[1]);
11987
11988 rtx cmp_val = operands[2];
11989 if (satisfies_constraint_M (cmp_val))
11990 cmp_val = const0_rtx;
11991
11992 emit_insn (gen_cmpgtsi_t (operands[0], cmp_val));
11993 emit_jump_insn (<CODE> == SMIN
11994 ? gen_branch_false (skip_label)
11995 : gen_branch_true (skip_label));
11996
11997 emit_label_after (skip_label, emit_move_insn (operands[0], operands[2]));
11998 DONE;
11999 })
12000
12001 ;; The SH2A clipu.b and clipu.w insns can be used to implement a min function
12002 ;; with a register and a constant.
12003 ;; The clipu.b and clipu.w set the SR.CS bit if the value in the register is
12004 ;; clipped, but there is currently no way of making use of this information.
12005 ;; The only way to read or reset the SR.CS bit is by accessing the SR.
12006 (define_expand "uminsi3"
12007 [(set (match_operand:SI 0 "arith_reg_dest")
12008 (umin:SI (match_operand:SI 1 "arith_reg_operand")
12009 (match_operand 2 "const_int_operand")))]
12010 "TARGET_SH2A"
12011 {
12012 if (INTVAL (operands[2]) == 1)
12013 {
12014 emit_insn (gen_clipu_one (operands[0], operands[1]));
12015 DONE;
12016 }
12017 else if (! clipu_max_const_int (operands[2], VOIDmode))
12018 FAIL;
12019 })
12020
12021 (define_insn "*clipu"
12022 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12023 (umin:SI (match_operand:SI 1 "arith_reg_operand" "0")
12024 (match_operand 2 "clipu_max_const_int")))]
12025 "TARGET_SH2A"
12026 {
12027 if (INTVAL (operands[2]) == 255)
12028 return "clipu.b %0";
12029 else if (INTVAL (operands[2]) == 65535)
12030 return "clipu.w %0";
12031 else
12032 gcc_unreachable ();
12033 }
12034 [(set_attr "type" "arith")])
12035
12036 (define_insn_and_split "clipu_one"
12037 [(set (match_operand:SI 0 "arith_reg_dest")
12038 (umin:SI (match_operand:SI 1 "arith_reg_operand") (const_int 1)))
12039 (clobber (reg:SI T_REG))]
12040 "TARGET_SH2A"
12041 "#"
12042 "&& can_create_pseudo_p ()"
12043 [(const_int 0)]
12044 {
12045 emit_insn (gen_cmpeqsi_t (operands[1], const0_rtx));
12046 emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
12047 DONE;
12048 })
12049
12050 ;; -------------------------------------------------------------------------
12051 ;; Misc
12052 ;; -------------------------------------------------------------------------
12053
12054 ;; String/block move insn.
12055
12056 (define_expand "movmemsi"
12057 [(parallel [(set (mem:BLK (match_operand:BLK 0))
12058 (mem:BLK (match_operand:BLK 1)))
12059 (use (match_operand:SI 2 "nonmemory_operand"))
12060 (use (match_operand:SI 3 "immediate_operand"))
12061 (clobber (reg:SI PR_REG))
12062 (clobber (reg:SI R4_REG))
12063 (clobber (reg:SI R5_REG))
12064 (clobber (reg:SI R0_REG))])]
12065 "TARGET_SH1 && ! TARGET_SH5"
12066 {
12067 if (expand_block_move (operands))
12068 DONE;
12069 else
12070 FAIL;
12071 })
12072
12073 (define_insn "block_move_real"
12074 [(parallel [(set (mem:BLK (reg:SI R4_REG))
12075 (mem:BLK (reg:SI R5_REG)))
12076 (use (match_operand:SI 0 "arith_reg_operand" "r"))
12077 (clobber (reg:SI PR_REG))
12078 (clobber (reg:SI R0_REG))])]
12079 "TARGET_SH1 && ! TARGET_HARD_SH4"
12080 "jsr @%0%#"
12081 [(set_attr "type" "sfunc")
12082 (set_attr "needs_delay_slot" "yes")])
12083
12084 (define_insn "block_lump_real"
12085 [(parallel [(set (mem:BLK (reg:SI R4_REG))
12086 (mem:BLK (reg:SI R5_REG)))
12087 (use (match_operand:SI 0 "arith_reg_operand" "r"))
12088 (use (reg:SI R6_REG))
12089 (clobber (reg:SI PR_REG))
12090 (clobber (reg:SI T_REG))
12091 (clobber (reg:SI R4_REG))
12092 (clobber (reg:SI R5_REG))
12093 (clobber (reg:SI R6_REG))
12094 (clobber (reg:SI R0_REG))])]
12095 "TARGET_SH1 && ! TARGET_HARD_SH4"
12096 "jsr @%0%#"
12097 [(set_attr "type" "sfunc")
12098 (set_attr "needs_delay_slot" "yes")])
12099
12100 (define_insn "block_move_real_i4"
12101 [(parallel [(set (mem:BLK (reg:SI R4_REG))
12102 (mem:BLK (reg:SI R5_REG)))
12103 (use (match_operand:SI 0 "arith_reg_operand" "r"))
12104 (clobber (reg:SI PR_REG))
12105 (clobber (reg:SI R0_REG))
12106 (clobber (reg:SI R1_REG))
12107 (clobber (reg:SI R2_REG))])]
12108 "TARGET_HARD_SH4"
12109 "jsr @%0%#"
12110 [(set_attr "type" "sfunc")
12111 (set_attr "needs_delay_slot" "yes")])
12112
12113 (define_insn "block_lump_real_i4"
12114 [(parallel [(set (mem:BLK (reg:SI R4_REG))
12115 (mem:BLK (reg:SI R5_REG)))
12116 (use (match_operand:SI 0 "arith_reg_operand" "r"))
12117 (use (reg:SI R6_REG))
12118 (clobber (reg:SI PR_REG))
12119 (clobber (reg:SI T_REG))
12120 (clobber (reg:SI R4_REG))
12121 (clobber (reg:SI R5_REG))
12122 (clobber (reg:SI R6_REG))
12123 (clobber (reg:SI R0_REG))
12124 (clobber (reg:SI R1_REG))
12125 (clobber (reg:SI R2_REG))
12126 (clobber (reg:SI R3_REG))])]
12127 "TARGET_HARD_SH4"
12128 "jsr @%0%#"
12129 [(set_attr "type" "sfunc")
12130 (set_attr "needs_delay_slot" "yes")])
12131
12132 ;; byte compare pattern
12133 ;; temp = a ^ b;
12134 ;; !((temp & 0xF000) && (temp & 0x0F00) && (temp & 0x00F0) && (temp & 0x000F))
12135 (define_insn "cmpstr_t"
12136 [(set (reg:SI T_REG)
12137 (eq:SI (and:SI
12138 (and:SI
12139 (and:SI
12140 (zero_extract:SI
12141 (xor:SI (match_operand:SI 0 "arith_reg_operand" "r")
12142 (match_operand:SI 1 "arith_reg_operand" "r"))
12143 (const_int 8) (const_int 0))
12144 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12145 (const_int 8) (const_int 8)))
12146 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12147 (const_int 8) (const_int 16)))
12148 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12149 (const_int 8) (const_int 24)))
12150 (const_int 0)))]
12151 "TARGET_SH1"
12152 "cmp/str %0,%1"
12153 [(set_attr "type" "mt_group")])
12154
12155 (define_expand "cmpstrsi"
12156 [(set (match_operand:SI 0 "register_operand")
12157 (compare:SI (match_operand:BLK 1 "memory_operand")
12158 (match_operand:BLK 2 "memory_operand")))
12159 (use (match_operand 3 "immediate_operand"))]
12160 "TARGET_SH1 && optimize"
12161 {
12162 if (! optimize_insn_for_size_p () && sh_expand_cmpstr (operands))
12163 DONE;
12164 else
12165 FAIL;
12166 })
12167
12168 (define_expand "cmpstrnsi"
12169 [(set (match_operand:SI 0 "register_operand")
12170 (compare:SI (match_operand:BLK 1 "memory_operand")
12171 (match_operand:BLK 2 "memory_operand")))
12172 (use (match_operand:SI 3 "immediate_operand"))
12173 (use (match_operand:SI 4 "immediate_operand"))]
12174 "TARGET_SH1 && optimize"
12175 {
12176 if (! optimize_insn_for_size_p () && sh_expand_cmpnstr (operands))
12177 DONE;
12178 else
12179 FAIL;
12180 })
12181
12182 (define_expand "strlensi"
12183 [(set (match_operand:SI 0 "register_operand")
12184 (unspec:SI [(match_operand:BLK 1 "memory_operand")
12185 (match_operand:SI 2 "immediate_operand")
12186 (match_operand:SI 3 "immediate_operand")]
12187 UNSPEC_BUILTIN_STRLEN))]
12188 "TARGET_SH1 && optimize"
12189 {
12190 if (! optimize_insn_for_size_p () && sh_expand_strlen (operands))
12191 DONE;
12192 else
12193 FAIL;
12194 })
12195
12196 (define_expand "setmemqi"
12197 [(parallel [(set (match_operand:BLK 0 "memory_operand")
12198 (match_operand 2 "const_int_operand"))
12199 (use (match_operand:QI 1 "const_int_operand"))
12200 (use (match_operand:QI 3 "const_int_operand"))])]
12201 "TARGET_SH1 && optimize"
12202 {
12203 if (optimize_insn_for_size_p ())
12204 FAIL;
12205
12206 sh_expand_setmem (operands);
12207 DONE;
12208 })
12209
12210 \f
12211 ;; -------------------------------------------------------------------------
12212 ;; Floating point instructions.
12213 ;; -------------------------------------------------------------------------
12214
12215 ;; FIXME: For now we disallow any memory operands for fpscr loads/stores,
12216 ;; except for post-inc loads and pre-dec stores for push/pop purposes.
12217 ;; This avoids problems with reload. As a consequence, user initiated fpscr
12218 ;; stores to memory will always be ferried through a general register.
12219 ;; User initiated fpscr loads always have to undergo bit masking to preserve
12220 ;; the current fpu mode settings for the compiler generated code. Thus such
12221 ;; fpscr loads will always have to go through general registers anyways.
12222 (define_insn "lds_fpscr"
12223 [(set (reg:SI FPSCR_REG)
12224 (match_operand:SI 0 "fpscr_movsrc_operand" "r,>"))
12225 (set (reg:SI FPSCR_STAT_REG)
12226 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_STAT))
12227 (set (reg:SI FPSCR_MODES_REG)
12228 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
12229 "TARGET_FPU_ANY"
12230 "@
12231 lds %0,fpscr
12232 lds.l %0,fpscr"
12233 [(set_attr "type" "gp_fpscr,mem_fpscr")])
12234
12235 ;; A move fpscr -> reg schedules like a move mac -> reg. Thus we use mac_gp
12236 ;; type for it.
12237 (define_insn "sts_fpscr"
12238 [(set (match_operand:SI 0 "fpscr_movdst_operand" "=r,<")
12239 (reg:SI FPSCR_REG))
12240 (use (reg:SI FPSCR_STAT_REG))
12241 (use (reg:SI FPSCR_MODES_REG))]
12242 "TARGET_FPU_ANY"
12243 "@
12244 sts fpscr,%0
12245 sts.l fpscr,%0"
12246 [(set_attr "type" "mac_gp,fstore")])
12247
12248 (define_expand "set_fpscr"
12249 [(parallel [(set (reg:SI FPSCR_REG)
12250 (match_operand:SI 0 "general_operand"))
12251 (set (reg:SI FPSCR_STAT_REG)
12252 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))])]
12253 "TARGET_FPU_ANY"
12254 {
12255 /* We have to mask out the FR, SZ and PR bits. To do that, we need to
12256 get the current FPSCR value first.
12257 (a & ~mask) | (b & mask) = a ^ ((a ^ b) & mask) */
12258
12259 rtx mask = force_reg (SImode, GEN_INT (FPSCR_FR | FPSCR_SZ | FPSCR_PR));
12260
12261 rtx a = force_reg (SImode, operands[0]);
12262
12263 rtx b = gen_reg_rtx (SImode);
12264 emit_insn (gen_sts_fpscr (b));
12265
12266 rtx a_xor_b = gen_reg_rtx (SImode);
12267 emit_insn (gen_xorsi3 (a_xor_b, a, b));
12268
12269 rtx a_xor_b_and_mask = gen_reg_rtx (SImode);
12270 emit_insn (gen_andsi3 (a_xor_b_and_mask, a_xor_b, mask));
12271
12272 rtx r = gen_reg_rtx (SImode);
12273 emit_insn (gen_xorsi3 (r, a_xor_b_and_mask, a));
12274 emit_insn (gen_lds_fpscr (r));
12275
12276 DONE;
12277 })
12278
12279 ;; ??? This uses the fp unit, but has no type indicating that.
12280 ;; If we did that, this would either give a bogus latency or introduce
12281 ;; a bogus FIFO constraint.
12282 ;; Since this insn is currently only used for prologues/epilogues,
12283 ;; it is probably best to claim no function unit, which matches the
12284 ;; current setting.
12285 (define_insn "toggle_sz"
12286 [(set (reg:SI FPSCR_REG)
12287 (xor:SI (reg:SI FPSCR_REG) (const_int FPSCR_SZ)))
12288 (set (reg:SI FPSCR_MODES_REG)
12289 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
12290 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12291 "fschg"
12292 [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
12293
12294 ;; Toggle FPU precision PR mode.
12295
12296 (define_insn "toggle_pr"
12297 [(set (reg:SI FPSCR_REG)
12298 (xor:SI (reg:SI FPSCR_REG) (const_int FPSCR_PR)))
12299 (set (reg:SI FPSCR_MODES_REG)
12300 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
12301 "TARGET_SH4A_FP"
12302 "fpchg"
12303 [(set_attr "type" "fpscr_toggle")])
12304
12305 (define_expand "addsf3"
12306 [(set (match_operand:SF 0 "fp_arith_reg_operand")
12307 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand")
12308 (match_operand:SF 2 "fp_arith_reg_operand")))]
12309 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12310 {
12311 if (TARGET_SH2E)
12312 {
12313 emit_insn (gen_addsf3_i (operands[0], operands[1], operands[2]));
12314 DONE;
12315 }
12316 })
12317
12318 (define_insn "*addsf3_media"
12319 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12320 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12321 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12322 "TARGET_SHMEDIA_FPU"
12323 "fadd.s %1, %2, %0"
12324 [(set_attr "type" "fparith_media")])
12325
12326 (define_insn_and_split "unary_sf_op"
12327 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12328 (vec_select:V2SF
12329 (vec_concat:V2SF
12330 (vec_select:SF
12331 (match_dup 0)
12332 (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
12333 (match_operator:SF 2 "unary_float_operator"
12334 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12335 (parallel [(match_operand 4
12336 "const_int_operand" "n")]))]))
12337 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
12338 "TARGET_SHMEDIA_FPU"
12339 "#"
12340 "TARGET_SHMEDIA_FPU && reload_completed"
12341 [(set (match_dup 5) (match_dup 6))]
12342 {
12343 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12344 rtx op1 = gen_rtx_REG (SFmode,
12345 (true_regnum (operands[1])
12346 + (INTVAL (operands[4]) ^ endian)));
12347
12348 operands[7] = gen_rtx_REG (SFmode,
12349 (true_regnum (operands[0])
12350 + (INTVAL (operands[3]) ^ endian)));
12351 operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
12352 }
12353 [(set_attr "type" "fparith_media")])
12354
12355 (define_insn_and_split "binary_sf_op0"
12356 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12357 (vec_concat:V2SF
12358 (match_operator:SF 3 "binary_float_operator"
12359 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12360 (parallel [(const_int 0)]))
12361 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
12362 (parallel [(const_int 0)]))])
12363 (vec_select:SF
12364 (match_dup 0)
12365 (parallel [(const_int 1)]))))]
12366 "TARGET_SHMEDIA_FPU"
12367 "#"
12368 "&& reload_completed"
12369 [(set (match_dup 4) (match_dup 5))]
12370 {
12371 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12372 rtx op1 = gen_rtx_REG (SFmode,
12373 true_regnum (operands[1]) + endian);
12374 rtx op2 = gen_rtx_REG (SFmode,
12375 true_regnum (operands[2]) + endian);
12376
12377 operands[4] = gen_rtx_REG (SFmode,
12378 true_regnum (operands[0]) + endian);
12379 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
12380 }
12381 [(set_attr "type" "fparith_media")])
12382
12383 (define_insn_and_split "binary_sf_op1"
12384 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12385 (vec_concat:V2SF
12386 (vec_select:SF
12387 (match_dup 0)
12388 (parallel [(const_int 0)]))
12389 (match_operator:SF 3 "binary_float_operator"
12390 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12391 (parallel [(const_int 1)]))
12392 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
12393 (parallel [(const_int 1)]))])))]
12394 "TARGET_SHMEDIA_FPU"
12395 "#"
12396 "&& reload_completed"
12397 [(set (match_dup 4) (match_dup 5))]
12398 {
12399 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12400 rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian));
12401 rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian));
12402
12403 operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian));
12404 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
12405 }
12406 [(set_attr "type" "fparith_media")])
12407
12408 (define_insn "addsf3_i"
12409 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12410 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
12411 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12412 (clobber (reg:SI FPSCR_STAT_REG))
12413 (use (reg:SI FPSCR_MODES_REG))]
12414 "TARGET_SH2E"
12415 "fadd %2,%0"
12416 [(set_attr "type" "fp")
12417 (set_attr "fp_mode" "single")])
12418
12419 (define_expand "subsf3"
12420 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12421 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12422 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
12423 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12424 {
12425 if (TARGET_SH2E)
12426 {
12427 emit_insn (gen_subsf3_i (operands[0], operands[1], operands[2]));
12428 DONE;
12429 }
12430 })
12431
12432 (define_insn "*subsf3_media"
12433 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12434 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12435 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12436 "TARGET_SHMEDIA_FPU"
12437 "fsub.s %1, %2, %0"
12438 [(set_attr "type" "fparith_media")])
12439
12440 (define_insn "subsf3_i"
12441 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12442 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
12443 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12444 (clobber (reg:SI FPSCR_STAT_REG))
12445 (use (reg:SI FPSCR_MODES_REG))]
12446 "TARGET_SH2E"
12447 "fsub %2,%0"
12448 [(set_attr "type" "fp")
12449 (set_attr "fp_mode" "single")])
12450
12451 (define_expand "mulsf3"
12452 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12453 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12454 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
12455 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12456 {
12457 if (TARGET_SH2E)
12458 {
12459 emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2]));
12460 DONE;
12461 }
12462 })
12463
12464 (define_insn "*mulsf3_media"
12465 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12466 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12467 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12468 "TARGET_SHMEDIA_FPU"
12469 "fmul.s %1, %2, %0"
12470 [(set_attr "type" "fparith_media")])
12471
12472 (define_insn "mulsf3_i"
12473 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12474 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
12475 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12476 (clobber (reg:SI FPSCR_STAT_REG))
12477 (use (reg:SI FPSCR_MODES_REG))]
12478 "TARGET_SH2E"
12479 "fmul %2,%0"
12480 [(set_attr "type" "fp")
12481 (set_attr "fp_mode" "single")])
12482
12483 ;; FMA (fused multiply-add) patterns
12484 (define_expand "fmasf4"
12485 [(set (match_operand:SF 0 "fp_arith_reg_operand")
12486 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand")
12487 (match_operand:SF 2 "fp_arith_reg_operand")
12488 (match_operand:SF 3 "fp_arith_reg_operand")))]
12489 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12490 {
12491 if (TARGET_SH2E)
12492 {
12493 emit_insn (gen_fmasf4_i (operands[0], operands[1], operands[2],
12494 operands[3]));
12495 DONE;
12496 }
12497 })
12498
12499 (define_insn "fmasf4_i"
12500 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12501 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w")
12502 (match_operand:SF 2 "fp_arith_reg_operand" "f")
12503 (match_operand:SF 3 "fp_arith_reg_operand" "0")))
12504 (clobber (reg:SI FPSCR_STAT_REG))
12505 (use (reg:SI FPSCR_MODES_REG))]
12506 "TARGET_SH2E"
12507 "fmac %1,%2,%0"
12508 [(set_attr "type" "fp")
12509 (set_attr "fp_mode" "single")])
12510
12511 (define_insn "fmasf4_media"
12512 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12513 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12514 (match_operand:SF 2 "fp_arith_reg_operand" "f")
12515 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
12516 "TARGET_SHMEDIA_FPU"
12517 "fmac.s %1, %2, %0"
12518 [(set_attr "type" "fparith_media")])
12519
12520 ;; For some cases such as 'a * b + a' the FMA pattern is not generated by
12521 ;; previous transformations. If FMA is generally allowed, let the combine
12522 ;; pass utilize it.
12523 (define_insn_and_split "*fmasf4"
12524 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12525 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
12526 (match_operand:SF 2 "fp_arith_reg_operand" "f"))
12527 (match_operand:SF 3 "arith_reg_operand" "0")))
12528 (clobber (reg:SI FPSCR_STAT_REG))
12529 (use (reg:SI FPSCR_MODES_REG))]
12530 "TARGET_SH2E && flag_fp_contract_mode != FP_CONTRACT_OFF"
12531 "fmac %1,%2,%0"
12532 "&& can_create_pseudo_p ()"
12533 [(parallel [(set (match_dup 0)
12534 (fma:SF (match_dup 1) (match_dup 2) (match_dup 3)))
12535 (clobber (reg:SI FPSCR_STAT_REG))
12536 (use (reg:SI FPSCR_MODES_REG))])]
12537 {
12538 /* Change 'b * a + a' into 'a * b + a'.
12539 This is better for register allocation. */
12540 if (REGNO (operands[2]) == REGNO (operands[3]))
12541 {
12542 rtx tmp = operands[1];
12543 operands[1] = operands[2];
12544 operands[2] = tmp;
12545 }
12546 }
12547 [(set_attr "type" "fp")
12548 (set_attr "fp_mode" "single")])
12549
12550 (define_insn "*fmasf4_media"
12551 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12552 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12553 (match_operand:SF 2 "fp_arith_reg_operand" "f"))
12554 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
12555 "TARGET_SHMEDIA_FPU && flag_fp_contract_mode != FP_CONTRACT_OFF"
12556 "fmac.s %1, %2, %0"
12557 [(set_attr "type" "fparith_media")])
12558
12559 (define_expand "divsf3"
12560 [(set (match_operand:SF 0 "fp_arith_reg_operand")
12561 (div:SF (match_operand:SF 1 "fp_arith_reg_operand")
12562 (match_operand:SF 2 "fp_arith_reg_operand")))]
12563 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12564 {
12565 if (TARGET_SH2E)
12566 {
12567 emit_insn (gen_divsf3_i (operands[0], operands[1], operands[2]));
12568 DONE;
12569 }
12570 })
12571
12572 (define_insn "*divsf3_media"
12573 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12574 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12575 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12576 "TARGET_SHMEDIA_FPU"
12577 "fdiv.s %1, %2, %0"
12578 [(set_attr "type" "fdiv_media")])
12579
12580 (define_insn "divsf3_i"
12581 [(set (match_operand:SF 0 "fp_arith_reg_dest" "=f")
12582 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
12583 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12584 (clobber (reg:SI FPSCR_STAT_REG))
12585 (use (reg:SI FPSCR_MODES_REG))]
12586 "TARGET_SH2E"
12587 "fdiv %2,%0"
12588 [(set_attr "type" "fdiv")
12589 (set_attr "fp_mode" "single")])
12590
12591 (define_insn "floatdisf2"
12592 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12593 (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
12594 "TARGET_SHMEDIA_FPU"
12595 "float.qs %1, %0"
12596 [(set_attr "type" "fpconv_media")])
12597
12598 (define_expand "floatsisf2"
12599 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12600 (float:SF (match_operand:SI 1 "fpul_operand" "")))]
12601 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12602 {
12603 if (!TARGET_SHMEDIA_FPU)
12604 {
12605 emit_insn (gen_floatsisf2_i4 (operands[0], operands[1]));
12606 DONE;
12607 }
12608 })
12609
12610 (define_insn "*floatsisf2_media"
12611 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12612 (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
12613 "TARGET_SHMEDIA_FPU"
12614 "float.ls %1, %0"
12615 [(set_attr "type" "fpconv_media")])
12616
12617 (define_insn "floatsisf2_i4"
12618 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12619 (float:SF (match_operand:SI 1 "fpul_operand" "y")))
12620 (clobber (reg:SI FPSCR_STAT_REG))
12621 (use (reg:SI FPSCR_MODES_REG))]
12622 "TARGET_SH2E"
12623 "float %1,%0"
12624 [(set_attr "type" "fp")
12625 (set_attr "fp_mode" "single")])
12626
12627 (define_insn "fix_truncsfdi2"
12628 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
12629 (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12630 "TARGET_SHMEDIA_FPU"
12631 "ftrc.sq %1, %0"
12632 [(set_attr "type" "fpconv_media")])
12633
12634 (define_expand "fix_truncsfsi2"
12635 [(set (match_operand:SI 0 "fpul_operand" "=y")
12636 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12637 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12638 {
12639 if (!TARGET_SHMEDIA_FPU)
12640 {
12641 emit_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1]));
12642 DONE;
12643 }
12644 })
12645
12646 (define_insn "*fix_truncsfsi2_media"
12647 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
12648 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12649 "TARGET_SHMEDIA_FPU"
12650 "ftrc.sl %1, %0"
12651 [(set_attr "type" "fpconv_media")])
12652
12653 (define_insn "fix_truncsfsi2_i4"
12654 [(set (match_operand:SI 0 "fpul_operand" "=y")
12655 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12656 (clobber (reg:SI FPSCR_STAT_REG))
12657 (use (reg:SI FPSCR_MODES_REG))]
12658 "TARGET_SH2E"
12659 "ftrc %1,%0"
12660 [(set_attr "type" "ftrc_s")
12661 (set_attr "fp_mode" "single")])
12662
12663 (define_insn "cmpgtsf_t"
12664 [(set (reg:SI T_REG)
12665 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12666 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12667 (clobber (reg:SI FPSCR_STAT_REG))
12668 (use (reg:SI FPSCR_MODES_REG))]
12669 "TARGET_SH2E || TARGET_SH4 || TARGET_SH2A_SINGLE"
12670 "fcmp/gt %1,%0"
12671 [(set_attr "type" "fp_cmp")
12672 (set_attr "fp_mode" "single")])
12673
12674 (define_insn "cmpeqsf_t"
12675 [(set (reg:SI T_REG)
12676 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12677 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12678 (clobber (reg:SI FPSCR_STAT_REG))
12679 (use (reg:SI FPSCR_MODES_REG))]
12680 "TARGET_SH2E || TARGET_SH4 || TARGET_SH2A_SINGLE"
12681 "fcmp/eq %1,%0"
12682 [(set_attr "type" "fp_cmp")
12683 (set_attr "fp_mode" "single")])
12684
12685 (define_insn "ieee_ccmpeqsf_t"
12686 [(set (reg:SI T_REG)
12687 (ior:SI (reg:SI T_REG)
12688 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12689 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
12690 (clobber (reg:SI FPSCR_STAT_REG))
12691 (use (reg:SI FPSCR_MODES_REG))]
12692 "TARGET_IEEE && TARGET_SH2E"
12693 {
12694 return output_ieee_ccmpeq (insn, operands);
12695 }
12696 [(set_attr "length" "4")
12697 (set_attr "fp_mode" "single")])
12698
12699 (define_insn "cmpeqsf_media"
12700 [(set (match_operand:SI 0 "register_operand" "=r")
12701 (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12702 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12703 "TARGET_SHMEDIA_FPU"
12704 "fcmpeq.s %1, %2, %0"
12705 [(set_attr "type" "fcmp_media")])
12706
12707 (define_insn "cmpgtsf_media"
12708 [(set (match_operand:SI 0 "register_operand" "=r")
12709 (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12710 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12711 "TARGET_SHMEDIA_FPU"
12712 "fcmpgt.s %1, %2, %0"
12713 [(set_attr "type" "fcmp_media")])
12714
12715 (define_insn "cmpgesf_media"
12716 [(set (match_operand:SI 0 "register_operand" "=r")
12717 (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12718 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12719 "TARGET_SHMEDIA_FPU"
12720 "fcmpge.s %1, %2, %0"
12721 [(set_attr "type" "fcmp_media")])
12722
12723 (define_insn "cmpunsf_media"
12724 [(set (match_operand:SI 0 "register_operand" "=r")
12725 (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12726 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12727 "TARGET_SHMEDIA_FPU"
12728 "fcmpun.s %1, %2, %0"
12729 [(set_attr "type" "fcmp_media")])
12730
12731 (define_expand "cbranchsf4"
12732 [(set (pc)
12733 (if_then_else (match_operator 0 "sh_float_comparison_operator"
12734 [(match_operand:SF 1 "arith_operand" "")
12735 (match_operand:SF 2 "arith_operand" "")])
12736 (match_operand 3 "" "")
12737 (pc)))]
12738 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12739 {
12740 if (TARGET_SHMEDIA)
12741 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
12742 operands[3]));
12743 else
12744 sh_emit_compare_and_branch (operands, SFmode);
12745 DONE;
12746 })
12747
12748 (define_expand "negsf2"
12749 [(set (match_operand:SF 0 "fp_arith_reg_operand")
12750 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand")))]
12751 "TARGET_SH2E || TARGET_SHMEDIA_FPU")
12752
12753 (define_insn "*negsf2_media"
12754 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12755 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12756 "TARGET_SHMEDIA_FPU"
12757 "fneg.s %1, %0"
12758 [(set_attr "type" "fmove_media")])
12759
12760 (define_insn "*negsf2_i"
12761 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12762 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))]
12763 "TARGET_SH2E"
12764 "fneg %0"
12765 [(set_attr "type" "fmove")])
12766
12767 (define_expand "sqrtsf2"
12768 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12769 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12770 "TARGET_SH3E || TARGET_SHMEDIA_FPU"
12771 {
12772 if (TARGET_SH3E)
12773 {
12774 emit_insn (gen_sqrtsf2_i (operands[0], operands[1]));
12775 DONE;
12776 }
12777 })
12778
12779 (define_insn "*sqrtsf2_media"
12780 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12781 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12782 "TARGET_SHMEDIA_FPU"
12783 "fsqrt.s %1, %0"
12784 [(set_attr "type" "fdiv_media")])
12785
12786 (define_insn "sqrtsf2_i"
12787 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12788 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12789 (clobber (reg:SI FPSCR_STAT_REG))
12790 (use (reg:SI FPSCR_MODES_REG))]
12791 "TARGET_SH3E"
12792 "fsqrt %0"
12793 [(set_attr "type" "fdiv")
12794 (set_attr "fp_mode" "single")])
12795
12796 (define_insn "rsqrtsf2"
12797 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12798 (div:SF (match_operand:SF 1 "immediate_operand" "i")
12799 (sqrt:SF (match_operand:SF 2 "fp_arith_reg_operand" "0"))))
12800 (clobber (reg:SI FPSCR_STAT_REG))
12801 (use (reg:SI FPSCR_MODES_REG))]
12802 "TARGET_FPU_ANY && TARGET_FSRRA
12803 && operands[1] == CONST1_RTX (SFmode)"
12804 "fsrra %0"
12805 [(set_attr "type" "fsrra")
12806 (set_attr "fp_mode" "single")])
12807
12808 ;; When the sincos pattern is defined, the builtin functions sin and cos
12809 ;; will be expanded to the sincos pattern and one of the output values will
12810 ;; remain unused.
12811 (define_expand "sincossf3"
12812 [(set (match_operand:SF 0 "nonimmediate_operand")
12813 (unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand")] UNSPEC_FCOSA))
12814 (set (match_operand:SF 1 "nonimmediate_operand")
12815 (unspec:SF [(match_dup 2)] UNSPEC_FSINA))]
12816 "TARGET_FPU_ANY && TARGET_FSCA"
12817 {
12818 rtx scaled = gen_reg_rtx (SFmode);
12819 rtx truncated = gen_reg_rtx (SImode);
12820 rtx fsca = gen_reg_rtx (V2SFmode);
12821 rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
12822
12823 emit_insn (gen_mulsf3 (scaled, operands[2], scale_reg));
12824 emit_insn (gen_fix_truncsfsi2 (truncated, scaled));
12825 emit_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf ()));
12826
12827 emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
12828 emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 0));
12829 DONE;
12830 })
12831
12832 (define_insn_and_split "fsca"
12833 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12834 (vec_concat:V2SF
12835 (unspec:SF [(mult:SF
12836 (float:SF (match_operand:SI 1 "fpul_fsca_operand" "y"))
12837 (match_operand:SF 2 "fsca_scale_factor" "i"))
12838 ] UNSPEC_FSINA)
12839 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
12840 ] UNSPEC_FCOSA)))
12841 (clobber (reg:SI FPSCR_STAT_REG))
12842 (use (reg:SI FPSCR_MODES_REG))]
12843 "TARGET_FPU_ANY && TARGET_FSCA"
12844 "fsca fpul,%d0"
12845 "&& !fpul_operand (operands[1], SImode)"
12846 [(const_int 0)]
12847 {
12848 /* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it
12849 to a simple reg, otherwise reload will have trouble reloading the
12850 pseudo into fpul. */
12851 rtx x = XEXP (operands[1], 0);
12852 while (x != NULL_RTX && !fpul_operand (x, SImode))
12853 {
12854 gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT);
12855 x = XEXP (x, 0);
12856 }
12857 gcc_assert (x != NULL_RTX && fpul_operand (x, SImode));
12858 emit_insn (gen_fsca (operands[0], x, operands[2]));
12859 DONE;
12860 }
12861 [(set_attr "type" "fsca")
12862 (set_attr "fp_mode" "single")])
12863
12864 (define_expand "abssf2"
12865 [(set (match_operand:SF 0 "fp_arith_reg_operand")
12866 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand")))]
12867 "TARGET_SH2E || TARGET_SHMEDIA_FPU")
12868
12869 (define_insn "*abssf2_media"
12870 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12871 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12872 "TARGET_SHMEDIA_FPU"
12873 "fabs.s %1, %0"
12874 [(set_attr "type" "fmove_media")])
12875
12876 (define_insn "*abssf2_i"
12877 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12878 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))]
12879 "TARGET_SH2E"
12880 "fabs %0"
12881 [(set_attr "type" "fmove")])
12882
12883 (define_expand "adddf3"
12884 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12885 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12886 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12887 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12888 {
12889 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12890 {
12891 emit_insn (gen_adddf3_i (operands[0], operands[1], operands[2]));
12892 DONE;
12893 }
12894 })
12895
12896 (define_insn "*adddf3_media"
12897 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12898 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12899 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12900 "TARGET_SHMEDIA_FPU"
12901 "fadd.d %1, %2, %0"
12902 [(set_attr "type" "dfparith_media")])
12903
12904 (define_insn "adddf3_i"
12905 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12906 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12907 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12908 (clobber (reg:SI FPSCR_STAT_REG))
12909 (use (reg:SI FPSCR_MODES_REG))]
12910 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12911 "fadd %2,%0"
12912 [(set_attr "type" "dfp_arith")
12913 (set_attr "fp_mode" "double")])
12914
12915 (define_expand "subdf3"
12916 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12917 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12918 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12919 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12920 {
12921 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12922 {
12923 emit_insn (gen_subdf3_i (operands[0], operands[1], operands[2]));
12924 DONE;
12925 }
12926 })
12927
12928 (define_insn "*subdf3_media"
12929 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12930 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12931 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12932 "TARGET_SHMEDIA_FPU"
12933 "fsub.d %1, %2, %0"
12934 [(set_attr "type" "dfparith_media")])
12935
12936 (define_insn "subdf3_i"
12937 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12938 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12939 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12940 (clobber (reg:SI FPSCR_STAT_REG))
12941 (use (reg:SI FPSCR_MODES_REG))]
12942 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12943 "fsub %2,%0"
12944 [(set_attr "type" "dfp_arith")
12945 (set_attr "fp_mode" "double")])
12946
12947 (define_expand "muldf3"
12948 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12949 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12950 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12951 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12952 {
12953 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12954 {
12955 emit_insn (gen_muldf3_i (operands[0], operands[1], operands[2]));
12956 DONE;
12957 }
12958 })
12959
12960 (define_insn "*muldf3_media"
12961 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12962 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12963 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12964 "TARGET_SHMEDIA_FPU"
12965 "fmul.d %1, %2, %0"
12966 [(set_attr "type" "dfmul_media")])
12967
12968 (define_insn "muldf3_i"
12969 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12970 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12971 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12972 (clobber (reg:SI FPSCR_STAT_REG))
12973 (use (reg:SI FPSCR_MODES_REG))]
12974 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12975 "fmul %2,%0"
12976 [(set_attr "type" "dfp_mul")
12977 (set_attr "fp_mode" "double")])
12978
12979 (define_expand "divdf3"
12980 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12981 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12982 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12983 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12984 {
12985 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12986 {
12987 emit_insn (gen_divdf3_i (operands[0], operands[1], operands[2]));
12988 DONE;
12989 }
12990 })
12991
12992 (define_insn "*divdf3_media"
12993 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12994 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12995 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12996 "TARGET_SHMEDIA_FPU"
12997 "fdiv.d %1, %2, %0"
12998 [(set_attr "type" "dfdiv_media")])
12999
13000 (define_insn "divdf3_i"
13001 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13002 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
13003 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
13004 (clobber (reg:SI FPSCR_STAT_REG))
13005 (use (reg:SI FPSCR_MODES_REG))]
13006 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13007 "fdiv %2,%0"
13008 [(set_attr "type" "dfdiv")
13009 (set_attr "fp_mode" "double")])
13010
13011 (define_insn "floatdidf2"
13012 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13013 (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
13014 "TARGET_SHMEDIA_FPU"
13015 "float.qd %1, %0"
13016 [(set_attr "type" "dfpconv_media")])
13017
13018 (define_expand "floatsidf2"
13019 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13020 (float:DF (match_operand:SI 1 "fpul_operand" "")))]
13021 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13022 {
13023 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13024 {
13025 emit_insn (gen_floatsidf2_i (operands[0], operands[1]));
13026 DONE;
13027 }
13028 })
13029
13030 (define_insn "*floatsidf2_media"
13031 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13032 (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
13033 "TARGET_SHMEDIA_FPU"
13034 "float.ld %1, %0"
13035 [(set_attr "type" "dfpconv_media")])
13036
13037 (define_insn "floatsidf2_i"
13038 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13039 (float:DF (match_operand:SI 1 "fpul_operand" "y")))
13040 (clobber (reg:SI FPSCR_STAT_REG))
13041 (use (reg:SI FPSCR_MODES_REG))]
13042 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13043 "float %1,%0"
13044 [(set_attr "type" "dfp_conv")
13045 (set_attr "fp_mode" "double")])
13046
13047 (define_insn "fix_truncdfdi2"
13048 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
13049 (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13050 "TARGET_SHMEDIA_FPU"
13051 "ftrc.dq %1, %0"
13052 [(set_attr "type" "dfpconv_media")])
13053
13054 (define_expand "fix_truncdfsi2"
13055 [(set (match_operand:SI 0 "fpul_operand" "")
13056 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
13057 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13058 {
13059 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13060 {
13061 emit_insn (gen_fix_truncdfsi2_i (operands[0], operands[1]));
13062 DONE;
13063 }
13064 })
13065
13066 (define_insn "*fix_truncdfsi2_media"
13067 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
13068 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13069 "TARGET_SHMEDIA_FPU"
13070 "ftrc.dl %1, %0"
13071 [(set_attr "type" "dfpconv_media")])
13072
13073 (define_insn "fix_truncdfsi2_i"
13074 [(set (match_operand:SI 0 "fpul_operand" "=y")
13075 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13076 (clobber (reg:SI FPSCR_STAT_REG))
13077 (use (reg:SI FPSCR_MODES_REG))]
13078 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13079 "ftrc %1,%0"
13080 [(set_attr "type" "dfp_conv")
13081 (set_attr "dfp_comp" "no")
13082 (set_attr "fp_mode" "double")])
13083
13084 (define_insn "cmpgtdf_t"
13085 [(set (reg:SI T_REG)
13086 (gt:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13087 (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13088 (clobber (reg:SI FPSCR_STAT_REG))
13089 (use (reg:SI FPSCR_MODES_REG))]
13090 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13091 "fcmp/gt %1,%0"
13092 [(set_attr "type" "dfp_cmp")
13093 (set_attr "fp_mode" "double")])
13094
13095 (define_insn "cmpeqdf_t"
13096 [(set (reg:SI T_REG)
13097 (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13098 (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13099 (clobber (reg:SI FPSCR_STAT_REG))
13100 (use (reg:SI FPSCR_MODES_REG))]
13101 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13102 "fcmp/eq %1,%0"
13103 [(set_attr "type" "dfp_cmp")
13104 (set_attr "fp_mode" "double")])
13105
13106 (define_insn "*ieee_ccmpeqdf_t"
13107 [(set (reg:SI T_REG)
13108 (ior:SI (reg:SI T_REG)
13109 (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13110 (match_operand:DF 1 "fp_arith_reg_operand" "f"))))
13111 (clobber (reg:SI FPSCR_STAT_REG))
13112 (use (reg:SI FPSCR_MODES_REG))]
13113 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13114 {
13115 return output_ieee_ccmpeq (insn, operands);
13116 }
13117 [(set_attr "length" "4")
13118 (set_attr "fp_mode" "double")])
13119
13120 (define_insn "cmpeqdf_media"
13121 [(set (match_operand:SI 0 "register_operand" "=r")
13122 (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13123 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13124 "TARGET_SHMEDIA_FPU"
13125 "fcmpeq.d %1,%2,%0"
13126 [(set_attr "type" "fcmp_media")])
13127
13128 (define_insn "cmpgtdf_media"
13129 [(set (match_operand:SI 0 "register_operand" "=r")
13130 (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13131 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13132 "TARGET_SHMEDIA_FPU"
13133 "fcmpgt.d %1,%2,%0"
13134 [(set_attr "type" "fcmp_media")])
13135
13136 (define_insn "cmpgedf_media"
13137 [(set (match_operand:SI 0 "register_operand" "=r")
13138 (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13139 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13140 "TARGET_SHMEDIA_FPU"
13141 "fcmpge.d %1,%2,%0"
13142 [(set_attr "type" "fcmp_media")])
13143
13144 (define_insn "cmpundf_media"
13145 [(set (match_operand:SI 0 "register_operand" "=r")
13146 (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13147 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13148 "TARGET_SHMEDIA_FPU"
13149 "fcmpun.d %1,%2,%0"
13150 [(set_attr "type" "fcmp_media")])
13151
13152 (define_expand "cbranchdf4"
13153 [(set (pc)
13154 (if_then_else (match_operator 0 "sh_float_comparison_operator"
13155 [(match_operand:DF 1 "arith_operand" "")
13156 (match_operand:DF 2 "arith_operand" "")])
13157 (match_operand 3 "" "")
13158 (pc)))]
13159 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13160 {
13161 if (TARGET_SHMEDIA)
13162 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
13163 operands[3]));
13164 else
13165 sh_emit_compare_and_branch (operands, DFmode);
13166 DONE;
13167 })
13168
13169 (define_expand "negdf2"
13170 [(set (match_operand:DF 0 "fp_arith_reg_operand")
13171 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13172 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU")
13173
13174 (define_insn "*negdf2_media"
13175 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13176 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13177 "TARGET_SHMEDIA_FPU"
13178 "fneg.d %1, %0"
13179 [(set_attr "type" "fmove_media")])
13180
13181 (define_insn "*negdf2_i"
13182 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13183 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))]
13184 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13185 "fneg %0"
13186 [(set_attr "type" "fmove")])
13187
13188 (define_expand "sqrtdf2"
13189 [(set (match_operand:DF 0 "fp_arith_reg_operand")
13190 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13191 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13192 {
13193 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13194 {
13195 emit_insn (gen_sqrtdf2_i (operands[0], operands[1]));
13196 DONE;
13197 }
13198 })
13199
13200 (define_insn "*sqrtdf2_media"
13201 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13202 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13203 "TARGET_SHMEDIA_FPU"
13204 "fsqrt.d %1, %0"
13205 [(set_attr "type" "dfdiv_media")])
13206
13207 (define_insn "sqrtdf2_i"
13208 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13209 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
13210 (clobber (reg:SI FPSCR_STAT_REG))
13211 (use (reg:SI FPSCR_MODES_REG))]
13212 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13213 "fsqrt %0"
13214 [(set_attr "type" "dfdiv")
13215 (set_attr "fp_mode" "double")])
13216
13217 (define_expand "absdf2"
13218 [(set (match_operand:DF 0 "fp_arith_reg_operand")
13219 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13220 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU")
13221
13222 (define_insn "*absdf2_media"
13223 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13224 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13225 "TARGET_SHMEDIA_FPU"
13226 "fabs.d %1, %0"
13227 [(set_attr "type" "fmove_media")])
13228
13229 (define_insn "*absdf2_i"
13230 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13231 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))]
13232 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13233 "fabs %0"
13234 [(set_attr "type" "fmove")])
13235
13236 (define_expand "extendsfdf2"
13237 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13238 (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
13239 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13240 {
13241 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13242 {
13243 emit_insn (gen_extendsfdf2_i4 (operands[0], operands[1]));
13244 DONE;
13245 }
13246 })
13247
13248 (define_insn "*extendsfdf2_media"
13249 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13250 (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13251 "TARGET_SHMEDIA_FPU"
13252 "fcnv.sd %1, %0"
13253 [(set_attr "type" "dfpconv_media")])
13254
13255 (define_insn "extendsfdf2_i4"
13256 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13257 (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
13258 (clobber (reg:SI FPSCR_STAT_REG))
13259 (use (reg:SI FPSCR_MODES_REG))]
13260 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13261 "fcnvsd %1,%0"
13262 [(set_attr "type" "fp")
13263 (set_attr "fp_mode" "double")])
13264
13265 (define_expand "truncdfsf2"
13266 [(set (match_operand:SF 0 "fpul_operand" "")
13267 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
13268 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13269 {
13270 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13271 {
13272 emit_insn (gen_truncdfsf2_i4 (operands[0], operands[1]));
13273 DONE;
13274 }
13275 })
13276
13277 (define_insn "*truncdfsf2_media"
13278 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13279 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13280 "TARGET_SHMEDIA_FPU"
13281 "fcnv.ds %1, %0"
13282 [(set_attr "type" "dfpconv_media")])
13283
13284 (define_insn "truncdfsf2_i4"
13285 [(set (match_operand:SF 0 "fpul_operand" "=y")
13286 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13287 (clobber (reg:SI FPSCR_STAT_REG))
13288 (use (reg:SI FPSCR_MODES_REG))]
13289 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13290 "fcnvds %1,%0"
13291 [(set_attr "type" "fp")
13292 (set_attr "fp_mode" "double")])
13293 \f
13294 ;; -------------------------------------------------------------------------
13295 ;; Bit field extract patterns.
13296 ;; -------------------------------------------------------------------------
13297
13298 ;; These give better code for packed bitfields, because they allow
13299 ;; auto-increment addresses to be generated.
13300
13301 (define_expand "insv"
13302 [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
13303 (match_operand:SI 1 "immediate_operand" "")
13304 (match_operand:SI 2 "immediate_operand" ""))
13305 (match_operand:SI 3 "general_operand" ""))]
13306 "TARGET_SH1 && TARGET_BIG_ENDIAN"
13307 {
13308 rtx addr_target, orig_address, shift_reg, qi_val;
13309 HOST_WIDE_INT bitsize, size, v = 0;
13310 rtx x = operands[3];
13311
13312 if (TARGET_SH2A && TARGET_BITOPS
13313 && (satisfies_constraint_Sbw (operands[0])
13314 || satisfies_constraint_Sbv (operands[0]))
13315 && satisfies_constraint_M (operands[1])
13316 && satisfies_constraint_K03 (operands[2]))
13317 {
13318 if (satisfies_constraint_N (operands[3]))
13319 {
13320 emit_insn (gen_bclr_m2a (operands[0], operands[2]));
13321 DONE;
13322 }
13323 else if (satisfies_constraint_M (operands[3]))
13324 {
13325 emit_insn (gen_bset_m2a (operands[0], operands[2]));
13326 DONE;
13327 }
13328 else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
13329 && satisfies_constraint_M (operands[1]))
13330 {
13331 emit_insn (gen_bst_m2a (operands[0], operands[2]));
13332 DONE;
13333 }
13334 else if (REG_P (operands[3])
13335 && satisfies_constraint_M (operands[1]))
13336 {
13337 emit_insn (gen_bld_reg (operands[3], const0_rtx));
13338 emit_insn (gen_bst_m2a (operands[0], operands[2]));
13339 DONE;
13340 }
13341 }
13342 /* ??? expmed doesn't care for non-register predicates. */
13343 if (! memory_operand (operands[0], VOIDmode)
13344 || ! immediate_operand (operands[1], VOIDmode)
13345 || ! immediate_operand (operands[2], VOIDmode)
13346 || ! general_operand (x, VOIDmode))
13347 FAIL;
13348 /* If this isn't a 16 / 24 / 32 bit field, or if
13349 it doesn't start on a byte boundary, then fail. */
13350 bitsize = INTVAL (operands[1]);
13351 if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
13352 || (INTVAL (operands[2]) % 8) != 0)
13353 FAIL;
13354
13355 size = bitsize / 8;
13356 orig_address = XEXP (operands[0], 0);
13357 shift_reg = gen_reg_rtx (SImode);
13358 if (CONST_INT_P (x))
13359 {
13360 v = INTVAL (x);
13361 qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
13362 }
13363 else
13364 {
13365 emit_insn (gen_movsi (shift_reg, operands[3]));
13366 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13367 }
13368 addr_target = copy_addr_to_reg (plus_constant (Pmode,
13369 orig_address, size - 1));
13370
13371 operands[0] = replace_equiv_address (operands[0], addr_target);
13372 emit_insn (gen_movqi (operands[0], qi_val));
13373
13374 while (size -= 1)
13375 {
13376 if (CONST_INT_P (x))
13377 qi_val
13378 = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
13379 else
13380 {
13381 emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
13382 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13383 }
13384 emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
13385 emit_insn (gen_movqi (operands[0], qi_val));
13386 }
13387
13388 DONE;
13389 })
13390
13391 (define_insn "movua"
13392 [(set (match_operand:SI 0 "register_operand" "=z")
13393 (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
13394 UNSPEC_MOVUA))]
13395 "TARGET_SH4A"
13396 "movua.l %1,%0"
13397 [(set_attr "type" "movua")])
13398
13399 ;; We shouldn't need this, but cse replaces increments with references
13400 ;; to other regs before flow has a chance to create post_inc
13401 ;; addressing modes, and only postreload's cse_move2add brings the
13402 ;; increments back to a usable form.
13403 (define_peephole2
13404 [(set (match_operand:SI 0 "register_operand" "")
13405 (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
13406 (const_int 32) (const_int 0)))
13407 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
13408 "TARGET_SH4A && REGNO (operands[0]) != REGNO (operands[1])"
13409 [(set (match_operand:SI 0 "register_operand" "")
13410 (sign_extract:SI (mem:SI (post_inc:SI
13411 (match_operand:SI 1 "register_operand" "")))
13412 (const_int 32) (const_int 0)))]
13413 "")
13414
13415 (define_expand "extv"
13416 [(set (match_operand:SI 0 "register_operand" "")
13417 (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
13418 (match_operand 2 "const_int_operand" "")
13419 (match_operand 3 "const_int_operand" "")))]
13420 "TARGET_SH4A || TARGET_SH2A"
13421 {
13422 if (TARGET_SH2A && TARGET_BITOPS
13423 && (satisfies_constraint_Sbw (operands[1])
13424 || satisfies_constraint_Sbv (operands[1]))
13425 && satisfies_constraint_M (operands[2])
13426 && satisfies_constraint_K03 (operands[3]))
13427 {
13428 emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
13429 if (REGNO (operands[0]) != T_REG)
13430 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
13431 DONE;
13432 }
13433 if (TARGET_SH4A
13434 && INTVAL (operands[2]) == 32
13435 && INTVAL (operands[3]) == 0
13436 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
13437 {
13438 rtx src = adjust_address (operands[1], BLKmode, 0);
13439 set_mem_size (src, 4);
13440 emit_insn (gen_movua (operands[0], src));
13441 DONE;
13442 }
13443
13444 FAIL;
13445 })
13446
13447 (define_expand "extzv"
13448 [(set (match_operand:SI 0 "register_operand" "")
13449 (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
13450 (match_operand 2 "const_int_operand" "")
13451 (match_operand 3 "const_int_operand" "")))]
13452 "TARGET_SH4A || TARGET_SH2A"
13453 {
13454 if (TARGET_SH2A && TARGET_BITOPS
13455 && (satisfies_constraint_Sbw (operands[1])
13456 || satisfies_constraint_Sbv (operands[1]))
13457 && satisfies_constraint_M (operands[2])
13458 && satisfies_constraint_K03 (operands[3]))
13459 {
13460 emit_insn (gen_bld_m2a (operands[1], operands[3]));
13461 if (REGNO (operands[0]) != T_REG)
13462 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
13463 DONE;
13464 }
13465 if (TARGET_SH4A
13466 && INTVAL (operands[2]) == 32
13467 && INTVAL (operands[3]) == 0
13468 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
13469 {
13470 rtx src = adjust_address (operands[1], BLKmode, 0);
13471 set_mem_size (src, 4);
13472 emit_insn (gen_movua (operands[0], src));
13473 DONE;
13474 }
13475
13476 FAIL;
13477 })
13478
13479 ;; SH2A instructions for bitwise operations.
13480 ;; FIXME: Convert multiple instruction insns to insn_and_split.
13481 ;; FIXME: Use iterators to fold at least and,xor,or insn variations.
13482
13483 ;; Clear a bit in a memory location.
13484 (define_insn "bclr_m2a"
13485 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13486 (and:QI
13487 (not:QI (ashift:QI (const_int 1)
13488 (match_operand:QI 1 "const_int_operand" "K03,K03")))
13489 (match_dup 0)))]
13490 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13491 "@
13492 bclr.b %1,%0
13493 bclr.b %1,@(0,%t0)"
13494 [(set_attr "length" "4,4")])
13495
13496 (define_insn "bclrmem_m2a"
13497 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13498 (and:QI (match_dup 0)
13499 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
13500 "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
13501 "@
13502 bclr.b %W1,%0
13503 bclr.b %W1,@(0,%t0)"
13504 [(set_attr "length" "4,4")])
13505
13506 ;; Set a bit in a memory location.
13507 (define_insn "bset_m2a"
13508 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13509 (ior:QI
13510 (ashift:QI (const_int 1)
13511 (match_operand:QI 1 "const_int_operand" "K03,K03"))
13512 (match_dup 0)))]
13513 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13514 "@
13515 bset.b %1,%0
13516 bset.b %1,@(0,%t0)"
13517 [(set_attr "length" "4,4")])
13518
13519 (define_insn "bsetmem_m2a"
13520 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13521 (ior:QI (match_dup 0)
13522 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
13523 "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
13524 "@
13525 bset.b %V1,%0
13526 bset.b %V1,@(0,%t0)"
13527 [(set_attr "length" "4,4")])
13528
13529 ;;; Transfer the contents of the T bit to a specified bit of memory.
13530 (define_insn "bst_m2a"
13531 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
13532 (if_then_else (eq (reg:SI T_REG) (const_int 0))
13533 (and:QI
13534 (not:QI (ashift:QI (const_int 1)
13535 (match_operand:QI 1 "const_int_operand" "K03,K03")))
13536 (match_dup 0))
13537 (ior:QI
13538 (ashift:QI (const_int 1) (match_dup 1))
13539 (match_dup 0))))]
13540 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13541 "@
13542 bst.b %1,%0
13543 bst.b %1,@(0,%t0)"
13544 [(set_attr "length" "4")])
13545
13546 ;; Store a specified bit of memory in the T bit.
13547 (define_insn "bld_m2a"
13548 [(set (reg:SI T_REG)
13549 (zero_extract:SI
13550 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
13551 (const_int 1)
13552 (match_operand 1 "const_int_operand" "K03,K03")))]
13553 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13554 "@
13555 bld.b %1,%0
13556 bld.b %1,@(0,%t0)"
13557 [(set_attr "length" "4,4")])
13558
13559 ;; Store a specified bit of memory in the T bit.
13560 (define_insn "bldsign_m2a"
13561 [(set (reg:SI T_REG)
13562 (sign_extract:SI
13563 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13564 (const_int 1)
13565 (match_operand 1 "const_int_operand" "K03,K03")))]
13566 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13567 "@
13568 bld.b %1,%0
13569 bld.b %1,@(0,%t0)"
13570 [(set_attr "length" "4,4")])
13571
13572 ;; Store a specified bit of the LSB 8 bits of a register in the T bit.
13573 (define_insn "bld_reg"
13574 [(set (reg:SI T_REG)
13575 (zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
13576 (const_int 1)
13577 (match_operand 1 "const_int_operand" "K03")))]
13578 "TARGET_SH2A && satisfies_constraint_K03 (operands[1])"
13579 "bld %1,%0")
13580
13581 (define_insn "*bld_regqi"
13582 [(set (reg:SI T_REG)
13583 (zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
13584 (const_int 1)
13585 (match_operand 1 "const_int_operand" "K03")))]
13586 "TARGET_SH2A && satisfies_constraint_K03 (operands[1])"
13587 "bld %1,%0")
13588
13589 ;; Take logical and of a specified bit of memory with the T bit and
13590 ;; store its result in the T bit.
13591 (define_insn "band_m2a"
13592 [(set (reg:SI T_REG)
13593 (and:SI (reg:SI T_REG)
13594 (zero_extract:SI
13595 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13596 (const_int 1)
13597 (match_operand 1 "const_int_operand" "K03,K03"))))]
13598 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13599 "@
13600 band.b %1,%0
13601 band.b %1,@(0,%t0)"
13602 [(set_attr "length" "4,4")])
13603
13604 (define_insn "bandreg_m2a"
13605 [(set (match_operand:SI 0 "register_operand" "=r,r")
13606 (and:SI (zero_extract:SI
13607 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13608 (const_int 1)
13609 (match_operand 2 "const_int_operand" "K03,K03"))
13610 (match_operand:SI 3 "register_operand" "r,r")))]
13611 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13612 {
13613 static const char* alt[] =
13614 {
13615 "band.b %2,%1" "\n"
13616 " movt %0",
13617
13618 "band.b %2,@(0,%t1)" "\n"
13619 " movt %0"
13620 };
13621 return alt[which_alternative];
13622 }
13623 [(set_attr "length" "6,6")])
13624
13625 ;; Take logical or of a specified bit of memory with the T bit and
13626 ;; store its result in the T bit.
13627 (define_insn "bor_m2a"
13628 [(set (reg:SI T_REG)
13629 (ior:SI (reg:SI T_REG)
13630 (zero_extract:SI
13631 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13632 (const_int 1)
13633 (match_operand 1 "const_int_operand" "K03,K03"))))]
13634 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13635 "@
13636 bor.b %1,%0
13637 bor.b %1,@(0,%t0)"
13638 [(set_attr "length" "4,4")])
13639
13640 (define_insn "borreg_m2a"
13641 [(set (match_operand:SI 0 "register_operand" "=r,r")
13642 (ior:SI (zero_extract:SI
13643 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13644 (const_int 1)
13645 (match_operand 2 "const_int_operand" "K03,K03"))
13646 (match_operand:SI 3 "register_operand" "=r,r")))]
13647 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13648 {
13649 static const char* alt[] =
13650 {
13651 "bor.b %2,%1" "\n"
13652 " movt %0",
13653
13654 "bor.b %2,@(0,%t1)" "\n"
13655 " movt %0"
13656 };
13657 return alt[which_alternative];
13658 }
13659 [(set_attr "length" "6,6")])
13660
13661 ;; Take exclusive or of a specified bit of memory with the T bit and
13662 ;; store its result in the T bit.
13663 (define_insn "bxor_m2a"
13664 [(set (reg:SI T_REG)
13665 (xor:SI (reg:SI T_REG)
13666 (zero_extract:SI
13667 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13668 (const_int 1)
13669 (match_operand 1 "const_int_operand" "K03,K03"))))]
13670 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13671 "@
13672 bxor.b %1,%0
13673 bxor.b %1,@(0,%t0)"
13674 [(set_attr "length" "4,4")])
13675
13676 (define_insn "bxorreg_m2a"
13677 [(set (match_operand:SI 0 "register_operand" "=r,r")
13678 (xor:SI (zero_extract:SI
13679 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13680 (const_int 1)
13681 (match_operand 2 "const_int_operand" "K03,K03"))
13682 (match_operand:SI 3 "register_operand" "=r,r")))]
13683 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13684 {
13685 static const char* alt[] =
13686 {
13687 "bxor.b %2,%1" "\n"
13688 " movt %0",
13689
13690 "bxor.b %2,@(0,%t1)" "\n"
13691 " movt %0"
13692 };
13693 return alt[which_alternative];
13694 }
13695 [(set_attr "length" "6,6")])
13696 \f
13697 ;; -------------------------------------------------------------------------
13698 ;; Peepholes
13699 ;; -------------------------------------------------------------------------
13700 ;; This matches cases where the bit in a memory location is set.
13701 (define_peephole2
13702 [(set (match_operand:SI 0 "register_operand")
13703 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand")))
13704 (set (match_dup 0)
13705 (ior:SI (match_dup 0)
13706 (match_operand:SI 2 "const_int_operand")))
13707 (set (match_dup 1)
13708 (match_operand 3 "arith_reg_operand"))]
13709 "TARGET_SH2A && TARGET_BITOPS
13710 && satisfies_constraint_Pso (operands[2])
13711 && REGNO (operands[0]) == REGNO (operands[3])"
13712 [(set (match_dup 1)
13713 (ior:QI (match_dup 1) (match_dup 2)))]
13714 "")
13715
13716 ;; This matches cases where the bit in a memory location is cleared.
13717 (define_peephole2
13718 [(set (match_operand:SI 0 "register_operand")
13719 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand")))
13720 (set (match_dup 0)
13721 (and:SI (match_dup 0)
13722 (match_operand:SI 2 "const_int_operand")))
13723 (set (match_dup 1)
13724 (match_operand 3 "arith_reg_operand"))]
13725 "TARGET_SH2A && TARGET_BITOPS
13726 && satisfies_constraint_Psz (operands[2])
13727 && REGNO (operands[0]) == REGNO (operands[3])"
13728 [(set (match_dup 1)
13729 (and:QI (match_dup 1) (match_dup 2)))]
13730 "")
13731
13732 ;; This matches cases where a stack pointer increment at the start of the
13733 ;; epilogue combines with a stack slot read loading the return value.
13734 (define_peephole
13735 [(set (match_operand:SI 0 "arith_reg_operand" "")
13736 (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
13737 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
13738 "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
13739 "mov.l @%1+,%0")
13740
13741 ;; See the comment on the dt combiner pattern above.
13742 (define_peephole
13743 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
13744 (plus:SI (match_dup 0)
13745 (const_int -1)))
13746 (set (reg:SI T_REG)
13747 (eq:SI (match_dup 0) (const_int 0)))]
13748 "TARGET_SH2"
13749 "dt %0")
13750
13751 ;; The following peepholes fold load sequences for which reload was not
13752 ;; able to generate a displacement addressing move insn.
13753 ;; This can happen when reload has to transform a move insn
13754 ;; without displacement into one with displacement. Or when reload can't
13755 ;; fit a displacement into the insn's constraints. In the latter case, the
13756 ;; load destination reg remains at r0, which reload compensates by inserting
13757 ;; another mov insn.
13758
13759 ;; Fold sequence:
13760 ;; mov #54,r0
13761 ;; mov.{b,w} @(r0,r15),r0
13762 ;; mov r0,r3
13763 ;; into:
13764 ;; mov.{b,w} @(54,r15),r3
13765 ;;
13766 (define_peephole2
13767 [(set (match_operand:SI 0 "arith_reg_dest" "")
13768 (match_operand:SI 1 "const_int_operand" ""))
13769 (set (match_operand:SI 2 "arith_reg_dest" "")
13770 (sign_extend:SI
13771 (mem:QI (plus:SI (match_dup 0)
13772 (match_operand:SI 3 "arith_reg_operand" "")))))
13773 (set (match_operand:QI 4 "arith_reg_dest" "")
13774 (match_operand:QI 5 "arith_reg_operand" ""))]
13775 "TARGET_SH2A
13776 && sh_legitimate_index_p (QImode, operands[1], true, true)
13777 && REGNO (operands[2]) == REGNO (operands[5])
13778 && peep2_reg_dead_p (3, operands[5])"
13779 [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))]
13780 "")
13781
13782 (define_peephole2
13783 [(set (match_operand:SI 0 "arith_reg_dest" "")
13784 (match_operand:SI 1 "const_int_operand" ""))
13785 (set (match_operand:SI 2 "arith_reg_dest" "")
13786 (sign_extend:SI
13787 (mem:HI (plus:SI (match_dup 0)
13788 (match_operand:SI 3 "arith_reg_operand" "")))))
13789 (set (match_operand:HI 4 "arith_reg_dest" "")
13790 (match_operand:HI 5 "arith_reg_operand" ""))]
13791 "TARGET_SH2A
13792 && sh_legitimate_index_p (HImode, operands[1], true, true)
13793 && REGNO (operands[2]) == REGNO (operands[5])
13794 && peep2_reg_dead_p (3, operands[5])"
13795 [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))]
13796 "")
13797
13798 ;; Fold sequence:
13799 ;; mov #54,r0
13800 ;; mov.{b,w} @(r0,r15),r1
13801 ;; into:
13802 ;; mov.{b,w} @(54,r15),r1
13803 ;;
13804 (define_peephole2
13805 [(set (match_operand:SI 0 "arith_reg_dest" "")
13806 (match_operand:SI 1 "const_int_operand" ""))
13807 (set (match_operand:SI 2 "arith_reg_dest" "")
13808 (sign_extend:SI
13809 (mem:QI (plus:SI (match_dup 0)
13810 (match_operand:SI 3 "arith_reg_operand" "")))))]
13811 "TARGET_SH2A
13812 && sh_legitimate_index_p (QImode, operands[1], true, true)
13813 && (peep2_reg_dead_p (2, operands[0])
13814 || REGNO (operands[0]) == REGNO (operands[2]))"
13815 [(set (match_dup 2)
13816 (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))]
13817 "")
13818
13819 (define_peephole2
13820 [(set (match_operand:SI 0 "arith_reg_dest" "")
13821 (match_operand:SI 1 "const_int_operand" ""))
13822 (set (match_operand:SI 2 "arith_reg_dest" "")
13823 (sign_extend:SI
13824 (mem:HI (plus:SI (match_dup 0)
13825 (match_operand:SI 3 "arith_reg_operand" "")))))]
13826 "TARGET_SH2A
13827 && sh_legitimate_index_p (HImode, operands[1], true, true)
13828 && (peep2_reg_dead_p (2, operands[0])
13829 || REGNO (operands[0]) == REGNO (operands[2]))"
13830 [(set (match_dup 2)
13831 (sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))]
13832 "")
13833
13834 ;; Fold sequence:
13835 ;; mov.{b,w} @(r0,r15),r0
13836 ;; mov r0,r3
13837 ;; into:
13838 ;; mov.{b,w} @(r0,r15),r3
13839 ;;
13840 ;; This can happen when initially a displacement address is picked, where
13841 ;; the destination reg is fixed to r0, and then the address is transformed
13842 ;; into 'r0 + reg'.
13843 (define_peephole2
13844 [(set (match_operand:SI 0 "arith_reg_dest" "")
13845 (sign_extend:SI
13846 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13847 (match_operand:SI 2 "arith_reg_operand" "")))))
13848 (set (match_operand:QI 3 "arith_reg_dest" "")
13849 (match_operand:QI 4 "arith_reg_operand" ""))]
13850 "TARGET_SH1
13851 && REGNO (operands[0]) == REGNO (operands[4])
13852 && peep2_reg_dead_p (2, operands[0])"
13853 [(set (match_dup 3)
13854 (mem:QI (plus:SI (match_dup 1) (match_dup 2))))]
13855 "")
13856
13857 (define_peephole2
13858 [(set (match_operand:SI 0 "arith_reg_dest" "")
13859 (sign_extend:SI
13860 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13861 (match_operand:SI 2 "arith_reg_operand" "")))))
13862 (set (match_operand:HI 3 "arith_reg_dest" "")
13863 (match_operand:HI 4 "arith_reg_operand" ""))]
13864 "TARGET_SH1
13865 && REGNO (operands[0]) == REGNO (operands[4])
13866 && peep2_reg_dead_p (2, operands[0])"
13867 [(set (match_dup 3)
13868 (mem:HI (plus:SI (match_dup 1) (match_dup 2))))]
13869 "")
13870
13871 (define_peephole
13872 [(set (match_operand:SI 0 "register_operand" "=r")
13873 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13874 (set (mem:SF (match_dup 0))
13875 (match_operand:SF 2 "general_movsrc_operand" ""))]
13876 "TARGET_SH1 && REGNO (operands[0]) == 0
13877 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
13878 || (GET_CODE (operands[2]) == SUBREG
13879 && REGNO (SUBREG_REG (operands[2])) < 16))
13880 && reg_unused_after (operands[0], insn)"
13881 "mov.l %2,@(%0,%1)")
13882
13883 (define_peephole
13884 [(set (match_operand:SI 0 "register_operand" "=r")
13885 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13886 (set (match_operand:SF 2 "general_movdst_operand" "")
13887
13888 (mem:SF (match_dup 0)))]
13889 "TARGET_SH1 && REGNO (operands[0]) == 0
13890 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
13891 || (GET_CODE (operands[2]) == SUBREG
13892 && REGNO (SUBREG_REG (operands[2])) < 16))
13893 && reg_unused_after (operands[0], insn)"
13894 "mov.l @(%0,%1),%2")
13895
13896 (define_peephole
13897 [(set (match_operand:SI 0 "register_operand" "=r")
13898 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13899 (set (mem:SF (match_dup 0))
13900 (match_operand:SF 2 "general_movsrc_operand" ""))]
13901 "TARGET_SH2E && REGNO (operands[0]) == 0
13902 && ((REG_P (operands[2])
13903 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
13904 || (GET_CODE (operands[2]) == SUBREG
13905 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
13906 && reg_unused_after (operands[0], insn)"
13907 "fmov{.s|} %2,@(%0,%1)")
13908
13909 (define_peephole
13910 [(set (match_operand:SI 0 "register_operand" "=r")
13911 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13912 (set (match_operand:SF 2 "general_movdst_operand" "")
13913
13914 (mem:SF (match_dup 0)))]
13915 "TARGET_SH2E && REGNO (operands[0]) == 0
13916 && ((REG_P (operands[2])
13917 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
13918 || (GET_CODE (operands[2]) == SUBREG
13919 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
13920 && reg_unused_after (operands[0], insn)"
13921 "fmov{.s|} @(%0,%1),%2")
13922
13923 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).
13924 (define_insn "sp_switch_1"
13925 [(set (reg:SI SP_REG) (unspec_volatile [(match_operand:SI 0 "" "")]
13926 UNSPECV_SP_SWITCH_B))]
13927 "TARGET_SH1"
13928 {
13929 return "mov.l r0,@-r15" "\n"
13930 " mov.l %0,r0" "\n"
13931 " mov.l @r0,r0" "\n"
13932 " mov.l r15,@-r0" "\n"
13933 " mov r0,r15";
13934 }
13935 [(set_attr "length" "10")])
13936
13937 ;; Switch back to the original stack for interrupt functions with the
13938 ;; sp_switch attribute.
13939 (define_insn "sp_switch_2"
13940 [(unspec_volatile [(const_int 0)]
13941 UNSPECV_SP_SWITCH_E)]
13942 "TARGET_SH1"
13943 {
13944 return "mov.l @r15,r15" "\n"
13945 " mov.l @r15+,r0";
13946 }
13947 [(set_attr "length" "4")])
13948
13949 ;; -------------------------------------------------------------------------
13950 ;; Integer vector moves
13951 ;; -------------------------------------------------------------------------
13952
13953 (define_expand "movv8qi"
13954 [(set (match_operand:V8QI 0 "general_movdst_operand" "")
13955 (match_operand:V8QI 1 "general_movsrc_operand" ""))]
13956 "TARGET_SHMEDIA"
13957 {
13958 prepare_move_operands (operands, V8QImode);
13959 })
13960
13961 (define_insn "movv8qi_i"
13962 [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
13963 (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13964 "TARGET_SHMEDIA
13965 && (register_operand (operands[0], V8QImode)
13966 || sh_register_operand (operands[1], V8QImode))"
13967 "@
13968 add %1, r63, %0
13969 movi %1, %0
13970 #
13971 ld%M1.q %m1, %0
13972 st%M0.q %m0, %N1"
13973 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
13974 (set_attr "length" "4,4,16,4,4")])
13975
13976 (define_split
13977 [(set (match_operand:V8QI 0 "arith_reg_dest" "")
13978 (subreg:V8QI (const_int 0) 0))]
13979 "TARGET_SHMEDIA"
13980 [(set (match_dup 0)
13981 (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
13982 (const_int 0) (const_int 0) (const_int 0)
13983 (const_int 0) (const_int 0)]))])
13984
13985 (define_split
13986 [(set (match_operand 0 "arith_reg_dest" "")
13987 (match_operand 1 "sh_rep_vec" ""))]
13988 "TARGET_SHMEDIA && reload_completed
13989 && GET_MODE (operands[0]) == GET_MODE (operands[1])
13990 && sh_vector_mode_supported_p (GET_MODE (operands[0]))
13991 && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
13992 && (XVECEXP (operands[1], 0, 0) != const0_rtx
13993 || XVECEXP (operands[1], 0, 1) != const0_rtx)
13994 && (XVECEXP (operands[1], 0, 0) != constm1_rtx
13995 || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
13996 [(set (match_dup 0) (match_dup 1))
13997 (match_dup 2)]
13998 {
13999 int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
14000 rtx elt1 = XVECEXP (operands[1], 0, 1);
14001
14002 if (unit_size > 2)
14003 operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
14004 else
14005 {
14006 if (unit_size < 2)
14007 operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
14008 operands[2] = gen_mperm_w0 (operands[0], operands[0]);
14009 }
14010 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
14011 operands[1] = XVECEXP (operands[1], 0, 0);
14012 if (unit_size < 2)
14013 {
14014 if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
14015 operands[1]
14016 = GEN_INT (TARGET_LITTLE_ENDIAN
14017 ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
14018 : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
14019 else
14020 {
14021 operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
14022 operands[1]
14023 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
14024 }
14025 }
14026 })
14027
14028 (define_split
14029 [(set (match_operand 0 "arith_reg_dest" "")
14030 (match_operand 1 "sh_const_vec" ""))]
14031 "TARGET_SHMEDIA && reload_completed
14032 && GET_MODE (operands[0]) == GET_MODE (operands[1])
14033 && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
14034 [(set (match_dup 0) (match_dup 1))]
14035 {
14036 rtx v = operands[1];
14037 enum machine_mode new_mode
14038 = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
14039
14040 operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
14041 operands[1]
14042 = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
14043 })
14044
14045 (define_expand "movv2hi"
14046 [(set (match_operand:V2HI 0 "general_movdst_operand" "")
14047 (match_operand:V2HI 1 "general_movsrc_operand" ""))]
14048 "TARGET_SHMEDIA"
14049 {
14050 prepare_move_operands (operands, V2HImode);
14051 })
14052
14053 (define_insn "movv2hi_i"
14054 [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
14055 (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
14056 "TARGET_SHMEDIA
14057 && (register_operand (operands[0], V2HImode)
14058 || sh_register_operand (operands[1], V2HImode))"
14059 "@
14060 add.l %1, r63, %0
14061 movi %1, %0
14062 #
14063 ld%M1.l %m1, %0
14064 st%M0.l %m0, %N1"
14065 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
14066 (set_attr "length" "4,4,16,4,4")
14067 (set (attr "highpart")
14068 (cond [(match_test "sh_contains_memref_p (insn)")
14069 (const_string "user")]
14070 (const_string "ignore")))])
14071
14072 (define_expand "movv4hi"
14073 [(set (match_operand:V4HI 0 "general_movdst_operand" "")
14074 (match_operand:V4HI 1 "general_movsrc_operand" ""))]
14075 "TARGET_SHMEDIA"
14076 {
14077 prepare_move_operands (operands, V4HImode);
14078 })
14079
14080 (define_insn "movv4hi_i"
14081 [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
14082 (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
14083 "TARGET_SHMEDIA
14084 && (register_operand (operands[0], V4HImode)
14085 || sh_register_operand (operands[1], V4HImode))"
14086 "@
14087 add %1, r63, %0
14088 movi %1, %0
14089 #
14090 ld%M1.q %m1, %0
14091 st%M0.q %m0, %N1"
14092 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
14093 (set_attr "length" "4,4,16,4,4")
14094 (set_attr "highpart" "depend")])
14095
14096 (define_expand "movv2si"
14097 [(set (match_operand:V2SI 0 "general_movdst_operand" "")
14098 (match_operand:V2SI 1 "general_movsrc_operand" ""))]
14099 "TARGET_SHMEDIA"
14100 {
14101 prepare_move_operands (operands, V2SImode);
14102 })
14103
14104 (define_insn "movv2si_i"
14105 [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
14106 (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
14107 "TARGET_SHMEDIA
14108 && (register_operand (operands[0], V2SImode)
14109 || sh_register_operand (operands[1], V2SImode))"
14110 "@
14111 add %1, r63, %0
14112 #
14113 #
14114 ld%M1.q %m1, %0
14115 st%M0.q %m0, %N1"
14116 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
14117 (set_attr "length" "4,4,16,4,4")
14118 (set_attr "highpart" "depend")])
14119
14120 ;; -------------------------------------------------------------------------
14121 ;; Multimedia Intrinsics
14122 ;; -------------------------------------------------------------------------
14123
14124 (define_insn "absv2si2"
14125 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14126 (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
14127 "TARGET_SHMEDIA"
14128 "mabs.l %1, %0"
14129 [(set_attr "type" "mcmp_media")
14130 (set_attr "highpart" "depend")])
14131
14132 (define_insn "absv4hi2"
14133 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14134 (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
14135 "TARGET_SHMEDIA"
14136 "mabs.w %1, %0"
14137 [(set_attr "type" "mcmp_media")
14138 (set_attr "highpart" "depend")])
14139
14140 (define_insn "addv2si3"
14141 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14142 (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
14143 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14144 "TARGET_SHMEDIA"
14145 "madd.l %1, %2, %0"
14146 [(set_attr "type" "arith_media")
14147 (set_attr "highpart" "depend")])
14148
14149 (define_insn "addv4hi3"
14150 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14151 (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
14152 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14153 "TARGET_SHMEDIA"
14154 "madd.w %1, %2, %0"
14155 [(set_attr "type" "arith_media")
14156 (set_attr "highpart" "depend")])
14157
14158 (define_insn_and_split "addv2hi3"
14159 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
14160 (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
14161 (match_operand:V2HI 2 "extend_reg_operand" "r")))]
14162 "TARGET_SHMEDIA"
14163 "#"
14164 "TARGET_SHMEDIA"
14165 [(const_int 0)]
14166 {
14167 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
14168 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
14169 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
14170 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
14171 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
14172
14173 emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
14174 emit_insn (gen_truncdisi2 (si_dst, di_dst));
14175 DONE;
14176 }
14177 [(set_attr "highpart" "must_split")])
14178
14179 (define_insn "ssaddv2si3"
14180 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14181 (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
14182 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14183 "TARGET_SHMEDIA"
14184 "madds.l %1, %2, %0"
14185 [(set_attr "type" "mcmp_media")
14186 (set_attr "highpart" "depend")])
14187
14188 (define_insn "usaddv8qi3"
14189 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14190 (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
14191 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
14192 "TARGET_SHMEDIA"
14193 "madds.ub %1, %2, %0"
14194 [(set_attr "type" "mcmp_media")
14195 (set_attr "highpart" "depend")])
14196
14197 (define_insn "ssaddv4hi3"
14198 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14199 (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
14200 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14201 "TARGET_SHMEDIA"
14202 "madds.w %1, %2, %0"
14203 [(set_attr "type" "mcmp_media")
14204 (set_attr "highpart" "depend")])
14205
14206 (define_insn "negcmpeqv8qi"
14207 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14208 (neg:V8QI (eq:V8QI
14209 (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
14210 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
14211 "TARGET_SHMEDIA"
14212 "mcmpeq.b %N1, %N2, %0"
14213 [(set_attr "type" "mcmp_media")
14214 (set_attr "highpart" "depend")])
14215
14216 (define_insn "negcmpeqv2si"
14217 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14218 (neg:V2SI (eq:V2SI
14219 (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
14220 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
14221 "TARGET_SHMEDIA"
14222 "mcmpeq.l %N1, %N2, %0"
14223 [(set_attr "type" "mcmp_media")
14224 (set_attr "highpart" "depend")])
14225
14226 (define_insn "negcmpeqv4hi"
14227 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14228 (neg:V4HI (eq:V4HI
14229 (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
14230 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14231 "TARGET_SHMEDIA"
14232 "mcmpeq.w %N1, %N2, %0"
14233 [(set_attr "type" "mcmp_media")
14234 (set_attr "highpart" "depend")])
14235
14236 (define_insn "negcmpgtuv8qi"
14237 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14238 (neg:V8QI (gtu:V8QI
14239 (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
14240 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
14241 "TARGET_SHMEDIA"
14242 "mcmpgt.ub %N1, %N2, %0"
14243 [(set_attr "type" "mcmp_media")
14244 (set_attr "highpart" "depend")])
14245
14246 (define_insn "negcmpgtv2si"
14247 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14248 (neg:V2SI (gt:V2SI
14249 (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
14250 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
14251 "TARGET_SHMEDIA"
14252 "mcmpgt.l %N1, %N2, %0"
14253 [(set_attr "type" "mcmp_media")
14254 (set_attr "highpart" "depend")])
14255
14256 (define_insn "negcmpgtv4hi"
14257 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14258 (neg:V4HI (gt:V4HI
14259 (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
14260 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14261 "TARGET_SHMEDIA"
14262 "mcmpgt.w %N1, %N2, %0"
14263 [(set_attr "type" "mcmp_media")
14264 (set_attr "highpart" "depend")])
14265
14266 (define_insn "mcmv"
14267 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14268 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14269 (match_operand:DI 2 "arith_reg_operand" "r"))
14270 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
14271 (not:DI (match_dup 2)))))]
14272 "TARGET_SHMEDIA"
14273 "mcmv %N1, %2, %0"
14274 [(set_attr "type" "arith_media")
14275 (set_attr "highpart" "depend")])
14276
14277 (define_insn "mcnvs_lw"
14278 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14279 (vec_concat:V4HI
14280 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
14281 (ss_truncate:V2HI
14282 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
14283 "TARGET_SHMEDIA"
14284 "mcnvs.lw %N1, %N2, %0"
14285 [(set_attr "type" "mcmp_media")])
14286
14287 (define_insn "mcnvs_wb"
14288 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14289 (vec_concat:V8QI
14290 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
14291 (ss_truncate:V4QI
14292 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14293 "TARGET_SHMEDIA"
14294 "mcnvs.wb %N1, %N2, %0"
14295 [(set_attr "type" "mcmp_media")])
14296
14297 (define_insn "mcnvs_wub"
14298 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14299 (vec_concat:V8QI
14300 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
14301 (us_truncate:V4QI
14302 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14303 "TARGET_SHMEDIA"
14304 "mcnvs.wub %N1, %N2, %0"
14305 [(set_attr "type" "mcmp_media")])
14306
14307 (define_insn "mextr_rl"
14308 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14309 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14310 (match_operand:HI 3 "mextr_bit_offset" "i"))
14311 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14312 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
14313 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
14314 {
14315 static char templ[21];
14316 sprintf (templ, "mextr%d %%N1, %%N2, %%0",
14317 (int) INTVAL (operands[3]) >> 3);
14318 return templ;
14319 }
14320 [(set_attr "type" "arith_media")])
14321
14322 (define_insn "*mextr_lr"
14323 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14324 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14325 (match_operand:HI 3 "mextr_bit_offset" "i"))
14326 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14327 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
14328 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
14329 {
14330 static char templ[21];
14331 sprintf (templ, "mextr%d %%N2, %%N1, %%0",
14332 (int) INTVAL (operands[4]) >> 3);
14333 return templ;
14334 }
14335 [(set_attr "type" "arith_media")])
14336
14337 ; mextrN can be modelled with vec_select / vec_concat, but the selection
14338 ; vector then varies depending on endianness.
14339 (define_expand "mextr1"
14340 [(match_operand:DI 0 "arith_reg_dest" "")
14341 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14342 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14343 "TARGET_SHMEDIA"
14344 {
14345 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14346 GEN_INT (1 * 8), GEN_INT (7 * 8)));
14347 DONE;
14348 })
14349
14350 (define_expand "mextr2"
14351 [(match_operand:DI 0 "arith_reg_dest" "")
14352 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14353 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14354 "TARGET_SHMEDIA"
14355 {
14356 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14357 GEN_INT (2 * 8), GEN_INT (6 * 8)));
14358 DONE;
14359 })
14360
14361 (define_expand "mextr3"
14362 [(match_operand:DI 0 "arith_reg_dest" "")
14363 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14364 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14365 "TARGET_SHMEDIA"
14366 {
14367 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14368 GEN_INT (3 * 8), GEN_INT (5 * 8)));
14369 DONE;
14370 })
14371
14372 (define_expand "mextr4"
14373 [(match_operand:DI 0 "arith_reg_dest" "")
14374 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14375 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14376 "TARGET_SHMEDIA"
14377 {
14378 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14379 GEN_INT (4 * 8), GEN_INT (4 * 8)));
14380 DONE;
14381 })
14382
14383 (define_expand "mextr5"
14384 [(match_operand:DI 0 "arith_reg_dest" "")
14385 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14386 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14387 "TARGET_SHMEDIA"
14388 {
14389 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14390 GEN_INT (5 * 8), GEN_INT (3 * 8)));
14391 DONE;
14392 })
14393
14394 (define_expand "mextr6"
14395 [(match_operand:DI 0 "arith_reg_dest" "")
14396 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14397 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14398 "TARGET_SHMEDIA"
14399 {
14400 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14401 GEN_INT (6 * 8), GEN_INT (2 * 8)));
14402 DONE;
14403 })
14404
14405 (define_expand "mextr7"
14406 [(match_operand:DI 0 "arith_reg_dest" "")
14407 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14408 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14409 "TARGET_SHMEDIA"
14410 {
14411 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14412 GEN_INT (7 * 8), GEN_INT (1 * 8)));
14413 DONE;
14414 })
14415
14416 (define_expand "mmacfx_wl"
14417 [(match_operand:V2SI 0 "arith_reg_dest" "")
14418 (match_operand:V2HI 1 "extend_reg_operand" "")
14419 (match_operand:V2HI 2 "extend_reg_operand" "")
14420 (match_operand:V2SI 3 "arith_reg_operand" "")]
14421 "TARGET_SHMEDIA"
14422 {
14423 emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
14424 operands[1], operands[2]));
14425 DONE;
14426 })
14427
14428 ;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
14429 ;; is depend
14430 (define_insn "mmacfx_wl_i"
14431 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14432 (ss_plus:V2SI
14433 (match_operand:V2SI 1 "arith_reg_operand" "0")
14434 (ss_truncate:V2SI
14435 (ashift:V2DI
14436 (sign_extend:V2DI
14437 (mult:V2SI
14438 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
14439 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
14440 (const_int 1)))))]
14441 "TARGET_SHMEDIA"
14442 "mmacfx.wl %2, %3, %0"
14443 [(set_attr "type" "mac_media")
14444 (set_attr "highpart" "depend")])
14445
14446 (define_expand "mmacnfx_wl"
14447 [(match_operand:V2SI 0 "arith_reg_dest" "")
14448 (match_operand:V2HI 1 "extend_reg_operand" "")
14449 (match_operand:V2HI 2 "extend_reg_operand" "")
14450 (match_operand:V2SI 3 "arith_reg_operand" "")]
14451 "TARGET_SHMEDIA"
14452 {
14453 emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
14454 operands[1], operands[2]));
14455 DONE;
14456 })
14457
14458 (define_insn "mmacnfx_wl_i"
14459 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14460 (ss_minus:V2SI
14461 (match_operand:V2SI 1 "arith_reg_operand" "0")
14462 (ss_truncate:V2SI
14463 (ashift:V2DI
14464 (sign_extend:V2DI
14465 (mult:V2SI
14466 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
14467 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
14468 (const_int 1)))))]
14469 "TARGET_SHMEDIA"
14470 "mmacnfx.wl %2, %3, %0"
14471 [(set_attr "type" "mac_media")
14472 (set_attr "highpart" "depend")])
14473
14474 (define_insn "mulv2si3"
14475 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14476 (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14477 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14478 "TARGET_SHMEDIA"
14479 "mmul.l %1, %2, %0"
14480 [(set_attr "type" "d2mpy_media")
14481 (set_attr "highpart" "depend")])
14482
14483 (define_insn "mulv4hi3"
14484 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14485 (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14486 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14487 "TARGET_SHMEDIA"
14488 "mmul.w %1, %2, %0"
14489 [(set_attr "type" "dmpy_media")
14490 (set_attr "highpart" "depend")])
14491
14492 (define_insn "mmulfx_l"
14493 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14494 (ss_truncate:V2SI
14495 (ashiftrt:V2DI
14496 (mult:V2DI
14497 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14498 (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
14499 (const_int 31))))]
14500 "TARGET_SHMEDIA"
14501 "mmulfx.l %1, %2, %0"
14502 [(set_attr "type" "d2mpy_media")
14503 (set_attr "highpart" "depend")])
14504
14505 (define_insn "mmulfx_w"
14506 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14507 (ss_truncate:V4HI
14508 (ashiftrt:V4SI
14509 (mult:V4SI
14510 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14511 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14512 (const_int 15))))]
14513 "TARGET_SHMEDIA"
14514 "mmulfx.w %1, %2, %0"
14515 [(set_attr "type" "dmpy_media")
14516 (set_attr "highpart" "depend")])
14517
14518 (define_insn "mmulfxrp_w"
14519 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14520 (ss_truncate:V4HI
14521 (ashiftrt:V4SI
14522 (plus:V4SI
14523 (mult:V4SI
14524 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14525 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14526 (const_int 16384))
14527 (const_int 15))))]
14528 "TARGET_SHMEDIA"
14529 "mmulfxrp.w %1, %2, %0"
14530 [(set_attr "type" "dmpy_media")
14531 (set_attr "highpart" "depend")])
14532
14533
14534 (define_expand "mmulhi_wl"
14535 [(match_operand:V2SI 0 "arith_reg_dest" "")
14536 (match_operand:V4HI 1 "arith_reg_operand" "")
14537 (match_operand:V4HI 2 "arith_reg_operand" "")]
14538 "TARGET_SHMEDIA"
14539 {
14540 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
14541 (operands[0], operands[1], operands[2]));
14542 DONE;
14543 })
14544
14545 (define_expand "mmullo_wl"
14546 [(match_operand:V2SI 0 "arith_reg_dest" "")
14547 (match_operand:V4HI 1 "arith_reg_operand" "")
14548 (match_operand:V4HI 2 "arith_reg_operand" "")]
14549 "TARGET_SHMEDIA"
14550 {
14551 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
14552 (operands[0], operands[1], operands[2]));
14553 DONE;
14554 })
14555
14556 (define_insn "mmul23_wl"
14557 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14558 (vec_select:V2SI
14559 (mult:V4SI
14560 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14561 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14562 (parallel [(const_int 2) (const_int 3)])))]
14563 "TARGET_SHMEDIA"
14564 {
14565 return (TARGET_LITTLE_ENDIAN
14566 ? "mmulhi.wl %1, %2, %0"
14567 : "mmullo.wl %1, %2, %0");
14568 }
14569 [(set_attr "type" "dmpy_media")
14570 (set (attr "highpart")
14571 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14572 (const_string "user")))])
14573
14574 (define_insn "mmul01_wl"
14575 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14576 (vec_select:V2SI
14577 (mult:V4SI
14578 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14579 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14580 (parallel [(const_int 0) (const_int 1)])))]
14581 "TARGET_SHMEDIA"
14582 {
14583 return (TARGET_LITTLE_ENDIAN
14584 ? "mmullo.wl %1, %2, %0"
14585 : "mmulhi.wl %1, %2, %0");
14586 }
14587 [(set_attr "type" "dmpy_media")
14588 (set (attr "highpart")
14589 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14590 (const_string "user")))])
14591
14592
14593 (define_expand "mmulsum_wq"
14594 [(match_operand:DI 0 "arith_reg_dest" "")
14595 (match_operand:V4HI 1 "arith_reg_operand" "")
14596 (match_operand:V4HI 2 "arith_reg_operand" "")
14597 (match_operand:DI 3 "arith_reg_operand" "")]
14598 "TARGET_SHMEDIA"
14599 {
14600 emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
14601 operands[1], operands[2]));
14602 DONE;
14603 })
14604
14605 (define_insn "mmulsum_wq_i"
14606 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14607 (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
14608 (plus:DI
14609 (plus:DI
14610 (vec_select:DI
14611 (mult:V4DI
14612 (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
14613 (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
14614 (parallel [(const_int 0)]))
14615 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14616 (sign_extend:V4DI (match_dup 3)))
14617 (parallel [(const_int 1)])))
14618 (plus:DI
14619 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14620 (sign_extend:V4DI (match_dup 3)))
14621 (parallel [(const_int 2)]))
14622 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14623 (sign_extend:V4DI (match_dup 3)))
14624 (parallel [(const_int 3)]))))))]
14625 "TARGET_SHMEDIA"
14626 "mmulsum.wq %2, %3, %0"
14627 [(set_attr "type" "mac_media")])
14628
14629 (define_expand "mperm_w"
14630 [(match_operand:V4HI 0 "arith_reg_dest" "=r")
14631 (match_operand:V4HI 1 "arith_reg_operand" "r")
14632 (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
14633 "TARGET_SHMEDIA"
14634 {
14635 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
14636 (operands[0], operands[1], operands[2]));
14637 DONE;
14638 })
14639
14640 ; This use of vec_select isn't exactly correct according to rtl.texi
14641 ; (because not constant), but it seems a straightforward extension.
14642 (define_insn "mperm_w_little"
14643 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14644 (vec_select:V4HI
14645 (match_operand:V4HI 1 "arith_reg_operand" "r")
14646 (parallel
14647 [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
14648 (const_int 2) (const_int 0))
14649 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
14650 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
14651 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
14652 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
14653 "mperm.w %1, %N2, %0"
14654 [(set_attr "type" "arith_media")])
14655
14656 (define_insn "mperm_w_big"
14657 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14658 (vec_select:V4HI
14659 (match_operand:V4HI 1 "arith_reg_operand" "r")
14660 (parallel
14661 [(zero_extract:QI (not:QI (match_operand:QI 2
14662 "extend_reg_or_0_operand" "rZ"))
14663 (const_int 2) (const_int 0))
14664 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
14665 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
14666 (zero_extract:QI (not:QI (match_dup 2))
14667 (const_int 2) (const_int 6))])))]
14668 "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
14669 "mperm.w %1, %N2, %0"
14670 [(set_attr "type" "arith_media")])
14671
14672 (define_insn "mperm_w0"
14673 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14674 (vec_duplicate:V4HI (truncate:HI (match_operand 1
14675 "trunc_hi_operand" "r"))))]
14676 "TARGET_SHMEDIA"
14677 "mperm.w %1, r63, %0"
14678 [(set_attr "type" "arith_media")
14679 (set_attr "highpart" "ignore")])
14680
14681 (define_expand "msad_ubq"
14682 [(match_operand:DI 0 "arith_reg_dest" "")
14683 (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
14684 (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
14685 (match_operand:DI 3 "arith_reg_operand" "")]
14686 "TARGET_SHMEDIA"
14687 {
14688 emit_insn (gen_msad_ubq_i (operands[0], operands[3],
14689 operands[1], operands[2]));
14690 DONE;
14691 })
14692
14693 (define_insn "msad_ubq_i"
14694 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14695 (plus:DI
14696 (plus:DI
14697 (plus:DI
14698 (plus:DI
14699 (match_operand:DI 1 "arith_reg_operand" "0")
14700 (abs:DI (vec_select:DI
14701 (minus:V8DI
14702 (zero_extend:V8DI
14703 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14704 (zero_extend:V8DI
14705 (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
14706 (parallel [(const_int 0)]))))
14707 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14708 (zero_extend:V8DI (match_dup 3)))
14709 (parallel [(const_int 1)]))))
14710 (plus:DI
14711 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14712 (zero_extend:V8DI (match_dup 3)))
14713 (parallel [(const_int 2)])))
14714 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14715 (zero_extend:V8DI (match_dup 3)))
14716 (parallel [(const_int 3)])))))
14717 (plus:DI
14718 (plus:DI
14719 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14720 (zero_extend:V8DI (match_dup 3)))
14721 (parallel [(const_int 4)])))
14722 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14723 (zero_extend:V8DI (match_dup 3)))
14724 (parallel [(const_int 5)]))))
14725 (plus:DI
14726 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14727 (zero_extend:V8DI (match_dup 3)))
14728 (parallel [(const_int 6)])))
14729 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14730 (zero_extend:V8DI (match_dup 3)))
14731 (parallel [(const_int 7)])))))))]
14732 "TARGET_SHMEDIA"
14733 "msad.ubq %N2, %N3, %0"
14734 [(set_attr "type" "mac_media")])
14735
14736 (define_insn "mshalds_l"
14737 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14738 (ss_truncate:V2SI
14739 (ashift:V2DI
14740 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14741 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14742 (const_int 31)))))]
14743 "TARGET_SHMEDIA"
14744 "mshalds.l %1, %2, %0"
14745 [(set_attr "type" "mcmp_media")
14746 (set_attr "highpart" "depend")])
14747
14748 (define_insn "mshalds_w"
14749 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14750 (ss_truncate:V4HI
14751 (ashift:V4SI
14752 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14753 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14754 (const_int 15)))))]
14755 "TARGET_SHMEDIA"
14756 "mshalds.w %1, %2, %0"
14757 [(set_attr "type" "mcmp_media")
14758 (set_attr "highpart" "depend")])
14759
14760 (define_insn "ashrv2si3"
14761 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14762 (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14763 (match_operand:DI 2 "arith_reg_operand" "r")))]
14764 "TARGET_SHMEDIA"
14765 "mshard.l %1, %2, %0"
14766 [(set_attr "type" "arith_media")
14767 (set_attr "highpart" "depend")])
14768
14769 (define_insn "ashrv4hi3"
14770 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14771 (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14772 (match_operand:DI 2 "arith_reg_operand" "r")))]
14773 "TARGET_SHMEDIA"
14774 "mshard.w %1, %2, %0"
14775 [(set_attr "type" "arith_media")
14776 (set_attr "highpart" "depend")])
14777
14778 (define_insn "mshards_q"
14779 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
14780 (ss_truncate:HI
14781 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
14782 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
14783 "TARGET_SHMEDIA"
14784 "mshards.q %1, %N2, %0"
14785 [(set_attr "type" "mcmp_media")])
14786
14787 (define_expand "mshfhi_b"
14788 [(match_operand:V8QI 0 "arith_reg_dest" "")
14789 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14790 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
14791 "TARGET_SHMEDIA"
14792 {
14793 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
14794 (operands[0], operands[1], operands[2]));
14795 DONE;
14796 })
14797
14798 (define_expand "mshflo_b"
14799 [(match_operand:V8QI 0 "arith_reg_dest" "")
14800 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14801 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
14802 "TARGET_SHMEDIA"
14803 {
14804 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
14805 (operands[0], operands[1], operands[2]));
14806 DONE;
14807 })
14808
14809 (define_insn "mshf4_b"
14810 [(set
14811 (match_operand:V8QI 0 "arith_reg_dest" "=r")
14812 (vec_select:V8QI
14813 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14814 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14815 (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
14816 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
14817 "TARGET_SHMEDIA"
14818 {
14819 return (TARGET_LITTLE_ENDIAN
14820 ? "mshfhi.b %N1, %N2, %0"
14821 : "mshflo.b %N1, %N2, %0");
14822 }
14823 [(set_attr "type" "arith_media")
14824 (set (attr "highpart")
14825 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14826 (const_string "user")))])
14827
14828 (define_insn "mshf0_b"
14829 [(set
14830 (match_operand:V8QI 0 "arith_reg_dest" "=r")
14831 (vec_select:V8QI
14832 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14833 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14834 (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
14835 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
14836 "TARGET_SHMEDIA"
14837 {
14838 return (TARGET_LITTLE_ENDIAN
14839 ? "mshflo.b %N1, %N2, %0"
14840 : "mshfhi.b %N1, %N2, %0");
14841 }
14842 [(set_attr "type" "arith_media")
14843 (set (attr "highpart")
14844 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14845 (const_string "user")))])
14846
14847 (define_expand "mshfhi_l"
14848 [(match_operand:V2SI 0 "arith_reg_dest" "")
14849 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14850 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
14851 "TARGET_SHMEDIA"
14852 {
14853 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
14854 (operands[0], operands[1], operands[2]));
14855 DONE;
14856 })
14857
14858 (define_expand "mshflo_l"
14859 [(match_operand:V2SI 0 "arith_reg_dest" "")
14860 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14861 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
14862 "TARGET_SHMEDIA"
14863 {
14864 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
14865 (operands[0], operands[1], operands[2]));
14866 DONE;
14867 })
14868
14869 (define_insn "mshf4_l"
14870 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14871 (vec_select:V2SI
14872 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14873 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
14874 (parallel [(const_int 1) (const_int 3)])))]
14875 "TARGET_SHMEDIA"
14876 {
14877 return (TARGET_LITTLE_ENDIAN
14878 ? "mshfhi.l %N1, %N2, %0"
14879 : "mshflo.l %N1, %N2, %0");
14880 }
14881 [(set_attr "type" "arith_media")
14882 (set (attr "highpart")
14883 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14884 (const_string "user")))])
14885
14886 (define_insn "mshf0_l"
14887 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14888 (vec_select:V2SI
14889 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14890 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
14891 (parallel [(const_int 0) (const_int 2)])))]
14892 "TARGET_SHMEDIA"
14893 {
14894 return (TARGET_LITTLE_ENDIAN
14895 ? "mshflo.l %N1, %N2, %0"
14896 : "mshfhi.l %N1, %N2, %0");
14897 }
14898 [(set_attr "type" "arith_media")
14899 (set (attr "highpart")
14900 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14901 (const_string "user")))])
14902
14903 (define_expand "mshfhi_w"
14904 [(match_operand:V4HI 0 "arith_reg_dest" "")
14905 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14906 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
14907 "TARGET_SHMEDIA"
14908 {
14909 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
14910 (operands[0], operands[1], operands[2]));
14911 DONE;
14912 })
14913
14914 (define_expand "mshflo_w"
14915 [(match_operand:V4HI 0 "arith_reg_dest" "")
14916 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14917 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
14918 "TARGET_SHMEDIA"
14919 {
14920 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
14921 (operands[0], operands[1], operands[2]));
14922 DONE;
14923 })
14924
14925 (define_insn "mshf4_w"
14926 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14927 (vec_select:V4HI
14928 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14929 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
14930 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
14931 "TARGET_SHMEDIA"
14932 {
14933 return (TARGET_LITTLE_ENDIAN
14934 ? "mshfhi.w %N1, %N2, %0"
14935 : "mshflo.w %N1, %N2, %0");
14936 }
14937 [(set_attr "type" "arith_media")
14938 (set (attr "highpart")
14939 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14940 (const_string "user")))])
14941
14942 (define_insn "mshf0_w"
14943 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14944 (vec_select:V4HI
14945 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14946 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
14947 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
14948 "TARGET_SHMEDIA"
14949 {
14950 return (TARGET_LITTLE_ENDIAN
14951 ? "mshflo.w %N1, %N2, %0"
14952 : "mshfhi.w %N1, %N2, %0");
14953 }
14954 [(set_attr "type" "arith_media")
14955 (set (attr "highpart")
14956 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14957 (const_string "user")))])
14958
14959 (define_insn "mshflo_w_x"
14960 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14961 (vec_select:V4HI
14962 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
14963 (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
14964 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
14965 "TARGET_SHMEDIA"
14966 "mshflo.w %N1, %N2, %0"
14967 [(set_attr "type" "arith_media")
14968 (set_attr "highpart" "ignore")])
14969
14970 ;; These are useful to expand ANDs and as combiner patterns.
14971 (define_insn_and_split "mshfhi_l_di"
14972 [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
14973 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
14974 (const_int 32))
14975 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
14976 (const_int -4294967296))))]
14977 "TARGET_SHMEDIA"
14978 "@
14979 mshfhi.l %N1, %N2, %0
14980 #"
14981 "TARGET_SHMEDIA && reload_completed
14982 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
14983 [(set (match_dup 3) (match_dup 4))
14984 (set (match_dup 5) (match_dup 6))]
14985 {
14986 operands[3] = gen_lowpart (SImode, operands[0]);
14987 operands[4] = gen_highpart (SImode, operands[1]);
14988 operands[5] = gen_highpart (SImode, operands[0]);
14989 operands[6] = gen_highpart (SImode, operands[2]);
14990 }
14991 [(set_attr "type" "arith_media")])
14992
14993 (define_insn "*mshfhi_l_di_rev"
14994 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14995 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14996 (const_int -4294967296))
14997 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14998 (const_int 32))))]
14999 "TARGET_SHMEDIA"
15000 "mshfhi.l %N2, %N1, %0"
15001 [(set_attr "type" "arith_media")])
15002
15003 (define_split
15004 [(set (match_operand:DI 0 "arith_reg_dest" "")
15005 (ior:DI (zero_extend:DI (match_operand:SI 1
15006 "extend_reg_or_0_operand" ""))
15007 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
15008 (const_int -4294967296))))
15009 (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
15010 "TARGET_SHMEDIA"
15011 [(const_int 0)]
15012 {
15013 emit_insn (gen_ashldi3_media (operands[3],
15014 simplify_gen_subreg (DImode, operands[1],
15015 SImode, 0),
15016 GEN_INT (32)));
15017 emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
15018 DONE;
15019 })
15020
15021 (define_insn "mshflo_l_di"
15022 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15023 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15024 (const_int 4294967295))
15025 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15026 (const_int 32))))]
15027
15028 "TARGET_SHMEDIA"
15029 "mshflo.l %N1, %N2, %0"
15030 [(set_attr "type" "arith_media")
15031 (set_attr "highpart" "ignore")])
15032
15033 (define_insn "*mshflo_l_di_rev"
15034 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15035 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15036 (const_int 32))
15037 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15038 (const_int 4294967295))))]
15039
15040 "TARGET_SHMEDIA"
15041 "mshflo.l %N2, %N1, %0"
15042 [(set_attr "type" "arith_media")
15043 (set_attr "highpart" "ignore")])
15044
15045 ;; Combiner pattern for trampoline initialization.
15046 (define_insn_and_split "*double_shori"
15047 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15048 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
15049 (const_int 32))
15050 (match_operand:DI 2 "const_int_operand" "n")))]
15051 "TARGET_SHMEDIA
15052 && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
15053 "#"
15054 "rtx_equal_p (operands[0], operands[1])"
15055 [(const_int 0)]
15056 {
15057 HOST_WIDE_INT v = INTVAL (operands[2]);
15058
15059 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
15060 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
15061 DONE;
15062 }
15063 [(set_attr "highpart" "ignore")])
15064
15065 (define_insn "*mshflo_l_di_x"
15066 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15067 (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
15068 "rZ"))
15069 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15070 (const_int 32))))]
15071 "TARGET_SHMEDIA"
15072 "mshflo.l %N1, %N2, %0"
15073 [(set_attr "type" "arith_media")
15074 (set_attr "highpart" "ignore")])
15075
15076 (define_insn_and_split "concat_v2sf"
15077 [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
15078 ;; (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
15079 (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
15080 (match_operand:SF 2 "register_operand" "rZ,f,f")))]
15081 "TARGET_SHMEDIA"
15082 "@
15083 mshflo.l %N1, %N2, %0
15084 #
15085 #"
15086 "TARGET_SHMEDIA && reload_completed
15087 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
15088 [(set (match_dup 3) (match_dup 1))
15089 (set (match_dup 4) (match_dup 2))]
15090 {
15091 operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
15092 operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
15093 }
15094 [(set_attr "type" "arith_media")
15095 (set_attr "highpart" "ignore")])
15096
15097 (define_insn "*mshflo_l_di_x_rev"
15098 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15099 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15100 (const_int 32))
15101 (zero_extend:DI
15102 (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
15103 "TARGET_SHMEDIA"
15104 "mshflo.l %N2, %N1, %0"
15105 [(set_attr "type" "arith_media")
15106 (set_attr "highpart" "ignore")])
15107
15108 (define_insn "ashlv2si3"
15109 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15110 (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
15111 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15112 "TARGET_SHMEDIA"
15113 "mshlld.l %1, %2, %0"
15114 [(set_attr "type" "arith_media")
15115 (set_attr "highpart" "depend")])
15116
15117 (define_split
15118 [(set (match_operand 0 "any_register_operand" "")
15119 (match_operator 3 "shift_operator"
15120 [(match_operand 1 "any_register_operand" "")
15121 (match_operand 2 "shift_count_reg_operand" "")]))]
15122 "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
15123 [(set (match_dup 0) (match_dup 3))]
15124 {
15125 rtx count = operands[2];
15126 enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
15127
15128 while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
15129 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
15130 || GET_CODE (count) == TRUNCATE)
15131 count = XEXP (count, 0);
15132 inner_mode = GET_MODE (count);
15133 count = simplify_gen_subreg (outer_mode, count, inner_mode,
15134 subreg_lowpart_offset (outer_mode, inner_mode));
15135 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
15136 operands[1], count);
15137 })
15138
15139 (define_insn "ashlv4hi3"
15140 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15141 (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
15142 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15143 "TARGET_SHMEDIA"
15144 "mshlld.w %1, %2, %0"
15145 [(set_attr "type" "arith_media")
15146 (set_attr "highpart" "depend")])
15147
15148 (define_insn "lshrv2si3"
15149 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15150 (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
15151 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15152 "TARGET_SHMEDIA"
15153 "mshlrd.l %1, %2, %0"
15154 [(set_attr "type" "arith_media")
15155 (set_attr "highpart" "depend")])
15156
15157 (define_insn "lshrv4hi3"
15158 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15159 (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
15160 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15161 "TARGET_SHMEDIA"
15162 "mshlrd.w %1, %2, %0"
15163 [(set_attr "type" "arith_media")
15164 (set_attr "highpart" "depend")])
15165
15166 (define_insn "subv2si3"
15167 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15168 (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15169 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15170 "TARGET_SHMEDIA"
15171 "msub.l %N1, %2, %0"
15172 [(set_attr "type" "arith_media")
15173 (set_attr "highpart" "depend")])
15174
15175 (define_insn "subv4hi3"
15176 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15177 (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15178 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15179 "TARGET_SHMEDIA"
15180 "msub.w %N1, %2, %0"
15181 [(set_attr "type" "arith_media")
15182 (set_attr "highpart" "depend")])
15183
15184 (define_insn_and_split "subv2hi3"
15185 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
15186 (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
15187 (match_operand:V2HI 2 "arith_reg_operand" "r")))]
15188 "TARGET_SHMEDIA"
15189 "#"
15190 "TARGET_SHMEDIA"
15191 [(const_int 0)]
15192 {
15193 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
15194 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
15195 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
15196 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
15197 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
15198
15199 emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
15200 emit_insn (gen_truncdisi2 (si_dst, di_dst));
15201 DONE;
15202 }
15203 [(set_attr "highpart" "must_split")])
15204
15205 (define_insn "sssubv2si3"
15206 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15207 (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15208 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15209 "TARGET_SHMEDIA"
15210 "msubs.l %N1, %2, %0"
15211 [(set_attr "type" "mcmp_media")
15212 (set_attr "highpart" "depend")])
15213
15214 (define_insn "ussubv8qi3"
15215 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15216 (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
15217 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
15218 "TARGET_SHMEDIA"
15219 "msubs.ub %N1, %2, %0"
15220 [(set_attr "type" "mcmp_media")
15221 (set_attr "highpart" "depend")])
15222
15223 (define_insn "sssubv4hi3"
15224 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15225 (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15226 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15227 "TARGET_SHMEDIA"
15228 "msubs.w %N1, %2, %0"
15229 [(set_attr "type" "mcmp_media")
15230 (set_attr "highpart" "depend")])
15231
15232 ;; -------------------------------------------------------------------------
15233 ;; Floating Point Intrinsics
15234 ;; -------------------------------------------------------------------------
15235
15236 (define_insn "fcosa_s"
15237 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15238 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
15239 UNSPEC_FCOSA))]
15240 "TARGET_SHMEDIA"
15241 "fcosa.s %1, %0"
15242 [(set_attr "type" "atrans_media")])
15243
15244 (define_insn "fsina_s"
15245 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15246 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
15247 UNSPEC_FSINA))]
15248 "TARGET_SHMEDIA"
15249 "fsina.s %1, %0"
15250 [(set_attr "type" "atrans_media")])
15251
15252 (define_insn "fipr"
15253 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15254 (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
15255 "fp_arith_reg_operand" "f")
15256 (match_operand:V4SF 2
15257 "fp_arith_reg_operand" "f"))
15258 (parallel [(const_int 0)]))
15259 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
15260 (parallel [(const_int 1)])))
15261 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
15262 (parallel [(const_int 2)]))
15263 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
15264 (parallel [(const_int 3)])))))]
15265 "TARGET_SHMEDIA"
15266 "fipr.s %1, %2, %0"
15267 [(set_attr "type" "fparith_media")])
15268
15269 (define_insn "fsrra_s"
15270 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15271 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
15272 UNSPEC_FSRRA))]
15273 "TARGET_SHMEDIA"
15274 "fsrra.s %1, %0"
15275 [(set_attr "type" "atrans_media")])
15276
15277 (define_insn "ftrv"
15278 [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
15279 (plus:V4SF
15280 (plus:V4SF
15281 (mult:V4SF
15282 (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
15283 (parallel [(const_int 0) (const_int 5)
15284 (const_int 10) (const_int 15)]))
15285 (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
15286 (mult:V4SF
15287 (vec_select:V4SF (match_dup 1)
15288 (parallel [(const_int 4) (const_int 9)
15289 (const_int 14) (const_int 3)]))
15290 (vec_select:V4SF (match_dup 2)
15291 (parallel [(const_int 1) (const_int 2)
15292 (const_int 3) (const_int 0)]))))
15293 (plus:V4SF
15294 (mult:V4SF
15295 (vec_select:V4SF (match_dup 1)
15296 (parallel [(const_int 8) (const_int 13)
15297 (const_int 2) (const_int 7)]))
15298 (vec_select:V4SF (match_dup 2)
15299 (parallel [(const_int 2) (const_int 3)
15300 (const_int 0) (const_int 1)])))
15301 (mult:V4SF
15302 (vec_select:V4SF (match_dup 1)
15303 (parallel [(const_int 12) (const_int 1)
15304 (const_int 6) (const_int 11)]))
15305 (vec_select:V4SF (match_dup 2)
15306 (parallel [(const_int 3) (const_int 0)
15307 (const_int 1) (const_int 2)]))))))]
15308 "TARGET_SHMEDIA"
15309 "ftrv.s %1, %2, %0"
15310 [(set_attr "type" "fparith_media")])
15311
15312 (define_insn "ldhi_l"
15313 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15314 (zero_extract:SI
15315 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
15316 (const_int 3))
15317 (const_int -3)))
15318 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
15319 (const_int 0)))]
15320 "TARGET_SHMEDIA32"
15321 "ldhi.l %U1, %0"
15322 [(set_attr "type" "load_media")])
15323
15324 (define_insn "ldhi_q"
15325 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15326 (zero_extract:DI
15327 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
15328 (const_int 7))
15329 (const_int -7)))
15330 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
15331 (const_int 0)))]
15332 "TARGET_SHMEDIA32"
15333 "ldhi.q %U1, %0"
15334 [(set_attr "type" "load_media")])
15335
15336 (define_insn_and_split "*ldhi_q_comb0"
15337 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15338 (zero_extract:DI
15339 (mem:DI (plus:SI (ior:SI (plus:SI
15340 (match_operand:SI 1 "register_operand" "r")
15341 (match_operand:SI 2 "ua_offset" "I06"))
15342 (const_int 7))
15343 (const_int -7)))
15344 (plus:SI (and:SI (match_dup 1) (const_int 7))
15345 (const_int 1))
15346 (const_int 0)))]
15347 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
15348 "#"
15349 ""
15350 [(pc)]
15351 {
15352 emit_insn (gen_ldhi_q (operands[0],
15353 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15354 DONE;
15355 })
15356
15357 (define_insn_and_split "*ldhi_q_comb1"
15358 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15359 (zero_extract:DI
15360 (mem:DI (plus:SI (ior:SI (plus:SI
15361 (match_operand:SI 1 "register_operand" "r")
15362 (match_operand:SI 2 "ua_offset" "I06"))
15363 (const_int 7))
15364 (const_int -7)))
15365 (plus:SI (and:SI (plus:SI (match_dup 1)
15366 (match_operand:SI 3 "ua_offset" "I06"))
15367 (const_int 7))
15368 (const_int 1))
15369 (const_int 0)))]
15370 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
15371 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
15372 "#"
15373 ""
15374 [(pc)]
15375 {
15376 emit_insn (gen_ldhi_q (operands[0],
15377 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15378 DONE;
15379 })
15380
15381 (define_insn "ldlo_l"
15382 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15383 (zero_extract:SI
15384 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
15385 (const_int -4)))
15386 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
15387 (and:SI (match_dup 1) (const_int 3))))]
15388 "TARGET_SHMEDIA32"
15389 "ldlo.l %U1, %0"
15390 [(set_attr "type" "load_media")])
15391
15392 (define_insn "ldlo_q"
15393 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15394 (zero_extract:DI
15395 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
15396 (const_int -8)))
15397 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
15398 (and:SI (match_dup 1) (const_int 7))))]
15399 "TARGET_SHMEDIA32"
15400 "ldlo.q %U1, %0"
15401 [(set_attr "type" "load_media")])
15402
15403 (define_insn_and_split "*ldlo_q_comb0"
15404 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15405 (zero_extract:DI
15406 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
15407 (match_operand:SI 2 "ua_offset" "I06"))
15408 (const_int -8)))
15409 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
15410 (and:SI (match_dup 1) (const_int 7))))]
15411 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
15412 "#"
15413 ""
15414 [(pc)]
15415 {
15416 emit_insn (gen_ldlo_q (operands[0],
15417 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15418 DONE;
15419 })
15420
15421 (define_insn_and_split "*ldlo_q_comb1"
15422 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15423 (zero_extract:DI
15424 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
15425 (match_operand:SI 2 "ua_offset" "I06"))
15426 (const_int -8)))
15427 (minus:SI (const_int 8)
15428 (and:SI (plus:SI (match_dup 1)
15429 (match_operand:SI 3 "ua_offset" "I06"))
15430 (const_int 7)))
15431 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
15432 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
15433 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
15434 "#"
15435 ""
15436 [(pc)]
15437 {
15438 emit_insn (gen_ldlo_q (operands[0],
15439 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15440 DONE;
15441 })
15442
15443 (define_insn "sthi_l"
15444 [(set (zero_extract:SI
15445 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
15446 (const_int 3))
15447 (const_int -3)))
15448 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
15449 (const_int 0))
15450 (match_operand:SI 1 "arith_reg_operand" "r"))]
15451 "TARGET_SHMEDIA32"
15452 "sthi.l %U0, %1"
15453 [(set_attr "type" "ustore_media")])
15454
15455 ;; All unaligned stores are considered to be 'narrow' because they typically
15456 ;; operate on less that a quadword, and when they operate on a full quadword,
15457 ;; the vanilla store high / store low sequence will cause a stall if not
15458 ;; scheduled apart.
15459 (define_insn "sthi_q"
15460 [(set (zero_extract:DI
15461 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
15462 (const_int 7))
15463 (const_int -7)))
15464 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
15465 (const_int 0))
15466 (match_operand:DI 1 "arith_reg_operand" "r"))]
15467 "TARGET_SHMEDIA32"
15468 "sthi.q %U0, %1"
15469 [(set_attr "type" "ustore_media")])
15470
15471 (define_insn_and_split "*sthi_q_comb0"
15472 [(set (zero_extract:DI
15473 (mem:DI (plus:SI (ior:SI (plus:SI
15474 (match_operand:SI 0 "register_operand" "r")
15475 (match_operand:SI 1 "ua_offset" "I06"))
15476 (const_int 7))
15477 (const_int -7)))
15478 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
15479 (const_int 0))
15480 (match_operand:DI 2 "arith_reg_operand" "r"))]
15481 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15482 "#"
15483 ""
15484 [(pc)]
15485 {
15486 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15487 operands[2]));
15488 DONE;
15489 })
15490
15491 (define_insn_and_split "*sthi_q_comb1"
15492 [(set (zero_extract:DI
15493 (mem:DI (plus:SI (ior:SI (plus:SI
15494 (match_operand:SI 0 "register_operand" "r")
15495 (match_operand:SI 1 "ua_offset" "I06"))
15496 (const_int 7))
15497 (const_int -7)))
15498 (plus:SI (and:SI (plus:SI (match_dup 0)
15499 (match_operand:SI 2 "ua_offset" "I06"))
15500 (const_int 7))
15501 (const_int 1))
15502 (const_int 0))
15503 (match_operand:DI 3 "arith_reg_operand" "r"))]
15504 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
15505 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15506 "#"
15507 ""
15508 [(pc)]
15509 {
15510 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15511 operands[3]));
15512 DONE;
15513 })
15514
15515 ;; This is highpart user because the address is used as full 64 bit.
15516 (define_insn "stlo_l"
15517 [(set (zero_extract:SI
15518 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
15519 (const_int -4)))
15520 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
15521 (and:SI (match_dup 0) (const_int 3)))
15522 (match_operand:SI 1 "arith_reg_operand" "r"))]
15523 "TARGET_SHMEDIA32"
15524 "stlo.l %U0, %1"
15525 [(set_attr "type" "ustore_media")])
15526
15527 (define_insn "stlo_q"
15528 [(set (zero_extract:DI
15529 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
15530 (const_int -8)))
15531 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
15532 (and:SI (match_dup 0) (const_int 7)))
15533 (match_operand:DI 1 "arith_reg_operand" "r"))]
15534 "TARGET_SHMEDIA32"
15535 "stlo.q %U0, %1"
15536 [(set_attr "type" "ustore_media")])
15537
15538 (define_insn_and_split "*stlo_q_comb0"
15539 [(set (zero_extract:DI
15540 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15541 (match_operand:SI 1 "ua_offset" "I06"))
15542 (const_int -8)))
15543 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
15544 (and:SI (match_dup 0) (const_int 7)))
15545 (match_operand:DI 2 "arith_reg_operand" "r"))]
15546 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15547 "#"
15548 ""
15549 [(pc)]
15550 {
15551 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15552 operands[2]));
15553 DONE;
15554 })
15555
15556 (define_insn_and_split "*stlo_q_comb1"
15557 [(set (zero_extract:DI
15558 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15559 (match_operand:SI 1 "ua_offset" "I06"))
15560 (const_int -8)))
15561 (minus:SI (const_int 8)
15562 (and:SI (plus:SI (match_dup 0)
15563 (match_operand:SI 2 "ua_offset" "I06"))
15564 (const_int 7)))
15565 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
15566 (match_operand:DI 3 "arith_reg_operand" "r"))]
15567 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15568 "#"
15569 ""
15570 [(pc)]
15571 {
15572 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15573 operands[3]));
15574 DONE;
15575 })
15576
15577 (define_insn "ldhi_l64"
15578 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15579 (zero_extract:SI
15580 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15581 (const_int 3))
15582 (const_int -3)))
15583 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
15584 (const_int 0)))]
15585 "TARGET_SHMEDIA64"
15586 "ldhi.l %U1, %0"
15587 [(set_attr "type" "load_media")])
15588
15589 (define_insn "ldhi_q64"
15590 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15591 (zero_extract:DI
15592 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15593 (const_int 7))
15594 (const_int -7)))
15595 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
15596 (const_int 0)))]
15597 "TARGET_SHMEDIA64"
15598 "ldhi.q %U1, %0"
15599 [(set_attr "type" "load_media")])
15600
15601 (define_insn "ldlo_l64"
15602 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15603 (zero_extract:SI
15604 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15605 (const_int -4)))
15606 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
15607 (and:DI (match_dup 1) (const_int 3))))]
15608 "TARGET_SHMEDIA64"
15609 "ldlo.l %U1, %0"
15610 [(set_attr "type" "load_media")])
15611
15612 (define_insn "ldlo_q64"
15613 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15614 (zero_extract:DI
15615 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15616 (const_int -8)))
15617 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
15618 (and:DI (match_dup 1) (const_int 7))))]
15619 "TARGET_SHMEDIA64"
15620 "ldlo.q %U1, %0"
15621 [(set_attr "type" "load_media")])
15622
15623 (define_insn "sthi_l64"
15624 [(set (zero_extract:SI
15625 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15626 (const_int 3))
15627 (const_int -3)))
15628 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
15629 (const_int 0))
15630 (match_operand:SI 1 "arith_reg_operand" "r"))]
15631 "TARGET_SHMEDIA64"
15632 "sthi.l %U0, %1"
15633 [(set_attr "type" "ustore_media")])
15634
15635 (define_insn "sthi_q64"
15636 [(set (zero_extract:DI
15637 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15638 (const_int 7))
15639 (const_int -7)))
15640 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
15641 (const_int 0))
15642 (match_operand:DI 1 "arith_reg_operand" "r"))]
15643 "TARGET_SHMEDIA64"
15644 "sthi.q %U0, %1"
15645 [(set_attr "type" "ustore_media")])
15646
15647 (define_insn "stlo_l64"
15648 [(set (zero_extract:SI
15649 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15650 (const_int -4)))
15651 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
15652 (and:DI (match_dup 0) (const_int 3)))
15653 (match_operand:SI 1 "arith_reg_operand" "r"))]
15654 "TARGET_SHMEDIA64"
15655 "stlo.l %U0, %1"
15656 [(set_attr "type" "ustore_media")])
15657
15658 (define_insn "stlo_q64"
15659 [(set (zero_extract:DI
15660 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15661 (const_int -8)))
15662 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
15663 (and:DI (match_dup 0) (const_int 7)))
15664 (match_operand:DI 1 "arith_reg_operand" "r"))]
15665 "TARGET_SHMEDIA64"
15666 "stlo.q %U0, %1"
15667 [(set_attr "type" "ustore_media")])
15668
15669 (define_insn "nsb"
15670 [(set (match_operand:QI 0 "arith_reg_dest" "=r")
15671 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15672 UNSPEC_NSB))]
15673 "TARGET_SHMEDIA"
15674 "nsb %1, %0"
15675 [(set_attr "type" "arith_media")])
15676
15677 (define_insn "nsbsi"
15678 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15679 (zero_extend:SI
15680 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15681 UNSPEC_NSB)))]
15682 "TARGET_SHMEDIA"
15683 "nsb %1, %0"
15684 [(set_attr "type" "arith_media")])
15685
15686 (define_insn "nsbdi"
15687 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15688 (zero_extend:DI
15689 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15690 UNSPEC_NSB)))]
15691 "TARGET_SHMEDIA"
15692 "nsb %1, %0"
15693 [(set_attr "type" "arith_media")])
15694
15695 (define_expand "ffsdi2"
15696 [(set (match_operand:DI 0 "arith_reg_dest" "")
15697 (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
15698 "TARGET_SHMEDIA"
15699 {
15700 rtx scratch = gen_reg_rtx (DImode);
15701 rtx last;
15702
15703 emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
15704 emit_insn (gen_xordi3 (scratch, operands[1], scratch));
15705 emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
15706 emit_insn (gen_nsbdi (scratch, scratch));
15707 emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
15708 emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
15709 last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
15710 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
15711
15712 DONE;
15713 })
15714
15715 (define_expand "ffssi2"
15716 [(set (match_operand:SI 0 "arith_reg_dest" "")
15717 (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
15718 "TARGET_SHMEDIA"
15719 {
15720 rtx scratch = gen_reg_rtx (SImode);
15721 rtx discratch = gen_reg_rtx (DImode);
15722 rtx last;
15723
15724 emit_insn (gen_adddi3 (discratch,
15725 simplify_gen_subreg (DImode, operands[1], SImode, 0),
15726 constm1_rtx));
15727 emit_insn (gen_andcdi3 (discratch,
15728 simplify_gen_subreg (DImode, operands[1], SImode, 0),
15729 discratch));
15730 emit_insn (gen_nsbsi (scratch, discratch));
15731 last = emit_insn (gen_subsi3 (operands[0],
15732 force_reg (SImode, GEN_INT (63)), scratch));
15733 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
15734
15735 DONE;
15736 })
15737
15738 (define_insn "byterev"
15739 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15740 (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
15741 (parallel [(const_int 7) (const_int 6) (const_int 5)
15742 (const_int 4) (const_int 3) (const_int 2)
15743 (const_int 1) (const_int 0)])))]
15744 "TARGET_SHMEDIA"
15745 "byterev %1, %0"
15746 [(set_attr "type" "arith_media")])
15747
15748 ;; In user mode, the "pref" instruction will raise a RADDERR exception
15749 ;; for accesses to [0x80000000,0xffffffff]. This makes it an unsuitable
15750 ;; implementation of __builtin_prefetch for VxWorks RTPs.
15751 (define_expand "prefetch"
15752 [(prefetch (match_operand 0 "address_operand" "")
15753 (match_operand:SI 1 "const_int_operand" "")
15754 (match_operand:SI 2 "const_int_operand" ""))]
15755 "(TARGET_SH2A || TARGET_SH3 || TARGET_SH5)
15756 && (TARGET_SHMEDIA || ! TARGET_VXWORKS_RTP)")
15757
15758 (define_insn "*prefetch"
15759 [(prefetch (match_operand:SI 0 "register_operand" "r")
15760 (match_operand:SI 1 "const_int_operand" "n")
15761 (match_operand:SI 2 "const_int_operand" "n"))]
15762 "(TARGET_SH2A || TARGET_SH3 || TARGET_SHCOMPACT) && ! TARGET_VXWORKS_RTP"
15763 "pref @%0"
15764 [(set_attr "type" "other")])
15765
15766 (define_insn "*prefetch_media"
15767 [(prefetch (match_operand:QI 0 "address_operand" "p")
15768 (match_operand:SI 1 "const_int_operand" "n")
15769 (match_operand:SI 2 "const_int_operand" "n"))]
15770 "TARGET_SHMEDIA"
15771 {
15772 operands[0] = gen_rtx_MEM (QImode, operands[0]);
15773 output_asm_insn ("ld%M0.b %m0,r63", operands);
15774 return "";
15775 }
15776 [(set_attr "type" "other")])
15777
15778 (define_insn "alloco_i"
15779 [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
15780 (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
15781 "TARGET_SHMEDIA32"
15782 {
15783 rtx xops[2];
15784
15785 if (GET_CODE (operands[0]) == PLUS)
15786 {
15787 xops[0] = XEXP (operands[0], 0);
15788 xops[1] = XEXP (operands[0], 1);
15789 }
15790 else
15791 {
15792 xops[0] = operands[0];
15793 xops[1] = const0_rtx;
15794 }
15795 output_asm_insn ("alloco %0, %1", xops);
15796 return "";
15797 }
15798 [(set_attr "type" "other")])
15799
15800 (define_split
15801 [(set (match_operand 0 "any_register_operand" "")
15802 (match_operand 1 "" ""))]
15803 "TARGET_SHMEDIA && reload_completed"
15804 [(set (match_dup 0) (match_dup 1))]
15805 {
15806 int n_changes = 0;
15807
15808 for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
15809 if (!n_changes)
15810 FAIL;
15811 })
15812
15813 ;; -------------------------------------------------------------------------
15814 ;; Stack Protector Patterns
15815 ;; -------------------------------------------------------------------------
15816
15817 (define_expand "stack_protect_set"
15818 [(set (match_operand 0 "memory_operand" "")
15819 (match_operand 1 "memory_operand" ""))]
15820 ""
15821 {
15822 if (TARGET_SHMEDIA)
15823 {
15824 if (TARGET_SHMEDIA64)
15825 emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
15826 else
15827 emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
15828 }
15829 else
15830 emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
15831
15832 DONE;
15833 })
15834
15835 (define_insn "stack_protect_set_si"
15836 [(set (match_operand:SI 0 "memory_operand" "=m")
15837 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15838 (set (match_scratch:SI 2 "=&r") (const_int 0))]
15839 "!TARGET_SHMEDIA"
15840 {
15841 return "mov.l %1,%2" "\n"
15842 " mov.l %2,%0" "\n"
15843 " mov #0,%2";
15844 }
15845 [(set_attr "type" "other")
15846 (set_attr "length" "6")])
15847
15848 (define_insn "stack_protect_set_si_media"
15849 [(set (match_operand:SI 0 "memory_operand" "=m")
15850 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15851 (set (match_scratch:SI 2 "=&r") (const_int 0))]
15852 "TARGET_SHMEDIA"
15853 {
15854 return "ld%M1.l %m1,%2" "\n"
15855 " st%M0.l %m0,%2" "\n"
15856 " movi 0,%2";
15857 }
15858 [(set_attr "type" "other")
15859 (set_attr "length" "12")])
15860
15861 (define_insn "stack_protect_set_di_media"
15862 [(set (match_operand:DI 0 "memory_operand" "=m")
15863 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15864 (set (match_scratch:DI 2 "=&r") (const_int 0))]
15865 "TARGET_SHMEDIA64"
15866 {
15867 return "ld%M1.q %m1,%2" "\n"
15868 " st%M0.q %m0,%2" "\n"
15869 " movi 0,%2";
15870 }
15871 [(set_attr "type" "other")
15872 (set_attr "length" "12")])
15873
15874 (define_expand "stack_protect_test"
15875 [(match_operand 0 "memory_operand" "")
15876 (match_operand 1 "memory_operand" "")
15877 (match_operand 2 "" "")]
15878 ""
15879 {
15880 if (TARGET_SHMEDIA)
15881 {
15882 rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
15883 rtx test;
15884
15885 test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
15886 if (TARGET_SHMEDIA64)
15887 {
15888 emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
15889 operands[1]));
15890 emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
15891 }
15892 else
15893 {
15894 emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
15895 operands[1]));
15896 emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
15897 }
15898 }
15899 else
15900 {
15901 emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
15902 emit_jump_insn (gen_branch_true (operands[2]));
15903 }
15904
15905 DONE;
15906 })
15907
15908 (define_insn "stack_protect_test_si"
15909 [(set (reg:SI T_REG)
15910 (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
15911 (match_operand:SI 1 "memory_operand" "m")]
15912 UNSPEC_SP_TEST))
15913 (set (match_scratch:SI 2 "=&r") (const_int 0))
15914 (set (match_scratch:SI 3 "=&r") (const_int 0))]
15915 "!TARGET_SHMEDIA"
15916 {
15917 return "mov.l %0,%2" "\n"
15918 " mov.l %1,%3" "\n"
15919 " cmp/eq %2,%3" "\n"
15920 " mov #0,%2" "\n"
15921 " mov #0,%3";
15922 }
15923 [(set_attr "type" "other")
15924 (set_attr "length" "10")])
15925
15926 (define_insn "stack_protect_test_si_media"
15927 [(set (match_operand:SI 0 "register_operand" "=&r")
15928 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
15929 (match_operand:SI 2 "memory_operand" "m")]
15930 UNSPEC_SP_TEST))
15931 (set (match_scratch:SI 3 "=&r") (const_int 0))]
15932 "TARGET_SHMEDIA"
15933 {
15934 return "ld%M1.l %m1,%0" "\n"
15935 " ld%M2.l %m2,%3" "\n"
15936 " cmpeq %0,%3,%0" "\n"
15937 " movi 0,%3";
15938 }
15939 [(set_attr "type" "other")
15940 (set_attr "length" "16")])
15941
15942 (define_insn "stack_protect_test_di_media"
15943 [(set (match_operand:DI 0 "register_operand" "=&r")
15944 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
15945 (match_operand:DI 2 "memory_operand" "m")]
15946 UNSPEC_SP_TEST))
15947 (set (match_scratch:DI 3 "=&r") (const_int 0))]
15948 "TARGET_SHMEDIA64"
15949 {
15950 return "ld%M1.q %m1,%0" "\n"
15951 " ld%M2.q %m2,%3" "\n"
15952 " cmpeq %0,%3,%0" "\n"
15953 " movi 0,%3";
15954 }
15955 [(set_attr "type" "other")
15956 (set_attr "length" "16")])
15957
15958 ;; -------------------------------------------------------------------------
15959 ;; Atomic operations
15960 ;; -------------------------------------------------------------------------
15961
15962 (include "sync.md")