re PR target/60039 (sh3 optimisation bug with -O2)
[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 (PIC_REG 12)
80 (FP_REG 14)
81 (SP_REG 15)
82
83 (PR_MEDIA_REG 18)
84 (T_MEDIA_REG 19)
85
86 (R0_REG 0)
87 (R1_REG 1)
88 (R2_REG 2)
89 (R3_REG 3)
90 (R4_REG 4)
91 (R5_REG 5)
92 (R6_REG 6)
93 (R7_REG 7)
94 (R8_REG 8)
95 (R9_REG 9)
96 (R10_REG 10)
97 (R20_REG 20)
98 (R21_REG 21)
99 (R22_REG 22)
100 (R23_REG 23)
101
102 (DR0_REG 64)
103 (DR2_REG 66)
104 (DR4_REG 68)
105 (FR23_REG 87)
106
107 (TR0_REG 128)
108 (TR1_REG 129)
109 (TR2_REG 130)
110
111 (XD0_REG 136)
112
113 ;; These are used with unspec.
114 (UNSPEC_COMPACT_ARGS 0)
115 (UNSPEC_MOVA 1)
116 (UNSPEC_CASESI 2)
117 (UNSPEC_DATALABEL 3)
118 (UNSPEC_BBR 4)
119 (UNSPEC_SFUNC 5)
120 (UNSPEC_PIC 6)
121 (UNSPEC_GOT 7)
122 (UNSPEC_GOTOFF 8)
123 (UNSPEC_PLT 9)
124 (UNSPEC_CALLER 10)
125 (UNSPEC_GOTPLT 11)
126 (UNSPEC_ICACHE 12)
127 (UNSPEC_INIT_TRAMP 13)
128 (UNSPEC_FCOSA 14)
129 (UNSPEC_FSRRA 15)
130 (UNSPEC_FSINA 16)
131 (UNSPEC_NSB 17)
132 (UNSPEC_ALLOCO 18)
133 (UNSPEC_TLSGD 20)
134 (UNSPEC_TLSLDM 21)
135 (UNSPEC_TLSIE 22)
136 (UNSPEC_DTPOFF 23)
137 (UNSPEC_GOTTPOFF 24)
138 (UNSPEC_TPOFF 25)
139 (UNSPEC_RA 26)
140 (UNSPEC_DIV_INV_M0 30)
141 (UNSPEC_DIV_INV_M1 31)
142 (UNSPEC_DIV_INV_M2 32)
143 (UNSPEC_DIV_INV_M3 33)
144 (UNSPEC_DIV_INV20 34)
145 (UNSPEC_DIV_INV_TABLE 37)
146 (UNSPEC_ASHIFTRT 35)
147 (UNSPEC_THUNK 36)
148 (UNSPEC_CHKADD 38)
149 (UNSPEC_SP_SET 40)
150 (UNSPEC_SP_TEST 41)
151 (UNSPEC_MOVUA 42)
152
153 ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT).
154 ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent.
155 (UNSPEC_EXTRACT_S16 43)
156 (UNSPEC_EXTRACT_U16 44)
157
158 ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR.
159 (UNSPEC_SYMOFF 45)
160
161 ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
162 (UNSPEC_PCREL_SYMOFF 46)
163
164 ;; Misc builtins
165 (UNSPEC_BUILTIN_STRLEN 47)
166
167 ;; These are used with unspec_volatile.
168 (UNSPECV_BLOCKAGE 0)
169 (UNSPECV_ALIGN 1)
170 (UNSPECV_CONST2 2)
171 (UNSPECV_CONST4 4)
172 (UNSPECV_CONST8 6)
173 (UNSPECV_WINDOW_END 10)
174 (UNSPECV_CONST_END 11)
175 (UNSPECV_EH_RETURN 12)
176 (UNSPECV_GBR 13)
177 (UNSPECV_SP_SWITCH_B 14)
178 (UNSPECV_SP_SWITCH_E 15)
179 ])
180
181 ;; -------------------------------------------------------------------------
182 ;; Attributes
183 ;; -------------------------------------------------------------------------
184
185 ;; Target CPU.
186
187 (define_attr "cpu"
188 "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
189 (const (symbol_ref "sh_cpu_attr")))
190
191 (define_attr "endian" "big,little"
192 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
193 (const_string "little") (const_string "big"))))
194
195 ;; Indicate if the default fpu mode is single precision.
196 (define_attr "fpu_single" "yes,no"
197 (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
198 (const_string "yes") (const_string "no"))))
199
200 (define_attr "fmovd" "yes,no"
201 (const (if_then_else (symbol_ref "TARGET_FMOVD")
202 (const_string "yes") (const_string "no"))))
203 ;; pipeline model
204 (define_attr "pipe_model" "sh1,sh4,sh5media"
205 (const
206 (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
207 (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
208 (const_string "sh1"))))
209
210 ;; cbranch conditional branch instructions
211 ;; jump unconditional jumps
212 ;; arith ordinary arithmetic
213 ;; arith3 a compound insn that behaves similarly to a sequence of
214 ;; three insns of type arith
215 ;; arith3b like above, but might end with a redirected branch
216 ;; load from memory
217 ;; load_si Likewise, SImode variant for general register.
218 ;; fload Likewise, but load to fp register.
219 ;; store to memory
220 ;; fstore floating point register to memory
221 ;; move general purpose register to register
222 ;; movi8 8-bit immediate to general purpose register
223 ;; mt_group other sh4 mt instructions
224 ;; fmove register to register, floating point
225 ;; smpy word precision integer multiply
226 ;; dmpy longword or doublelongword precision integer multiply
227 ;; return rts
228 ;; pload load of pr reg, which can't be put into delay slot of rts
229 ;; prset copy register to pr reg, ditto
230 ;; pstore store of pr reg, which can't be put into delay slot of jsr
231 ;; prget copy pr to register, ditto
232 ;; pcload pc relative load of constant value
233 ;; pcfload Likewise, but load to fp register.
234 ;; pcload_si Likewise, SImode variant for general register.
235 ;; rte return from exception
236 ;; sfunc special function call with known used registers
237 ;; call function call
238 ;; fp floating point
239 ;; fpscr_toggle toggle a bit in the fpscr
240 ;; fdiv floating point divide (or square root)
241 ;; gp_fpul move from general purpose register to fpul
242 ;; fpul_gp move from fpul to general purpose register
243 ;; mac_gp move from mac[lh] to general purpose register
244 ;; gp_mac move from general purpose register to mac[lh]
245 ;; mac_mem move from mac[lh] to memory
246 ;; mem_mac move from memory to mac[lh]
247 ;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv
248 ;; ftrc_s fix_truncsfsi2_i4
249 ;; dfdiv double precision floating point divide (or square root)
250 ;; cwb ic_invalidate_line_i
251 ;; movua SH4a unaligned load
252 ;; fsrra square root reciprocal approximate
253 ;; fsca sine and cosine approximate
254 ;; tls_load load TLS related address
255 ;; arith_media SHmedia arithmetic, logical, and shift instructions
256 ;; cbranch_media SHmedia conditional branch instructions
257 ;; cmp_media SHmedia compare instructions
258 ;; dfdiv_media SHmedia double precision divide and square root
259 ;; dfmul_media SHmedia double precision multiply instruction
260 ;; dfparith_media SHmedia double precision floating point arithmetic
261 ;; dfpconv_media SHmedia double precision floating point conversions
262 ;; dmpy_media SHmedia longword multiply
263 ;; fcmp_media SHmedia floating point compare instructions
264 ;; fdiv_media SHmedia single precision divide and square root
265 ;; fload_media SHmedia floating point register load instructions
266 ;; fmove_media SHmedia floating point register moves (inc. fabs and fneg)
267 ;; fparith_media SHmedia single precision floating point arithmetic
268 ;; fpconv_media SHmedia single precision floating point conversions
269 ;; fstore_media SHmedia floating point register store instructions
270 ;; gettr_media SHmedia gettr instruction
271 ;; invalidate_line_media SHmedia invalidate_line sequence
272 ;; jump_media SHmedia unconditional branch instructions
273 ;; load_media SHmedia general register load instructions
274 ;; pt_media SHmedia pt instruction (expanded by assembler)
275 ;; ptabs_media SHmedia ptabs instruction
276 ;; store_media SHmedia general register store instructions
277 ;; mcmp_media SHmedia multimedia compare, absolute, saturating ops
278 ;; mac_media SHmedia mac-style fixed point operations
279 ;; d2mpy_media SHmedia: two 32-bit integer multiplies
280 ;; atrans_media SHmedia approximate transcendental functions
281 ;; ustore_media SHmedia unaligned stores
282 ;; nil no-op move, will be deleted.
283
284 (define_attr "type"
285 "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,
286 fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore,
287 prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s,
288 dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,
289 gp_mac,mac_mem,mem_mac,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load,
290 arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,
291 dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,
292 fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,
293 jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,
294 d2mpy_media,atrans_media,ustore_media,nil,other"
295 (const_string "other"))
296
297 ;; We define a new attribute namely "insn_class".We use
298 ;; this for the DFA based pipeline description.
299 ;;
300 ;; mt_group SH4 "mt" group instructions.
301 ;;
302 ;; ex_group SH4 "ex" group instructions.
303 ;;
304 ;; ls_group SH4 "ls" group instructions.
305 ;;
306 (define_attr "insn_class"
307 "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
308 (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
309 (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group")
310 (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,
311 store,fstore,gp_fpul,fpul_gp") (const_string "ls_group")
312 (eq_attr "type" "cbranch,jump") (const_string "br_group")
313 (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
314 (const_string "fe_group")
315 (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,
316 prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb,
317 gp_mac,mac_mem,mem_mac") (const_string "co_group")]
318 (const_string "none")))
319
320 ;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
321 ;; so these do not belong in an insn group, although they are modeled
322 ;; with their own define_insn_reservations.
323
324 ;; Indicate what precision must be selected in fpscr for this insn, if any.
325 (define_attr "fp_mode" "single,double,none" (const_string "none"))
326
327 ;; Indicate if the fpu mode is set by this instruction
328 ;; "unknown" must have the value as "none" in fp_mode, and means
329 ;; that the instruction/abi has left the processor in an unknown
330 ;; state.
331 ;; "none" means that nothing has changed and no mode is set.
332 ;; This attribute is only used for the Renesas ABI.
333 (define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
334
335 ; If a conditional branch destination is within -252..258 bytes away
336 ; from the instruction it can be 2 bytes long. Something in the
337 ; range -4090..4100 bytes can be 6 bytes long. All other conditional
338 ; branches are initially assumed to be 16 bytes long.
339 ; In machine_dependent_reorg, we split all branches that are longer than
340 ; 2 bytes.
341
342 ;; The maximum range used for SImode constant pool entries is 1018. A final
343 ;; instruction can add 8 bytes while only being 4 bytes in size, thus we
344 ;; can have a total of 1022 bytes in the pool. Add 4 bytes for a branch
345 ;; instruction around the pool table, 2 bytes of alignment before the table,
346 ;; and 30 bytes of alignment after the table. That gives a maximum total
347 ;; pool size of 1058 bytes.
348 ;; Worst case code/pool content size ratio is 1:2 (using asms).
349 ;; Thus, in the worst case, there is one instruction in front of a maximum
350 ;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
351 ;; code. For the last n bytes of code, there are 2n + 36 bytes of pool.
352 ;; If we have a forward branch, the initial table will be put after the
353 ;; unconditional branch.
354 ;;
355 ;; ??? We could do much better by keeping track of the actual pcloads within
356 ;; the branch range and in the pcload range in front of the branch range.
357
358 ;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
359 ;; inside an le.
360 (define_attr "short_cbranch_p" "no,yes"
361 (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
362 (const_string "no")
363 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
364 (const_string "yes")
365 (match_test "NEXT_INSN (PREV_INSN (insn)) != insn")
366 (const_string "no")
367 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
368 (const_string "yes")
369 ] (const_string "no")))
370
371 (define_attr "med_branch_p" "no,yes"
372 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
373 (const_int 1988))
374 (const_string "yes")
375 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
376 (const_string "no")
377 (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
378 (const_int 8186))
379 (const_string "yes")
380 ] (const_string "no")))
381
382 (define_attr "med_cbranch_p" "no,yes"
383 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
384 (const_int 1986))
385 (const_string "yes")
386 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
387 (const_string "no")
388 (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
389 (const_int 8184))
390 (const_string "yes")
391 ] (const_string "no")))
392
393 (define_attr "braf_branch_p" "no,yes"
394 (cond [(match_test "! TARGET_SH2")
395 (const_string "no")
396 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
397 (const_int 20660))
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 32764))
402 (const_int 65530))
403 (const_string "yes")
404 ] (const_string "no")))
405
406 (define_attr "braf_cbranch_p" "no,yes"
407 (cond [(match_test "! TARGET_SH2")
408 (const_string "no")
409 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
410 (const_int 20658))
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 32762))
415 (const_int 65528))
416 (const_string "yes")
417 ] (const_string "no")))
418
419 ;; An unconditional jump in the range -4092..4098 can be 2 bytes long.
420 ;; For wider ranges, we need a combination of a code and a data part.
421 ;; If we can get a scratch register for a long range jump, the code
422 ;; part can be 4 bytes long; otherwise, it must be 8 bytes long.
423 ;; If the jump is in the range -32764..32770, the data part can be 2 bytes
424 ;; long; otherwise, it must be 6 bytes long.
425
426 ;; All other instructions are two bytes long by default.
427
428 ;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
429 ;; but getattrtab doesn't understand this.
430 (define_attr "length" ""
431 (cond [(eq_attr "type" "cbranch")
432 (cond [(eq_attr "short_cbranch_p" "yes")
433 (const_int 2)
434 (eq_attr "med_cbranch_p" "yes")
435 (const_int 6)
436 (eq_attr "braf_cbranch_p" "yes")
437 (const_int 12)
438 ;; ??? using pc is not computed transitively.
439 (ne (match_dup 0) (match_dup 0))
440 (const_int 14)
441 (match_test "flag_pic")
442 (const_int 24)
443 ] (const_int 16))
444 (eq_attr "type" "jump")
445 (cond [(eq_attr "med_branch_p" "yes")
446 (const_int 2)
447 (and (match_test "prev_nonnote_insn (insn)")
448 (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
449 (symbol_ref "INSN"))
450 (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
451 (symbol_ref "code_for_indirect_jump_scratch"))))
452 (cond [(eq_attr "braf_branch_p" "yes")
453 (const_int 6)
454 (not (match_test "flag_pic"))
455 (const_int 10)
456 (match_test "TARGET_SH2")
457 (const_int 10)] (const_int 18))
458 (eq_attr "braf_branch_p" "yes")
459 (const_int 10)
460 ;; ??? using pc is not computed transitively.
461 (ne (match_dup 0) (match_dup 0))
462 (const_int 12)
463 (match_test "flag_pic")
464 (const_int 22)
465 ] (const_int 14))
466 (eq_attr "type" "pt_media")
467 (if_then_else (match_test "TARGET_SHMEDIA64")
468 (const_int 20) (const_int 12))
469 (and (eq_attr "type" "jump_media")
470 (match_test "TARGET_SH5_CUT2_WORKAROUND"))
471 (const_int 8)
472 ] (if_then_else (match_test "TARGET_SHMEDIA")
473 (const_int 4)
474 (const_int 2))))
475
476 ;; DFA descriptions for the pipelines
477
478 (include "sh1.md")
479 (include "shmedia.md")
480 (include "sh4.md")
481
482 (include "iterators.md")
483 (include "predicates.md")
484 (include "constraints.md")
485
486 ;; Definitions for filling delay slots
487
488 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
489
490 (define_attr "banked" "yes,no"
491 (cond [(match_test "sh_loads_bankedreg_p (insn)")
492 (const_string "yes")]
493 (const_string "no")))
494
495 ;; ??? This should be (nil) instead of (const_int 0)
496 (define_attr "hit_stack" "yes,no"
497 (cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)"))
498 (const_string "no")]
499 (const_string "yes")))
500
501 (define_attr "interrupt_function" "no,yes"
502 (const (symbol_ref "current_function_interrupt")))
503
504 (define_attr "in_delay_slot" "yes,no"
505 (cond [(eq_attr "type" "cbranch") (const_string "no")
506 (eq_attr "type" "pcload,pcload_si") (const_string "no")
507 (eq_attr "needs_delay_slot" "yes") (const_string "no")
508 (eq_attr "length" "2") (const_string "yes")
509 ] (const_string "no")))
510
511 (define_attr "cond_delay_slot" "yes,no"
512 (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
513 ] (const_string "no")))
514
515 (define_attr "is_sfunc" ""
516 (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
517
518 (define_attr "is_mac_media" ""
519 (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
520
521 (define_attr "branch_zero" "yes,no"
522 (cond [(eq_attr "type" "!cbranch") (const_string "no")
523 (ne (symbol_ref "(next_active_insn (insn)\
524 == (prev_active_insn\
525 (XEXP (SET_SRC (PATTERN (insn)), 1))))\
526 && get_attr_length (next_active_insn (insn)) == 2")
527 (const_int 0))
528 (const_string "yes")]
529 (const_string "no")))
530
531 ;; SH4 Double-precision computation with double-precision result -
532 ;; the two halves are ready at different times.
533 (define_attr "dfp_comp" "yes,no"
534 (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
535 (const_string "no")))
536
537 ;; Insns for which the latency of a preceding fp insn is decreased by one.
538 (define_attr "late_fp_use" "yes,no" (const_string "no"))
539 ;; And feeding insns for which this relevant.
540 (define_attr "any_fp_comp" "yes,no"
541 (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
542 (const_string "yes")]
543 (const_string "no")))
544
545 (define_attr "any_int_load" "yes,no"
546 (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
547 (const_string "yes")]
548 (const_string "no")))
549
550 (define_attr "highpart" "user, ignore, extend, depend, must_split"
551 (const_string "user"))
552
553 (define_delay
554 (eq_attr "needs_delay_slot" "yes")
555 [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
556
557 ;; Since a normal return (rts) implicitly uses the PR register,
558 ;; we can't allow PR register loads in an rts delay slot.
559 ;; On the SH1* and SH2*, the rte instruction reads the return pc from the
560 ;; stack, and thus we can't put a pop instruction in its delay slot.
561 ;; On the SH3* and SH4*, the rte instruction does not use the stack, so a
562 ;; pop instruction can go in the delay slot, unless it references a banked
563 ;; register (the register bank is switched by rte).
564 (define_delay
565 (eq_attr "type" "return")
566 [(and (eq_attr "in_delay_slot" "yes")
567 (ior (and (eq_attr "interrupt_function" "no")
568 (eq_attr "type" "!pload,prset"))
569 (and (eq_attr "interrupt_function" "yes")
570 (ior (match_test "TARGET_SH3") (eq_attr "hit_stack" "no"))
571 (eq_attr "banked" "no"))))
572 (nil) (nil)])
573
574 ;; Since a call implicitly uses the PR register, we can't allow
575 ;; a PR register store in a jsr delay slot.
576
577 (define_delay
578 (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
579 [(and (eq_attr "in_delay_slot" "yes")
580 (eq_attr "type" "!pstore,prget")) (nil) (nil)])
581
582 ;; Say that we have annulled true branches, since this gives smaller and
583 ;; faster code when branches are predicted as not taken.
584
585 ;; ??? The non-annulled condition should really be "in_delay_slot",
586 ;; but insns that can be filled in non-annulled get priority over insns
587 ;; that can only be filled in anulled.
588
589 (define_delay
590 (and (eq_attr "type" "cbranch")
591 (match_test "TARGET_SH2"))
592 ;; SH2e has a hardware bug that pretty much prohibits the use of
593 ;; annulled delay slots.
594 [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
595 (not (eq_attr "cpu" "sh2e"))) (nil)])
596 \f
597 ;; -------------------------------------------------------------------------
598 ;; SImode signed integer comparisons
599 ;; -------------------------------------------------------------------------
600
601 ;; Various patterns to generate the TST #imm, R0 instruction.
602 ;; Although this adds some pressure on the R0 register, it can potentially
603 ;; result in faster code, even if the operand has to be moved to R0 first.
604 ;; This is because on SH4 TST #imm, R0 and MOV Rm, Rn are both MT group
605 ;; instructions and thus will be executed in parallel. On SH4A TST #imm, R0
606 ;; is an EX group instruction but still can be executed in parallel with the
607 ;; MT group MOV Rm, Rn instruction.
608
609 ;; Usual TST #imm, R0 patterns for SI, HI and QI
610 ;; This is usually used for bit patterns other than contiguous bits
611 ;; and single bits.
612 (define_insn "tstsi_t"
613 [(set (reg:SI T_REG)
614 (eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r")
615 (match_operand:SI 1 "logical_operand" "K08,r"))
616 (const_int 0)))]
617 "TARGET_SH1"
618 "tst %1,%0"
619 [(set_attr "type" "mt_group")])
620
621 (define_insn "tsthi_t"
622 [(set (reg:SI T_REG)
623 (eq:SI (subreg:SI (and:HI (match_operand:HI 0 "logical_operand" "%z")
624 (match_operand 1 "const_int_operand")) 0)
625 (const_int 0)))]
626 "TARGET_SH1
627 && CONST_OK_FOR_K08 (INTVAL (operands[1]))"
628 "tst %1,%0"
629 [(set_attr "type" "mt_group")])
630
631 (define_insn "tstqi_t"
632 [(set (reg:SI T_REG)
633 (eq:SI (subreg:SI (and:QI (match_operand:QI 0 "logical_operand" "%z")
634 (match_operand 1 "const_int_operand")) 0)
635 (const_int 0)))]
636 "TARGET_SH1
637 && (CONST_OK_FOR_K08 (INTVAL (operands[1]))
638 || CONST_OK_FOR_I08 (INTVAL (operands[1])))"
639 {
640 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
641 return "tst %1,%0";
642 }
643 [(set_attr "type" "mt_group")])
644
645 ;; Test low QI subreg against zero.
646 ;; This avoids unnecessary zero extension before the test.
647 (define_insn "*tstqi_t_zero"
648 [(set (reg:SI T_REG)
649 (eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))]
650 "TARGET_SH1"
651 "tst #255,%0"
652 [(set_attr "type" "mt_group")])
653
654 ;; This pattern might be risky because it also tests the upper bits and not
655 ;; only the subreg. However, it seems that combine will get to this only
656 ;; when testing sign/zero extended values. In this case the extended upper
657 ;; bits do not matter.
658 (define_insn "*tst<mode>_t_zero"
659 [(set (reg:SI T_REG)
660 (eq:SI
661 (subreg:QIHI
662 (and:SI (match_operand:SI 0 "arith_reg_operand" "%r")
663 (match_operand:SI 1 "arith_reg_operand" "r")) <lowpart_le>)
664 (const_int 0)))]
665 "TARGET_SH1 && TARGET_LITTLE_ENDIAN"
666 "tst %0,%1"
667 [(set_attr "type" "mt_group")])
668
669 (define_insn "*tst<mode>_t_zero"
670 [(set (reg:SI T_REG)
671 (eq:SI
672 (subreg:QIHI
673 (and:SI (match_operand:SI 0 "arith_reg_operand" "%r")
674 (match_operand:SI 1 "arith_reg_operand" "r")) <lowpart_be>)
675 (const_int 0)))]
676 "TARGET_SH1 && TARGET_BIG_ENDIAN"
677 "tst %0,%1"
678 [(set_attr "type" "mt_group")])
679
680 ;; Extract LSB, negate and store in T bit.
681 (define_insn "tstsi_t_and_not"
682 [(set (reg:SI T_REG)
683 (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z"))
684 (const_int 1)))]
685 "TARGET_SH1"
686 "tst #1,%0"
687 [(set_attr "type" "mt_group")])
688
689 ;; Extract contiguous bits and compare them against zero.
690 (define_insn "tst<mode>_t_zero_extract_eq"
691 [(set (reg:SI T_REG)
692 (eq:SI (zero_extract:SI (match_operand:QIHISIDI 0 "logical_operand" "z")
693 (match_operand:SI 1 "const_int_operand")
694 (match_operand:SI 2 "const_int_operand"))
695 (const_int 0)))]
696 "TARGET_SH1
697 && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))"
698 {
699 operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
700 return "tst %1,%0";
701 }
702 [(set_attr "type" "mt_group")])
703
704 ;; This split is required when testing bits in a QI subreg.
705 (define_split
706 [(set (reg:SI T_REG)
707 (eq:SI
708 (if_then_else:SI
709 (zero_extract:SI (match_operand 0 "logical_operand")
710 (match_operand 1 "const_int_operand")
711 (match_operand 2 "const_int_operand"))
712 (match_operand 3 "const_int_operand")
713 (const_int 0))
714 (const_int 0)))]
715 "TARGET_SH1
716 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
717 && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
718 [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3))
719 (const_int 0)))]
720 {
721 if (GET_MODE (operands[0]) == QImode)
722 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
723 })
724
725 ;; Extract single bit, negate and store it in the T bit.
726 ;; Not used for SH4A.
727 (define_insn "tstsi_t_zero_extract_xor"
728 [(set (reg:SI T_REG)
729 (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
730 (match_operand:SI 3 "const_int_operand"))
731 (match_operand:SI 1 "const_int_operand")
732 (match_operand:SI 2 "const_int_operand")))]
733 "TARGET_SH1
734 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
735 && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
736 "tst %3,%0"
737 [(set_attr "type" "mt_group")])
738
739 ;; Extract single bit, negate and store it in the T bit.
740 ;; Used for SH4A little endian.
741 (define_insn "tstsi_t_zero_extract_subreg_xor_little"
742 [(set (reg:SI T_REG)
743 (zero_extract:SI
744 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
745 (match_operand:SI 3 "const_int_operand")) 0)
746 (match_operand:SI 1 "const_int_operand")
747 (match_operand:SI 2 "const_int_operand")))]
748 "TARGET_SH1 && TARGET_LITTLE_ENDIAN
749 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
750 == (INTVAL (operands[3]) & 255)
751 && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
752 {
753 operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
754 return "tst %3,%0";
755 }
756 [(set_attr "type" "mt_group")])
757
758 ;; Extract single bit, negate and store it in the T bit.
759 ;; Used for SH4A big endian.
760 (define_insn "tstsi_t_zero_extract_subreg_xor_big"
761 [(set (reg:SI T_REG)
762 (zero_extract:SI
763 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
764 (match_operand:SI 3 "const_int_operand")) 3)
765 (match_operand:SI 1 "const_int_operand")
766 (match_operand:SI 2 "const_int_operand")))]
767 "TARGET_SH1 && TARGET_BIG_ENDIAN
768 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
769 == (INTVAL (operands[3]) & 255)
770 && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
771 {
772 operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
773 return "tst %3,%0";
774 }
775 [(set_attr "type" "mt_group")])
776
777 (define_insn "cmpeqsi_t"
778 [(set (reg:SI T_REG)
779 (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
780 (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
781 "TARGET_SH1"
782 "@
783 tst %0,%0
784 cmp/eq %1,%0
785 cmp/eq %1,%0"
786 [(set_attr "type" "mt_group")])
787
788 ;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this
789 ;; pattern by itself. What this actually does is:
790 ;; x == 0: (1 >> 0-0) & 1 = 1
791 ;; x != 0: (1 >> 0-x) & 1 = 0
792 ;; Without this the test pr51244-8.c fails on SH2A and SH4A.
793 (define_insn_and_split "*cmpeqsi_t"
794 [(set (reg:SI T_REG)
795 (and:SI (lshiftrt:SI
796 (const_int 1)
797 (neg:SI (match_operand:SI 0 "arith_reg_operand" "r")))
798 (const_int 1)))]
799 "TARGET_SH1"
800 "#"
801 "&& 1"
802 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))])
803
804 (define_insn "cmpgtsi_t"
805 [(set (reg:SI T_REG)
806 (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
807 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
808 "TARGET_SH1"
809 "@
810 cmp/pl %0
811 cmp/gt %1,%0"
812 [(set_attr "type" "mt_group")])
813
814 (define_insn "cmpgesi_t"
815 [(set (reg:SI T_REG)
816 (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
817 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
818 "TARGET_SH1"
819 "@
820 cmp/pz %0
821 cmp/ge %1,%0"
822 [(set_attr "type" "mt_group")])
823
824 ;; FIXME: This is actually wrong. There is no way to literally move a
825 ;; general reg to t reg. Luckily, it seems that this pattern will be only
826 ;; used when the general reg is known be either '0' or '1' during combine.
827 ;; What we actually need is reg != 0 -> T, but we have only reg == 0 -> T.
828 ;; Due to interactions with other patterns, combine fails to pick the latter
829 ;; and invert the dependent logic.
830 (define_insn "*negtstsi"
831 [(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))]
832 "TARGET_SH1"
833 "cmp/pl %0"
834 [(set_attr "type" "mt_group")])
835
836 ;; Some integer sign comparison patterns can be realized with the div0s insn.
837 ;; div0s Rm,Rn T = (Rm >> 31) ^ (Rn >> 31)
838 (define_insn "cmp_div0s_0"
839 [(set (reg:SI T_REG)
840 (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
841 (match_operand:SI 1 "arith_reg_operand" "r"))
842 (const_int 31)))]
843 "TARGET_SH1"
844 "div0s %0,%1"
845 [(set_attr "type" "arith")])
846
847 (define_insn "cmp_div0s_1"
848 [(set (reg:SI T_REG)
849 (lt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
850 (match_operand:SI 1 "arith_reg_operand" "r"))
851 (const_int 0)))]
852 "TARGET_SH1"
853 "div0s %0,%1"
854 [(set_attr "type" "arith")])
855
856 (define_insn_and_split "*cmp_div0s_0"
857 [(set (match_operand:SI 0 "arith_reg_dest" "")
858 (lshiftrt:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
859 (match_operand:SI 2 "arith_reg_operand" ""))
860 (const_int 31)))
861 (clobber (reg:SI T_REG))]
862 "TARGET_SH1"
863 "#"
864 "&& 1"
865 [(set (reg:SI T_REG)
866 (lshiftrt:SI (xor:SI (match_dup 1) (match_dup 2)) (const_int 31)))
867 (set (match_dup 0) (reg:SI T_REG))])
868
869 (define_insn "*cmp_div0s_0"
870 [(set (reg:SI T_REG)
871 (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
872 (const_int 31))
873 (ge:SI (match_operand:SI 1 "arith_reg_operand")
874 (const_int 0))))]
875 "TARGET_SH1"
876 "div0s %0,%1"
877 [(set_attr "type" "arith")])
878
879 (define_insn_and_split "*cmp_div0s_1"
880 [(set (match_operand:SI 0 "arith_reg_dest" "")
881 (ge:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
882 (match_operand:SI 2 "arith_reg_operand" ""))
883 (const_int 0)))
884 (clobber (reg:SI T_REG))]
885 "TARGET_SH1"
886 "#"
887 "&& can_create_pseudo_p ()"
888 [(const_int 0)]
889 ;; We have to go through the movnegt expander here which will handle the
890 ;; SH2A vs non-SH2A cases.
891 {
892 emit_insn (gen_cmp_div0s_1 (operands[1], operands[2]));
893 emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
894 DONE;
895 })
896
897 (define_insn_and_split "*cmp_div0s_1"
898 [(set (reg:SI T_REG)
899 (ge:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
900 (match_operand:SI 1 "arith_reg_operand" ""))
901 (const_int 0)))]
902 "TARGET_SH1"
903 "#"
904 "&& can_create_pseudo_p ()"
905 [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 0) (match_dup 1))
906 (const_int 0)))
907 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
908
909 (define_insn_and_split "*cmp_div0s_1"
910 [(set (reg:SI T_REG)
911 (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
912 (const_int 31))
913 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
914 (const_int 31))))]
915 "TARGET_SH1"
916 "#"
917 "&& can_create_pseudo_p ()"
918 [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 0) (match_dup 1))
919 (const_int 0)))
920 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
921
922 ;; -------------------------------------------------------------------------
923 ;; SImode compare and branch
924 ;; -------------------------------------------------------------------------
925
926 (define_expand "cbranchsi4"
927 [(set (pc)
928 (if_then_else (match_operator 0 "comparison_operator"
929 [(match_operand:SI 1 "arith_operand" "")
930 (match_operand:SI 2 "arith_operand" "")])
931 (label_ref (match_operand 3 "" ""))
932 (pc)))
933 (clobber (reg:SI T_REG))]
934 ""
935 {
936 if (TARGET_SHMEDIA)
937 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
938 operands[2], operands[3]));
939 else
940 expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
941
942 DONE;
943 })
944
945 ;; Combine patterns to invert compare and branch operations for which we
946 ;; don't have actual comparison insns. These patterns are used in cases
947 ;; which appear after the initial cbranchsi expansion, which also does
948 ;; some condition inversion.
949 (define_split
950 [(set (pc)
951 (if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "")
952 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
953 (label_ref (match_operand 2))
954 (pc)))
955 (clobber (reg:SI T_REG))]
956 "TARGET_SH1"
957 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1)))
958 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
959 (label_ref (match_dup 2))
960 (pc)))])
961
962 ;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A
963 ;; and SH2A combine fails to simplify this pattern by itself.
964 ;; What this actually does is:
965 ;; x == 0: (1 >> 0-0) & 1 = 1
966 ;; x != 0: (1 >> 0-x) & 1 = 0
967 ;; Without this the test pr51244-8.c fails on SH2A and SH4A.
968 (define_split
969 [(set (pc)
970 (if_then_else
971 (eq (and:SI (lshiftrt:SI
972 (const_int 1)
973 (neg:SI (match_operand:SI 0 "arith_reg_operand" "")))
974 (const_int 1))
975 (const_int 0))
976 (label_ref (match_operand 2))
977 (pc)))
978 (clobber (reg:SI T_REG))]
979 "TARGET_SH1"
980 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))
981 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
982 (label_ref (match_dup 2))
983 (pc)))])
984
985 ;; FIXME: These could probably use code iterators for the compare op.
986 (define_split
987 [(set (pc)
988 (if_then_else (le (match_operand:SI 0 "arith_reg_operand" "")
989 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
990 (label_ref (match_operand 2))
991 (pc)))
992 (clobber (reg:SI T_REG))]
993 "TARGET_SH1"
994 [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1)))
995 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
996 (label_ref (match_dup 2))
997 (pc)))])
998
999 (define_split
1000 [(set (pc)
1001 (if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "")
1002 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1003 (label_ref (match_operand 2))
1004 (pc)))
1005 (clobber (reg:SI T_REG))]
1006 "TARGET_SH1"
1007 [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1)))
1008 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1009 (label_ref (match_dup 2))
1010 (pc)))])
1011
1012 (define_split
1013 [(set (pc)
1014 (if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "")
1015 (match_operand:SI 1 "arith_reg_operand" ""))
1016 (label_ref (match_operand 2))
1017 (pc)))
1018 (clobber (reg:SI T_REG))]
1019 "TARGET_SH1"
1020 [(set (reg:SI T_REG) (gtu:SI (match_dup 0) (match_dup 1)))
1021 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1022 (label_ref (match_dup 2))
1023 (pc)))])
1024
1025 (define_split
1026 [(set (pc)
1027 (if_then_else (ltu (match_operand:SI 0 "arith_reg_operand" "")
1028 (match_operand:SI 1 "arith_reg_operand" ""))
1029 (label_ref (match_operand 2))
1030 (pc)))
1031 (clobber (reg:SI T_REG))]
1032 "TARGET_SH1"
1033 [(set (reg:SI T_REG) (geu:SI (match_dup 0) (match_dup 1)))
1034 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1035 (label_ref (match_dup 2))
1036 (pc)))])
1037
1038 ;; Compare and branch combine patterns for div0s comparisons.
1039 (define_insn_and_split "*cbranch_div0s"
1040 [(set (pc)
1041 (if_then_else (lt (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
1042 (match_operand:SI 1 "arith_reg_operand" ""))
1043 (const_int 0))
1044 (label_ref (match_operand 2))
1045 (pc)))
1046 (clobber (reg:SI T_REG))]
1047 "TARGET_SH1"
1048 "#"
1049 "&& 1"
1050 [(set (reg:SI T_REG)
1051 (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1052 (set (pc)
1053 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1054 (label_ref (match_dup 2))
1055 (pc)))])
1056
1057 (define_insn_and_split "*cbranch_div0s"
1058 [(set (pc)
1059 (if_then_else (ge (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
1060 (match_operand:SI 1 "arith_reg_operand" ""))
1061 (const_int 0))
1062 (label_ref (match_operand 2))
1063 (pc)))
1064 (clobber (reg:SI T_REG))]
1065 "TARGET_SH1"
1066 "#"
1067 "&& 1"
1068 [(set (reg:SI T_REG)
1069 (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1070 (set (pc)
1071 (if_then_else (eq (reg:SI T_REG) (const_int 0))
1072 (label_ref (match_dup 2))
1073 (pc)))])
1074
1075 ;; Conditional move combine pattern for div0s comparisons.
1076 ;; This is used when TARGET_PRETEND_CMOVE is in effect.
1077 (define_insn_and_split "*movsicc_div0s"
1078 [(set (match_operand:SI 0 "arith_reg_dest" "")
1079 (if_then_else:SI (ge (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
1080 (match_operand:SI 2 "arith_reg_operand" ""))
1081 (const_int 0))
1082 (match_operand:SI 3 "arith_reg_operand" "")
1083 (match_operand:SI 4 "general_movsrc_operand" "")))
1084 (clobber (reg:SI T_REG))]
1085 "TARGET_PRETEND_CMOVE"
1086 "#"
1087 "&& 1"
1088 [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2))
1089 (const_int 0)))
1090 (set (match_dup 0)
1091 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1092 (match_dup 4)
1093 (match_dup 3)))])
1094
1095 (define_insn_and_split "*movsicc_div0s"
1096 [(set (match_operand:SI 0 "arith_reg_dest")
1097 (if_then_else:SI (eq (lshiftrt:SI
1098 (match_operand:SI 1 "arith_reg_operand")
1099 (const_int 31))
1100 (lshiftrt:SI
1101 (match_operand:SI 2 "arith_reg_operand")
1102 (const_int 31)))
1103 (match_operand:SI 3 "arith_reg_operand")
1104 (match_operand:SI 4 "general_movsrc_operand")))
1105 (clobber (reg:SI T_REG))]
1106 "TARGET_PRETEND_CMOVE"
1107 "#"
1108 "&& 1"
1109 [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2))
1110 (const_int 0)))
1111 (set (match_dup 0)
1112 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1113 (match_dup 4)
1114 (match_dup 3)))])
1115
1116 ;; -------------------------------------------------------------------------
1117 ;; SImode unsigned integer comparisons
1118 ;; -------------------------------------------------------------------------
1119
1120 ;; Usually comparisons of 'unsigned int >= 0' are optimized away completely.
1121 ;; However, especially when optimizations are off (e.g. -O0) such comparisons
1122 ;; might remain and we have to handle them. If the '>= 0' case wasn't
1123 ;; handled here, something else would just load a '0' into the second operand
1124 ;; and do the comparison. We can do slightly better by just setting the
1125 ;; T bit to '1'.
1126 (define_insn_and_split "cmpgeusi_t"
1127 [(set (reg:SI T_REG)
1128 (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1129 (match_operand:SI 1 "arith_reg_or_0_operand" "r")))]
1130 "TARGET_SH1"
1131 "cmp/hs %1,%0"
1132 "&& satisfies_constraint_Z (operands[1])"
1133 [(set (reg:SI T_REG) (const_int 1))]
1134 ""
1135 [(set_attr "type" "mt_group")])
1136
1137 (define_insn "cmpgtusi_t"
1138 [(set (reg:SI T_REG)
1139 (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1140 (match_operand:SI 1 "arith_reg_operand" "r")))]
1141 "TARGET_SH1"
1142 "cmp/hi %1,%0"
1143 [(set_attr "type" "mt_group")])
1144 \f
1145 ;; -------------------------------------------------------------------------
1146 ;; DImode compare and branch
1147 ;; -------------------------------------------------------------------------
1148
1149 ;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
1150 ;; Therefore, we aim to have a set of three branches that go straight to the
1151 ;; destination, i.e. only one of them is taken at any one time.
1152 ;; This mechanism should also be slightly better for the sh4-200.
1153
1154 (define_expand "cbranchdi4"
1155 [(set (pc)
1156 (if_then_else (match_operator 0 "comparison_operator"
1157 [(match_operand:DI 1 "arith_operand" "")
1158 (match_operand:DI 2 "arith_operand" "")])
1159 (label_ref (match_operand 3 "" ""))
1160 (pc)))
1161 (clobber (match_dup 4))
1162 (clobber (reg:SI T_REG))]
1163 "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
1164 {
1165 enum rtx_code comparison;
1166
1167 if (TARGET_SHMEDIA)
1168 {
1169 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
1170 operands[2], operands[3]));
1171 DONE;
1172 }
1173 else if (!TARGET_CBRANCHDI4)
1174 {
1175 sh_emit_compare_and_branch (operands, DImode);
1176 DONE;
1177 }
1178 else
1179 {
1180 if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
1181 DONE;
1182
1183 comparison = prepare_cbranch_operands (operands, DImode,
1184 LAST_AND_UNUSED_RTX_CODE);
1185 if (comparison != GET_CODE (operands[0]))
1186 operands[0]
1187 = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
1188 operands[4] = gen_rtx_SCRATCH (SImode);
1189 }
1190 })
1191
1192 (define_insn_and_split "cbranchdi4_i"
1193 [(set (pc)
1194 (if_then_else (match_operator 0 "comparison_operator"
1195 [(match_operand:DI 1 "arith_operand" "r,r")
1196 (match_operand:DI 2 "arith_operand" "rN,I08")])
1197 (label_ref (match_operand 3 "" ""))
1198 (pc)))
1199 (clobber (match_scratch:SI 4 "=X,&r"))
1200 (clobber (reg:SI T_REG))]
1201 "TARGET_CBRANCHDI4"
1202 "#"
1203 "&& reload_completed"
1204 [(pc)]
1205 {
1206 if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
1207 FAIL;
1208 DONE;
1209 })
1210
1211 ;; -------------------------------------------------------------------------
1212 ;; DImode signed integer comparisons
1213 ;; -------------------------------------------------------------------------
1214
1215 (define_insn ""
1216 [(set (reg:SI T_REG)
1217 (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
1218 (match_operand:DI 1 "arith_operand" "r"))
1219 (const_int 0)))]
1220 "TARGET_SH1"
1221 {
1222 return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0",
1223 insn, operands);
1224 }
1225 [(set_attr "length" "6")
1226 (set_attr "type" "arith3b")])
1227
1228 (define_insn "cmpeqdi_t"
1229 [(set (reg:SI T_REG)
1230 (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1231 (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
1232 "TARGET_SH1"
1233 {
1234 static const char* alt[] =
1235 {
1236 "tst %S0,%S0" "\n"
1237 " bf 0f" "\n"
1238 " tst %R0,%R0" "\n"
1239 "0:",
1240
1241 "cmp/eq %S1,%S0" "\n"
1242 " bf 0f" "\n"
1243 " cmp/eq %R1,%R0" "\n"
1244 "0:"
1245 };
1246 return alt[which_alternative];
1247 }
1248 [(set_attr "length" "6")
1249 (set_attr "type" "arith3b")])
1250
1251 (define_split
1252 [(set (reg:SI T_REG)
1253 (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
1254 (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
1255 ;; If we applied this split when not optimizing, it would only be
1256 ;; applied during the machine-dependent reorg, when no new basic blocks
1257 ;; may be created.
1258 "TARGET_SH1 && reload_completed && optimize"
1259 [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
1260 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1261 (label_ref (match_dup 6))
1262 (pc)))
1263 (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
1264 (match_dup 6)]
1265 {
1266 operands[2] = gen_highpart (SImode, operands[0]);
1267 operands[3] = operands[1] == const0_rtx
1268 ? const0_rtx
1269 : gen_highpart (SImode, operands[1]);
1270 operands[4] = gen_lowpart (SImode, operands[0]);
1271 operands[5] = gen_lowpart (SImode, operands[1]);
1272 operands[6] = gen_label_rtx ();
1273 })
1274
1275 (define_insn "cmpgtdi_t"
1276 [(set (reg:SI T_REG)
1277 (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1278 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1279 "TARGET_SH2"
1280 {
1281 static const char* alt[] =
1282 {
1283 "cmp/eq %S1,%S0" "\n"
1284 " bf{.|/}s 0f" "\n"
1285 " cmp/gt %S1,%S0" "\n"
1286 " cmp/hi %R1,%R0" "\n"
1287 "0:",
1288
1289 "tst %S0,%S0" "\n"
1290 " bf{.|/}s 0f" "\n"
1291 " cmp/pl %S0" "\n"
1292 " cmp/hi %S0,%R0" "\n"
1293 "0:"
1294 };
1295 return alt[which_alternative];
1296 }
1297 [(set_attr "length" "8")
1298 (set_attr "type" "arith3")])
1299
1300 (define_insn "cmpgedi_t"
1301 [(set (reg:SI T_REG)
1302 (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1303 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1304 "TARGET_SH2"
1305 {
1306 static const char* alt[] =
1307 {
1308 "cmp/eq %S1,%S0" "\n"
1309 " bf{.|/}s 0f" "\n"
1310 " cmp/ge %S1,%S0" "\n"
1311 " cmp/hs %R1,%R0" "\n"
1312 "0:",
1313
1314 "cmp/pz %S0"
1315 };
1316 return alt[which_alternative];
1317 }
1318 [(set_attr "length" "8,2")
1319 (set_attr "type" "arith3,mt_group")])
1320 \f
1321 ;; -------------------------------------------------------------------------
1322 ;; DImode unsigned integer comparisons
1323 ;; -------------------------------------------------------------------------
1324
1325 (define_insn "cmpgeudi_t"
1326 [(set (reg:SI T_REG)
1327 (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1328 (match_operand:DI 1 "arith_reg_operand" "r")))]
1329 "TARGET_SH2"
1330 {
1331 return "cmp/eq %S1,%S0" "\n"
1332 " bf{.|/}s 0f" "\n"
1333 " cmp/hs %S1,%S0" "\n"
1334 " cmp/hs %R1,%R0" "\n"
1335 "0:";
1336 }
1337 [(set_attr "length" "8")
1338 (set_attr "type" "arith3")])
1339
1340 (define_insn "cmpgtudi_t"
1341 [(set (reg:SI T_REG)
1342 (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1343 (match_operand:DI 1 "arith_reg_operand" "r")))]
1344 "TARGET_SH2"
1345 {
1346 return "cmp/eq %S1,%S0" "\n"
1347 " bf{.|/}s 0f" "\n"
1348 " cmp/hi %S1,%S0" "\n"
1349 " cmp/hi %R1,%R0" "\n"
1350 "0:";
1351 }
1352 [(set_attr "length" "8")
1353 (set_attr "type" "arith3")])
1354
1355 (define_insn "cmpeqsi_media"
1356 [(set (match_operand:SI 0 "register_operand" "=r")
1357 (eq:SI (match_operand:SI 1 "logical_operand" "%r")
1358 (match_operand:SI 2 "cmp_operand" "Nr")))]
1359 "TARGET_SHMEDIA"
1360 "cmpeq %1, %N2, %0"
1361 [(set_attr "type" "cmp_media")])
1362
1363 (define_insn "cmpeqdi_media"
1364 [(set (match_operand:SI 0 "register_operand" "=r")
1365 (eq:SI (match_operand:DI 1 "register_operand" "%r")
1366 (match_operand:DI 2 "cmp_operand" "Nr")))]
1367 "TARGET_SHMEDIA"
1368 "cmpeq %1, %N2, %0"
1369 [(set_attr "type" "cmp_media")])
1370
1371 (define_insn "cmpgtsi_media"
1372 [(set (match_operand:SI 0 "register_operand" "=r")
1373 (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
1374 (match_operand:SI 2 "cmp_operand" "rN")))]
1375 "TARGET_SHMEDIA"
1376 "cmpgt %N1, %N2, %0"
1377 [(set_attr "type" "cmp_media")])
1378
1379 (define_insn "cmpgtdi_media"
1380 [(set (match_operand:SI 0 "register_operand" "=r")
1381 (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1382 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1383 "TARGET_SHMEDIA"
1384 "cmpgt %N1, %N2, %0"
1385 [(set_attr "type" "cmp_media")])
1386
1387 (define_insn "cmpgtusi_media"
1388 [(set (match_operand:SI 0 "register_operand" "=r")
1389 (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
1390 (match_operand:SI 2 "cmp_operand" "rN")))]
1391 "TARGET_SHMEDIA"
1392 "cmpgtu %N1, %N2, %0"
1393 [(set_attr "type" "cmp_media")])
1394
1395 (define_insn "cmpgtudi_media"
1396 [(set (match_operand:SI 0 "register_operand" "=r")
1397 (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1398 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1399 "TARGET_SHMEDIA"
1400 "cmpgtu %N1, %N2, %0"
1401 [(set_attr "type" "cmp_media")])
1402
1403 ; This pattern is for combine.
1404 (define_insn "*cmpne0sisi_media"
1405 [(set (match_operand:SI 0 "register_operand" "=r")
1406 (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
1407 "TARGET_SHMEDIA"
1408 "cmpgtu %1,r63,%0"
1409 [(set_attr "type" "cmp_media")])
1410
1411 ;; -------------------------------------------------------------------------
1412 ;; Conditional move instructions
1413 ;; -------------------------------------------------------------------------
1414
1415 ;; The insn names may seem reversed, but note that cmveq performs the move
1416 ;; if op1 == 0, and cmvne does it if op1 != 0.
1417
1418 (define_insn "movdicc_false"
1419 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1420 (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
1421 (const_int 0))
1422 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1423 (match_operand:DI 3 "arith_reg_operand" "0")))]
1424 "TARGET_SHMEDIA"
1425 "cmveq %1, %N2, %0"
1426 [(set_attr "type" "arith_media")])
1427
1428 (define_insn "movdicc_true"
1429 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1430 (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
1431 (const_int 0))
1432 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1433 (match_operand:DI 3 "arith_reg_operand" "0")))]
1434 "TARGET_SHMEDIA"
1435 "cmvne %1, %N2, %0"
1436 [(set_attr "type" "arith_media")])
1437
1438 (define_peephole2
1439 [(set (match_operand:DI 0 "arith_reg_dest" "")
1440 (if_then_else:DI (match_operator 3 "equality_comparison_operator"
1441 [(match_operand:DI 1 "arith_reg_operand" "")
1442 (const_int 0)])
1443 (match_operand:DI 2 "arith_reg_dest" "")
1444 (match_dup 0)))
1445 (set (match_dup 2) (match_dup 0))]
1446 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1447 [(set (match_dup 2)
1448 (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
1449 {
1450 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1451 VOIDmode, operands[1], CONST0_RTX (DImode));
1452 })
1453
1454 (define_peephole2
1455 [(set (match_operand:DI 0 "general_movdst_operand" "")
1456 (match_operand:DI 1 "arith_reg_or_0_operand" ""))
1457 (set (match_operand:DI 2 "arith_reg_dest" "")
1458 (if_then_else:DI (match_operator 4 "equality_comparison_operator"
1459 [(match_operand:DI 3 "arith_reg_operand" "")
1460 (const_int 0)])
1461 (match_dup 0)
1462 (match_dup 2)))]
1463 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1464 [(set (match_dup 2)
1465 (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
1466 "")
1467
1468 (define_expand "movdicc"
1469 [(set (match_operand:DI 0 "register_operand" "")
1470 (if_then_else:DI (match_operand 1 "comparison_operator" "")
1471 (match_operand:DI 2 "register_operand" "")
1472 (match_operand:DI 3 "register_operand" "")))]
1473 "TARGET_SHMEDIA"
1474 {
1475 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1476 && GET_MODE (XEXP (operands[1], 0)) == DImode
1477 && XEXP (operands[1], 1) == const0_rtx)
1478 ;
1479 else
1480 {
1481 if (!can_create_pseudo_p ())
1482 FAIL;
1483
1484 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1485 GET_CODE (operands[1]),
1486 XEXP (operands[1], 0),
1487 XEXP (operands[1], 1));
1488 if (!operands[1])
1489 FAIL;
1490 }
1491 })
1492
1493 ;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1494 ;; SImode to DImode.
1495 (define_insn "movsicc_false"
1496 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1497 (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1498 (const_int 0))
1499 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1500 (match_operand:SI 3 "arith_reg_operand" "0")))]
1501 "TARGET_SHMEDIA"
1502 "cmveq %1, %N2, %0"
1503 [(set_attr "type" "arith_media")])
1504
1505 (define_insn "movsicc_true"
1506 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1507 (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1508 (const_int 0))
1509 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1510 (match_operand:SI 3 "arith_reg_operand" "0")))]
1511 "TARGET_SHMEDIA"
1512 "cmvne %1, %N2, %0"
1513 [(set_attr "type" "arith_media")])
1514
1515 (define_peephole2
1516 [(set (match_operand:SI 0 "arith_reg_dest" "")
1517 (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1518 [(match_operand:SI 1 "arith_reg_operand" "")
1519 (const_int 0)])
1520 (match_operand:SI 2 "arith_reg_dest" "")
1521 (match_dup 0)))
1522 (set (match_dup 2) (match_dup 0))]
1523 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1524 [(set (match_dup 2)
1525 (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1526 {
1527 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1528 VOIDmode, operands[1], CONST0_RTX (SImode));
1529 })
1530
1531 (define_peephole2
1532 [(set (match_operand:SI 0 "general_movdst_operand" "")
1533 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1534 (set (match_operand:SI 2 "arith_reg_dest" "")
1535 (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1536 [(match_operand:SI 3 "arith_reg_operand" "")
1537 (const_int 0)])
1538 (match_dup 0)
1539 (match_dup 2)))]
1540 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1541 && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1542 [(set (match_dup 2)
1543 (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1544 {
1545 replace_rtx (operands[4], operands[0], operands[1]);
1546 })
1547
1548 (define_peephole2
1549 [(set (match_operand 0 "any_register_operand" "")
1550 (match_operand 1 "any_register_operand" ""))
1551 (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1552 (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1553 "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1554 <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1555 && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1556 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1557 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1558 && ! reg_overlap_mentioned_p (operands[0], operands[3])
1559 && ! reg_overlap_mentioned_p (operands[2], operands[0])
1560 && ! reg_overlap_mentioned_p (operands[0], operands[1])
1561 && (REGNO_REG_CLASS (REGNO (operands[0]))
1562 == REGNO_REG_CLASS (REGNO (operands[2])))
1563 && (REGNO_REG_CLASS (REGNO (operands[1]))
1564 == REGNO_REG_CLASS (REGNO (operands[0])))"
1565 [(set (match_dup 0) (match_dup 3))
1566 (set (match_dup 4) (match_dup 5))]
1567 {
1568 rtx set1, set2, insn2;
1569 rtx replacements[4];
1570
1571 /* We want to replace occurrences of operands[0] with operands[1] and
1572 operands[2] with operands[0] in operands[4]/operands[5].
1573 Doing just two replace_rtx calls naively would result in the second
1574 replacement undoing all that the first did if operands[1] and operands[2]
1575 are identical, so we must do this simultaneously. */
1576 replacements[0] = operands[0];
1577 replacements[1] = operands[1];
1578 replacements[2] = operands[2];
1579 replacements[3] = operands[0];
1580 if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1581 || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1582 || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1583 FAIL;
1584
1585 operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1586 replace_n_hard_rtx (operands[4], replacements, 2, 1);
1587 operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1588 /* The operands array is aliased to recog_data.operand, which gets
1589 clobbered by extract_insn, so finish with it now. */
1590 set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1591 set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1592 /* ??? The last insn might be a jump insn, but the generic peephole2 code
1593 always uses emit_insn. */
1594 /* Check that we don't violate matching constraints or earlyclobbers. */
1595 extract_insn (emit_insn (set1));
1596 if (! constrain_operands (1))
1597 goto failure;
1598 insn2 = emit (set2);
1599 if (GET_CODE (insn2) == BARRIER)
1600 goto failure;
1601 extract_insn (insn2);
1602 if (! constrain_operands (1))
1603 {
1604 rtx tmp;
1605 failure:
1606 tmp = replacements[0];
1607 replacements[0] = replacements[1];
1608 replacements[1] = tmp;
1609 tmp = replacements[2];
1610 replacements[2] = replacements[3];
1611 replacements[3] = tmp;
1612 replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1613 replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1614 replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1615 FAIL;
1616 }
1617 DONE;
1618 })
1619
1620 ;; The register allocator is rather clumsy in handling multi-way conditional
1621 ;; moves, so allow the combiner to make them, and we split them up after
1622 ;; reload. */
1623 (define_insn_and_split "*movsicc_umin"
1624 [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1625 (umin:SI (if_then_else:SI
1626 (eq (match_operand:SI 1 "arith_reg_operand" "r")
1627 (const_int 0))
1628 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1629 (match_operand:SI 3 "register_operand" "0"))
1630 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1631 (clobber (match_scratch:SI 5 "=&r"))]
1632 "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1633 "#"
1634 "TARGET_SHMEDIA && reload_completed"
1635 [(pc)]
1636 {
1637 emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1638 operands[3]));
1639 emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1640 emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1641 operands[0]));
1642 DONE;
1643 })
1644
1645 (define_insn "*movsicc_t_false"
1646 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1647 (if_then_else (eq (reg:SI T_REG) (const_int 0))
1648 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1649 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1650 "TARGET_PRETEND_CMOVE
1651 && (arith_reg_operand (operands[1], SImode)
1652 || (immediate_operand (operands[1], SImode)
1653 && satisfies_constraint_I08 (operands[1])))"
1654 {
1655 return "bt 0f" "\n"
1656 " mov %1,%0" "\n"
1657 "0:";
1658 }
1659 [(set_attr "type" "mt_group,arith") ;; poor approximation
1660 (set_attr "length" "4")])
1661
1662 (define_insn "*movsicc_t_true"
1663 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1664 (if_then_else (ne (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 "bf 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_expand "movsicc"
1680 [(set (match_operand:SI 0 "arith_reg_dest" "")
1681 (if_then_else:SI (match_operand 1 "comparison_operator" "")
1682 (match_operand:SI 2 "arith_reg_or_0_operand" "")
1683 (match_operand:SI 3 "arith_reg_operand" "")))]
1684 "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1685 {
1686 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1687 && GET_MODE (XEXP (operands[1], 0)) == SImode
1688 && (TARGET_SHMEDIA
1689 || (REG_P (XEXP (operands[1], 0))
1690 && REGNO (XEXP (operands[1], 0)) == T_REG))
1691 && XEXP (operands[1], 1) == const0_rtx)
1692 ;
1693
1694 else if (TARGET_PRETEND_CMOVE)
1695 {
1696 enum rtx_code code = GET_CODE (operands[1]);
1697 enum rtx_code new_code = code;
1698 rtx op0 = XEXP (operands[1], 0);
1699 rtx op1 = XEXP (operands[1], 1);
1700
1701 if (! currently_expanding_to_rtl)
1702 FAIL;
1703 switch (code)
1704 {
1705 case LT: case LE: case LEU: case LTU:
1706 if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1707 break;
1708 case NE:
1709 new_code = reverse_condition (code);
1710 break;
1711 case EQ: case GT: case GE: case GEU: case GTU:
1712 break;
1713 default:
1714 FAIL;
1715 }
1716 sh_emit_scc_to_t (new_code, op0, op1);
1717 operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1718 gen_rtx_REG (SImode, T_REG), const0_rtx);
1719 }
1720 else
1721 {
1722 if (!can_create_pseudo_p ())
1723 FAIL;
1724
1725 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1726 GET_CODE (operands[1]),
1727 XEXP (operands[1], 0),
1728 XEXP (operands[1], 1));
1729 if (!operands[1])
1730 FAIL;
1731 }
1732 })
1733
1734 (define_expand "movqicc"
1735 [(set (match_operand:QI 0 "register_operand" "")
1736 (if_then_else:QI (match_operand 1 "comparison_operator" "")
1737 (match_operand:QI 2 "register_operand" "")
1738 (match_operand:QI 3 "register_operand" "")))]
1739 "TARGET_SHMEDIA"
1740 {
1741 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1742 operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1743 operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1744 emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1745 DONE;
1746 })
1747 \f
1748 ;; -------------------------------------------------------------------------
1749 ;; Addition instructions
1750 ;; -------------------------------------------------------------------------
1751
1752 (define_expand "adddi3"
1753 [(set (match_operand:DI 0 "arith_reg_operand")
1754 (plus:DI (match_operand:DI 1 "arith_reg_operand")
1755 (match_operand:DI 2 "arith_operand")))]
1756 ""
1757 {
1758 if (TARGET_SH1)
1759 {
1760 operands[2] = force_reg (DImode, operands[2]);
1761 emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1762 DONE;
1763 }
1764 })
1765
1766 (define_insn "*adddi3_media"
1767 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1768 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1769 (match_operand:DI 2 "arith_operand" "r,I10")))]
1770 "TARGET_SHMEDIA"
1771 "@
1772 add %1, %2, %0
1773 addi %1, %2, %0"
1774 [(set_attr "type" "arith_media")])
1775
1776 (define_insn "*adddisi3_media"
1777 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1778 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1779 (match_operand:DI 2 "arith_operand" "r,I10")))]
1780 "TARGET_SHMEDIA"
1781 "@
1782 add.l %1, %2, %0
1783 addi.l %1, %2, %0"
1784 [(set_attr "type" "arith_media")
1785 (set_attr "highpart" "ignore")])
1786
1787 (define_insn "adddi3z_media"
1788 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1789 (zero_extend:DI
1790 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1791 (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1792 "TARGET_SHMEDIA"
1793 "addz.l %1, %N2, %0"
1794 [(set_attr "type" "arith_media")
1795 (set_attr "highpart" "ignore")])
1796
1797 (define_insn_and_split "adddi3_compact"
1798 [(set (match_operand:DI 0 "arith_reg_dest")
1799 (plus:DI (match_operand:DI 1 "arith_reg_operand")
1800 (match_operand:DI 2 "arith_reg_operand")))
1801 (clobber (reg:SI T_REG))]
1802 "TARGET_SH1"
1803 "#"
1804 "&& can_create_pseudo_p ()"
1805 [(const_int 0)]
1806 {
1807 emit_insn (gen_clrt ());
1808 emit_insn (gen_addc (gen_lowpart (SImode, operands[0]),
1809 gen_lowpart (SImode, operands[1]),
1810 gen_lowpart (SImode, operands[2])));
1811 emit_insn (gen_addc (gen_highpart (SImode, operands[0]),
1812 gen_highpart (SImode, operands[1]),
1813 gen_highpart (SImode, operands[2])));
1814 DONE;
1815 })
1816
1817 (define_insn "addc"
1818 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1819 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1820 (match_operand:SI 2 "arith_reg_operand" "r"))
1821 (reg:SI T_REG)))
1822 (set (reg:SI T_REG)
1823 (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1824 "TARGET_SH1"
1825 "addc %2,%0"
1826 [(set_attr "type" "arith")])
1827
1828 ;; A simplified version of the addc insn, where the exact value of the
1829 ;; T bit doesn't matter. This is easier for combine to pick up.
1830 ;; We allow a reg or 0 for one of the operands in order to be able to
1831 ;; do 'reg + T' sequences. Reload will load the constant 0 into the reg
1832 ;; as needed.
1833 (define_insn "*addc"
1834 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1835 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1836 (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
1837 (match_operand:SI 3 "t_reg_operand" "")))
1838 (clobber (reg:SI T_REG))]
1839 "TARGET_SH1"
1840 "addc %2,%0"
1841 [(set_attr "type" "arith")])
1842
1843 ;; Split 'reg + reg + 1' into a sett addc sequence, as it can be scheduled
1844 ;; better, if the sett insn can be done early.
1845 (define_insn_and_split "*addc_r_r_1"
1846 [(set (match_operand:SI 0 "arith_reg_dest" "")
1847 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
1848 (match_operand:SI 2 "arith_reg_operand" ""))
1849 (const_int 1)))
1850 (clobber (reg:SI T_REG))]
1851 "TARGET_SH1"
1852 "#"
1853 "&& 1"
1854 [(set (reg:SI T_REG) (const_int 1))
1855 (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
1856 (reg:SI T_REG)))
1857 (clobber (reg:SI T_REG))])])
1858
1859 ;; Left shifts by one are usually done with an add insn to avoid T_REG
1860 ;; clobbers. Thus addc can also be used to do something like '(x << 1) + 1'.
1861 (define_insn_and_split "*addc_2r_1"
1862 [(set (match_operand:SI 0 "arith_reg_dest")
1863 (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
1864 (const_int 2))
1865 (const_int 1)))
1866 (clobber (reg:SI T_REG))]
1867 "TARGET_SH1"
1868 "#"
1869 "&& 1"
1870 [(set (reg:SI T_REG) (const_int 1))
1871 (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 1))
1872 (reg:SI T_REG)))
1873 (clobber (reg:SI T_REG))])])
1874
1875 ;; Sometimes combine will try to do 'reg + (0-reg) + 1' if the *addc pattern
1876 ;; matched. Split this up into a simple sub add sequence, as this will save
1877 ;; us one sett insn.
1878 (define_insn_and_split "*minus_plus_one"
1879 [(set (match_operand:SI 0 "arith_reg_dest" "")
1880 (plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
1881 (match_operand:SI 2 "arith_reg_operand" ""))
1882 (const_int 1)))]
1883 "TARGET_SH1"
1884 "#"
1885 "&& 1"
1886 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1887 (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))])
1888
1889 ;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn.
1890 ;; If the 0 constant can be CSE-ed, this becomes a one instruction
1891 ;; operation, as opposed to sequences such as
1892 ;; movt r2
1893 ;; add r2,r3
1894 ;;
1895 ;; Even if the constant is not CSE-ed, a sequence such as
1896 ;; mov #0,r2
1897 ;; addc r2,r3
1898 ;; can be scheduled much better since the load of the constant can be
1899 ;; done earlier, before any comparison insns that store the result in
1900 ;; the T bit.
1901 (define_insn_and_split "*addc_r_1"
1902 [(set (match_operand:SI 0 "arith_reg_dest" "")
1903 (plus:SI (match_operand:SI 1 "t_reg_operand" "")
1904 (match_operand:SI 2 "arith_reg_operand" "")))
1905 (clobber (reg:SI T_REG))]
1906 "TARGET_SH1"
1907 "#"
1908 "&& 1"
1909 [(parallel [(set (match_dup 0)
1910 (plus:SI (plus:SI (match_dup 2) (const_int 0))
1911 (match_dup 1)))
1912 (clobber (reg:SI T_REG))])])
1913
1914 ;; Use shlr-addc to do 'reg + (reg & 1)'.
1915 (define_insn_and_split "*addc_r_lsb"
1916 [(set (match_operand:SI 0 "arith_reg_dest")
1917 (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1918 (const_int 1))
1919 (match_operand:SI 2 "arith_reg_operand")))
1920 (clobber (reg:SI T_REG))]
1921 "TARGET_SH1"
1922 "#"
1923 "&& can_create_pseudo_p ()"
1924 [(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2)))
1925 (clobber (reg:SI T_REG))])]
1926 {
1927 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1]));
1928 })
1929
1930 ;; Use shlr-addc to do 'reg + reg + (reg & 1)'.
1931 (define_insn_and_split "*addc_r_r_lsb"
1932 [(set (match_operand:SI 0 "arith_reg_dest")
1933 (plus:SI (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1934 (const_int 1))
1935 (match_operand:SI 2 "arith_reg_operand"))
1936 (match_operand:SI 3 "arith_reg_operand")))
1937 (clobber (reg:SI T_REG))]
1938 "TARGET_SH1"
1939 "#"
1940 "&& can_create_pseudo_p ()"
1941 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
1942 (reg:SI T_REG)))
1943 (clobber (reg:SI T_REG))])]
1944 {
1945 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1]));
1946 })
1947
1948 ;; Canonicalize 'reg + (reg & 1) + reg' into 'reg + reg + (reg & 1)'.
1949 (define_insn_and_split "*addc_r_lsb_r"
1950 [(set (match_operand:SI 0 "arith_reg_dest")
1951 (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1952 (const_int 1))
1953 (plus:SI (match_operand:SI 2 "arith_reg_operand")
1954 (match_operand:SI 3 "arith_reg_operand"))))
1955 (clobber (reg:SI T_REG))]
1956 "TARGET_SH1"
1957 "#"
1958 "&& can_create_pseudo_p ()"
1959 [(parallel [(set (match_dup 0)
1960 (plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1))
1961 (match_dup 2))
1962 (match_dup 3)))
1963 (clobber (reg:SI T_REG))])])
1964
1965 ;; Canonicalize '2 * reg + (reg & 1)' into 'reg + reg + (reg & 1)'.
1966 (define_insn_and_split "*addc_2r_lsb"
1967 [(set (match_operand:SI 0 "arith_reg_dest")
1968 (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1969 (const_int 1))
1970 (mult:SI (match_operand:SI 2 "arith_reg_operand")
1971 (const_int 2))))
1972 (clobber (reg:SI T_REG))]
1973 "TARGET_SH1"
1974 "#"
1975 "&& can_create_pseudo_p ()"
1976 [(parallel [(set (match_dup 0)
1977 (plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1))
1978 (match_dup 2))
1979 (match_dup 2)))
1980 (clobber (reg:SI T_REG))])])
1981
1982 ;; Use shll-addc to do 'reg + ((unsigned int)reg >> 31)'.
1983 (define_insn_and_split "*addc_r_msb"
1984 [(set (match_operand:SI 0 "arith_reg_dest")
1985 (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
1986 (const_int 31))
1987 (match_operand:SI 2 "arith_reg_operand")))
1988 (clobber (reg:SI T_REG))]
1989 "TARGET_SH1"
1990 "#"
1991 "&& can_create_pseudo_p ()"
1992 [(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2)))
1993 (clobber (reg:SI T_REG))])]
1994 {
1995 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1]));
1996 })
1997
1998 ;; Use shll-addc to do 'reg + reg + ((unsigned int)reg >> 31)'.
1999 (define_insn_and_split "*addc_r_r_msb"
2000 [(set (match_operand:SI 0 "arith_reg_dest")
2001 (plus:SI (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
2002 (const_int 31))
2003 (match_operand:SI 2 "arith_reg_operand"))
2004 (match_operand:SI 3 "arith_reg_operand")))
2005 (clobber (reg:SI T_REG))]
2006 "TARGET_SH1"
2007 "#"
2008 "&& can_create_pseudo_p ()"
2009 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
2010 (reg:SI T_REG)))
2011 (clobber (reg:SI T_REG))])]
2012 {
2013 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1]));
2014 })
2015
2016 ;; Canonicalize '2 * reg + ((unsigned int)reg >> 31)'
2017 ;; into 'reg + reg + (reg & 1)'.
2018 (define_insn_and_split "*addc_2r_msb"
2019 [(set (match_operand:SI 0 "arith_reg_dest")
2020 (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
2021 (const_int 2))
2022 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
2023 (const_int 31))))
2024 (clobber (reg:SI T_REG))]
2025 "TARGET_SH1"
2026 "#"
2027 "&& can_create_pseudo_p ()"
2028 [(parallel [(set (match_dup 0)
2029 (plus:SI (plus:SI (lshiftrt:SI (match_dup 2) (const_int 31))
2030 (match_dup 1))
2031 (match_dup 1)))
2032 (clobber (reg:SI T_REG))])])
2033
2034 (define_expand "addsi3"
2035 [(set (match_operand:SI 0 "arith_reg_operand" "")
2036 (plus:SI (match_operand:SI 1 "arith_operand" "")
2037 (match_operand:SI 2 "arith_operand" "")))]
2038 ""
2039 {
2040 if (TARGET_SHMEDIA)
2041 operands[1] = force_reg (SImode, operands[1]);
2042 })
2043
2044 (define_insn "addsi3_media"
2045 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
2046 (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
2047 (match_operand:SI 2 "arith_operand" "r,I10")))]
2048 "TARGET_SHMEDIA"
2049 "@
2050 add.l %1, %2, %0
2051 addi.l %1, %2, %0"
2052 [(set_attr "type" "arith_media")
2053 (set_attr "highpart" "ignore")])
2054
2055 (define_insn "addsidi3_media"
2056 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
2057 (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
2058 "%r,r")
2059 (match_operand:SI 2 "arith_operand"
2060 "r,I10"))))]
2061 "TARGET_SHMEDIA"
2062 "@
2063 add.l %1, %2, %0
2064 addi.l %1, %2, %0"
2065 [(set_attr "type" "arith_media")
2066 (set_attr "highpart" "ignore")])
2067
2068 (define_insn "*addsi3_compact"
2069 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2070 (plus:SI (match_operand:SI 1 "arith_operand" "%0")
2071 (match_operand:SI 2 "arith_operand" "rI08")))]
2072 "TARGET_SH1"
2073 "add %2,%0"
2074 [(set_attr "type" "arith")])
2075
2076 ;; -------------------------------------------------------------------------
2077 ;; Subtraction instructions
2078 ;; -------------------------------------------------------------------------
2079
2080 (define_expand "subdi3"
2081 [(set (match_operand:DI 0 "arith_reg_operand" "")
2082 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
2083 (match_operand:DI 2 "arith_reg_operand" "")))]
2084 ""
2085 {
2086 if (TARGET_SH1)
2087 {
2088 operands[1] = force_reg (DImode, operands[1]);
2089 emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
2090 DONE;
2091 }
2092 })
2093
2094 (define_insn "*subdi3_media"
2095 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2096 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
2097 (match_operand:DI 2 "arith_reg_operand" "r")))]
2098 "TARGET_SHMEDIA"
2099 "sub %N1, %2, %0"
2100 [(set_attr "type" "arith_media")])
2101
2102 (define_insn "subdisi3_media"
2103 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
2104 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
2105 (match_operand:DI 2 "arith_reg_operand" "r")))]
2106 "TARGET_SHMEDIA"
2107 "sub.l %N1, %2, %0"
2108 [(set_attr "type" "arith_media")
2109 (set_attr "highpart" "ignore")])
2110
2111 (define_insn_and_split "subdi3_compact"
2112 [(set (match_operand:DI 0 "arith_reg_dest")
2113 (minus:DI (match_operand:DI 1 "arith_reg_operand")
2114 (match_operand:DI 2 "arith_reg_operand")))
2115 (clobber (reg:SI T_REG))]
2116 "TARGET_SH1"
2117 "#"
2118 "&& can_create_pseudo_p ()"
2119 [(const_int 0)]
2120 {
2121 emit_insn (gen_clrt ());
2122 emit_insn (gen_subc (gen_lowpart (SImode, operands[0]),
2123 gen_lowpart (SImode, operands[1]),
2124 gen_lowpart (SImode, operands[2])));
2125 emit_insn (gen_subc (gen_highpart (SImode, operands[0]),
2126 gen_highpart (SImode, operands[1]),
2127 gen_highpart (SImode, operands[2])));
2128 DONE;
2129 })
2130
2131 (define_insn "subc"
2132 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2133 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2134 (match_operand:SI 2 "arith_reg_operand" "r"))
2135 (reg:SI T_REG)))
2136 (set (reg:SI T_REG)
2137 (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
2138 (reg:SI T_REG))
2139 (match_dup 1)))]
2140 "TARGET_SH1"
2141 "subc %2,%0"
2142 [(set_attr "type" "arith")])
2143
2144 ;; A simplified version of the subc insn, where the exact value of the
2145 ;; T bit doesn't matter. This is easier for combine to pick up.
2146 ;; We allow a reg or 0 for one of the operands in order to be able to
2147 ;; do 'reg - T' sequences. Reload will load the constant 0 into the reg
2148 ;; as needed.
2149 (define_insn "*subc"
2150 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2151 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2152 (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
2153 (match_operand:SI 3 "t_reg_operand" "")))
2154 (clobber (reg:SI T_REG))]
2155 "TARGET_SH1"
2156 "subc %2,%0"
2157 [(set_attr "type" "arith")])
2158
2159 ;; Split reg - reg - 1 into a sett subc sequence, as it can be scheduled
2160 ;; better, if the sett insn can be done early.
2161 ;; Notice that combine turns 'a - b - 1' into 'a + (~b)'.
2162 (define_insn_and_split "*subc"
2163 [(set (match_operand:SI 0 "arith_reg_dest" "")
2164 (plus:SI (not:SI (match_operand:SI 1 "arith_reg_operand" ""))
2165 (match_operand:SI 2 "arith_reg_operand" "")))
2166 (clobber (reg:SI T_REG))]
2167 "TARGET_SH1"
2168 "#"
2169 "&& 1"
2170 [(set (reg:SI T_REG) (const_int 1))
2171 (parallel [(set (match_dup 0)
2172 (minus:SI (minus:SI (match_dup 2) (match_dup 1))
2173 (reg:SI T_REG)))
2174 (clobber (reg:SI T_REG))])])
2175
2176 ;; Split 'reg - T' into 'reg - 0 - T' to utilize the subc insn.
2177 ;; If the 0 constant can be CSE-ed, this becomes a one instruction
2178 ;; operation, as opposed to sequences such as
2179 ;; movt r2
2180 ;; sub r2,r3
2181 ;;
2182 ;; Even if the constant is not CSE-ed, a sequence such as
2183 ;; mov #0,r2
2184 ;; subc r2,r3
2185 ;; can be scheduled much better since the load of the constant can be
2186 ;; done earlier, before any comparison insns that store the result in
2187 ;; the T bit.
2188 (define_insn_and_split "*subc"
2189 [(set (match_operand:SI 0 "arith_reg_dest" "")
2190 (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
2191 (match_operand:SI 2 "t_reg_operand" "")))
2192 (clobber (reg:SI T_REG))]
2193 "TARGET_SH1"
2194 "#"
2195 "&& 1"
2196 [(parallel [(set (match_dup 0)
2197 (minus:SI (minus:SI (match_dup 1) (const_int 0))
2198 (match_dup 2)))
2199 (clobber (reg:SI T_REG))])])
2200
2201 (define_insn "*subsi3_internal"
2202 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2203 (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2204 (match_operand:SI 2 "arith_reg_operand" "r")))]
2205 "TARGET_SH1"
2206 "sub %2,%0"
2207 [(set_attr "type" "arith")])
2208
2209 (define_insn_and_split "*subsi3_media"
2210 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2211 (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
2212 (match_operand:SI 2 "extend_reg_operand" "r")))]
2213 "TARGET_SHMEDIA
2214 && (operands[1] != constm1_rtx
2215 || (GET_CODE (operands[2]) != TRUNCATE
2216 && GET_CODE (operands[2]) != SUBREG))"
2217 "sub.l %N1, %2, %0"
2218 "operands[1] == constm1_rtx"
2219 [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
2220 ""
2221 [(set_attr "type" "arith_media")
2222 (set_attr "highpart" "ignore")])
2223
2224 (define_split
2225 [(set (match_operand:SI 0 "arith_reg_dest" "")
2226 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2227 "general_extend_operand"
2228 "") 0)) 0)))]
2229 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
2230 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2231 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2232 "")
2233
2234 (define_split
2235 [(set (match_operand:SI 0 "arith_reg_dest" "")
2236 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2237 "general_extend_operand"
2238 "") 0)) 3)))]
2239 "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
2240 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2241 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2242 "")
2243
2244 ;; Convert
2245 ;; constant - reg
2246 ;; to
2247 ;; neg reg
2248 ;; add reg, #const
2249 ;; since this will sometimes save one instruction.
2250 ;; Otherwise we might get a sequence like
2251 ;; mov #const, rY
2252 ;; sub rY, rX
2253 ;; mov rX, rY
2254 ;; if the source and dest regs are the same.
2255 (define_expand "subsi3"
2256 [(set (match_operand:SI 0 "arith_reg_operand" "")
2257 (minus:SI (match_operand:SI 1 "arith_operand" "")
2258 (match_operand:SI 2 "arith_reg_operand" "")))]
2259 ""
2260 {
2261 if (TARGET_SH1 && CONST_INT_P (operands[1]))
2262 {
2263 emit_insn (gen_negsi2 (operands[0], operands[2]));
2264 emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
2265 DONE;
2266 }
2267 if (TARGET_SHMEDIA)
2268 {
2269 if (!can_create_pseudo_p ()
2270 && ! arith_reg_or_0_operand (operands[1], SImode))
2271 FAIL;
2272 if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
2273 operands[1] = force_reg (SImode, operands[1]);
2274 }
2275 })
2276 \f
2277 ;; -------------------------------------------------------------------------
2278 ;; Division instructions
2279 ;; -------------------------------------------------------------------------
2280
2281 ;; We take advantage of the library routines which don't clobber as many
2282 ;; registers as a normal function call would.
2283
2284 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
2285 ;; also has an effect on the register that holds the address of the sfunc.
2286 ;; To make this work, we have an extra dummy insn that shows the use
2287 ;; of this register for reorg.
2288
2289 (define_insn "use_sfunc_addr"
2290 [(set (reg:SI PR_REG)
2291 (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
2292 "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
2293 ""
2294 [(set_attr "length" "0")])
2295
2296 (define_insn "udivsi3_sh2a"
2297 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2298 (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
2299 (match_operand:SI 2 "arith_reg_operand" "z")))]
2300 "TARGET_SH2A"
2301 "divu %2,%1"
2302 [(set_attr "type" "arith")
2303 (set_attr "in_delay_slot" "no")])
2304
2305 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
2306 ;; hard register 0. If we used hard register 0, then the next instruction
2307 ;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg
2308 ;; gets allocated to a stack slot that needs its address reloaded, then
2309 ;; there is nothing to prevent reload from using r0 to reload the address.
2310 ;; This reload would clobber the value in r0 we are trying to store.
2311 ;; If we let reload allocate r0, then this problem can never happen.
2312 (define_insn "udivsi3_i1"
2313 [(set (match_operand:SI 0 "register_operand" "=z")
2314 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2315 (clobber (reg:SI T_REG))
2316 (clobber (reg:SI PR_REG))
2317 (clobber (reg:SI R1_REG))
2318 (clobber (reg:SI R4_REG))
2319 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2320 "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2321 "jsr @%1%#"
2322 [(set_attr "type" "sfunc")
2323 (set_attr "needs_delay_slot" "yes")])
2324
2325 ; Since shmedia-nofpu code could be linked against shcompact code, and
2326 ; the udivsi3 libcall has the same name, we must consider all registers
2327 ; clobbered that are in the union of the registers clobbered by the
2328 ; shmedia and the shcompact implementation. Note, if the shcompact
2329 ; implementation actually used shcompact code, we'd need to clobber
2330 ; also r23 and fr23.
2331 (define_insn "udivsi3_i1_media"
2332 [(set (match_operand:SI 0 "register_operand" "=z")
2333 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2334 (clobber (reg:SI T_MEDIA_REG))
2335 (clobber (reg:SI PR_MEDIA_REG))
2336 (clobber (reg:SI R20_REG))
2337 (clobber (reg:SI R21_REG))
2338 (clobber (reg:SI R22_REG))
2339 (clobber (reg:DI TR0_REG))
2340 (clobber (reg:DI TR1_REG))
2341 (clobber (reg:DI TR2_REG))
2342 (use (match_operand 1 "target_reg_operand" "b"))]
2343 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2344 "blink %1, r18"
2345 [(set_attr "type" "sfunc")
2346 (set_attr "needs_delay_slot" "yes")])
2347
2348 (define_expand "udivsi3_i4_media"
2349 [(set (match_dup 3)
2350 (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
2351 (set (match_dup 4)
2352 (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
2353 (set (match_dup 5) (float:DF (match_dup 3)))
2354 (set (match_dup 6) (float:DF (match_dup 4)))
2355 (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
2356 (set (match_dup 8) (fix:DI (match_dup 7)))
2357 (set (match_operand:SI 0 "register_operand" "")
2358 (truncate:SI (match_dup 8)))]
2359 "TARGET_SHMEDIA_FPU"
2360 {
2361 operands[3] = gen_reg_rtx (DImode);
2362 operands[4] = gen_reg_rtx (DImode);
2363 operands[5] = gen_reg_rtx (DFmode);
2364 operands[6] = gen_reg_rtx (DFmode);
2365 operands[7] = gen_reg_rtx (DFmode);
2366 operands[8] = gen_reg_rtx (DImode);
2367 })
2368
2369 (define_insn "udivsi3_i4"
2370 [(set (match_operand:SI 0 "register_operand" "=y")
2371 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2372 (clobber (reg:SI T_REG))
2373 (clobber (reg:SI PR_REG))
2374 (clobber (reg:DF DR0_REG))
2375 (clobber (reg:DF DR2_REG))
2376 (clobber (reg:DF DR4_REG))
2377 (clobber (reg:SI R0_REG))
2378 (clobber (reg:SI R1_REG))
2379 (clobber (reg:SI R4_REG))
2380 (clobber (reg:SI R5_REG))
2381 (use (reg:PSI FPSCR_REG))
2382 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2383 "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2384 "jsr @%1%#"
2385 [(set_attr "type" "sfunc")
2386 (set_attr "fp_mode" "double")
2387 (set_attr "needs_delay_slot" "yes")])
2388
2389 (define_insn "udivsi3_i4_single"
2390 [(set (match_operand:SI 0 "register_operand" "=y")
2391 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2392 (clobber (reg:SI T_REG))
2393 (clobber (reg:SI PR_REG))
2394 (clobber (reg:DF DR0_REG))
2395 (clobber (reg:DF DR2_REG))
2396 (clobber (reg:DF DR4_REG))
2397 (clobber (reg:SI R0_REG))
2398 (clobber (reg:SI R1_REG))
2399 (clobber (reg:SI R4_REG))
2400 (clobber (reg:SI R5_REG))
2401 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2402 "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2403 && TARGET_FPU_SINGLE"
2404 "jsr @%1%#"
2405 [(set_attr "type" "sfunc")
2406 (set_attr "needs_delay_slot" "yes")])
2407
2408 (define_insn "udivsi3_i4_int"
2409 [(set (match_operand:SI 0 "register_operand" "=z")
2410 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2411 (clobber (reg:SI T_REG))
2412 (clobber (reg:SI R1_REG))
2413 (clobber (reg:SI PR_REG))
2414 (clobber (reg:SI MACH_REG))
2415 (clobber (reg:SI MACL_REG))
2416 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2417 "TARGET_SH1"
2418 "jsr @%1%#"
2419 [(set_attr "type" "sfunc")
2420 (set_attr "needs_delay_slot" "yes")])
2421
2422
2423 (define_expand "udivsi3"
2424 [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
2425 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2426 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2427 (parallel [(set (match_operand:SI 0 "register_operand" "")
2428 (udiv:SI (reg:SI R4_REG)
2429 (reg:SI R5_REG)))
2430 (clobber (reg:SI T_REG))
2431 (clobber (reg:SI PR_REG))
2432 (clobber (reg:SI R4_REG))
2433 (use (match_dup 3))])]
2434 ""
2435 {
2436 rtx last;
2437
2438 operands[3] = gen_reg_rtx (Pmode);
2439 /* Emit the move of the address to a pseudo outside of the libcall. */
2440 if (TARGET_DIVIDE_CALL_TABLE)
2441 {
2442 /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
2443 that causes problems when the divide code is supposed to come from a
2444 separate library. Division by zero is undefined, so dividing 1 can be
2445 implemented by comparing with the divisor. */
2446 if (operands[1] == const1_rtx && currently_expanding_to_rtl)
2447 {
2448 rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
2449 emit_insn (gen_cstoresi4 (operands[0], test,
2450 operands[1], operands[2]));
2451 DONE;
2452 }
2453 else if (operands[2] == const0_rtx)
2454 {
2455 emit_move_insn (operands[0], operands[2]);
2456 DONE;
2457 }
2458 function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT);
2459 last = gen_udivsi3_i4_int (operands[0], operands[3]);
2460 }
2461 else if (TARGET_DIVIDE_CALL_FP)
2462 {
2463 function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC);
2464 if (TARGET_FPU_SINGLE)
2465 last = gen_udivsi3_i4_single (operands[0], operands[3]);
2466 else
2467 last = gen_udivsi3_i4 (operands[0], operands[3]);
2468 }
2469 else if (TARGET_SHMEDIA_FPU)
2470 {
2471 operands[1] = force_reg (SImode, operands[1]);
2472 operands[2] = force_reg (SImode, operands[2]);
2473 emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
2474 DONE;
2475 }
2476 else if (TARGET_SH2A)
2477 {
2478 operands[1] = force_reg (SImode, operands[1]);
2479 operands[2] = force_reg (SImode, operands[2]);
2480 emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
2481 DONE;
2482 }
2483 else if (TARGET_SH5)
2484 {
2485 function_symbol (operands[3],
2486 TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3",
2487 SFUNC_STATIC);
2488
2489 if (TARGET_SHMEDIA)
2490 last = gen_udivsi3_i1_media (operands[0], operands[3]);
2491 else if (TARGET_FPU_ANY)
2492 last = gen_udivsi3_i4_single (operands[0], operands[3]);
2493 else
2494 last = gen_udivsi3_i1 (operands[0], operands[3]);
2495 }
2496 else
2497 {
2498 function_symbol (operands[3], "__udivsi3", SFUNC_STATIC);
2499 last = gen_udivsi3_i1 (operands[0], operands[3]);
2500 }
2501 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2502 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2503 emit_insn (last);
2504 DONE;
2505 })
2506
2507 (define_insn "divsi3_sh2a"
2508 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2509 (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
2510 (match_operand:SI 2 "arith_reg_operand" "z")))]
2511 "TARGET_SH2A"
2512 "divs %2,%1"
2513 [(set_attr "type" "arith")
2514 (set_attr "in_delay_slot" "no")])
2515
2516 (define_insn "divsi3_i1"
2517 [(set (match_operand:SI 0 "register_operand" "=z")
2518 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2519 (clobber (reg:SI T_REG))
2520 (clobber (reg:SI PR_REG))
2521 (clobber (reg:SI R1_REG))
2522 (clobber (reg:SI R2_REG))
2523 (clobber (reg:SI R3_REG))
2524 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2525 "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2526 "jsr @%1%#"
2527 [(set_attr "type" "sfunc")
2528 (set_attr "needs_delay_slot" "yes")])
2529
2530 (define_insn "divsi3_i1_media"
2531 [(set (match_operand:SI 0 "register_operand" "=z")
2532 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2533 (clobber (reg:SI T_MEDIA_REG))
2534 (clobber (reg:SI PR_MEDIA_REG))
2535 (clobber (reg:SI R1_REG))
2536 (clobber (reg:SI R20_REG))
2537 (clobber (reg:SI R21_REG))
2538 (clobber (reg:SI TR0_REG))
2539 (use (match_operand 1 "target_reg_operand" "b"))]
2540 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2541 "blink %1, r18"
2542 [(set_attr "type" "sfunc")])
2543
2544 (define_insn "divsi3_media_2"
2545 [(set (match_operand:SI 0 "register_operand" "=z")
2546 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2547 (clobber (reg:SI T_MEDIA_REG))
2548 (clobber (reg:SI PR_MEDIA_REG))
2549 (clobber (reg:SI R1_REG))
2550 (clobber (reg:SI R21_REG))
2551 (clobber (reg:SI TR0_REG))
2552 (use (reg:SI R20_REG))
2553 (use (match_operand 1 "target_reg_operand" "b"))]
2554 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2555 "blink %1, r18"
2556 [(set_attr "type" "sfunc")])
2557
2558 ;; This pattern acts as a placeholder for -mdiv=inv:call to carry
2559 ;; hard reg clobbers and data dependencies that we need when we want
2560 ;; to rematerialize the division into a call.
2561 (define_insn_and_split "divsi_inv_call"
2562 [(set (match_operand:SI 0 "register_operand" "=r")
2563 (div:SI (match_operand:SI 1 "register_operand" "r")
2564 (match_operand:SI 2 "register_operand" "r")))
2565 (clobber (reg:SI R4_REG))
2566 (clobber (reg:SI R5_REG))
2567 (clobber (reg:SI T_MEDIA_REG))
2568 (clobber (reg:SI PR_MEDIA_REG))
2569 (clobber (reg:SI R1_REG))
2570 (clobber (reg:SI R21_REG))
2571 (clobber (reg:SI TR0_REG))
2572 (clobber (reg:SI R20_REG))
2573 (use (match_operand:SI 3 "register_operand" "r"))]
2574 "TARGET_SHMEDIA"
2575 "#"
2576 "&& (reload_in_progress || reload_completed)"
2577 [(set (match_dup 0) (match_dup 3))]
2578 ""
2579 [(set_attr "highpart" "must_split")])
2580
2581 ;; This is the combiner pattern for -mdiv=inv:call .
2582 (define_insn_and_split "*divsi_inv_call_combine"
2583 [(set (match_operand:SI 0 "register_operand" "=z")
2584 (div:SI (match_operand:SI 1 "register_operand" "r")
2585 (match_operand:SI 2 "register_operand" "r")))
2586 (clobber (reg:SI R4_REG))
2587 (clobber (reg:SI R5_REG))
2588 (clobber (reg:SI T_MEDIA_REG))
2589 (clobber (reg:SI PR_MEDIA_REG))
2590 (clobber (reg:SI R1_REG))
2591 (clobber (reg:SI R21_REG))
2592 (clobber (reg:SI TR0_REG))
2593 (clobber (reg:SI R20_REG))
2594 (use (unspec:SI [(match_dup 1)
2595 (match_operand:SI 3 "" "")
2596 (unspec:SI [(match_operand:SI 4 "" "")
2597 (match_dup 3)
2598 (match_operand:DI 5 "" "")]
2599 UNSPEC_DIV_INV_M2)
2600 (match_operand:DI 6 "" "")
2601 (const_int 0)
2602 (const_int 0)]
2603 UNSPEC_DIV_INV_M3))]
2604 "TARGET_SHMEDIA"
2605 "#"
2606 "&& (reload_in_progress || reload_completed)"
2607 [(pc)]
2608 {
2609 const char *name = sh_divsi3_libfunc;
2610 enum sh_function_kind kind = SFUNC_GOT;
2611 rtx sym;
2612
2613 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2614 emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2615 while (TARGET_DIVIDE_INV_CALL2)
2616 {
2617 rtx x = operands[3];
2618
2619 if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2620 break;
2621 x = XVECEXP (x, 0, 0);
2622 name = "__sdivsi3_2";
2623 kind = SFUNC_STATIC;
2624 emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2625 break;
2626 }
2627 sym = function_symbol (NULL, name, kind);
2628 emit_insn (gen_divsi3_media_2 (operands[0], sym));
2629 DONE;
2630 }
2631 [(set_attr "highpart" "must_split")])
2632
2633 (define_expand "divsi3_i4_media"
2634 [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2635 (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2636 (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2637 (set (match_operand:SI 0 "register_operand" "=r")
2638 (fix:SI (match_dup 5)))]
2639 "TARGET_SHMEDIA_FPU"
2640 {
2641 operands[3] = gen_reg_rtx (DFmode);
2642 operands[4] = gen_reg_rtx (DFmode);
2643 operands[5] = gen_reg_rtx (DFmode);
2644 })
2645
2646 (define_insn "divsi3_i4"
2647 [(set (match_operand:SI 0 "register_operand" "=y")
2648 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2649 (clobber (reg:SI PR_REG))
2650 (clobber (reg:DF DR0_REG))
2651 (clobber (reg:DF DR2_REG))
2652 (use (reg:PSI FPSCR_REG))
2653 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2654 "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2655 "jsr @%1%#"
2656 [(set_attr "type" "sfunc")
2657 (set_attr "fp_mode" "double")
2658 (set_attr "needs_delay_slot" "yes")])
2659
2660 (define_insn "divsi3_i4_single"
2661 [(set (match_operand:SI 0 "register_operand" "=y")
2662 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2663 (clobber (reg:SI PR_REG))
2664 (clobber (reg:DF DR0_REG))
2665 (clobber (reg:DF DR2_REG))
2666 (clobber (reg:SI R2_REG))
2667 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2668 "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2669 && TARGET_FPU_SINGLE"
2670 "jsr @%1%#"
2671 [(set_attr "type" "sfunc")
2672 (set_attr "needs_delay_slot" "yes")])
2673
2674 (define_insn "divsi3_i4_int"
2675 [(set (match_operand:SI 0 "register_operand" "=z")
2676 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2677 (clobber (reg:SI T_REG))
2678 (clobber (reg:SI PR_REG))
2679 (clobber (reg:SI R1_REG))
2680 (clobber (reg:SI MACH_REG))
2681 (clobber (reg:SI MACL_REG))
2682 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2683 "TARGET_SH1"
2684 "jsr @%1%#"
2685 [(set_attr "type" "sfunc")
2686 (set_attr "needs_delay_slot" "yes")])
2687
2688 (define_expand "divsi3"
2689 [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2690 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2691 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2692 (parallel [(set (match_operand:SI 0 "register_operand" "")
2693 (div:SI (reg:SI R4_REG)
2694 (reg:SI R5_REG)))
2695 (clobber (reg:SI T_REG))
2696 (clobber (reg:SI PR_REG))
2697 (clobber (reg:SI R1_REG))
2698 (clobber (reg:SI R2_REG))
2699 (clobber (reg:SI R3_REG))
2700 (use (match_dup 3))])]
2701 ""
2702 {
2703 rtx last;
2704
2705 operands[3] = gen_reg_rtx (Pmode);
2706 /* Emit the move of the address to a pseudo outside of the libcall. */
2707 if (TARGET_DIVIDE_CALL_TABLE)
2708 {
2709 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2710 last = gen_divsi3_i4_int (operands[0], operands[3]);
2711 }
2712 else if (TARGET_DIVIDE_CALL_FP)
2713 {
2714 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2715 if (TARGET_FPU_SINGLE)
2716 last = gen_divsi3_i4_single (operands[0], operands[3]);
2717 else
2718 last = gen_divsi3_i4 (operands[0], operands[3]);
2719 }
2720 else if (TARGET_SH2A)
2721 {
2722 operands[1] = force_reg (SImode, operands[1]);
2723 operands[2] = force_reg (SImode, operands[2]);
2724 emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2725 DONE;
2726 }
2727 else if (TARGET_DIVIDE_INV)
2728 {
2729 rtx dividend = operands[1];
2730 rtx divisor = operands[2];
2731 rtx tab_base;
2732 rtx nsb_res = gen_reg_rtx (DImode);
2733 rtx norm64 = gen_reg_rtx (DImode);
2734 rtx tab_ix = gen_reg_rtx (DImode);
2735 rtx norm32 = gen_reg_rtx (SImode);
2736 rtx i92 = force_reg (DImode, GEN_INT (92));
2737 rtx scratch0a = gen_reg_rtx (DImode);
2738 rtx scratch0b = gen_reg_rtx (DImode);
2739 rtx inv0 = gen_reg_rtx (SImode);
2740 rtx scratch1a = gen_reg_rtx (DImode);
2741 rtx scratch1b = gen_reg_rtx (DImode);
2742 rtx shift = gen_reg_rtx (DImode);
2743 rtx i2p27, i43;
2744 rtx inv1 = gen_reg_rtx (SImode);
2745 rtx scratch2a = gen_reg_rtx (DImode);
2746 rtx scratch2b = gen_reg_rtx (SImode);
2747 rtx inv2 = gen_reg_rtx (SImode);
2748 rtx scratch3a = gen_reg_rtx (DImode);
2749 rtx scratch3b = gen_reg_rtx (DImode);
2750 rtx scratch3c = gen_reg_rtx (DImode);
2751 rtx scratch3d = gen_reg_rtx (SImode);
2752 rtx scratch3e = gen_reg_rtx (DImode);
2753 rtx result = gen_reg_rtx (SImode);
2754
2755 if (! arith_reg_or_0_operand (dividend, SImode))
2756 dividend = force_reg (SImode, dividend);
2757 if (! arith_reg_operand (divisor, SImode))
2758 divisor = force_reg (SImode, divisor);
2759 if (flag_pic && Pmode != DImode)
2760 {
2761 tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2762 tab_base = gen_datalabel_ref (tab_base);
2763 tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2764 }
2765 else
2766 {
2767 tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table");
2768 tab_base = gen_datalabel_ref (tab_base);
2769 tab_base = force_reg (DImode, tab_base);
2770 }
2771 if (TARGET_DIVIDE_INV20U)
2772 i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2773 else
2774 i2p27 = GEN_INT (0);
2775 if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2776 i43 = force_reg (DImode, GEN_INT (43));
2777 else
2778 i43 = GEN_INT (0);
2779 emit_insn (gen_nsbdi (nsb_res,
2780 simplify_gen_subreg (DImode, divisor, SImode, 0)));
2781 emit_insn (gen_ashldi3_media (norm64,
2782 gen_rtx_SUBREG (DImode, divisor, 0),
2783 nsb_res));
2784 emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2785 emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2786 emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2787 inv0, scratch0a, scratch0b,
2788 scratch1a, scratch1b));
2789 emit_insn (gen_subdi3 (shift, i92, nsb_res));
2790 emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2791 scratch2a));
2792 emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2793 i2p27, i43,
2794 scratch3a, scratch3b, scratch3c,
2795 scratch2a, scratch2b, scratch3d, scratch3e));
2796 if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2797 emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2798 else if (TARGET_DIVIDE_INV_FP)
2799 emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2800 gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2801 gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2802 gen_reg_rtx (DFmode)));
2803 else
2804 emit_move_insn (operands[0], result);
2805 DONE;
2806 }
2807 else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2808 {
2809 operands[1] = force_reg (SImode, operands[1]);
2810 operands[2] = force_reg (SImode, operands[2]);
2811 emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2812 DONE;
2813 }
2814 else if (TARGET_SH5)
2815 {
2816 if (TARGET_DIVIDE_CALL2)
2817 {
2818 rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2819 tab_base = gen_datalabel_ref (tab_base);
2820 emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2821 }
2822 if (TARGET_FPU_ANY && TARGET_SH1)
2823 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2824 else if (TARGET_DIVIDE_CALL2)
2825 function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC);
2826 else
2827 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2828
2829 if (TARGET_SHMEDIA)
2830 last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2831 (operands[0], operands[3]));
2832 else if (TARGET_FPU_ANY)
2833 last = gen_divsi3_i4_single (operands[0], operands[3]);
2834 else
2835 last = gen_divsi3_i1 (operands[0], operands[3]);
2836 }
2837 else
2838 {
2839 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2840 last = gen_divsi3_i1 (operands[0], operands[3]);
2841 }
2842 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2843 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2844 emit_insn (last);
2845 DONE;
2846 })
2847
2848 ;; operands: scratch, tab_base, tab_ix
2849 ;; These are unspecs because we could generate an indexed addressing mode
2850 ;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2851 ;; confuse reload. See PR27117.
2852 (define_insn "divsi_inv_qitable"
2853 [(set (match_operand:DI 0 "register_operand" "=r")
2854 (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2855 (match_operand:DI 2 "register_operand" "r")]
2856 UNSPEC_DIV_INV_TABLE)))]
2857 "TARGET_SHMEDIA"
2858 "ldx.ub %1, %2, %0"
2859 [(set_attr "type" "load_media")
2860 (set_attr "highpart" "user")])
2861
2862 ;; operands: scratch, tab_base, tab_ix
2863 (define_insn "divsi_inv_hitable"
2864 [(set (match_operand:DI 0 "register_operand" "=r")
2865 (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2866 (match_operand:DI 2 "register_operand" "r")]
2867 UNSPEC_DIV_INV_TABLE)))]
2868 "TARGET_SHMEDIA"
2869 "ldx.w %1, %2, %0"
2870 [(set_attr "type" "load_media")
2871 (set_attr "highpart" "user")])
2872
2873 ;; operands: inv0, tab_base, tab_ix, norm32
2874 ;; scratch equiv in sdivsi3_2: r19, r21
2875 (define_expand "divsi_inv_m0"
2876 [(set (match_operand:SI 0 "register_operand" "=r")
2877 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2878 (match_operand:DI 2 "register_operand" "r")
2879 (match_operand:SI 3 "register_operand" "r")]
2880 UNSPEC_DIV_INV_M0))
2881 (clobber (match_operand:DI 4 "register_operand" "=r"))
2882 (clobber (match_operand:DI 5 "register_operand" "=r"))]
2883 "TARGET_SHMEDIA"
2884 {
2885 /*
2886 tab_base: r20
2887 tab_ix: r21
2888 norm32: r25
2889 ldx.ub r20, r21, r19 // u0.8
2890 shlli r21, 1, r21
2891 muls.l r25, r19, r19 // s2.38
2892 ldx.w r20, r21, r21 // s2.14
2893 shari r19, 24, r19 // truncate to s2.14
2894 sub r21, r19, r19 // some 11 bit inverse in s1.14
2895 */
2896
2897 rtx inv0 = operands[0];
2898 rtx tab_base = operands[1];
2899 rtx tab_ix = operands[2];
2900 rtx norm32 = operands[3];
2901 rtx scratch0 = operands[4];
2902 rtx scratch0_si = gen_lowpart (SImode, scratch0);
2903 rtx scratch1 = operands[5];
2904
2905 emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2906 emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2907 emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2908 emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2909 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2910 emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2911 DONE;
2912 })
2913
2914 ;; operands: inv1, tab_base, tab_ix, norm32
2915 (define_insn_and_split "divsi_inv_m1"
2916 [(set (match_operand:SI 0 "register_operand" "=r")
2917 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2918 (match_operand:DI 2 "register_operand" "r")
2919 (match_operand:SI 3 "register_operand" "r")]
2920 UNSPEC_DIV_INV_M1))
2921 (clobber (match_operand:SI 4 "register_operand" "=r"))
2922 (clobber (match_operand:DI 5 "register_operand" "=r"))
2923 (clobber (match_operand:DI 6 "register_operand" "=r"))
2924 (clobber (match_operand:DI 7 "register_operand" "=r"))
2925 (clobber (match_operand:DI 8 "register_operand" "=r"))]
2926 "TARGET_SHMEDIA"
2927 "#"
2928 "&& !can_create_pseudo_p ()"
2929 [(pc)]
2930 {
2931 /* inv0: r19
2932 muls.l r19, r19, r18 // u0.28
2933 muls.l r25, r18, r18 // s2.58
2934 shlli r19, 45, r0 // multiply by two and convert to s2.58
2935 sub r0, r18, r18
2936 shari r18, 28, r18 // some 18 bit inverse in s1.30
2937 */
2938
2939 rtx inv1 = operands[0];
2940 rtx tab_base = operands[1];
2941 rtx tab_ix = operands[2];
2942 rtx norm32 = operands[3];
2943 rtx inv0 = operands[4];
2944 rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2945 rtx scratch0a = operands[5];
2946 rtx scratch0b = operands[6];
2947 rtx scratch0 = operands[7];
2948 rtx scratch1 = operands[8];
2949 rtx scratch1_si = gen_lowpart (SImode, scratch1);
2950
2951 emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2952 scratch0a, scratch0b));
2953 emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2954 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2955 emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2956 emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2957 emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2958 DONE;
2959 })
2960
2961 ;; operands: inv2, norm32, inv1, i92
2962 (define_insn_and_split "divsi_inv_m2"
2963 [(set (match_operand:SI 0 "register_operand" "=r")
2964 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2965 (match_operand:SI 2 "register_operand" "r")
2966 (match_operand:DI 3 "register_operand" "r")]
2967 UNSPEC_DIV_INV_M2))
2968 (clobber (match_operand:DI 4 "register_operand" "=r"))]
2969 "TARGET_SHMEDIA"
2970 "#"
2971 "&& !can_create_pseudo_p ()"
2972 [(pc)]
2973 {
2974 /*
2975 muls.l r18, r25, r0 // s2.60
2976 shari r0, 16, r0 // s-16.44
2977 sub
2978 muls.l r0, r18, r19 // s-16.74
2979 shari r19, 30, r19 // s-16.44
2980 */
2981 rtx inv2 = operands[0];
2982 rtx norm32 = operands[1];
2983 rtx inv1 = operands[2];
2984 rtx i92 = operands[3];
2985 rtx scratch0 = operands[4];
2986 rtx scratch0_si = gen_lowpart (SImode, scratch0);
2987
2988 emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2989 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2990 emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2991 emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2992 emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2993 DONE;
2994 })
2995
2996 (define_insn_and_split "divsi_inv_m3"
2997 [(set (match_operand:SI 0 "register_operand" "=r")
2998 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2999 (match_operand:SI 2 "register_operand" "r")
3000 (match_operand:SI 3 "register_operand" "r")
3001 (match_operand:DI 4 "register_operand" "r")
3002 (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
3003 (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
3004 UNSPEC_DIV_INV_M3))
3005 (clobber (match_operand:DI 7 "register_operand" "=r"))
3006 (clobber (match_operand:DI 8 "register_operand" "=r"))
3007 (clobber (match_operand:DI 9 "register_operand" "=r"))
3008 (clobber (match_operand:DI 10 "register_operand" "=r"))
3009 (clobber (match_operand:SI 11 "register_operand" "=r"))
3010 (clobber (match_operand:SI 12 "register_operand" "=r"))
3011 (clobber (match_operand:DI 13 "register_operand" "=r"))]
3012 "TARGET_SHMEDIA"
3013 "#"
3014 "&& !can_create_pseudo_p ()"
3015 [(pc)]
3016 {
3017 /*
3018 r0: result r1: shift r4: dividend r18: inv1 r19: inv2
3019 r0: scratch0 r19: scratch1 r21: scratch2
3020
3021 muls.l r18, r4, r25 // s32.30
3022 muls.l r19, r4, r19 // s15.30
3023 shari r25, 63, r21
3024 shari r19, 14, r19 // s18.-14
3025 sub r25, r19, r0
3026 shard r0, r1, r0
3027 sub r0, r21, r0
3028 */
3029
3030 rtx result = operands[0];
3031 rtx dividend = operands[1];
3032 rtx inv1 = operands[2];
3033 rtx inv2 = operands[3];
3034 rtx shift = operands[4];
3035 rtx scratch0 = operands[7];
3036 rtx scratch1 = operands[8];
3037 rtx scratch2 = operands[9];
3038
3039 if (satisfies_constraint_N (dividend))
3040 {
3041 emit_move_insn (result, dividend);
3042 DONE;
3043 }
3044
3045 emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
3046 emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
3047 emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
3048 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
3049 emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
3050 emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
3051 emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
3052 DONE;
3053 })
3054
3055 ;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
3056 ;; inv1: tab_base, tab_ix, norm32
3057 ;; inv2: norm32, inv1, i92
3058 (define_insn_and_split "divsi_inv_m1_3"
3059 [(set (match_operand:SI 0 "register_operand" "=r")
3060 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
3061 (unspec:SI [(match_operand:DI 2 "register_operand" "r")
3062 (match_operand:DI 3 "register_operand" "r")
3063 (match_operand:SI 4 "register_operand" "r")]
3064 UNSPEC_DIV_INV_M1)
3065 (unspec:SI [(match_dup 4)
3066 (unspec:SI [(match_dup 2)
3067 (match_dup 3)
3068 (match_dup 4)] UNSPEC_DIV_INV_M1)
3069 (match_operand:SI 5 "" "")]
3070 UNSPEC_DIV_INV_M2)
3071 (match_operand:DI 6 "register_operand" "r")
3072 (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
3073 (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
3074 UNSPEC_DIV_INV_M3))
3075 (clobber (match_operand:DI 9 "register_operand" "=r"))
3076 (clobber (match_operand:DI 10 "register_operand" "=r"))
3077 (clobber (match_operand:DI 11 "register_operand" "=r"))
3078 (clobber (match_operand:DI 12 "register_operand" "=r"))
3079 (clobber (match_operand:SI 13 "register_operand" "=r"))
3080 (clobber (match_operand:SI 14 "register_operand" "=r"))
3081 (clobber (match_operand:DI 15 "register_operand" "=r"))]
3082 "TARGET_SHMEDIA
3083 && (TARGET_DIVIDE_INV_MINLAT
3084 || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
3085 "#"
3086 "&& !can_create_pseudo_p ()"
3087 [(pc)]
3088 {
3089 rtx result = operands[0];
3090 rtx dividend = operands[1];
3091 rtx tab_base = operands[2];
3092 rtx tab_ix = operands[3];
3093 rtx norm32 = operands[4];
3094 /* rtx i92 = operands[5]; */
3095 rtx shift = operands[6];
3096 rtx i2p27 = operands[7];
3097 rtx i43 = operands[8];
3098 rtx scratch0 = operands[9];
3099 rtx scratch0_si = gen_lowpart (SImode, scratch0);
3100 rtx scratch1 = operands[10];
3101 rtx scratch1_si = gen_lowpart (SImode, scratch1);
3102 rtx scratch2 = operands[11];
3103 rtx scratch3 = operands[12];
3104 rtx scratch4 = operands[13];
3105 rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
3106 rtx scratch5 = operands[14];
3107 rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
3108 rtx scratch6 = operands[15];
3109
3110 emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
3111 scratch0, scratch1));
3112 /* inv0 == scratch4 */
3113 if (! TARGET_DIVIDE_INV20U)
3114 {
3115 emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
3116 i2p27 = scratch0;
3117 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
3118 }
3119 else
3120 {
3121 emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
3122 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
3123 }
3124 emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
3125 emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
3126 emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
3127 /* inv1 == scratch4 */
3128
3129 if (TARGET_DIVIDE_INV_MINLAT)
3130 {
3131 emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
3132 emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
3133 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
3134 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
3135 emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
3136 emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
3137 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
3138 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
3139 emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
3140 emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
3141 emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
3142 }
3143 else
3144 {
3145 rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
3146 /* Use separate scratch regs for nsb and sign to allow scheduling. */
3147 emit_insn (gen_nsbdi (scratch6,
3148 simplify_gen_subreg (DImode, dividend, SImode, 0)));
3149 emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
3150 emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
3151 emit_insn (gen_divsi_inv20 (scratch2,
3152 norm32, scratch4, dividend,
3153 scratch6, scratch3, i43,
3154 /* scratch0 may be shared with i2p27. */
3155 scratch0, scratch1, scratch5,
3156 label, label, i2p27));
3157 }
3158 emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
3159 emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
3160 DONE;
3161 })
3162
3163 (define_insn "divsi_inv20"
3164 [(set (match_operand:DI 0 "register_operand" "=&r")
3165 (unspec:DI [(match_operand:SI 1 "register_operand" "r")
3166 (match_operand:SI 2 "register_operand" "r")
3167 (match_operand:SI 3 "register_operand" "r")
3168 (match_operand:DI 4 "register_operand" "r")
3169 (match_operand:DI 5 "register_operand" "r")
3170 (match_operand:DI 6 "register_operand" "r")
3171 (match_operand:DI 12 "register_operand" "r")
3172 (match_operand 10 "target_operand" "b")
3173 (match_operand 11 "immediate_operand" "i")]
3174 UNSPEC_DIV_INV20))
3175 (clobber (match_operand:DI 7 "register_operand" "=&r"))
3176 (clobber (match_operand:DI 8 "register_operand" "=&r"))
3177 (clobber (match_operand:SI 9 "register_operand" "=r"))]
3178 "TARGET_SHMEDIA
3179 && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
3180 {
3181 /* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
3182 %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
3183 %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
3184 %10 label (tr), %11 label (imm)
3185
3186 muls.l inv1, norm32, scratch0 // s2.60
3187 muls.l inv1, dividend, result // s32.30
3188 xor i2p27, result_sign, round_scratch
3189 bge/u dividend_nsb, i43, tr.. (label)
3190 shari scratch0, 16, scratch0 // s-16.44
3191 muls.l sratch0_si, inv1, scratch0 // s-16.74
3192 sub result, round_scratch, result
3193 shari dividend, 14, scratch1 // s19.-14
3194 shari scratch0, 30, scratch0 // s-16.44
3195 muls.l scratch0, scratch1, round_scratch // s15.30
3196 label:
3197 sub result, round_scratch, result */
3198
3199 const bool likely = TARGET_DIVIDE_INV20L;
3200 if (likely)
3201 return
3202 "muls.l %2, %3, %0" "\n"
3203 " xor %12, %5, %7" "\n"
3204 " bge/l %4, %6, %10" "\n"
3205 " muls.l %2, %1, %8" "\n"
3206 " shari %8, 16, %8" "\n"
3207 " muls.l %8, %2, %8" "\n"
3208 " shari %3, 14, %9" "\n"
3209 " shari %8, 30, %8" "\n"
3210 " muls.l %8, %9, %8" "\n"
3211 " sub %0, %8, %0" "\n"
3212 "%11: add %0, %7, %0";
3213 else
3214 return
3215 "muls.l %2, %1, %8" "\n"
3216 " muls.l %2, %3, %0" "\n"
3217 " xor %12, %5, %7" "\n"
3218 " bge/u %4, %6, %10" "\n"
3219 " shari %8, 16, %8" "\n"
3220 " muls.l %8, %2, %8" "\n"
3221 " sub %0, %7, %0" "\n"
3222 " shari %3, 14, %9" "\n"
3223 " shari %8, 30, %8" "\n"
3224 " muls.l %8, %9, %7" "\n"
3225 "%11: sub %0, %7, %0";
3226 })
3227
3228 (define_insn_and_split "divsi_inv_fp"
3229 [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
3230 (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
3231 (match_operand:SI 2 "register_operand" "rf")))
3232 (use (match_operand:SI 3 "general_movsrc_operand" "r"))
3233 (clobber (match_operand:SI 4 "register_operand" "=r"))
3234 (clobber (match_operand:SI 5 "register_operand" "=r"))
3235 (clobber (match_operand:DF 6 "register_operand" "=r"))
3236 (clobber (match_operand:DF 7 "register_operand" "=r"))
3237 (clobber (match_operand:DF 8 "register_operand" "=r"))]
3238 "TARGET_SHMEDIA_FPU"
3239 "#"
3240 "&& (reload_in_progress || reload_completed)"
3241 [(set (match_dup 0) (match_dup 3))]
3242 ""
3243 [(set_attr "highpart" "must_split")])
3244
3245 ;; If a matching group of divide-by-inverse instructions is in the same
3246 ;; basic block after gcse & loop optimizations, we want to transform them
3247 ;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
3248 (define_insn_and_split "*divsi_inv_fp_combine"
3249 [(set (match_operand:SI 0 "register_operand" "=f")
3250 (div:SI (match_operand:SI 1 "register_operand" "f")
3251 (match_operand:SI 2 "register_operand" "f")))
3252 (use (unspec:SI [(match_dup 1)
3253 (match_operand:SI 3 "" "")
3254 (unspec:SI [(match_operand:SI 4 "" "")
3255 (match_dup 3)
3256 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
3257 (match_operand:DI 6 "" "")
3258 (const_int 0)
3259 (const_int 0)] UNSPEC_DIV_INV_M3))
3260 (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
3261 (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
3262 (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
3263 (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
3264 (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
3265 "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
3266 "#"
3267 "&& 1"
3268 [(set (match_dup 9) (float:DF (match_dup 1)))
3269 (set (match_dup 10) (float:DF (match_dup 2)))
3270 (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
3271 (set (match_dup 8)
3272 (fix:SI (match_dup 11)))
3273 (set (match_dup 0) (match_dup 8))]
3274 {
3275 if (! fp_arith_reg_operand (operands[1], SImode))
3276 {
3277 emit_move_insn (operands[7], operands[1]);
3278 operands[1] = operands[7];
3279 }
3280 if (! fp_arith_reg_operand (operands[2], SImode))
3281 {
3282 emit_move_insn (operands[8], operands[2]);
3283 operands[2] = operands[8];
3284 }
3285 }
3286 [(set_attr "highpart" "must_split")])
3287 \f
3288 ;; -------------------------------------------------------------------------
3289 ;; Multiplication instructions
3290 ;; -------------------------------------------------------------------------
3291
3292 (define_insn "umulhisi3_i"
3293 [(set (reg:SI MACL_REG)
3294 (mult:SI (zero_extend:SI
3295 (match_operand:HI 0 "arith_reg_operand" "r"))
3296 (zero_extend:SI
3297 (match_operand:HI 1 "arith_reg_operand" "r"))))]
3298 "TARGET_SH1"
3299 "mulu.w %1,%0"
3300 [(set_attr "type" "smpy")])
3301
3302 (define_insn "mulhisi3_i"
3303 [(set (reg:SI MACL_REG)
3304 (mult:SI (sign_extend:SI
3305 (match_operand:HI 0 "arith_reg_operand" "r"))
3306 (sign_extend:SI
3307 (match_operand:HI 1 "arith_reg_operand" "r"))))]
3308 "TARGET_SH1"
3309 "muls.w %1,%0"
3310 [(set_attr "type" "smpy")])
3311
3312 (define_expand "mulhisi3"
3313 [(set (reg:SI MACL_REG)
3314 (mult:SI (sign_extend:SI
3315 (match_operand:HI 1 "arith_reg_operand" ""))
3316 (sign_extend:SI
3317 (match_operand:HI 2 "arith_reg_operand" ""))))
3318 (set (match_operand:SI 0 "arith_reg_operand" "")
3319 (reg:SI MACL_REG))]
3320 "TARGET_SH1"
3321 {
3322 rtx insn, macl;
3323
3324 macl = gen_rtx_REG (SImode, MACL_REG);
3325 start_sequence ();
3326 emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
3327 insn = get_insns ();
3328 end_sequence ();
3329 /* expand_binop can't find a suitable code in umul_widen_optab to
3330 make a REG_EQUAL note from, so make one here.
3331 See also smulsi3_highpart.
3332 ??? Alternatively, we could put this at the calling site of expand_binop,
3333 i.e. expand_expr. */
3334 /* Use emit_libcall_block for loop invariant code motion and to make
3335 a REG_EQUAL note. */
3336 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3337
3338 DONE;
3339 })
3340
3341 (define_expand "umulhisi3"
3342 [(set (reg:SI MACL_REG)
3343 (mult:SI (zero_extend:SI
3344 (match_operand:HI 1 "arith_reg_operand" ""))
3345 (zero_extend:SI
3346 (match_operand:HI 2 "arith_reg_operand" ""))))
3347 (set (match_operand:SI 0 "arith_reg_operand" "")
3348 (reg:SI MACL_REG))]
3349 "TARGET_SH1"
3350 {
3351 rtx insn, macl;
3352
3353 macl = gen_rtx_REG (SImode, MACL_REG);
3354 start_sequence ();
3355 emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
3356 insn = get_insns ();
3357 end_sequence ();
3358 /* expand_binop can't find a suitable code in umul_widen_optab to
3359 make a REG_EQUAL note from, so make one here.
3360 See also smulsi3_highpart.
3361 ??? Alternatively, we could put this at the calling site of expand_binop,
3362 i.e. expand_expr. */
3363 /* Use emit_libcall_block for loop invariant code motion and to make
3364 a REG_EQUAL note. */
3365 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3366
3367 DONE;
3368 })
3369
3370 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
3371 ;; a call to a routine which clobbers known registers.
3372 (define_insn ""
3373 [(set (match_operand:SI 1 "register_operand" "=z")
3374 (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
3375 (clobber (reg:SI MACL_REG))
3376 (clobber (reg:SI T_REG))
3377 (clobber (reg:SI PR_REG))
3378 (clobber (reg:SI R3_REG))
3379 (clobber (reg:SI R2_REG))
3380 (clobber (reg:SI R1_REG))
3381 (use (match_operand:SI 0 "arith_reg_operand" "r"))]
3382 "TARGET_SH1"
3383 "jsr @%0%#"
3384 [(set_attr "type" "sfunc")
3385 (set_attr "needs_delay_slot" "yes")])
3386
3387 (define_expand "mulsi3_call"
3388 [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
3389 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
3390 (parallel[(set (match_operand:SI 0 "register_operand" "")
3391 (mult:SI (reg:SI R4_REG)
3392 (reg:SI R5_REG)))
3393 (clobber (reg:SI MACL_REG))
3394 (clobber (reg:SI T_REG))
3395 (clobber (reg:SI PR_REG))
3396 (clobber (reg:SI R3_REG))
3397 (clobber (reg:SI R2_REG))
3398 (clobber (reg:SI R1_REG))
3399 (use (match_operand:SI 3 "register_operand" ""))])]
3400 "TARGET_SH1"
3401 "")
3402
3403 (define_insn "mul_r"
3404 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3405 (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
3406 (match_operand:SI 2 "arith_reg_operand" "z")))]
3407 "TARGET_SH2A"
3408 "mulr %2,%0"
3409 [(set_attr "type" "dmpy")])
3410
3411 (define_insn "mul_l"
3412 [(set (reg:SI MACL_REG)
3413 (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
3414 (match_operand:SI 1 "arith_reg_operand" "r")))]
3415 "TARGET_SH2"
3416 "mul.l %1,%0"
3417 [(set_attr "type" "dmpy")])
3418
3419 (define_expand "mulsi3"
3420 [(set (reg:SI MACL_REG)
3421 (mult:SI (match_operand:SI 1 "arith_reg_operand" "")
3422 (match_operand:SI 2 "arith_reg_operand" "")))
3423 (set (match_operand:SI 0 "arith_reg_operand" "")
3424 (reg:SI MACL_REG))]
3425 "TARGET_SH1"
3426 {
3427 if (!TARGET_SH2)
3428 {
3429 /* The address must be set outside the libcall,
3430 since it goes into a pseudo. */
3431 rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC);
3432 rtx addr = force_reg (SImode, sym);
3433 rtx insns = gen_mulsi3_call (operands[0], operands[1],
3434 operands[2], addr);
3435 emit_insn (insns);
3436 }
3437 else
3438 {
3439 rtx macl = gen_rtx_REG (SImode, MACL_REG);
3440
3441 emit_insn (gen_mul_l (operands[1], operands[2]));
3442 /* consec_sets_giv can only recognize the first insn that sets a
3443 giv as the giv insn. So we must tag this also with a REG_EQUAL
3444 note. */
3445 emit_insn (gen_movsi_i ((operands[0]), macl));
3446 }
3447 DONE;
3448 })
3449
3450 (define_insn "mulsidi3_i"
3451 [(set (reg:SI MACH_REG)
3452 (truncate:SI
3453 (lshiftrt:DI
3454 (mult:DI
3455 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3456 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3457 (const_int 32))))
3458 (set (reg:SI MACL_REG)
3459 (mult:SI (match_dup 0)
3460 (match_dup 1)))]
3461 "TARGET_SH2"
3462 "dmuls.l %1,%0"
3463 [(set_attr "type" "dmpy")])
3464
3465 (define_expand "mulsidi3"
3466 [(set (match_operand:DI 0 "arith_reg_dest" "")
3467 (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3468 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3469 "TARGET_SH2 || TARGET_SHMEDIA"
3470 {
3471 if (TARGET_SH2)
3472 {
3473 emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2]));
3474 DONE;
3475 }
3476 })
3477
3478 (define_insn "mulsidi3_media"
3479 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3480 (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3481 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3482 "TARGET_SHMEDIA"
3483 "muls.l %1, %2, %0"
3484 [(set_attr "type" "dmpy_media")
3485 (set_attr "highpart" "ignore")])
3486
3487 (define_insn_and_split "mulsidi3_compact"
3488 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3489 (mult:DI
3490 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3491 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3492 (clobber (reg:SI MACH_REG))
3493 (clobber (reg:SI MACL_REG))]
3494 "TARGET_SH2"
3495 "#"
3496 "&& 1"
3497 [(const_int 0)]
3498 {
3499 rtx low_dst = gen_lowpart (SImode, operands[0]);
3500 rtx high_dst = gen_highpart (SImode, operands[0]);
3501
3502 emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
3503
3504 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3505 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3506 /* We need something to tag the possible REG_EQUAL notes on to. */
3507 emit_move_insn (operands[0], operands[0]);
3508 DONE;
3509 })
3510
3511 (define_insn "umulsidi3_i"
3512 [(set (reg:SI MACH_REG)
3513 (truncate:SI
3514 (lshiftrt:DI
3515 (mult:DI
3516 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3517 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3518 (const_int 32))))
3519 (set (reg:SI MACL_REG)
3520 (mult:SI (match_dup 0)
3521 (match_dup 1)))]
3522 "TARGET_SH2"
3523 "dmulu.l %1,%0"
3524 [(set_attr "type" "dmpy")])
3525
3526 (define_expand "umulsidi3"
3527 [(set (match_operand:DI 0 "arith_reg_dest" "")
3528 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3529 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3530 "TARGET_SH2 || TARGET_SHMEDIA"
3531 {
3532 if (TARGET_SH2)
3533 {
3534 emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2]));
3535 DONE;
3536 }
3537 })
3538
3539 (define_insn "umulsidi3_media"
3540 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3541 (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3542 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3543 "TARGET_SHMEDIA"
3544 "mulu.l %1, %2, %0"
3545 [(set_attr "type" "dmpy_media")
3546 (set_attr "highpart" "ignore")])
3547
3548 (define_insn_and_split "umulsidi3_compact"
3549 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3550 (mult:DI
3551 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3552 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3553 (clobber (reg:SI MACH_REG))
3554 (clobber (reg:SI MACL_REG))]
3555 "TARGET_SH2"
3556 "#"
3557 "&& 1"
3558 [(const_int 0)]
3559 {
3560 rtx low_dst = gen_lowpart (SImode, operands[0]);
3561 rtx high_dst = gen_highpart (SImode, operands[0]);
3562
3563 emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
3564
3565 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3566 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3567 /* We need something to tag the possible REG_EQUAL notes on to. */
3568 emit_move_insn (operands[0], operands[0]);
3569 DONE;
3570 })
3571
3572 (define_insn "smulsi3_highpart_i"
3573 [(set (reg:SI MACH_REG)
3574 (truncate:SI
3575 (lshiftrt:DI
3576 (mult:DI
3577 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3578 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3579 (const_int 32))))
3580 (clobber (reg:SI MACL_REG))]
3581 "TARGET_SH2"
3582 "dmuls.l %1,%0"
3583 [(set_attr "type" "dmpy")])
3584
3585 (define_expand "smulsi3_highpart"
3586 [(parallel
3587 [(set (reg:SI MACH_REG)
3588 (truncate:SI
3589 (lshiftrt:DI
3590 (mult:DI
3591 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3592 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3593 (const_int 32))))
3594 (clobber (reg:SI MACL_REG))])
3595 (set (match_operand:SI 0 "arith_reg_operand" "")
3596 (reg:SI MACH_REG))]
3597 "TARGET_SH2"
3598 {
3599 rtx insn, mach;
3600
3601 mach = gen_rtx_REG (SImode, MACH_REG);
3602 start_sequence ();
3603 emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3604 insn = get_insns ();
3605 end_sequence ();
3606 /* expand_binop can't find a suitable code in mul_highpart_optab to
3607 make a REG_EQUAL note from, so make one here.
3608 See also {,u}mulhisi.
3609 ??? Alternatively, we could put this at the calling site of expand_binop,
3610 i.e. expand_mult_highpart. */
3611 /* Use emit_libcall_block for loop invariant code motion and to make
3612 a REG_EQUAL note. */
3613 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3614
3615 DONE;
3616 })
3617
3618 (define_insn "umulsi3_highpart_i"
3619 [(set (reg:SI MACH_REG)
3620 (truncate:SI
3621 (lshiftrt:DI
3622 (mult:DI
3623 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3624 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3625 (const_int 32))))
3626 (clobber (reg:SI MACL_REG))]
3627 "TARGET_SH2"
3628 "dmulu.l %1,%0"
3629 [(set_attr "type" "dmpy")])
3630
3631 (define_expand "umulsi3_highpart"
3632 [(parallel
3633 [(set (reg:SI MACH_REG)
3634 (truncate:SI
3635 (lshiftrt:DI
3636 (mult:DI
3637 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3638 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3639 (const_int 32))))
3640 (clobber (reg:SI MACL_REG))])
3641 (set (match_operand:SI 0 "arith_reg_operand" "")
3642 (reg:SI MACH_REG))]
3643 "TARGET_SH2"
3644 {
3645 rtx insn, mach;
3646
3647 mach = gen_rtx_REG (SImode, MACH_REG);
3648 start_sequence ();
3649 emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3650 insn = get_insns ();
3651 end_sequence ();
3652 /* Use emit_libcall_block for loop invariant code motion and to make
3653 a REG_EQUAL note. */
3654 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3655
3656 DONE;
3657 })
3658
3659 (define_insn_and_split "muldi3"
3660 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3661 (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3662 (match_operand:DI 2 "arith_reg_operand" "r")))
3663 (clobber (match_scratch:DI 3 "=&r"))
3664 (clobber (match_scratch:DI 4 "=r"))]
3665 "TARGET_SHMEDIA"
3666 "#"
3667 "reload_completed"
3668 [(const_int 0)]
3669 {
3670 rtx op3_v2si, op2_v2si;
3671
3672 op3_v2si = operands[3];
3673 if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3674 {
3675 op3_v2si = XEXP (op3_v2si, 0);
3676 op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3677 }
3678 op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3679 op2_v2si = operands[2];
3680 if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3681 {
3682 op2_v2si = XEXP (op2_v2si, 0);
3683 op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3684 }
3685 op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3686 emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3687 emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3688 emit_insn (gen_umulsidi3_media (operands[4],
3689 sh_gen_truncate (SImode, operands[1], 0),
3690 sh_gen_truncate (SImode, operands[2], 0)));
3691 emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3692 emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3693 emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3694 emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3695 DONE;
3696 })
3697 \f
3698 ;; -------------------------------------------------------------------------
3699 ;; Logical operations
3700 ;; -------------------------------------------------------------------------
3701
3702 (define_expand "andsi3"
3703 [(set (match_operand:SI 0 "arith_reg_operand" "")
3704 (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3705 (match_operand:SI 2 "logical_and_operand" "")))]
3706 ""
3707 {
3708 /* If it is possible to turn the and insn into a zero extension
3709 already, redundant zero extensions will be folded, which results
3710 in better code.
3711 Ideally the splitter of *andsi_compact would be enough, if redundant
3712 zero extensions were detected after the combine pass, which does not
3713 happen at the moment. */
3714 if (TARGET_SH1)
3715 {
3716 if (satisfies_constraint_Jmb (operands[2]))
3717 {
3718 emit_insn (gen_zero_extendqisi2 (operands[0],
3719 gen_lowpart (QImode, operands[1])));
3720 DONE;
3721 }
3722 else if (satisfies_constraint_Jmw (operands[2]))
3723 {
3724 emit_insn (gen_zero_extendhisi2 (operands[0],
3725 gen_lowpart (HImode, operands[1])));
3726 DONE;
3727 }
3728 }
3729 })
3730
3731 (define_insn_and_split "*andsi_compact"
3732 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r")
3733 (and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0")
3734 (match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))]
3735 "TARGET_SH1"
3736 "@
3737 extu.b %1,%0
3738 extu.w %1,%0
3739 and %2,%0
3740 and %2,%0"
3741 "&& 1"
3742 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
3743 {
3744 if (satisfies_constraint_Jmb (operands[2]))
3745 operands[1] = gen_lowpart (QImode, operands[1]);
3746 else if (satisfies_constraint_Jmw (operands[2]))
3747 operands[1] = gen_lowpart (HImode, operands[1]);
3748 else
3749 FAIL;
3750 }
3751 [(set_attr "type" "arith")])
3752
3753 (define_insn "*andsi3_media"
3754 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3755 (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3756 (match_operand:SI 2 "logical_operand" "r,I10")))]
3757 "TARGET_SHMEDIA"
3758 "@
3759 and %1, %2, %0
3760 andi %1, %2, %0"
3761 [(set_attr "type" "arith_media")])
3762
3763 (define_insn "*andsi3_bclr"
3764 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3765 (and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3766 (match_operand:SI 2 "const_int_operand" "Psz")))]
3767 "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
3768 "bclr %W2,%0"
3769 [(set_attr "type" "arith")])
3770
3771 (define_insn_and_split "anddi3"
3772 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3773 (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3774 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
3775 "TARGET_SHMEDIA"
3776 "@
3777 and %1, %2, %0
3778 andi %1, %2, %0
3779 #"
3780 "reload_completed
3781 && ! logical_operand (operands[2], DImode)"
3782 [(const_int 0)]
3783 {
3784 if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3785 emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3786 else
3787 emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3788 DONE;
3789 }
3790 [(set_attr "type" "arith_media")])
3791
3792 (define_insn "andcsi3"
3793 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3794 (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3795 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3796 "TARGET_SHMEDIA"
3797 "andc %1,%2,%0"
3798 [(set_attr "type" "arith_media")])
3799
3800 (define_insn "andcdi3"
3801 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3802 (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3803 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3804 "TARGET_SHMEDIA"
3805 "andc %1,%2,%0"
3806 [(set_attr "type" "arith_media")])
3807
3808 (define_expand "iorsi3"
3809 [(set (match_operand:SI 0 "arith_reg_operand" "")
3810 (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3811 (match_operand:SI 2 "logical_operand" "")))]
3812 ""
3813 "")
3814
3815 (define_insn "*iorsi3_compact"
3816 [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3817 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3818 (match_operand:SI 2 "logical_operand" "r,K08")))]
3819 "TARGET_SH1
3820 && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
3821 "or %2,%0"
3822 [(set_attr "type" "arith")])
3823
3824 (define_insn "*iorsi3_media"
3825 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3826 (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3827 (match_operand:SI 2 "logical_operand" "r,I10")))]
3828 "TARGET_SHMEDIA"
3829 "@
3830 or %1, %2, %0
3831 ori %1, %2, %0"
3832 [(set_attr "type" "arith_media")])
3833
3834 (define_insn "*iorsi3_bset"
3835 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3836 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3837 (match_operand:SI 2 "const_int_operand" "Pso")))]
3838 "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
3839 "bset %V2,%0"
3840 [(set_attr "type" "arith")])
3841
3842 (define_insn "iordi3"
3843 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3844 (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3845 (match_operand:DI 2 "logical_operand" "r,I10")))]
3846 "TARGET_SHMEDIA"
3847 "@
3848 or %1, %2, %0
3849 ori %1, %2, %0"
3850 [(set_attr "type" "arith_media")])
3851
3852 (define_insn_and_split "*logical_sidi3"
3853 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3854 (sign_extend:DI (match_operator:SI 3 "logical_operator"
3855 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3856 (match_operand:SI 2 "logical_operand" "r,I10")])))]
3857 "TARGET_SHMEDIA"
3858 "#"
3859 "&& reload_completed"
3860 [(set (match_dup 0) (match_dup 3))]
3861 {
3862 operands[3]
3863 = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3864 simplify_gen_subreg (DImode, operands[1], SImode, 0),
3865 simplify_gen_subreg (DImode, operands[2], SImode, 0));
3866 })
3867
3868 (define_insn_and_split "*logical_sidisi3"
3869 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3870 (truncate:SI (sign_extend:DI
3871 (match_operator:SI 3 "logical_operator"
3872 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3873 (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3874 "TARGET_SHMEDIA"
3875 "#"
3876 "&& 1"
3877 [(set (match_dup 0) (match_dup 3))])
3878
3879 (define_insn_and_split "*logical_sidi3_2"
3880 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3881 (sign_extend:DI (truncate:SI (sign_extend:DI
3882 (match_operator:SI 3 "logical_operator"
3883 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3884 (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3885 "TARGET_SHMEDIA"
3886 "#"
3887 "&& 1"
3888 [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3889
3890 (define_expand "xorsi3"
3891 [(set (match_operand:SI 0 "arith_reg_operand" "")
3892 (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3893 (match_operand:SI 2 "xor_operand" "")))]
3894 ""
3895 "")
3896
3897 (define_insn "*xorsi3_compact"
3898 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3899 (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3900 (match_operand:SI 2 "logical_operand" "K08,r")))]
3901 "TARGET_SH1"
3902 "xor %2,%0"
3903 [(set_attr "type" "arith")])
3904
3905 ;; The *logical_op_t pattern helps combine eliminating sign/zero extensions
3906 ;; of results where one of the inputs is a T bit store. Notice that this
3907 ;; pattern must not match during reload. If reload picks this pattern it
3908 ;; will be impossible to split it afterwards.
3909 (define_insn_and_split "*logical_op_t"
3910 [(set (match_operand:SI 0 "arith_reg_dest")
3911 (match_operator:SI 3 "logical_operator"
3912 [(match_operand:SI 1 "arith_reg_operand")
3913 (match_operand:SI 2 "t_reg_operand")]))]
3914 "TARGET_SH1 && can_create_pseudo_p ()"
3915 "#"
3916 "&& 1"
3917 [(set (match_dup 4) (reg:SI T_REG))
3918 (set (match_dup 0) (match_dup 3))]
3919 {
3920 operands[4] = gen_reg_rtx (SImode);
3921 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
3922 operands[1], operands[4]);
3923 })
3924
3925 (define_insn "*xorsi3_media"
3926 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3927 (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3928 (match_operand:SI 2 "xor_operand" "r,I06")))]
3929 "TARGET_SHMEDIA"
3930 "@
3931 xor %1, %2, %0
3932 xori %1, %2, %0"
3933 [(set_attr "type" "arith_media")])
3934
3935 (define_insn "xordi3"
3936 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3937 (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3938 (match_operand:DI 2 "xor_operand" "r,I06")))]
3939 "TARGET_SHMEDIA"
3940 "@
3941 xor %1, %2, %0
3942 xori %1, %2, %0"
3943 [(set_attr "type" "arith_media")])
3944
3945 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3946 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
3947 (define_split
3948 [(set (match_operand:DI 0 "arith_reg_dest" "")
3949 (sign_extend:DI (match_operator 4 "binary_logical_operator"
3950 [(match_operand 1 "any_register_operand" "")
3951 (match_operand 2 "any_register_operand" "")])))]
3952 "TARGET_SHMEDIA"
3953 [(set (match_dup 5) (match_dup 4))
3954 (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3955 {
3956 enum machine_mode inmode = GET_MODE (operands[1]);
3957 int offset = 0;
3958
3959 if (GET_CODE (operands[0]) == SUBREG)
3960 {
3961 offset = SUBREG_BYTE (operands[0]);
3962 operands[0] = SUBREG_REG (operands[0]);
3963 }
3964 gcc_assert (REG_P (operands[0]));
3965 if (TARGET_BIG_ENDIAN)
3966 offset += 8 - GET_MODE_SIZE (inmode);
3967 operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3968 })
3969 \f
3970 ;; -------------------------------------------------------------------------
3971 ;; Shifts and rotates
3972 ;; -------------------------------------------------------------------------
3973
3974 (define_expand "rotldi3"
3975 [(set (match_operand:DI 0 "arith_reg_dest" "")
3976 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "")
3977 (match_operand:HI 2 "mextr_bit_offset" "")))]
3978 "TARGET_SHMEDIA"
3979 {
3980 if (! mextr_bit_offset (operands[2], HImode))
3981 FAIL;
3982 })
3983
3984 (define_insn "rotldi3_mextr"
3985 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3986 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3987 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3988 "TARGET_SHMEDIA"
3989 {
3990 static char templ[16];
3991 sprintf (templ, "mextr%d %%1,%%1,%%0",
3992 8 - (int) (INTVAL (operands[2]) >> 3));
3993 return templ;
3994 }
3995 [(set_attr "type" "arith_media")])
3996
3997 (define_expand "rotrdi3"
3998 [(set (match_operand:DI 0 "arith_reg_dest" "")
3999 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "")
4000 (match_operand:HI 2 "mextr_bit_offset" "")))]
4001 "TARGET_SHMEDIA"
4002 {
4003 if (! mextr_bit_offset (operands[2], HImode))
4004 FAIL;
4005 })
4006
4007 (define_insn "rotrdi3_mextr"
4008 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4009 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
4010 (match_operand:HI 2 "mextr_bit_offset" "i")))]
4011 "TARGET_SHMEDIA"
4012 {
4013 static char templ[16];
4014 sprintf (templ, "mextr%d %%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3);
4015 return templ;
4016 }
4017 [(set_attr "type" "arith_media")])
4018
4019 (define_split
4020 [(set (match_operand:DI 0 "arith_reg_dest" "")
4021 (ior:DI (zero_extend:DI (mem:QI (match_operand 1
4022 "ua_address_operand" "")))
4023 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
4024 (const_int 8))))
4025 (clobber (match_operand:DI 3 "register_operand" ""))]
4026 "TARGET_SHMEDIA"
4027 [(match_dup 4) (match_dup 5)]
4028 {
4029 operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
4030 (operands[3], operands[1]));
4031 operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
4032 GEN_INT (56), GEN_INT (8));
4033 })
4034
4035 (define_expand "rotrsi3"
4036 [(set (match_operand:SI 0 "arith_reg_dest")
4037 (rotatert:SI (match_operand:SI 1 "arith_reg_operand")
4038 (match_operand:SI 2 "const_int_operand")))]
4039 "TARGET_SH1"
4040 {
4041 HOST_WIDE_INT ival = INTVAL (operands[2]);
4042 if (ival == 1)
4043 {
4044 emit_insn (gen_rotrsi3_1 (operands[0], operands[1]));
4045 DONE;
4046 }
4047
4048 FAIL;
4049 })
4050
4051 (define_insn "rotrsi3_1"
4052 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4053 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
4054 (const_int 1)))
4055 (set (reg:SI T_REG)
4056 (and:SI (match_dup 1) (const_int 1)))]
4057 "TARGET_SH1"
4058 "rotr %0"
4059 [(set_attr "type" "arith")])
4060
4061 ;; A slimplified version of rotr for combine.
4062 (define_insn "*rotrsi3_1"
4063 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4064 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
4065 (const_int 1)))
4066 (clobber (reg:SI T_REG))]
4067 "TARGET_SH1"
4068 "rotr %0"
4069 [(set_attr "type" "arith")])
4070
4071 (define_insn "rotlsi3_1"
4072 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4073 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4074 (const_int 1)))
4075 (set (reg:SI T_REG)
4076 (lshiftrt:SI (match_dup 1) (const_int 31)))]
4077 "TARGET_SH1"
4078 "rotl %0"
4079 [(set_attr "type" "arith")])
4080
4081 ;; A simplified version of rotl for combine.
4082 (define_insn "*rotlsi3_1"
4083 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4084 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4085 (const_int 1)))
4086 (clobber (reg:SI T_REG))]
4087 "TARGET_SH1"
4088 "rotl %0"
4089 [(set_attr "type" "arith")])
4090
4091 (define_insn "rotlsi3_31"
4092 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4093 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4094 (const_int 31)))
4095 (clobber (reg:SI T_REG))]
4096 "TARGET_SH1"
4097 "rotr %0"
4098 [(set_attr "type" "arith")])
4099
4100 (define_insn "rotlsi3_16"
4101 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4102 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
4103 (const_int 16)))]
4104 "TARGET_SH1"
4105 "swap.w %1,%0"
4106 [(set_attr "type" "arith")])
4107
4108 (define_expand "rotlsi3"
4109 [(set (match_operand:SI 0 "arith_reg_dest")
4110 (rotate:SI (match_operand:SI 1 "arith_reg_operand")
4111 (match_operand:SI 2 "const_int_operand")))]
4112 "TARGET_SH1"
4113 {
4114 static const char rot_tab[] = {
4115 000, 000, 000, 000, 000, 000, 010, 001,
4116 001, 001, 011, 013, 003, 003, 003, 003,
4117 003, 003, 003, 003, 003, 013, 012, 002,
4118 002, 002, 010, 000, 000, 000, 000, 000,
4119 };
4120
4121 int count = INTVAL (operands[2]);
4122 int choice = rot_tab[count];
4123 if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
4124 FAIL;
4125 choice &= 7;
4126 switch (choice)
4127 {
4128 case 0:
4129 emit_move_insn (operands[0], operands[1]);
4130 count -= (count & 16) * 2;
4131 break;
4132 case 3:
4133 emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
4134 count -= 16;
4135 break;
4136 case 1:
4137 case 2:
4138 {
4139 rtx parts[2];
4140 parts[0] = gen_reg_rtx (SImode);
4141 parts[1] = gen_reg_rtx (SImode);
4142 emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
4143 emit_move_insn (parts[choice-1], operands[1]);
4144 emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
4145 emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
4146 emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
4147 count = (count & ~16) - 8;
4148 }
4149 }
4150
4151 for (; count > 0; count--)
4152 emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
4153 for (; count < 0; count++)
4154 emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4155
4156 DONE;
4157 })
4158
4159 (define_insn "rotlhi3_8"
4160 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4161 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
4162 (const_int 8)))]
4163 "TARGET_SH1"
4164 "swap.b %1,%0"
4165 [(set_attr "type" "arith")])
4166
4167 (define_expand "rotlhi3"
4168 [(set (match_operand:HI 0 "arith_reg_operand")
4169 (rotate:HI (match_operand:HI 1 "arith_reg_operand")
4170 (match_operand:HI 2 "const_int_operand")))]
4171 "TARGET_SH1"
4172 {
4173 if (INTVAL (operands[2]) != 8)
4174 FAIL;
4175 })
4176
4177 ;; The rotcr and rotcl insns are used primarily in DImode shifts by one.
4178 ;; They can also be used to implement things like
4179 ;; bool t = a == b;
4180 ;; int x0 = (y >> 1) | (t << 31); // rotcr
4181 ;; int x1 = (y << 1) | t; // rotcl
4182 (define_insn "rotcr"
4183 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4184 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4185 (const_int 1))
4186 (ashift:SI (match_operand:SI 2 "t_reg_operand")
4187 (const_int 31))))
4188 (set (reg:SI T_REG)
4189 (and:SI (match_dup 1) (const_int 1)))]
4190 "TARGET_SH1"
4191 "rotcr %0"
4192 [(set_attr "type" "arith")])
4193
4194 (define_insn "rotcl"
4195 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4196 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4197 (const_int 1))
4198 (match_operand:SI 2 "t_reg_operand")))
4199 (set (reg:SI T_REG)
4200 (lshiftrt:SI (match_dup 1) (const_int 31)))]
4201 "TARGET_SH1"
4202 "rotcl %0"
4203 [(set_attr "type" "arith")])
4204
4205 ;; Simplified rotcr version for combine, which allows arbitrary shift
4206 ;; amounts for the reg. If the shift amount is '1' rotcr can be used
4207 ;; directly. Otherwise we have to insert a shift in between.
4208 (define_insn_and_split "*rotcr"
4209 [(set (match_operand:SI 0 "arith_reg_dest")
4210 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4211 (match_operand:SI 2 "const_int_operand"))
4212 (ashift:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4213 (const_int 31))))
4214 (clobber (reg:SI T_REG))]
4215 "TARGET_SH1"
4216 "#"
4217 "&& can_create_pseudo_p ()"
4218 [(const_int 0)]
4219 {
4220 if (INTVAL (operands[2]) > 1)
4221 {
4222 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4223 rtx prev_set_t_insn = NULL_RTX;
4224 rtx tmp_t_reg = NULL_RTX;
4225
4226 /* If we're going to emit a shift sequence that clobbers the T_REG,
4227 try to find the previous insn that sets the T_REG and emit the
4228 shift insn before that insn, to remove the T_REG dependency.
4229 If the insn that sets the T_REG cannot be found, store the T_REG
4230 in a temporary reg and restore it after the shift. */
4231 if (sh_lshrsi_clobbers_t_reg_p (shift_count)
4232 && ! sh_dynamicalize_shift_p (shift_count))
4233 {
4234 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4235
4236 /* Skip the nott insn, which was probably inserted by the splitter
4237 of *rotcr_neg_t. Don't use one of the recog functions
4238 here during insn splitting, since that causes problems in later
4239 passes. */
4240 if (prev_set_t_insn != NULL_RTX)
4241 {
4242 rtx pat = PATTERN (prev_set_t_insn);
4243 if (GET_CODE (pat) == SET
4244 && t_reg_operand (XEXP (pat, 0), SImode)
4245 && negt_reg_operand (XEXP (pat, 1), SImode))
4246 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4247 }
4248
4249 if (! (prev_set_t_insn != NULL_RTX
4250 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4251 && ! reg_referenced_p (get_t_reg_rtx (),
4252 PATTERN (prev_set_t_insn))))
4253 {
4254 prev_set_t_insn = NULL_RTX;
4255 tmp_t_reg = gen_reg_rtx (SImode);
4256 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4257 }
4258 }
4259
4260 rtx shift_result = gen_reg_rtx (SImode);
4261 rtx shift_insn = gen_lshrsi3 (shift_result, operands[1], shift_count);
4262 operands[1] = shift_result;
4263
4264 /* Emit the shift insn before the insn that sets T_REG, if possible. */
4265 if (prev_set_t_insn != NULL_RTX)
4266 emit_insn_before (shift_insn, prev_set_t_insn);
4267 else
4268 emit_insn (shift_insn);
4269
4270 /* Restore T_REG if it has been saved before. */
4271 if (tmp_t_reg != NULL_RTX)
4272 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4273 }
4274
4275 /* For the rotcr insn to work, operands[3] must be in T_REG.
4276 If it is not we can get it there by shifting it right one bit.
4277 In this case T_REG is not an input for this insn, thus we don't have to
4278 pay attention as of where to insert the shlr insn. */
4279 if (! t_reg_operand (operands[3], SImode))
4280 {
4281 /* We don't care about the shifted result here, only the T_REG. */
4282 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4283 operands[3] = get_t_reg_rtx ();
4284 }
4285
4286 emit_insn (gen_rotcr (operands[0], operands[1], operands[3]));
4287 DONE;
4288 })
4289
4290 ;; If combine tries the same as above but with swapped operands, split
4291 ;; it so that it will try the pattern above.
4292 (define_split
4293 [(set (match_operand:SI 0 "arith_reg_dest")
4294 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4295 (const_int 31))
4296 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4297 (match_operand:SI 3 "const_int_operand"))))]
4298 "TARGET_SH1 && can_create_pseudo_p ()"
4299 [(parallel [(set (match_dup 0)
4300 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4301 (ashift:SI (match_dup 1) (const_int 31))))
4302 (clobber (reg:SI T_REG))])])
4303
4304 ;; Basically the same as the rotcr pattern above, but for rotcl.
4305 ;; FIXME: Fold copy pasted split code for rotcr and rotcl.
4306 (define_insn_and_split "*rotcl"
4307 [(set (match_operand:SI 0 "arith_reg_dest")
4308 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4309 (match_operand:SI 2 "const_int_operand"))
4310 (and:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4311 (const_int 1))))
4312 (clobber (reg:SI T_REG))]
4313 "TARGET_SH1"
4314 "#"
4315 "&& can_create_pseudo_p ()"
4316 [(const_int 0)]
4317 {
4318 gcc_assert (INTVAL (operands[2]) > 0);
4319
4320 if (INTVAL (operands[2]) > 1)
4321 {
4322 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4323 rtx prev_set_t_insn = NULL_RTX;
4324 rtx tmp_t_reg = NULL_RTX;
4325
4326 /* If we're going to emit a shift sequence that clobbers the T_REG,
4327 try to find the previous insn that sets the T_REG and emit the
4328 shift insn before that insn, to remove the T_REG dependency.
4329 If the insn that sets the T_REG cannot be found, store the T_REG
4330 in a temporary reg and restore it after the shift. */
4331 if (sh_ashlsi_clobbers_t_reg_p (shift_count)
4332 && ! sh_dynamicalize_shift_p (shift_count))
4333 {
4334 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4335
4336 /* Skip the nott insn, which was probably inserted by the splitter
4337 of *rotcl_neg_t. Don't use one of the recog functions
4338 here during insn splitting, since that causes problems in later
4339 passes. */
4340 if (prev_set_t_insn != NULL_RTX)
4341 {
4342 rtx pat = PATTERN (prev_set_t_insn);
4343 if (GET_CODE (pat) == SET
4344 && t_reg_operand (XEXP (pat, 0), SImode)
4345 && negt_reg_operand (XEXP (pat, 1), SImode))
4346 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4347 }
4348
4349 if (! (prev_set_t_insn != NULL_RTX
4350 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4351 && ! reg_referenced_p (get_t_reg_rtx (),
4352 PATTERN (prev_set_t_insn))))
4353 {
4354 prev_set_t_insn = NULL_RTX;
4355 tmp_t_reg = gen_reg_rtx (SImode);
4356 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4357 }
4358 }
4359
4360 rtx shift_result = gen_reg_rtx (SImode);
4361 rtx shift_insn = gen_ashlsi3 (shift_result, operands[1], shift_count);
4362 operands[1] = shift_result;
4363
4364 /* Emit the shift insn before the insn that sets T_REG, if possible. */
4365 if (prev_set_t_insn != NULL_RTX)
4366 emit_insn_before (shift_insn, prev_set_t_insn);
4367 else
4368 emit_insn (shift_insn);
4369
4370 /* Restore T_REG if it has been saved before. */
4371 if (tmp_t_reg != NULL_RTX)
4372 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4373 }
4374
4375 /* For the rotcl insn to work, operands[3] must be in T_REG.
4376 If it is not we can get it there by shifting it right one bit.
4377 In this case T_REG is not an input for this insn, thus we don't have to
4378 pay attention as of where to insert the shlr insn. */
4379 if (! t_reg_operand (operands[3], SImode))
4380 {
4381 /* We don't care about the shifted result here, only the T_REG. */
4382 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4383 operands[3] = get_t_reg_rtx ();
4384 }
4385
4386 emit_insn (gen_rotcl (operands[0], operands[1], operands[3]));
4387 DONE;
4388 })
4389
4390 ;; rotcl combine pattern variations
4391 (define_insn_and_split "*rotcl"
4392 [(set (match_operand:SI 0 "arith_reg_dest")
4393 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4394 (match_operand:SI 2 "const_int_operand"))
4395 (match_operand:SI 3 "t_reg_operand")))
4396 (clobber (reg:SI T_REG))]
4397 "TARGET_SH1"
4398 "#"
4399 "&& can_create_pseudo_p ()"
4400 [(parallel [(set (match_dup 0)
4401 (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4402 (and:SI (match_dup 3) (const_int 1))))
4403 (clobber (reg:SI T_REG))])])
4404
4405 (define_insn_and_split "*rotcl"
4406 [(set (match_operand:SI 0 "arith_reg_dest")
4407 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4408 (const_int 1))
4409 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4410 (match_operand:SI 3 "const_int_operand"))))
4411 (clobber (reg:SI T_REG))]
4412 "TARGET_SH1"
4413 "#"
4414 "&& can_create_pseudo_p ()"
4415 [(parallel [(set (match_dup 0)
4416 (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4417 (and:SI (match_dup 1) (const_int 1))))
4418 (clobber (reg:SI T_REG))])])
4419
4420 (define_insn_and_split "*rotcl"
4421 [(set (match_operand:SI 0 "arith_reg_dest")
4422 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4423 (match_operand:SI 2 "const_int_operand"))
4424 (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4425 (const_int 31))))
4426 (clobber (reg:SI T_REG))]
4427 "TARGET_SH1"
4428 "#"
4429 "&& can_create_pseudo_p ()"
4430 [(parallel [(set (match_dup 0)
4431 (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4432 (and:SI (reg:SI T_REG) (const_int 1))))
4433 (clobber (reg:SI T_REG))])]
4434 {
4435 /* We don't care about the result of the left shift, only the T_REG. */
4436 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4437 })
4438
4439 (define_insn_and_split "*rotcl"
4440 [(set (match_operand:SI 0 "arith_reg_dest")
4441 (ior:SI (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4442 (const_int 31))
4443 (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4444 (match_operand:SI 2 "const_int_operand"))))
4445 (clobber (reg:SI T_REG))]
4446 "TARGET_SH1"
4447 "#"
4448 "&& can_create_pseudo_p ()"
4449 [(parallel [(set (match_dup 0)
4450 (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4451 (and:SI (reg:SI T_REG) (const_int 1))))
4452 (clobber (reg:SI T_REG))])]
4453 {
4454 /* We don't care about the result of the left shift, only the T_REG. */
4455 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4456 })
4457
4458 ;; rotcr combine bridge pattern which will make combine try out more
4459 ;; complex patterns.
4460 (define_insn_and_split "*rotcr"
4461 [(set (match_operand:SI 0 "arith_reg_dest")
4462 (ashift:SI (match_operand:SI 1 "t_reg_operand") (const_int 31)))]
4463 "TARGET_SH1"
4464 "#"
4465 "&& 1"
4466 [(set (match_dup 0) (match_dup 1))
4467 (parallel [(set (match_dup 0)
4468 (ior:SI (lshiftrt:SI (match_dup 0) (const_int 1))
4469 (ashift:SI (match_dup 1) (const_int 31))))
4470 (set (reg:SI T_REG)
4471 (and:SI (match_dup 0) (const_int 1)))])])
4472
4473 (define_insn_and_split "*rotcr"
4474 [(set (match_operand:SI 0 "arith_reg_dest")
4475 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
4476 (const_int -2147483648)) ;; 0xffffffff80000000
4477 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4478 (const_int 1))))
4479 (clobber (reg:SI T_REG))]
4480 "TARGET_SH1"
4481 "#"
4482 "&& can_create_pseudo_p ()"
4483 [(const_int 0)]
4484 {
4485 rtx tmp = gen_reg_rtx (SImode);
4486 emit_insn (gen_shll (tmp, operands[1]));
4487 emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ()));
4488 DONE;
4489 })
4490
4491 ;; rotcr combine patterns for rotating in the negated T_REG value.
4492 (define_insn_and_split "*rotcr_neg_t"
4493 [(set (match_operand:SI 0 "arith_reg_dest")
4494 (ior:SI (match_operand:SI 1 "negt_reg_shl31_operand")
4495 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4496 (match_operand:SI 3 "const_int_operand"))))
4497 (clobber (reg:SI T_REG))]
4498 "TARGET_SH1"
4499 "#"
4500 "&& can_create_pseudo_p ()"
4501 [(parallel [(set (match_dup 0)
4502 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4503 (ashift:SI (reg:SI T_REG) (const_int 31))))
4504 (clobber (reg:SI T_REG))])]
4505 {
4506 emit_insn (gen_nott (get_t_reg_rtx ()));
4507 })
4508
4509 (define_insn_and_split "*rotcr_neg_t"
4510 [(set (match_operand:SI 0 "arith_reg_dest")
4511 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4512 (match_operand:SI 2 "const_int_operand"))
4513 (match_operand:SI 3 "negt_reg_shl31_operand")))
4514 (clobber (reg:SI T_REG))]
4515 "TARGET_SH1"
4516 "#"
4517 "&& can_create_pseudo_p ()"
4518 [(parallel [(set (match_dup 0)
4519 (ior:SI (lshiftrt:SI (match_dup 1) (match_dup 2))
4520 (ashift:SI (reg:SI T_REG) (const_int 31))))
4521 (clobber (reg:SI T_REG))])]
4522 {
4523 emit_insn (gen_nott (get_t_reg_rtx ()));
4524 })
4525
4526 ;; rotcl combine patterns for rotating in the negated T_REG value.
4527 ;; For some strange reason these have to be specified as splits which combine
4528 ;; will pick up. If they are specified as insn_and_split like the
4529 ;; *rotcr_neg_t patterns above, combine would recognize them successfully
4530 ;; but not emit them on non-SH2A targets.
4531 (define_split
4532 [(set (match_operand:SI 0 "arith_reg_dest")
4533 (ior:SI (match_operand:SI 1 "negt_reg_operand")
4534 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4535 (match_operand:SI 3 "const_int_operand"))))]
4536 "TARGET_SH1"
4537 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4538 (parallel [(set (match_dup 0)
4539 (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4540 (and:SI (reg:SI T_REG) (const_int 1))))
4541 (clobber (reg:SI T_REG))])])
4542
4543 (define_split
4544 [(set (match_operand:SI 0 "arith_reg_dest")
4545 (ior:SI (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4546 (match_operand:SI 3 "const_int_operand"))
4547 (match_operand:SI 1 "negt_reg_operand")))]
4548 "TARGET_SH1"
4549 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4550 (parallel [(set (match_dup 0)
4551 (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4552 (and:SI (reg:SI T_REG) (const_int 1))))
4553 (clobber (reg:SI T_REG))])])
4554
4555 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4556 ;; SImode shift left
4557
4558 (define_expand "ashlsi3"
4559 [(set (match_operand:SI 0 "arith_reg_operand" "")
4560 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
4561 (match_operand:SI 2 "shift_count_operand" "")))]
4562 ""
4563 {
4564 if (TARGET_SHMEDIA)
4565 {
4566 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
4567 DONE;
4568 }
4569 if (TARGET_DYNSHIFT
4570 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
4571 operands[2] = force_reg (SImode, operands[2]);
4572
4573 /* If the ashlsi3_* insn is going to clobber the T_REG it must be
4574 expanded here. */
4575 if (CONST_INT_P (operands[2])
4576 && sh_ashlsi_clobbers_t_reg_p (operands[2])
4577 && ! sh_dynamicalize_shift_p (operands[2]))
4578 {
4579 emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1],
4580 operands[2]));
4581 DONE;
4582 }
4583
4584 /* Expand a library call for the dynamic shift. */
4585 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
4586 {
4587 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
4588 rtx funcaddr = gen_reg_rtx (Pmode);
4589 function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC);
4590 emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr));
4591
4592 DONE;
4593 }
4594 })
4595
4596 (define_insn "ashlsi3_k"
4597 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4598 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
4599 (match_operand:SI 2 "p27_shift_count_operand" "M,P27")))]
4600 "TARGET_SH1"
4601 "@
4602 add %0,%0
4603 shll%O2 %0"
4604 [(set_attr "type" "arith")])
4605
4606 (define_insn_and_split "ashlsi3_d"
4607 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4608 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4609 (match_operand:SI 2 "shift_count_operand" "r")))]
4610 "TARGET_DYNSHIFT"
4611 "shld %2,%0"
4612 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
4613 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4614 [(const_int 0)]
4615 {
4616 if (satisfies_constraint_P27 (operands[2]))
4617 {
4618 emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2]));
4619 DONE;
4620 }
4621 else if (! satisfies_constraint_P27 (operands[2]))
4622 {
4623 /* This must happen before reload, otherwise the constant will be moved
4624 into a register due to the "r" constraint, after which this split
4625 cannot be done anymore.
4626 Unfortunately the move insn will not always be eliminated.
4627 Also, here we must not create a shift sequence that clobbers the
4628 T_REG. */
4629 emit_move_insn (operands[0], operands[1]);
4630 gen_shifty_op (ASHIFT, operands);
4631 DONE;
4632 }
4633
4634 FAIL;
4635 }
4636 [(set_attr "type" "dyn_shift")])
4637
4638 ;; If dynamic shifts are not available use a library function.
4639 ;; By specifying the pattern we reduce the number of call clobbered regs.
4640 ;; In order to make combine understand the truncation of the shift amount
4641 ;; operand we have to allow it to use pseudo regs for the shift operands.
4642 (define_insn "ashlsi3_d_call"
4643 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
4644 (ashift:SI (reg:SI R4_REG)
4645 (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
4646 (const_int 31))))
4647 (use (match_operand:SI 2 "arith_reg_operand" "r"))
4648 (clobber (reg:SI T_REG))
4649 (clobber (reg:SI PR_REG))]
4650 "TARGET_SH1 && !TARGET_DYNSHIFT"
4651 "jsr @%2%#"
4652 [(set_attr "type" "sfunc")
4653 (set_attr "needs_delay_slot" "yes")])
4654
4655 (define_insn_and_split "ashlsi3_n"
4656 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4657 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4658 (match_operand:SI 2 "not_p27_shift_count_operand" "")))]
4659 "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4660 "#"
4661 "&& (reload_completed
4662 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4663 [(const_int 0)]
4664 {
4665 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4666 {
4667 /* If this pattern was picked and dynamic shifts are supported, switch
4668 to dynamic shift pattern before reload. */
4669 operands[2] = force_reg (SImode, operands[2]);
4670 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4671 }
4672 else
4673 gen_shifty_op (ASHIFT, operands);
4674
4675 DONE;
4676 })
4677
4678 (define_insn_and_split "ashlsi3_n_clobbers_t"
4679 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4680 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4681 (match_operand:SI 2 "not_p27_shift_count_operand" "")))
4682 (clobber (reg:SI T_REG))]
4683 "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])"
4684 "#"
4685 "&& (reload_completed || INTVAL (operands[2]) == 31
4686 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4687 [(const_int 0)]
4688 {
4689 if (INTVAL (operands[2]) == 31)
4690 {
4691 /* If the shift amount is 31 we split into a different sequence before
4692 reload so that it gets a chance to allocate R0 for the sequence.
4693 If it fails to do so (due to pressure on R0), it will take one insn
4694 more for the and. */
4695 emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx));
4696 emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4697 }
4698 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4699 {
4700 /* If this pattern was picked and dynamic shifts are supported, switch
4701 to dynamic shift pattern before reload. */
4702 operands[2] = force_reg (SImode, operands[2]);
4703 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4704 }
4705 else
4706 gen_shifty_op (ASHIFT, operands);
4707
4708 DONE;
4709 })
4710
4711 (define_insn "shll"
4712 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4713 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
4714 (set (reg:SI T_REG)
4715 (lt:SI (match_dup 1) (const_int 0)))]
4716 "TARGET_SH1"
4717 "shll %0"
4718 [(set_attr "type" "arith")])
4719
4720 (define_insn "*ashlsi_c_void"
4721 [(set (reg:SI T_REG)
4722 (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
4723 (clobber (match_scratch:SI 1 "=0"))]
4724 "TARGET_SH1 && cse_not_expected"
4725 "shll %0"
4726 [(set_attr "type" "arith")])
4727
4728 (define_peephole2
4729 [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
4730 (set (reg:SI T_REG)
4731 (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
4732 "TARGET_SH1
4733 && peep2_reg_dead_p (2, operands[0])
4734 && peep2_reg_dead_p (2, operands[1])"
4735 [(const_int 0)]
4736 {
4737 emit_insn (gen_shll (operands[1], operands[1]));
4738 DONE;
4739 })
4740
4741 (define_insn "ashlsi3_media"
4742 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4743 (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
4744 (match_operand:SI 2 "shift_count_operand" "r,n")))]
4745 "TARGET_SHMEDIA"
4746 "@
4747 shlld.l %1, %2, %0
4748 shlli.l %1, %2, %0"
4749 [(set_attr "type" "arith_media")
4750 (set_attr "highpart" "ignore")])
4751
4752 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4753 ;; HImode shift left
4754
4755 (define_expand "ashlhi3"
4756 [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
4757 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
4758 (match_operand:SI 2 "nonmemory_operand" "")))
4759 (clobber (reg:SI T_REG))])]
4760 "TARGET_SH1"
4761 {
4762 if (!CONST_INT_P (operands[2]))
4763 FAIL;
4764 /* It may be possible to call gen_ashlhi3 directly with more generic
4765 operands. Make sure operands[1] is a HImode register here. */
4766 if (!arith_reg_operand (operands[1], HImode))
4767 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4768 })
4769
4770 (define_insn "ashlhi3_k"
4771 [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4772 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
4773 (match_operand:HI 2 "const_int_operand" "M,P27")))]
4774 "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
4775 "@
4776 add %0,%0
4777 shll%O2 %0"
4778 [(set_attr "type" "arith")])
4779
4780 (define_insn_and_split "*ashlhi3_n"
4781 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4782 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
4783 (match_operand:HI 2 "const_int_operand" "n")))
4784 (clobber (reg:SI T_REG))]
4785 "TARGET_SH1"
4786 "#"
4787 "&& reload_completed"
4788 [(use (reg:SI R0_REG))]
4789 {
4790 gen_shifty_hi_op (ASHIFT, operands);
4791 DONE;
4792 })
4793
4794 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4795 ;; DImode shift left
4796
4797 (define_expand "ashldi3"
4798 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4799 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
4800 (match_operand:DI 2 "immediate_operand" "")))
4801 (clobber (reg:SI T_REG))])]
4802 ""
4803 {
4804 if (TARGET_SHMEDIA)
4805 {
4806 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
4807 DONE;
4808 }
4809 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
4810 {
4811 emit_insn (gen_ashldi3_k (operands[0], operands[1]));
4812 DONE;
4813 }
4814 else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32)
4815 {
4816 emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
4817 DONE;
4818 }
4819 else
4820 FAIL;
4821 })
4822
4823 ;; Expander for DImode shift left with SImode operations.
4824 (define_expand "ashldi3_std"
4825 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4826 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4827 (match_operand:DI 2 "const_int_operand" "n")))]
4828 "TARGET_SH1 && INTVAL (operands[2]) < 32"
4829 {
4830 rtx low_src = gen_lowpart (SImode, operands[1]);
4831 rtx high_src = gen_highpart (SImode, operands[1]);
4832 rtx dst = gen_reg_rtx (DImode);
4833 rtx low_dst = gen_lowpart (SImode, dst);
4834 rtx high_dst = gen_highpart (SImode, dst);
4835 rtx tmp0 = gen_reg_rtx (SImode);
4836 rtx tmp1 = gen_reg_rtx (SImode);
4837
4838 emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
4839 emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));
4840 emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));
4841 emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
4842 emit_move_insn (operands[0], dst);
4843 DONE;
4844 })
4845
4846 (define_insn_and_split "ashldi3_k"
4847 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4848 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
4849 (const_int 1)))
4850 (clobber (reg:SI T_REG))]
4851 "TARGET_SH1"
4852 "#"
4853 "&& reload_completed"
4854 [(const_int 0)]
4855 {
4856 rtx high = gen_highpart (SImode, operands[0]);
4857 rtx low = gen_lowpart (SImode, operands[0]);
4858 emit_insn (gen_shll (low, low));
4859 emit_insn (gen_rotcl (high, high, get_t_reg_rtx ()));
4860 DONE;
4861 })
4862
4863 (define_insn "ashldi3_media"
4864 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4865 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4866 (match_operand:DI 2 "shift_count_operand" "r,n")))]
4867 "TARGET_SHMEDIA"
4868 "@
4869 shlld %1, %2, %0
4870 shlli %1, %2, %0"
4871 [(set_attr "type" "arith_media")])
4872
4873 (define_insn "*ashldisi3_media"
4874 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4875 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4876 (match_operand:DI 2 "const_int_operand" "n")))]
4877 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4878 "shlli.l %1, %2, %0"
4879 [(set_attr "type" "arith_media")
4880 (set_attr "highpart" "ignore")])
4881
4882 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4883 ;; SImode arithmetic shift right
4884 ;;
4885 ;; We can't do HImode right shifts correctly unless we start out with an
4886 ;; explicit zero / sign extension; doing that would result in worse overall
4887 ;; code, so just let the machine independent code widen the mode.
4888 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
4889
4890 (define_expand "ashrsi3"
4891 [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
4892 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
4893 (match_operand:SI 2 "nonmemory_operand" "")))
4894 (clobber (reg:SI T_REG))])]
4895 ""
4896 {
4897 if (TARGET_SHMEDIA)
4898 {
4899 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
4900 DONE;
4901 }
4902 if (expand_ashiftrt (operands))
4903 DONE;
4904 else
4905 FAIL;
4906 })
4907
4908 (define_insn "shar"
4909 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4910 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4911 (const_int 1)))
4912 (set (reg:SI T_REG)
4913 (and:SI (match_dup 1) (const_int 1)))]
4914 "TARGET_SH1"
4915 "shar %0"
4916 [(set_attr "type" "arith")])
4917
4918 (define_insn "ashrsi3_k"
4919 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4920 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4921 (match_operand:SI 2 "const_int_operand" "M")))
4922 (clobber (reg:SI T_REG))]
4923 "TARGET_SH1 && INTVAL (operands[2]) == 1"
4924 "shar %0"
4925 [(set_attr "type" "arith")])
4926
4927 (define_insn_and_split "ashrsi2_16"
4928 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4929 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
4930 (const_int 16)))]
4931 "TARGET_SH1"
4932 "#"
4933 "&& 1"
4934 [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
4935 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
4936 {
4937 operands[2] = gen_lowpart (HImode, operands[0]);
4938 })
4939
4940 (define_insn_and_split "ashrsi2_31"
4941 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4942 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4943 (const_int 31)))
4944 (clobber (reg:SI T_REG))]
4945 "TARGET_SH1"
4946 "#"
4947 "&& 1"
4948 [(const_int 0)]
4949 {
4950 emit_insn (gen_shll (operands[0], operands[1]));
4951 emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
4952 DONE;
4953 })
4954
4955 (define_insn "ashrsi3_d"
4956 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4957 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4958 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4959 "TARGET_DYNSHIFT"
4960 "shad %2,%0"
4961 [(set_attr "type" "dyn_shift")])
4962
4963 (define_insn "ashrsi3_n"
4964 [(set (reg:SI R4_REG)
4965 (ashiftrt:SI (reg:SI R4_REG)
4966 (match_operand:SI 0 "const_int_operand" "i")))
4967 (clobber (reg:SI T_REG))
4968 (clobber (reg:SI PR_REG))
4969 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
4970 "TARGET_SH1"
4971 "jsr @%1%#"
4972 [(set_attr "type" "sfunc")
4973 (set_attr "needs_delay_slot" "yes")])
4974
4975 (define_insn "ashrsi3_media"
4976 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4977 (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
4978 (match_operand:SI 2 "shift_count_operand" "r,n")))]
4979 "TARGET_SHMEDIA"
4980 "@
4981 shard.l %1, %2, %0
4982 shari.l %1, %2, %0"
4983 [(set_attr "type" "arith_media")
4984 (set_attr "highpart" "ignore")])
4985
4986 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4987 ;; DImode arithmetic shift right
4988
4989 (define_expand "ashrdi3"
4990 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4991 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4992 (match_operand:DI 2 "immediate_operand" "")))
4993 (clobber (reg:SI T_REG))])]
4994 ""
4995 {
4996 if (TARGET_SHMEDIA)
4997 {
4998 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4999 DONE;
5000 }
5001 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5002 FAIL;
5003 })
5004
5005 (define_insn_and_split "ashrdi3_k"
5006 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5007 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5008 (const_int 1)))
5009 (clobber (reg:SI T_REG))]
5010 "TARGET_SH1"
5011 "#"
5012 "&& reload_completed"
5013 [(const_int 0)]
5014 {
5015 rtx high = gen_highpart (SImode, operands[0]);
5016 rtx low = gen_lowpart (SImode, operands[0]);
5017 emit_insn (gen_shar (high, high));
5018 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5019 DONE;
5020 })
5021
5022 (define_insn "ashrdi3_media"
5023 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5024 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5025 (match_operand:DI 2 "shift_count_operand" "r,n")))]
5026 "TARGET_SHMEDIA
5027 && (arith_reg_dest (operands[0], DImode)
5028 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
5029 "@
5030 shard %1, %2, %0
5031 shari %1, %2, %0"
5032 [(set_attr "type" "arith_media")])
5033
5034 (define_insn "*ashrdisi3_media"
5035 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5036 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5037 (match_operand:DI 2 "const_int_operand" "n")))]
5038 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5039 "shari.l %1, %2, %0"
5040 [(set_attr "type" "arith_media")
5041 (set_attr "highpart" "ignore")])
5042
5043 (define_insn "ashrdisi3_media_high"
5044 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5045 (truncate:SI
5046 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5047 (match_operand:DI 2 "const_int_operand" "n"))))]
5048 "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
5049 "shari %1, %2, %0"
5050 [(set_attr "type" "arith_media")])
5051
5052 (define_insn "ashrdisi3_media_opaque"
5053 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5054 (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
5055 (match_operand:DI 2 "const_int_operand" "n")]
5056 UNSPEC_ASHIFTRT))]
5057 "TARGET_SHMEDIA"
5058 "shari %1, %2, %0"
5059 [(set_attr "type" "arith_media")])
5060
5061 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5062 ;; SImode logical shift right
5063
5064 (define_expand "lshrsi3"
5065 [(set (match_operand:SI 0 "arith_reg_dest" "")
5066 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
5067 (match_operand:SI 2 "shift_count_operand" "")))]
5068 ""
5069 {
5070 if (TARGET_SHMEDIA)
5071 {
5072 emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
5073 DONE;
5074 }
5075
5076 /* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn
5077 here, otherwise the pattern will never match due to the shift amount reg
5078 negation. */
5079 if (TARGET_DYNSHIFT
5080 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
5081 {
5082 rtx neg_count = force_reg (SImode,
5083 gen_int_mode (- INTVAL (operands[2]), SImode));
5084 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
5085 DONE;
5086 }
5087
5088 if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2]))
5089 {
5090 rtx neg_count = gen_reg_rtx (SImode);
5091 emit_insn (gen_negsi2 (neg_count, operands[2]));
5092 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
5093 DONE;
5094 }
5095
5096 /* If the lshrsi3_* insn is going to clobber the T_REG it must be
5097 expanded here. */
5098 if (CONST_INT_P (operands[2])
5099 && sh_lshrsi_clobbers_t_reg_p (operands[2])
5100 && ! sh_dynamicalize_shift_p (operands[2]))
5101 {
5102 emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1],
5103 operands[2]));
5104 DONE;
5105 }
5106
5107 /* Expand a library call for the dynamic shift. */
5108 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
5109 {
5110 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
5111 rtx funcaddr = gen_reg_rtx (Pmode);
5112 function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC);
5113 emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr));
5114 DONE;
5115 }
5116 })
5117
5118 (define_insn "lshrsi3_k"
5119 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5120 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5121 (match_operand:SI 2 "p27_rshift_count_operand" "P27")))]
5122 "TARGET_SH1"
5123 "shlr%O2 %0"
5124 [(set_attr "type" "arith")])
5125
5126 (define_insn_and_split "lshrsi3_d"
5127 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5128 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5129 (neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))]
5130 "TARGET_DYNSHIFT"
5131 "shld %2,%0"
5132 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
5133 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5134 [(const_int 0)]
5135 {
5136 if (satisfies_constraint_P27 (operands[2]))
5137 {
5138 /* This will not be done for a shift amount of 1, because it would
5139 clobber the T_REG. */
5140 emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2]));
5141 DONE;
5142 }
5143 else if (! satisfies_constraint_P27 (operands[2]))
5144 {
5145 /* This must happen before reload, otherwise the constant will be moved
5146 into a register due to the "r" constraint, after which this split
5147 cannot be done anymore.
5148 Unfortunately the move insn will not always be eliminated.
5149 Also, here we must not create a shift sequence that clobbers the
5150 T_REG. */
5151 emit_move_insn (operands[0], operands[1]);
5152 gen_shifty_op (LSHIFTRT, operands);
5153 DONE;
5154 }
5155
5156 FAIL;
5157 }
5158 [(set_attr "type" "dyn_shift")])
5159
5160 ;; If dynamic shifts are not available use a library function.
5161 ;; By specifying the pattern we reduce the number of call clobbered regs.
5162 ;; In order to make combine understand the truncation of the shift amount
5163 ;; operand we have to allow it to use pseudo regs for the shift operands.
5164 (define_insn "lshrsi3_d_call"
5165 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
5166 (lshiftrt:SI (reg:SI R4_REG)
5167 (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
5168 (const_int 31))))
5169 (use (match_operand:SI 2 "arith_reg_operand" "r"))
5170 (clobber (reg:SI T_REG))
5171 (clobber (reg:SI PR_REG))]
5172 "TARGET_SH1 && !TARGET_DYNSHIFT"
5173 "jsr @%2%#"
5174 [(set_attr "type" "sfunc")
5175 (set_attr "needs_delay_slot" "yes")])
5176
5177 (define_insn_and_split "lshrsi3_n"
5178 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5179 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5180 (match_operand:SI 2 "not_p27_rshift_count_operand")))]
5181 "TARGET_SH1 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5182 "#"
5183 "&& (reload_completed
5184 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5185 [(const_int 0)]
5186 {
5187 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5188 {
5189 /* If this pattern was picked and dynamic shifts are supported, switch
5190 to dynamic shift pattern before reload. */
5191 operands[2] = force_reg (SImode,
5192 gen_int_mode (- INTVAL (operands[2]), SImode));
5193 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5194 }
5195 else
5196 gen_shifty_op (LSHIFTRT, operands);
5197
5198 DONE;
5199 })
5200
5201 ;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of
5202 ;; the shlr pattern.
5203 (define_insn_and_split "lshrsi3_n_clobbers_t"
5204 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5205 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5206 (match_operand:SI 2 "not_p27_rshift_count_operand")))
5207 (clobber (reg:SI T_REG))]
5208 "TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])"
5209 "#"
5210 "&& (reload_completed || INTVAL (operands[2]) == 31
5211 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5212 [(const_int 0)]
5213 {
5214 if (INTVAL (operands[2]) == 31)
5215 {
5216 emit_insn (gen_shll (operands[0], operands[1]));
5217 emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
5218 }
5219 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5220 {
5221 /* If this pattern was picked and dynamic shifts are supported, switch
5222 to dynamic shift pattern before reload. */
5223 operands[2] = force_reg (SImode,
5224 gen_int_mode (- INTVAL (operands[2]), SImode));
5225 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5226 }
5227 else
5228 gen_shifty_op (LSHIFTRT, operands);
5229
5230 DONE;
5231 })
5232
5233 (define_insn "shlr"
5234 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5235 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5236 (const_int 1)))
5237 (set (reg:SI T_REG)
5238 (and:SI (match_dup 1) (const_int 1)))]
5239 "TARGET_SH1"
5240 "shlr %0"
5241 [(set_attr "type" "arith")])
5242
5243 (define_insn "lshrsi3_media"
5244 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5245 (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5246 (match_operand:SI 2 "shift_count_operand" "r,n")))]
5247 "TARGET_SHMEDIA"
5248 "@
5249 shlrd.l %1, %2, %0
5250 shlri.l %1, %2, %0"
5251 [(set_attr "type" "arith_media")
5252 (set_attr "highpart" "ignore")])
5253
5254 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5255 ;; DImode logical shift right
5256
5257 (define_expand "lshrdi3"
5258 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5259 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
5260 (match_operand:DI 2 "immediate_operand" "")))
5261 (clobber (reg:SI T_REG))])]
5262 ""
5263 {
5264 if (TARGET_SHMEDIA)
5265 {
5266 emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
5267 DONE;
5268 }
5269 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5270 FAIL;
5271 })
5272
5273 (define_insn_and_split "lshrdi3_k"
5274 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5275 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5276 (const_int 1)))
5277 (clobber (reg:SI T_REG))]
5278 "TARGET_SH1"
5279 "#"
5280 "&& reload_completed"
5281 [(const_int 0)]
5282 {
5283 rtx high = gen_highpart (SImode, operands[0]);
5284 rtx low = gen_lowpart (SImode, operands[0]);
5285 emit_insn (gen_shlr (high, high));
5286 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5287 DONE;
5288 })
5289
5290 (define_insn "lshrdi3_media"
5291 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5292 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5293 (match_operand:DI 2 "shift_count_operand" "r,n")))]
5294 "TARGET_SHMEDIA
5295 && (arith_reg_dest (operands[0], DImode)
5296 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
5297 "@
5298 shlrd %1, %2, %0
5299 shlri %1, %2, %0"
5300 [(set_attr "type" "arith_media")])
5301
5302 (define_insn "*lshrdisi3_media"
5303 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5304 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5305 (match_operand:DI 2 "const_int_operand" "n")))]
5306 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5307 "shlri.l %1, %2, %0"
5308 [(set_attr "type" "arith_media")
5309 (set_attr "highpart" "ignore")])
5310
5311 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5312 ;; Combined left/right shifts
5313
5314 (define_split
5315 [(set (match_operand:SI 0 "register_operand" "")
5316 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5317 (match_operand:SI 2 "const_int_operand" ""))
5318 (match_operand:SI 3 "const_int_operand" "")))]
5319 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5320 [(use (reg:SI R0_REG))]
5321 {
5322 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5323 FAIL;
5324 DONE;
5325 })
5326
5327 (define_split
5328 [(set (match_operand:SI 0 "register_operand" "")
5329 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5330 (match_operand:SI 2 "const_int_operand" ""))
5331 (match_operand:SI 3 "const_int_operand" "")))
5332 (clobber (reg:SI T_REG))]
5333 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5334 [(use (reg:SI R0_REG))]
5335 {
5336 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5337 FAIL;
5338 DONE;
5339 })
5340
5341 (define_insn ""
5342 [(set (match_operand:SI 0 "register_operand" "=r")
5343 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5344 (match_operand:SI 2 "const_int_operand" "n"))
5345 (match_operand:SI 3 "const_int_operand" "n")))
5346 (clobber (reg:SI T_REG))]
5347 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
5348 "#"
5349 [(set (attr "length")
5350 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5351 (const_string "4")
5352 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5353 (const_string "6")
5354 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5355 (const_string "8")
5356 (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
5357 (const_string "10")
5358 (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
5359 (const_string "12")
5360 (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
5361 (const_string "14")
5362 (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
5363 (const_string "16")]
5364 (const_string "18")))
5365 (set_attr "type" "arith")])
5366
5367 (define_insn ""
5368 [(set (match_operand:SI 0 "register_operand" "=z")
5369 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5370 (match_operand:SI 2 "const_int_operand" "n"))
5371 (match_operand:SI 3 "const_int_operand" "n")))
5372 (clobber (reg:SI T_REG))]
5373 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
5374 "#"
5375 [(set (attr "length")
5376 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5377 (const_string "4")
5378 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5379 (const_string "6")
5380 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5381 (const_string "8")]
5382 (const_string "10")))
5383 (set_attr "type" "arith")])
5384
5385 ;; shift left / and combination with a scratch register: The combine pass
5386 ;; does not accept the individual instructions, even though they are
5387 ;; cheap. But it needs a precise description so that it is usable after
5388 ;; reload.
5389 (define_insn "and_shl_scratch"
5390 [(set (match_operand:SI 0 "register_operand" "=r,&r")
5391 (lshiftrt:SI
5392 (ashift:SI
5393 (and:SI
5394 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
5395 (match_operand:SI 2 "const_int_operand" "N,n"))
5396 (match_operand:SI 3 "" "0,r"))
5397 (match_operand:SI 4 "const_int_operand" "n,n"))
5398 (match_operand:SI 5 "const_int_operand" "n,n")))
5399 (clobber (reg:SI T_REG))]
5400 "TARGET_SH1"
5401 "#"
5402 [(set (attr "length")
5403 (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
5404 (const_string "4")
5405 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
5406 (const_string "6")
5407 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
5408 (const_string "8")
5409 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
5410 (const_string "10")]
5411 (const_string "12")))
5412 (set_attr "type" "arith")])
5413
5414 (define_split
5415 [(set (match_operand:SI 0 "register_operand" "")
5416 (lshiftrt:SI
5417 (ashift:SI
5418 (and:SI
5419 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
5420 (match_operand:SI 2 "const_int_operand" ""))
5421 (match_operand:SI 3 "register_operand" ""))
5422 (match_operand:SI 4 "const_int_operand" ""))
5423 (match_operand:SI 5 "const_int_operand" "")))
5424 (clobber (reg:SI T_REG))]
5425 "TARGET_SH1"
5426 [(use (reg:SI R0_REG))]
5427 {
5428 rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
5429
5430 if (INTVAL (operands[2]))
5431 {
5432 gen_shifty_op (LSHIFTRT, operands);
5433 }
5434 emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
5435 operands[2] = operands[4];
5436 gen_shifty_op (ASHIFT, operands);
5437 if (INTVAL (operands[5]))
5438 {
5439 operands[2] = operands[5];
5440 gen_shifty_op (LSHIFTRT, operands);
5441 }
5442 DONE;
5443 })
5444
5445 ;; signed left/right shift combination.
5446 (define_split
5447 [(set (match_operand:SI 0 "register_operand" "")
5448 (sign_extract:SI
5449 (ashift:SI (match_operand:SI 1 "register_operand" "")
5450 (match_operand:SI 2 "const_int_operand" ""))
5451 (match_operand:SI 3 "const_int_operand" "")
5452 (const_int 0)))
5453 (clobber (reg:SI T_REG))]
5454 "TARGET_SH1"
5455 [(use (reg:SI R0_REG))]
5456 {
5457 if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1]))
5458 FAIL;
5459 DONE;
5460 })
5461
5462 (define_insn "shl_sext_ext"
5463 [(set (match_operand:SI 0 "register_operand" "=r")
5464 (sign_extract:SI
5465 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5466 (match_operand:SI 2 "const_int_operand" "n"))
5467 (match_operand:SI 3 "const_int_operand" "n")
5468 (const_int 0)))
5469 (clobber (reg:SI T_REG))]
5470 "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
5471 "#"
5472 [(set (attr "length")
5473 (cond [(match_test "shl_sext_length (insn)")
5474 (const_string "2")
5475 (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
5476 (const_string "4")
5477 (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5478 (const_string "6")
5479 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5480 (const_string "8")
5481 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5482 (const_string "10")
5483 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5484 (const_string "12")
5485 (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
5486 (const_string "14")
5487 (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
5488 (const_string "16")]
5489 (const_string "18")))
5490 (set_attr "type" "arith")])
5491
5492 (define_insn "shl_sext_sub"
5493 [(set (match_operand:SI 0 "register_operand" "=z")
5494 (sign_extract:SI
5495 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5496 (match_operand:SI 2 "const_int_operand" "n"))
5497 (match_operand:SI 3 "const_int_operand" "n")
5498 (const_int 0)))
5499 (clobber (reg:SI T_REG))]
5500 "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
5501 "#"
5502 [(set (attr "length")
5503 (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5504 (const_string "6")
5505 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5506 (const_string "8")
5507 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5508 (const_string "10")
5509 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5510 (const_string "12")]
5511 (const_string "14")))
5512 (set_attr "type" "arith")])
5513
5514 ;; The xtrct_left and xtrct_right patterns are used in expansions of DImode
5515 ;; shifts by 16, and allow the xtrct instruction to be generated from C
5516 ;; source.
5517 (define_insn "xtrct_left"
5518 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5519 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5520 (const_int 16))
5521 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
5522 (const_int 16))))]
5523 "TARGET_SH1"
5524 "xtrct %1,%0"
5525 [(set_attr "type" "arith")])
5526
5527 (define_insn "xtrct_right"
5528 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5529 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5530 (const_int 16))
5531 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
5532 (const_int 16))))]
5533 "TARGET_SH1"
5534 "xtrct %2,%0"
5535 [(set_attr "type" "arith")])
5536
5537 ;; -------------------------------------------------------------------------
5538 ;; Unary arithmetic
5539 ;; -------------------------------------------------------------------------
5540
5541 (define_insn "negc"
5542 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5543 (neg:SI (plus:SI (reg:SI T_REG)
5544 (match_operand:SI 1 "arith_reg_operand" "r"))))
5545 (set (reg:SI T_REG)
5546 (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
5547 (const_int 0)))]
5548 "TARGET_SH1"
5549 "negc %1,%0"
5550 [(set_attr "type" "arith")])
5551
5552 ;; A simplified version of the negc insn, where the exact value of the
5553 ;; T bit doesn't matter. This is easier for combine to pick up.
5554 ;; Notice that '0 - x - 1' is the same as '~x', thus we don't specify
5555 ;; extra patterns for this case.
5556 (define_insn "*negc"
5557 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5558 (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5559 (match_operand:SI 2 "t_reg_operand" "")))
5560 (clobber (reg:SI T_REG))]
5561 "TARGET_SH1"
5562 "negc %1,%0"
5563 [(set_attr "type" "arith")])
5564
5565 (define_insn "*negdi_media"
5566 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5567 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
5568 "TARGET_SHMEDIA"
5569 "sub r63, %1, %0"
5570 [(set_attr "type" "arith_media")])
5571
5572 ;; Don't split into individual negc insns immediately so that neg:DI (abs:DI)
5573 ;; can be combined.
5574 (define_expand "negdi2"
5575 [(parallel [(set (match_operand:DI 0 "arith_reg_dest")
5576 (neg:DI (match_operand:DI 1 "arith_reg_operand")))
5577 (clobber (reg:SI T_REG))])]
5578 "TARGET_SH1")
5579
5580 (define_insn_and_split "*negdi2"
5581 [(set (match_operand:DI 0 "arith_reg_dest")
5582 (neg:DI (match_operand:DI 1 "arith_reg_operand")))
5583 (clobber (reg:SI T_REG))]
5584 "TARGET_SH1"
5585 "#"
5586 "&& can_create_pseudo_p ()"
5587 [(const_int 0)]
5588 {
5589 emit_insn (gen_clrt ());
5590 emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
5591 gen_lowpart (SImode, operands[1])));
5592 emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
5593 gen_highpart (SImode, operands[1])));
5594 DONE;
5595 })
5596
5597 (define_insn "negsi2"
5598 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5599 (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5600 "TARGET_SH1"
5601 "neg %1,%0"
5602 [(set_attr "type" "arith")])
5603
5604 (define_insn_and_split "one_cmplsi2"
5605 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5606 (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5607 "TARGET_SH1"
5608 "not %1,%0"
5609 "&& can_create_pseudo_p ()"
5610 [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0)))
5611 (set (match_dup 0) (reg:SI T_REG))]
5612 {
5613 /* PR 54685
5614 If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following
5615 sequence:
5616
5617 (set (reg0) (not:SI (reg0) (reg1)))
5618 (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31)))
5619 (clobber (reg:SI T_REG))])
5620
5621 ... match and combine the sequence manually in the split pass after the
5622 combine pass. Notice that combine does try the target pattern of this
5623 split, but if the pattern is added it interferes with other patterns, in
5624 particular with the div0s comparisons.
5625 This could also be done with a peephole but doing it here before register
5626 allocation can save one temporary.
5627 When we're here, the not:SI pattern obviously has been matched already
5628 and we only have to see whether the following insn is the left shift. */
5629
5630 rtx i = next_nonnote_insn_bb (curr_insn);
5631 if (i == NULL_RTX || !NONJUMP_INSN_P (i))
5632 FAIL;
5633
5634 rtx p = PATTERN (i);
5635 if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2)
5636 FAIL;
5637
5638 rtx p0 = XVECEXP (p, 0, 0);
5639 rtx p1 = XVECEXP (p, 0, 1);
5640
5641 if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31))) */
5642 GET_CODE (p0) == SET
5643 && GET_CODE (XEXP (p0, 1)) == LSHIFTRT
5644 && REG_P (XEXP (XEXP (p0, 1), 0))
5645 && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0])
5646 && CONST_INT_P (XEXP (XEXP (p0, 1), 1))
5647 && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31
5648
5649 /* (clobber (reg:SI T_REG)) */
5650 && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0))
5651 && REGNO (XEXP (p1, 0)) == T_REG)
5652 {
5653 operands[0] = XEXP (p0, 0);
5654 set_insn_deleted (i);
5655 }
5656 else
5657 FAIL;
5658 }
5659 [(set_attr "type" "arith")])
5660
5661 (define_expand "one_cmpldi2"
5662 [(set (match_operand:DI 0 "arith_reg_dest" "")
5663 (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
5664 (const_int -1)))]
5665 "TARGET_SHMEDIA" "")
5666
5667 (define_expand "abs<mode>2"
5668 [(parallel [(set (match_operand:SIDI 0 "arith_reg_dest")
5669 (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
5670 (clobber (reg:SI T_REG))])]
5671 "TARGET_SH1")
5672
5673 (define_insn_and_split "*abs<mode>2"
5674 [(set (match_operand:SIDI 0 "arith_reg_dest")
5675 (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
5676 (clobber (reg:SI T_REG))]
5677 "TARGET_SH1"
5678 "#"
5679 "&& can_create_pseudo_p ()"
5680 [(const_int 0)]
5681 {
5682 if (<MODE>mode == SImode)
5683 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5684 else
5685 {
5686 rtx high_src = gen_highpart (SImode, operands[1]);
5687 emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5688 }
5689
5690 emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
5691 const1_rtx));
5692 DONE;
5693 })
5694
5695 (define_insn_and_split "*negabs<mode>2"
5696 [(set (match_operand:SIDI 0 "arith_reg_dest")
5697 (neg:SIDI (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))))
5698 (clobber (reg:SI T_REG))]
5699 "TARGET_SH1"
5700 "#"
5701 "&& can_create_pseudo_p ()"
5702 [(const_int 0)]
5703 {
5704 if (<MODE>mode == SImode)
5705 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5706 else
5707 {
5708 rtx high_src = gen_highpart (SImode, operands[1]);
5709 emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5710 }
5711
5712 emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
5713 const0_rtx));
5714 DONE;
5715 })
5716
5717 ;; The SH4 202 can do zero-offset branches without pipeline stalls.
5718 ;; This can be used as some kind of conditional execution, which is useful
5719 ;; for abs.
5720 ;; Actually the instruction scheduling should decide whether to use a
5721 ;; zero-offset branch or not for any generic case involving a single
5722 ;; instruction on SH4 202.
5723 (define_insn_and_split "negsi_cond"
5724 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5725 (if_then_else
5726 (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand" "M,N"))
5727 (match_operand:SI 1 "arith_reg_operand" "0,0")
5728 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
5729 "TARGET_SH1 && TARGET_ZDCBRANCH"
5730 {
5731 static const char* alt[] =
5732 {
5733 "bt 0f" "\n"
5734 " neg %2,%0" "\n"
5735 "0:",
5736
5737 "bf 0f" "\n"
5738 " neg %2,%0" "\n"
5739 "0:"
5740 };
5741 return alt[which_alternative];
5742 }
5743 "TARGET_SH1 && ! TARGET_ZDCBRANCH"
5744 [(const_int 0)]
5745 {
5746 rtx skip_neg_label = gen_label_rtx ();
5747
5748 emit_move_insn (operands[0], operands[1]);
5749
5750 emit_jump_insn (INTVAL (operands[3])
5751 ? gen_branch_true (skip_neg_label)
5752 : gen_branch_false (skip_neg_label));
5753
5754 emit_label_after (skip_neg_label,
5755 emit_insn (gen_negsi2 (operands[0], operands[1])));
5756 DONE;
5757 }
5758 [(set_attr "type" "arith") ;; poor approximation
5759 (set_attr "length" "4")])
5760
5761 (define_insn_and_split "negdi_cond"
5762 [(set (match_operand:DI 0 "arith_reg_dest")
5763 (if_then_else
5764 (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand"))
5765 (match_operand:DI 1 "arith_reg_operand")
5766 (neg:DI (match_operand:DI 2 "arith_reg_operand"))))
5767 (clobber (reg:SI T_REG))]
5768 "TARGET_SH1"
5769 "#"
5770 "&& can_create_pseudo_p ()"
5771 [(const_int 0)]
5772 {
5773 rtx skip_neg_label = gen_label_rtx ();
5774
5775 emit_move_insn (operands[0], operands[1]);
5776
5777 emit_jump_insn (INTVAL (operands[3])
5778 ? gen_branch_true (skip_neg_label)
5779 : gen_branch_false (skip_neg_label));
5780
5781 if (!INTVAL (operands[3]))
5782 emit_insn (gen_clrt ());
5783
5784 emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
5785 gen_lowpart (SImode, operands[1])));
5786 emit_label_after (skip_neg_label,
5787 emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
5788 gen_highpart (SImode, operands[1]))));
5789 DONE;
5790 })
5791
5792 (define_expand "bswapsi2"
5793 [(set (match_operand:SI 0 "arith_reg_dest" "")
5794 (bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))]
5795 "TARGET_SH1"
5796 {
5797 if (! can_create_pseudo_p ())
5798 FAIL;
5799 else
5800 {
5801 rtx tmp0 = gen_reg_rtx (SImode);
5802 rtx tmp1 = gen_reg_rtx (SImode);
5803
5804 emit_insn (gen_swapbsi2 (tmp0, operands[1]));
5805 emit_insn (gen_rotlsi3_16 (tmp1, tmp0));
5806 emit_insn (gen_swapbsi2 (operands[0], tmp1));
5807 DONE;
5808 }
5809 })
5810
5811 (define_insn "swapbsi2"
5812 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5813 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
5814 (const_int 4294901760))
5815 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5816 (const_int 65280))
5817 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5818 (const_int 255)))))]
5819 "TARGET_SH1"
5820 "swap.b %1,%0"
5821 [(set_attr "type" "arith")])
5822
5823 ;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying
5824 ;; partial byte swap expressions such as...
5825 ;; ((x & 0xFF) << 8) | ((x >> 8) & 0xFF).
5826 ;; ...which are currently not handled by the tree optimizers.
5827 ;; The combine pass will not initially try to combine the full expression,
5828 ;; but only some sub-expressions. In such a case the *swapbisi2_and_shl8
5829 ;; pattern acts as an intermediate pattern that will eventually lead combine
5830 ;; to the swapbsi2 pattern above.
5831 ;; As a side effect this also improves code that does (x & 0xFF) << 8
5832 ;; or (x << 8) & 0xFF00.
5833 (define_insn_and_split "*swapbisi2_and_shl8"
5834 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5835 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5836 (const_int 8))
5837 (const_int 65280))
5838 (match_operand:SI 2 "arith_reg_operand" "r")))]
5839 "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5840 "#"
5841 "&& can_create_pseudo_p ()"
5842 [(const_int 0)]
5843 {
5844 rtx tmp0 = gen_reg_rtx (SImode);
5845 rtx tmp1 = gen_reg_rtx (SImode);
5846
5847 emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1])));
5848 emit_insn (gen_swapbsi2 (tmp1, tmp0));
5849 emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2]));
5850 DONE;
5851 })
5852
5853 ;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another
5854 ;; intermediate pattern that will help the combine pass arriving at swapbsi2.
5855 (define_insn_and_split "*swapbhisi2"
5856 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5857 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5858 (const_int 8))
5859 (const_int 65280))
5860 (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))]
5861 "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5862 "#"
5863 "&& can_create_pseudo_p ()"
5864 [(const_int 0)]
5865 {
5866 rtx tmp = gen_reg_rtx (SImode);
5867
5868 emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1])));
5869 emit_insn (gen_swapbsi2 (operands[0], tmp));
5870 DONE;
5871 })
5872
5873 ;; In some cases the swapbsi2 pattern might leave a sequence such as...
5874 ;; swap.b r4,r4
5875 ;; mov r4,r0
5876 ;;
5877 ;; which can be simplified to...
5878 ;; swap.b r4,r0
5879 (define_peephole2
5880 [(set (match_operand:SI 0 "arith_reg_dest" "")
5881 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5882 (const_int 4294901760))
5883 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5884 (const_int 65280))
5885 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5886 (const_int 255)))))
5887 (set (match_operand:SI 2 "arith_reg_dest" "")
5888 (match_dup 0))]
5889 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
5890 [(set (match_dup 2)
5891 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5892 (const_int 4294901760))
5893 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5894 (const_int 65280))
5895 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5896 (const_int 255)))))])
5897 \f
5898 ;; -------------------------------------------------------------------------
5899 ;; Zero extension instructions
5900 ;; -------------------------------------------------------------------------
5901
5902 (define_insn "zero_extendsidi2"
5903 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5904 (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
5905 "TARGET_SHMEDIA"
5906 "addz.l %1, r63, %0"
5907 [(set_attr "type" "arith_media")
5908 (set_attr "highpart" "extend")])
5909
5910 (define_insn "zero_extendhidi2"
5911 [(set (match_operand:DI 0 "register_operand" "=r,r")
5912 (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5913 "TARGET_SHMEDIA"
5914 "@
5915 #
5916 ld%M1.uw %m1, %0"
5917 [(set_attr "type" "*,load_media")
5918 (set (attr "highpart")
5919 (cond [(match_test "sh_contains_memref_p (insn)")
5920 (const_string "user")]
5921 (const_string "ignore")))])
5922
5923 (define_split
5924 [(set (match_operand:DI 0 "register_operand" "")
5925 (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
5926 "TARGET_SHMEDIA && reload_completed"
5927 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
5928 (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
5929 {
5930 if (GET_CODE (operands[1]) == TRUNCATE)
5931 operands[1] = XEXP (operands[1], 0);
5932 })
5933
5934 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
5935 ;; reload the entire truncate expression.
5936 (define_insn_and_split "*loaddi_trunc"
5937 [(set (match_operand 0 "any_register_operand" "=r")
5938 (truncate (match_operand:DI 1 "memory_operand" "m")))]
5939 "TARGET_SHMEDIA && reload_completed"
5940 "#"
5941 "TARGET_SHMEDIA && reload_completed"
5942 [(set (match_dup 0) (match_dup 1))]
5943 {
5944 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
5945 })
5946
5947 (define_insn "zero_extendqidi2"
5948 [(set (match_operand:DI 0 "register_operand" "=r,r")
5949 (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5950 "TARGET_SHMEDIA"
5951 "@
5952 andi %1, 255, %0
5953 ld%M1.ub %m1, %0"
5954 [(set_attr "type" "arith_media,load_media")
5955 (set (attr "highpart")
5956 (cond [(match_test "sh_contains_memref_p (insn)")
5957 (const_string "user")]
5958 (const_string "ignore")))])
5959
5960 (define_expand "zero_extend<mode>si2"
5961 [(set (match_operand:SI 0 "arith_reg_dest")
5962 (zero_extend:SI (match_operand:QIHI 1 "zero_extend_operand")))])
5963
5964 (define_insn_and_split "*zero_extend<mode>si2_compact"
5965 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5966 (zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
5967 "TARGET_SH1"
5968 "extu.<bw> %1,%0"
5969 "&& can_create_pseudo_p ()"
5970 [(set (match_dup 0) (match_dup 2))]
5971 {
5972 /* Sometimes combine fails to combine a T bit or negated T bit store to a
5973 reg with a following zero extension. In the split pass after combine,
5974 try to figure out how the extended reg was set. If it originated from
5975 the T bit we can replace the zero extension with a reg move, which will
5976 be eliminated. Notice that this also helps the *cbranch_t splitter when
5977 it tries to post-combine tests and conditional branches, as it does not
5978 check for zero extensions. */
5979 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
5980 if (operands[2] == NULL_RTX)
5981 FAIL;
5982 }
5983 [(set_attr "type" "arith")])
5984
5985 (define_insn "*zero_extendhisi2_media"
5986 [(set (match_operand:SI 0 "register_operand" "=r,r")
5987 (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5988 "TARGET_SHMEDIA"
5989 "@
5990 #
5991 ld%M1.uw %m1, %0"
5992 [(set_attr "type" "arith_media,load_media")
5993 (set (attr "highpart")
5994 (cond [(match_test "sh_contains_memref_p (insn)")
5995 (const_string "user")]
5996 (const_string "ignore")))])
5997
5998 (define_split
5999 [(set (match_operand:SI 0 "register_operand" "")
6000 (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6001 "TARGET_SHMEDIA && reload_completed"
6002 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6003 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
6004 {
6005 rtx op1 = operands[1];
6006
6007 if (GET_CODE (op1) == TRUNCATE)
6008 op1 = XEXP (op1, 0);
6009 operands[2]
6010 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6011 subreg_lowpart_offset (SImode, GET_MODE (op1)));
6012 })
6013
6014 (define_insn "*zero_extendqisi2_media"
6015 [(set (match_operand:SI 0 "register_operand" "=r,r")
6016 (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6017 "TARGET_SHMEDIA"
6018 "@
6019 andi %1, 255, %0
6020 ld%M1.ub %m1, %0"
6021 [(set_attr "type" "arith_media,load_media")
6022 (set (attr "highpart")
6023 (cond [(match_test "sh_contains_memref_p (insn)")
6024 (const_string "user")]
6025 (const_string "ignore")))])
6026
6027 (define_insn "zero_extendqihi2"
6028 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6029 (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6030 "TARGET_SH1"
6031 "extu.b %1,%0"
6032 [(set_attr "type" "arith")])
6033
6034 ;; SH2A supports two zero extending load instructions: movu.b and movu.w.
6035 ;; They could also be used for simple memory addresses like @Rn by setting
6036 ;; the displacement value to zero. However, doing so too early results in
6037 ;; missed opportunities for other optimizations such as post-inc or index
6038 ;; addressing loads.
6039 ;; Although the 'zero_extend_movu_operand' predicate does not allow simple
6040 ;; register addresses (an address without a displacement, index, post-inc),
6041 ;; zero-displacement addresses might be generated during reload, wich are
6042 ;; simplified to simple register addresses in turn. Thus, we have to
6043 ;; provide the Sdd and Sra alternatives in the patterns.
6044 (define_insn "*zero_extend<mode>si2_disp_mem"
6045 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
6046 (zero_extend:SI
6047 (match_operand:QIHI 1 "zero_extend_movu_operand" "Sdd,Sra")))]
6048 "TARGET_SH2A"
6049 "@
6050 movu.<bw> %1,%0
6051 movu.<bw> @(0,%t1),%0"
6052 [(set_attr "type" "load")
6053 (set_attr "length" "4")])
6054
6055 ;; Convert the zero extending loads in sequences such as:
6056 ;; movu.b @(1,r5),r0 movu.w @(2,r5),r0
6057 ;; mov.b r0,@(1,r4) mov.b r0,@(1,r4)
6058 ;;
6059 ;; back to sign extending loads like:
6060 ;; mov.b @(1,r5),r0 mov.w @(2,r5),r0
6061 ;; mov.b r0,@(1,r4) mov.b r0,@(1,r4)
6062 ;;
6063 ;; if the extension type is irrelevant. The sign extending mov.{b|w} insn
6064 ;; is only 2 bytes in size if the displacement is {K04|K05}.
6065 ;; If the displacement is greater it doesn't matter, so we convert anyways.
6066 (define_peephole2
6067 [(set (match_operand:SI 0 "arith_reg_dest" "")
6068 (zero_extend:SI (match_operand 1 "displacement_mem_operand" "")))
6069 (set (match_operand 2 "nonimmediate_operand" "")
6070 (match_operand 3 "arith_reg_operand" ""))]
6071 "TARGET_SH2A
6072 && REGNO (operands[0]) == REGNO (operands[3])
6073 && peep2_reg_dead_p (2, operands[0])
6074 && GET_MODE_SIZE (GET_MODE (operands[2]))
6075 <= GET_MODE_SIZE (GET_MODE (operands[1]))"
6076 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
6077 (set (match_dup 2) (match_dup 3))])
6078
6079 ;; Fold sequences such as
6080 ;; mov.b @r3,r7
6081 ;; extu.b r7,r7
6082 ;; into
6083 ;; movu.b @(0,r3),r7
6084 ;; This does not reduce the code size but the number of instructions is
6085 ;; halved, which results in faster code.
6086 (define_peephole2
6087 [(set (match_operand:SI 0 "arith_reg_dest" "")
6088 (sign_extend:SI (match_operand 1 "simple_mem_operand" "")))
6089 (set (match_operand:SI 2 "arith_reg_dest" "")
6090 (zero_extend:SI (match_operand 3 "arith_reg_operand" "")))]
6091 "TARGET_SH2A
6092 && GET_MODE (operands[1]) == GET_MODE (operands[3])
6093 && (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode)
6094 && REGNO (operands[0]) == REGNO (operands[3])
6095 && (REGNO (operands[2]) == REGNO (operands[0])
6096 || peep2_reg_dead_p (2, operands[0]))"
6097 [(set (match_dup 2) (zero_extend:SI (match_dup 4)))]
6098 {
6099 operands[4]
6100 = replace_equiv_address (operands[1],
6101 gen_rtx_PLUS (SImode, XEXP (operands[1], 0),
6102 const0_rtx));
6103 })
6104
6105 ;; -------------------------------------------------------------------------
6106 ;; Sign extension instructions
6107 ;; -------------------------------------------------------------------------
6108
6109 ;; ??? This should be a define expand.
6110 ;; ??? Or perhaps it should be dropped?
6111
6112 ;; convert_move generates good code for SH[1-4].
6113 (define_insn "extendsidi2"
6114 [(set (match_operand:DI 0 "register_operand" "=r,r,r")
6115 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
6116 "TARGET_SHMEDIA"
6117 "@
6118 add.l %1, r63, %0
6119 ld%M1.l %m1, %0
6120 fmov.sl %1, %0"
6121 [(set_attr "type" "arith_media,load_media,fpconv_media")
6122 (set (attr "highpart")
6123 (cond [(match_test "sh_contains_memref_p (insn)")
6124 (const_string "user")]
6125 (const_string "extend")))])
6126
6127 (define_insn "extendhidi2"
6128 [(set (match_operand:DI 0 "register_operand" "=r,r")
6129 (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6130 "TARGET_SHMEDIA"
6131 "@
6132 #
6133 ld%M1.w %m1, %0"
6134 [(set_attr "type" "*,load_media")
6135 (set (attr "highpart")
6136 (cond [(match_test "sh_contains_memref_p (insn)")
6137 (const_string "user")]
6138 (const_string "ignore")))])
6139
6140 (define_split
6141 [(set (match_operand:DI 0 "register_operand" "")
6142 (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
6143 "TARGET_SHMEDIA && reload_completed"
6144 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
6145 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
6146 {
6147 if (GET_CODE (operands[1]) == TRUNCATE)
6148 operands[1] = XEXP (operands[1], 0);
6149 })
6150
6151 (define_insn "extendqidi2"
6152 [(set (match_operand:DI 0 "register_operand" "=r,r")
6153 (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6154 "TARGET_SHMEDIA"
6155 "@
6156 #
6157 ld%M1.b %m1, %0"
6158 [(set_attr "type" "*,load_media")
6159 (set (attr "highpart")
6160 (cond [(match_test "sh_contains_memref_p (insn)")
6161 (const_string "user")]
6162 (const_string "ignore")))])
6163
6164 (define_split
6165 [(set (match_operand:DI 0 "register_operand" "")
6166 (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
6167 "TARGET_SHMEDIA && reload_completed"
6168 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
6169 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
6170 {
6171 if (GET_CODE (operands[1]) == TRUNCATE)
6172 operands[1] = XEXP (operands[1], 0);
6173 })
6174
6175 (define_expand "extend<mode>si2"
6176 [(set (match_operand:SI 0 "arith_reg_dest")
6177 (sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))])
6178
6179 (define_insn "*extendhisi2_media"
6180 [(set (match_operand:SI 0 "register_operand" "=r,r")
6181 (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6182 "TARGET_SHMEDIA"
6183 "@
6184 #
6185 ld%M1.w %m1, %0"
6186 [(set_attr "type" "arith_media,load_media")
6187 (set (attr "highpart")
6188 (cond [(match_test "sh_contains_memref_p (insn)")
6189 (const_string "user")]
6190 (const_string "ignore")))])
6191
6192 (define_split
6193 [(set (match_operand:SI 0 "register_operand" "")
6194 (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6195 "TARGET_SHMEDIA && reload_completed"
6196 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6197 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
6198 {
6199 rtx op1 = operands[1];
6200 if (GET_CODE (op1) == TRUNCATE)
6201 op1 = XEXP (op1, 0);
6202 operands[2]
6203 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6204 subreg_lowpart_offset (SImode, GET_MODE (op1)));
6205 })
6206
6207 (define_insn_and_split "*extend<mode>si2_compact_reg"
6208 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6209 (sign_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
6210 "TARGET_SH1"
6211 "exts.<bw> %1,%0"
6212 "&& can_create_pseudo_p ()"
6213 [(set (match_dup 0) (match_dup 2))]
6214 {
6215 /* Sometimes combine fails to combine a T bit or negated T bit store to a
6216 reg with a following sign extension. In the split pass after combine,
6217 try to figure the extended reg was set. If it originated from the T
6218 bit we can replace the sign extension with a reg move, which will be
6219 eliminated. */
6220 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
6221 if (operands[2] == NULL_RTX)
6222 FAIL;
6223 }
6224 [(set_attr "type" "arith")])
6225
6226 ;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute.
6227 ;; See movqi insns.
6228 (define_insn "*extend<mode>si2_compact_mem_disp"
6229 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
6230 (sign_extend:SI
6231 (mem:QIHI
6232 (plus:SI
6233 (match_operand:SI 1 "arith_reg_operand" "%r,r")
6234 (match_operand:SI 2 "const_int_operand" "<disp04>,N")))))]
6235 "TARGET_SH1 && ! TARGET_SH2A
6236 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
6237 "@
6238 mov.<bw> @(%O2,%1),%0
6239 mov.<bw> @%1,%0"
6240 [(set_attr "type" "load")])
6241
6242 (define_insn "*extend<mode>si2_compact_mem_disp"
6243 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
6244 (sign_extend:SI
6245 (mem:QIHI
6246 (plus:SI
6247 (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6248 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>")))))]
6249 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
6250 "@
6251 mov.<bw> @(%O2,%1),%0
6252 mov.<bw> @%1,%0
6253 mov.<bw> @(%O2,%1),%0"
6254 [(set_attr "type" "load")
6255 (set_attr "length" "2,2,4")])
6256
6257 ;; The *_snd patterns will take care of other QImode/HImode addressing
6258 ;; modes than displacement addressing. They must be defined _after_ the
6259 ;; displacement addressing patterns. Otherwise the displacement addressing
6260 ;; patterns will not be picked.
6261 (define_insn "*extend<mode>si2_compact_snd"
6262 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6263 (sign_extend:SI
6264 (match_operand:QIHI 1 "movsrc_no_disp_mem_operand" "Snd")))]
6265 "TARGET_SH1"
6266 "mov.<bw> %1,%0"
6267 [(set_attr "type" "load")])
6268
6269 (define_insn "*extendqisi2_media"
6270 [(set (match_operand:SI 0 "register_operand" "=r,r")
6271 (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6272 "TARGET_SHMEDIA"
6273 "@
6274 #
6275 ld%M1.b %m1, %0"
6276 [(set_attr "type" "arith_media,load_media")
6277 (set (attr "highpart")
6278 (cond [(match_test "sh_contains_memref_p (insn)")
6279 (const_string "user")]
6280 (const_string "ignore")))])
6281
6282 (define_split
6283 [(set (match_operand:SI 0 "register_operand" "")
6284 (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
6285 "TARGET_SHMEDIA && reload_completed"
6286 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
6287 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
6288 {
6289 rtx op1 = operands[1];
6290 if (GET_CODE (op1) == TRUNCATE)
6291 op1 = XEXP (op1, 0);
6292 operands[2]
6293 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6294 subreg_lowpart_offset (SImode, GET_MODE (op1)));
6295 })
6296
6297 (define_expand "extendqihi2"
6298 [(set (match_operand:HI 0 "arith_reg_dest" "")
6299 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "")))]
6300 ""
6301 "")
6302
6303 (define_insn "*extendqihi2_compact_reg"
6304 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6305 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6306 "TARGET_SH1"
6307 "exts.b %1,%0"
6308 [(set_attr "type" "arith")])
6309
6310 ;; It would seem useful to combine the truncXi patterns into the movXi
6311 ;; patterns, but unary operators are ignored when matching constraints,
6312 ;; so we need separate patterns.
6313 (define_insn "truncdisi2"
6314 [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
6315 (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
6316 "TARGET_SHMEDIA"
6317 "@
6318 add.l %1, r63, %0
6319 st%M0.l %m0, %1
6320 fst%M0.s %m0, %T1
6321 fmov.ls %1, %0
6322 fmov.sl %T1, %0
6323 fmov.s %T1, %0"
6324 [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,
6325 fpconv_media,fmove_media")
6326 (set (attr "highpart")
6327 (cond [(match_test "sh_contains_memref_p (insn)")
6328 (const_string "user")]
6329 (const_string "extend")))])
6330
6331 (define_insn "truncdihi2"
6332 [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
6333 (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
6334 "TARGET_SHMEDIA"
6335 {
6336 static const char* alt[] =
6337 {
6338 "shlli %1,48,%0" "\n"
6339 " shlri %0,48,%0",
6340
6341 "st%M0.w %m0, %1"
6342 };
6343 return alt[which_alternative];
6344 }
6345 [(set_attr "type" "arith_media,store_media")
6346 (set_attr "length" "8,4")
6347 (set (attr "highpart")
6348 (cond [(match_test "sh_contains_memref_p (insn)")
6349 (const_string "user")]
6350 (const_string "extend")))])
6351
6352 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
6353 ; Because we use zero extension, we can't provide signed QImode compares
6354 ; using a simple compare or conditional branch insn.
6355 (define_insn "truncdiqi2"
6356 [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
6357 (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
6358 "TARGET_SHMEDIA"
6359 "@
6360 andi %1, 255, %0
6361 st%M0.b %m0, %1"
6362 [(set_attr "type" "arith_media,store")
6363 (set (attr "highpart")
6364 (cond [(match_test "sh_contains_memref_p (insn)")
6365 (const_string "user")]
6366 (const_string "extend")))])
6367
6368 ;; -------------------------------------------------------------------------
6369 ;; Move instructions
6370 ;; -------------------------------------------------------------------------
6371
6372 ;; define push and pop so it is easy for sh.c
6373 ;; We can't use push and pop on SHcompact because the stack must always
6374 ;; be 8-byte aligned.
6375 (define_expand "push"
6376 [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
6377 (match_operand:SI 0 "register_operand" "r,l,x"))]
6378 "TARGET_SH1 && ! TARGET_SH5"
6379 "")
6380
6381 (define_expand "pop"
6382 [(set (match_operand:SI 0 "register_operand" "=r,l,x")
6383 (mem:SI (post_inc:SI (reg:SI SP_REG))))]
6384 "TARGET_SH1 && ! TARGET_SH5"
6385 "")
6386
6387 (define_expand "push_e"
6388 [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
6389 (match_operand:SF 0 "" ""))
6390 (use (reg:PSI FPSCR_REG))
6391 (clobber (scratch:SI))])]
6392 "TARGET_SH1 && ! TARGET_SH5"
6393 "")
6394
6395 (define_insn "push_fpul"
6396 [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
6397 "TARGET_SH2E && ! TARGET_SH5"
6398 "sts.l fpul,@-r15"
6399 [(set_attr "type" "fstore")
6400 (set_attr "late_fp_use" "yes")
6401 (set_attr "hit_stack" "yes")])
6402
6403 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
6404 ;; so use that.
6405 (define_expand "push_4"
6406 [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
6407 (match_operand:DF 0 "" ""))
6408 (use (reg:PSI FPSCR_REG))
6409 (clobber (scratch:SI))])]
6410 "TARGET_SH1 && ! TARGET_SH5"
6411 "")
6412
6413 (define_expand "pop_e"
6414 [(parallel [(set (match_operand:SF 0 "" "")
6415 (mem:SF (post_inc:SI (reg:SI SP_REG))))
6416 (use (reg:PSI FPSCR_REG))
6417 (clobber (scratch:SI))])]
6418 "TARGET_SH1 && ! TARGET_SH5"
6419 "")
6420
6421 (define_insn "pop_fpul"
6422 [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
6423 "TARGET_SH2E && ! TARGET_SH5"
6424 "lds.l @r15+,fpul"
6425 [(set_attr "type" "load")
6426 (set_attr "hit_stack" "yes")])
6427
6428 (define_expand "pop_4"
6429 [(parallel [(set (match_operand:DF 0 "" "")
6430 (mem:DF (post_inc:SI (reg:SI SP_REG))))
6431 (use (reg:PSI FPSCR_REG))
6432 (clobber (scratch:SI))])]
6433 "TARGET_SH1 && ! TARGET_SH5"
6434 "")
6435
6436 (define_expand "push_fpscr"
6437 [(const_int 0)]
6438 "TARGET_SH2E"
6439 {
6440 rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
6441 gen_rtx_PRE_DEC (Pmode,
6442 stack_pointer_rtx)),
6443 get_fpscr_rtx ()));
6444 add_reg_note (insn, REG_INC, stack_pointer_rtx);
6445 DONE;
6446 })
6447
6448 (define_expand "pop_fpscr"
6449 [(const_int 0)]
6450 "TARGET_SH2E"
6451 {
6452 rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
6453 gen_frame_mem (PSImode,
6454 gen_rtx_POST_INC (Pmode,
6455 stack_pointer_rtx))));
6456 add_reg_note (insn, REG_INC, stack_pointer_rtx);
6457 DONE;
6458 })
6459
6460 ;; The clrt and sett patterns can happen as the result of optimization and
6461 ;; insn expansion.
6462 ;; Comparisons might get simplified to a move of zero or 1 into the T reg.
6463 ;; In this case they might not disappear completely, because the T reg is
6464 ;; a fixed hard reg.
6465 ;; When DImode operations that use the T reg as carry/borrow are split into
6466 ;; individual SImode operations, the T reg is usually cleared before the
6467 ;; first SImode insn.
6468 (define_insn "clrt"
6469 [(set (reg:SI T_REG) (const_int 0))]
6470 "TARGET_SH1"
6471 "clrt"
6472 [(set_attr "type" "mt_group")])
6473
6474 (define_insn "sett"
6475 [(set (reg:SI T_REG) (const_int 1))]
6476 "TARGET_SH1"
6477 "sett"
6478 [(set_attr "type" "mt_group")])
6479
6480 ;; Use the combine pass to transform sequences such as
6481 ;; mov r5,r0
6482 ;; add #1,r0
6483 ;; shll2 r0
6484 ;; mov.l @(r0,r4),r0
6485 ;; into
6486 ;; shll2 r5
6487 ;; add r4,r5
6488 ;; mov.l @(4,r5),r0
6489 ;;
6490 ;; See also PR 39423.
6491 ;; Notice that these patterns have a T_REG clobber, because the shift
6492 ;; sequence that will be split out might clobber the T_REG. Ideally, the
6493 ;; clobber would be added conditionally, depending on the result of
6494 ;; sh_ashlsi_clobbers_t_reg_p. When splitting out the shifts we must go
6495 ;; through the ashlsi3 expander in order to get the right shift insn --
6496 ;; a T_REG clobbering or non-clobbering shift sequence or dynamic shift.
6497 ;; FIXME: Combine never tries this kind of patterns for DImode.
6498 (define_insn_and_split "*movsi_index_disp_load"
6499 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6500 (match_operand:SI 1 "mem_index_disp_operand" "m"))
6501 (clobber (reg:SI T_REG))]
6502 "TARGET_SH1"
6503 "#"
6504 "&& can_create_pseudo_p ()"
6505 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6506 (set (match_dup 0) (match_dup 7))]
6507 {
6508 rtx mem = operands[1];
6509 rtx plus0_rtx = XEXP (mem, 0);
6510 rtx plus1_rtx = XEXP (plus0_rtx, 0);
6511 rtx mult_rtx = XEXP (plus1_rtx, 0);
6512
6513 operands[1] = XEXP (mult_rtx, 0);
6514 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6515 operands[3] = XEXP (plus1_rtx, 1);
6516 operands[4] = XEXP (plus0_rtx, 1);
6517 operands[5] = gen_reg_rtx (SImode);
6518 operands[6] = gen_reg_rtx (SImode);
6519 operands[7] =
6520 replace_equiv_address (mem,
6521 gen_rtx_PLUS (SImode, operands[6], operands[4]));
6522
6523 emit_insn (gen_ashlsi3 (operands[5], operands[1], operands[2]));
6524 })
6525
6526 (define_insn_and_split "*movhi_index_disp_load"
6527 [(set (match_operand:SI 0 "arith_reg_dest")
6528 (SZ_EXTEND:SI (match_operand:HI 1 "mem_index_disp_operand")))
6529 (clobber (reg:SI T_REG))]
6530 "TARGET_SH1"
6531 "#"
6532 "&& can_create_pseudo_p ()"
6533 [(const_int 0)]
6534 {
6535 rtx mem = operands[1];
6536 rtx plus0_rtx = XEXP (mem, 0);
6537 rtx plus1_rtx = XEXP (plus0_rtx, 0);
6538 rtx mult_rtx = XEXP (plus1_rtx, 0);
6539
6540 rtx op_1 = XEXP (mult_rtx, 0);
6541 rtx op_2 = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6542 rtx op_3 = XEXP (plus1_rtx, 1);
6543 rtx op_4 = XEXP (plus0_rtx, 1);
6544 rtx op_5 = gen_reg_rtx (SImode);
6545 rtx op_6 = gen_reg_rtx (SImode);
6546 rtx op_7 = replace_equiv_address (mem, gen_rtx_PLUS (SImode, op_6, op_4));
6547
6548 emit_insn (gen_ashlsi3 (op_5, op_1, op_2));
6549 emit_insn (gen_addsi3 (op_6, op_5, op_3));
6550
6551 if (<CODE> == SIGN_EXTEND)
6552 {
6553 emit_insn (gen_extendhisi2 (operands[0], op_7));
6554 DONE;
6555 }
6556 else if (<CODE> == ZERO_EXTEND)
6557 {
6558 /* On SH2A the movu.w insn can be used for zero extending loads. */
6559 if (TARGET_SH2A)
6560 emit_insn (gen_zero_extendhisi2 (operands[0], op_7));
6561 else
6562 {
6563 emit_insn (gen_extendhisi2 (operands[0], op_7));
6564 emit_insn (gen_zero_extendhisi2 (operands[0],
6565 gen_lowpart (HImode, operands[0])));
6566 }
6567 DONE;
6568 }
6569 else
6570 FAIL;
6571 })
6572
6573 (define_insn_and_split "*mov<mode>_index_disp_store"
6574 [(set (match_operand:HISI 0 "mem_index_disp_operand" "=m")
6575 (match_operand:HISI 1 "arith_reg_operand" "r"))
6576 (clobber (reg:SI T_REG))]
6577 "TARGET_SH1"
6578 "#"
6579 "&& can_create_pseudo_p ()"
6580 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6581 (set (match_dup 7) (match_dup 1))]
6582 {
6583 rtx mem = operands[0];
6584 rtx plus0_rtx = XEXP (mem, 0);
6585 rtx plus1_rtx = XEXP (plus0_rtx, 0);
6586 rtx mult_rtx = XEXP (plus1_rtx, 0);
6587
6588 operands[0] = XEXP (mult_rtx, 0);
6589 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6590 operands[3] = XEXP (plus1_rtx, 1);
6591 operands[4] = XEXP (plus0_rtx, 1);
6592 operands[5] = gen_reg_rtx (SImode);
6593 operands[6] = gen_reg_rtx (SImode);
6594 operands[7] =
6595 replace_equiv_address (mem,
6596 gen_rtx_PLUS (SImode, operands[6], operands[4]));
6597
6598 emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2]));
6599 })
6600
6601 ;; t/r must come after r/r, lest reload will try to reload stuff like
6602 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
6603 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
6604 (define_insn "movsi_i"
6605 [(set (match_operand:SI 0 "general_movdst_operand"
6606 "=r,r,r,r,r,r,m,<,<,x,l,x,l,r")
6607 (match_operand:SI 1 "general_movsrc_operand"
6608 "Q,r,I08,mr,x,l,r,x,l,r,r,>,>,i"))]
6609 "TARGET_SH1
6610 && ! TARGET_SH2E
6611 && ! TARGET_SH2A
6612 && (register_operand (operands[0], SImode)
6613 || register_operand (operands[1], SImode))"
6614 "@
6615 mov.l %1,%0
6616 mov %1,%0
6617 mov %1,%0
6618 mov.l %1,%0
6619 sts %1,%0
6620 sts %1,%0
6621 mov.l %1,%0
6622 sts.l %1,%0
6623 sts.l %1,%0
6624 lds %1,%0
6625 lds %1,%0
6626 lds.l %1,%0
6627 lds.l %1,%0
6628 fake %1,%0"
6629 [(set_attr "type" "pcload_si,move,movi8,load_si,mac_gp,prget,store,mac_mem,
6630 pstore,gp_mac,prset,mem_mac,pload,pcload_si")
6631 (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
6632
6633 ;; t/r must come after r/r, lest reload will try to reload stuff like
6634 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
6635 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
6636 ;; will require a reload.
6637 ;; ??? We can't include f/f because we need the proper FPSCR setting when
6638 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
6639 (define_insn "movsi_ie"
6640 [(set (match_operand:SI 0 "general_movdst_operand"
6641 "=r,r,r,r,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
6642 (match_operand:SI 1 "general_movsrc_operand"
6643 "Q,r,I08,I20,I28,mr,x,l,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
6644 "(TARGET_SH2E || TARGET_SH2A)
6645 && (register_operand (operands[0], SImode)
6646 || register_operand (operands[1], SImode))"
6647 "@
6648 mov.l %1,%0
6649 mov %1,%0
6650 mov %1,%0
6651 movi20 %1,%0
6652 movi20s %1,%0
6653 mov.l %1,%0
6654 sts %1,%0
6655 sts %1,%0
6656 mov.l %1,%0
6657 sts.l %1,%0
6658 sts.l %1,%0
6659 lds %1,%0
6660 lds %1,%0
6661 lds.l %1,%0
6662 lds.l %1,%0
6663 lds.l %1,%0
6664 sts.l %1,%0
6665 fake %1,%0
6666 lds %1,%0
6667 sts %1,%0
6668 fsts fpul,%0
6669 flds %1,fpul
6670 fmov %1,%0
6671 ! move optimized away"
6672 [(set_attr "type" "pcload_si,move,movi8,move,move,load_si,mac_gp,prget,store,
6673 mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore,
6674 pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
6675 (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
6676 (set_attr_alternative "length"
6677 [(const_int 2)
6678 (const_int 2)
6679 (const_int 2)
6680 (const_int 4)
6681 (const_int 4)
6682 (if_then_else
6683 (match_test "TARGET_SH2A")
6684 (const_int 4) (const_int 2))
6685 (const_int 2)
6686 (const_int 2)
6687 (if_then_else
6688 (match_test "TARGET_SH2A")
6689 (const_int 4) (const_int 2))
6690 (const_int 2)
6691 (const_int 2)
6692 (const_int 2)
6693 (const_int 2)
6694 (const_int 2)
6695 (const_int 2)
6696 (const_int 2)
6697 (const_int 2)
6698 (const_int 2)
6699 (const_int 2)
6700 (const_int 2)
6701 (const_int 2)
6702 (const_int 2)
6703 (const_int 2)
6704 (const_int 0)])])
6705
6706 (define_insn "movsi_i_lowpart"
6707 [(set (strict_low_part
6708 (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
6709 (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,r,i"))]
6710 "TARGET_SH1
6711 && (register_operand (operands[0], SImode)
6712 || register_operand (operands[1], SImode))"
6713 "@
6714 mov.l %1,%0
6715 mov %1,%0
6716 mov %1,%0
6717 mov.l %1,%0
6718 sts %1,%0
6719 sts %1,%0
6720 mov.l %1,%0
6721 fake %1,%0"
6722 [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,store,pcload")])
6723
6724 (define_insn_and_split "load_ra"
6725 [(set (match_operand:SI 0 "general_movdst_operand" "")
6726 (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
6727 "TARGET_SH1"
6728 "#"
6729 "&& ! currently_expanding_to_rtl"
6730 [(set (match_dup 0) (match_dup 1))]
6731 {
6732 if (TARGET_SHCOMPACT && crtl->saves_all_registers)
6733 operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
6734 })
6735
6736 ;; The '?'s in the following constraints may not reflect the time taken
6737 ;; to perform the move. They are there to discourage the use of floating-
6738 ;; point registers for storing integer values.
6739 (define_insn "*movsi_media"
6740 [(set (match_operand:SI 0 "general_movdst_operand"
6741 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
6742 (match_operand:SI 1 "general_movsrc_operand"
6743 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
6744 "TARGET_SHMEDIA_FPU
6745 && (register_operand (operands[0], SImode)
6746 || sh_register_operand (operands[1], SImode)
6747 || GET_CODE (operands[1]) == TRUNCATE)"
6748 "@
6749 add.l %1, r63, %0
6750 movi %1, %0
6751 #
6752 ld%M1.l %m1, %0
6753 st%M0.l %m0, %N1
6754 fld%M1.s %m1, %0
6755 fst%M0.s %m0, %1
6756 fmov.ls %N1, %0
6757 fmov.sl %1, %0
6758 fmov.s %1, %0
6759 ptabs %1, %0
6760 gettr %1, %0
6761 pt %1, %0"
6762 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
6763 fload_media,fstore_media,fload_media,fpconv_media,
6764 fmove_media,ptabs_media,gettr_media,pt_media")
6765 (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
6766 (set (attr "highpart")
6767 (cond [(match_test "sh_contains_memref_p (insn)")
6768 (const_string "user")]
6769 (const_string "ignore")))])
6770
6771 (define_insn "*movsi_media_nofpu"
6772 [(set (match_operand:SI 0 "general_movdst_operand"
6773 "=r,r,r,r,m,*b,r,*b")
6774 (match_operand:SI 1 "general_movsrc_operand"
6775 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
6776 "TARGET_SHMEDIA
6777 && (register_operand (operands[0], SImode)
6778 || sh_register_operand (operands[1], SImode)
6779 || GET_CODE (operands[1]) == TRUNCATE)"
6780 "@
6781 add.l %1, r63, %0
6782 movi %1, %0
6783 #
6784 ld%M1.l %m1, %0
6785 st%M0.l %m0, %N1
6786 ptabs %1, %0
6787 gettr %1, %0
6788 pt %1, %0"
6789 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
6790 ptabs_media,gettr_media,pt_media")
6791 (set_attr "length" "4,4,8,4,4,4,4,12")
6792 (set (attr "highpart")
6793 (cond [(match_test "sh_contains_memref_p (insn)")
6794 (const_string "user")]
6795 (const_string "ignore")))])
6796
6797 (define_expand "movsi_const"
6798 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6799 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6800 (const_int 16)] UNSPEC_EXTRACT_S16)))
6801 (set (match_dup 0)
6802 (ior:SI (ashift:SI (match_dup 0) (const_int 16))
6803 (const:SI (unspec:SI [(match_dup 1)
6804 (const_int 0)] UNSPEC_EXTRACT_U16))))]
6805 "TARGET_SHMEDIA && reload_completed
6806 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6807 {
6808 if (GET_CODE (operands[1]) == LABEL_REF
6809 && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
6810 LABEL_NUSES (XEXP (operands[1], 0)) += 2;
6811 else if (GOTOFF_P (operands[1]))
6812 {
6813 rtx unspec = XEXP (operands[1], 0);
6814
6815 if (! UNSPEC_GOTOFF_P (unspec))
6816 {
6817 unspec = XEXP (unspec, 0);
6818 if (! UNSPEC_GOTOFF_P (unspec))
6819 abort ();
6820 }
6821 if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
6822 && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
6823 LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
6824 }
6825 })
6826
6827 (define_expand "movsi_const_16bit"
6828 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6829 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6830 (const_int 0)] UNSPEC_EXTRACT_S16)))]
6831 "TARGET_SHMEDIA && flag_pic && reload_completed
6832 && GET_CODE (operands[1]) == SYMBOL_REF"
6833 "")
6834
6835 (define_split
6836 [(set (match_operand:SI 0 "arith_reg_dest" "")
6837 (match_operand:SI 1 "immediate_operand" ""))]
6838 "TARGET_SHMEDIA && reload_completed
6839 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6840 [(const_int 0)]
6841 {
6842 rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
6843
6844 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
6845
6846 DONE;
6847 })
6848
6849 (define_split
6850 [(set (match_operand:SI 0 "register_operand" "")
6851 (match_operand:SI 1 "immediate_operand" ""))]
6852 "TARGET_SHMEDIA && reload_completed
6853 && ((CONST_INT_P (operands[1])
6854 && ! satisfies_constraint_I16 (operands[1]))
6855 || GET_CODE (operands[1]) == CONST_DOUBLE)"
6856 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
6857
6858 (define_expand "movsi"
6859 [(set (match_operand:SI 0 "general_movdst_operand" "")
6860 (match_operand:SI 1 "general_movsrc_operand" ""))]
6861 ""
6862 {
6863 prepare_move_operands (operands, SImode);
6864 })
6865
6866 (define_expand "ic_invalidate_line"
6867 [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
6868 (match_dup 1)] UNSPEC_ICACHE)
6869 (clobber (scratch:SI))])]
6870 "TARGET_HARD_SH4 || TARGET_SH5"
6871 {
6872 if (TARGET_SHMEDIA)
6873 {
6874 emit_insn (gen_ic_invalidate_line_media (operands[0]));
6875 DONE;
6876 }
6877 else if (TARGET_SHCOMPACT)
6878 {
6879 operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC);
6880 operands[1] = force_reg (Pmode, operands[1]);
6881 emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
6882 DONE;
6883 }
6884 else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
6885 {
6886 emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
6887 DONE;
6888 }
6889 operands[0] = force_reg (Pmode, operands[0]);
6890 operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
6891 Pmode)));
6892 })
6893
6894 ;; The address %0 is assumed to be 4-aligned at least. Thus, by ORing
6895 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
6896 ;; the requirement *1*00 for associative address writes. The alignment of
6897 ;; %0 implies that its least significant bit is cleared,
6898 ;; thus we clear the V bit of a matching entry if there is one.
6899 (define_insn "ic_invalidate_line_i"
6900 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
6901 (match_operand:SI 1 "register_operand" "r")]
6902 UNSPEC_ICACHE)
6903 (clobber (match_scratch:SI 2 "=&r"))]
6904 "TARGET_HARD_SH4"
6905 {
6906 return "ocbwb @%0" "\n"
6907 " extu.w %0,%2" "\n"
6908 " or %1,%2" "\n"
6909 " mov.l %0,@%2";
6910 }
6911 [(set_attr "length" "8")
6912 (set_attr "type" "cwb")])
6913
6914 (define_insn "ic_invalidate_line_sh4a"
6915 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
6916 UNSPEC_ICACHE)]
6917 "TARGET_SH4A_ARCH || TARGET_SH4_300"
6918 {
6919 return "ocbwb @%0" "\n"
6920 " synco" "\n"
6921 " icbi @%0";
6922 }
6923 [(set_attr "length" "16") ;; FIXME: Why 16 and not 6? Looks like typo.
6924 (set_attr "type" "cwb")])
6925
6926 ;; ??? could make arg 0 an offsettable memory operand to allow to save
6927 ;; an add in the code that calculates the address.
6928 (define_insn "ic_invalidate_line_media"
6929 [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
6930 UNSPEC_ICACHE)]
6931 "TARGET_SHMEDIA"
6932 {
6933 return "ocbwb %0,0" "\n"
6934 " synco" "\n"
6935 " icbi %0,0" "\n"
6936 " synci";
6937 }
6938 [(set_attr "length" "16")
6939 (set_attr "type" "invalidate_line_media")])
6940
6941 (define_insn "ic_invalidate_line_compact"
6942 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
6943 (match_operand:SI 1 "register_operand" "r")]
6944 UNSPEC_ICACHE)
6945 (clobber (reg:SI PR_REG))]
6946 "TARGET_SHCOMPACT"
6947 "jsr @%1%#"
6948 [(set_attr "type" "sfunc")
6949 (set_attr "needs_delay_slot" "yes")])
6950
6951 (define_expand "initialize_trampoline"
6952 [(match_operand:SI 0 "" "")
6953 (match_operand:SI 1 "" "")
6954 (match_operand:SI 2 "" "")]
6955 "TARGET_SHCOMPACT"
6956 {
6957 rtx sfun, tramp;
6958
6959 tramp = force_reg (Pmode, operands[0]);
6960 sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline",
6961 SFUNC_STATIC));
6962 emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
6963 emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
6964
6965 emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
6966 DONE;
6967 })
6968
6969 (define_insn "initialize_trampoline_compact"
6970 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
6971 (match_operand:SI 1 "register_operand" "r")
6972 (reg:SI R2_REG) (reg:SI R3_REG)]
6973 UNSPEC_INIT_TRAMP)
6974
6975 (clobber (reg:SI PR_REG))]
6976 "TARGET_SHCOMPACT"
6977 "jsr @%1%#"
6978 [(set_attr "type" "sfunc")
6979 (set_attr "needs_delay_slot" "yes")])
6980
6981 (define_expand "movhi"
6982 [(set (match_operand:HI 0 "general_movdst_operand" "")
6983 (match_operand:HI 1 "general_movsrc_operand" ""))]
6984 ""
6985 {
6986 prepare_move_operands (operands, HImode);
6987 })
6988
6989 (define_expand "movqi"
6990 [(set (match_operand:QI 0 "general_operand" "")
6991 (match_operand:QI 1 "general_operand" ""))]
6992 ""
6993 {
6994 prepare_move_operands (operands, QImode);
6995 })
6996
6997 ;; Specifying the displacement addressing load / store patterns separately
6998 ;; before the generic movqi / movhi pattern allows controlling the order
6999 ;; in which load / store insns are selected in a more fine grained way.
7000 ;; FIXME: The non-SH2A and SH2A variants should be combined by adding
7001 ;; "enabled" attribute as it is done in other targets.
7002 (define_insn "*mov<mode>_store_mem_disp04"
7003 [(set (mem:QIHI
7004 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
7005 (match_operand:SI 1 "const_int_operand" "<disp04>,N")))
7006 (match_operand:QIHI 2 "arith_reg_operand" "z,r"))]
7007 "TARGET_SH1 && sh_legitimate_index_p (<MODE>mode, operands[1], false, true)"
7008 "@
7009 mov.<bw> %2,@(%O1,%0)
7010 mov.<bw> %2,@%0"
7011 [(set_attr "type" "store")])
7012
7013 (define_insn "*mov<mode>_store_mem_disp12"
7014 [(set (mem:QIHI
7015 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
7016 (match_operand:SI 1 "const_int_operand" "<disp12>")))
7017 (match_operand:QIHI 2 "arith_reg_operand" "r"))]
7018 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[1], true, true)"
7019 "mov.<bw> %2,@(%O1,%0)"
7020 [(set_attr "type" "store")
7021 (set_attr "length" "4")])
7022
7023 (define_insn "*mov<mode>_load_mem_disp04"
7024 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r")
7025 (mem:QIHI
7026 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
7027 (match_operand:SI 2 "const_int_operand" "<disp04>,N"))))]
7028 "TARGET_SH1 && ! TARGET_SH2A
7029 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
7030 "@
7031 mov.<bw> @(%O2,%1),%0
7032 mov.<bw> @%1,%0"
7033 [(set_attr "type" "load")])
7034
7035 (define_insn "*mov<mode>_load_mem_disp12"
7036 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r,r")
7037 (mem:QIHI
7038 (plus:SI
7039 (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
7040 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>"))))]
7041 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
7042 "@
7043 mov.<bw> @(%O2,%1),%0
7044 mov.<bw> @%1,%0
7045 mov.<bw> @(%O2,%1),%0"
7046 [(set_attr "type" "load")
7047 (set_attr "length" "2,2,4")])
7048
7049 ;; The order of the constraint alternatives is important here.
7050 ;; Q/r has to come first, otherwise PC relative loads might wrongly get
7051 ;; placed into delay slots. Since there is no QImode PC relative load, the
7052 ;; Q constraint and general_movsrc_operand will reject it for QImode.
7053 ;; The Snd alternatives should come before Sdd in order to avoid a preference
7054 ;; of using r0 als the register operand for addressing modes other than
7055 ;; displacement addressing.
7056 ;; The Sdd alternatives allow only r0 as register operand, even though on
7057 ;; SH2A any register could be allowed by switching to a 32 bit insn.
7058 ;; Generally sticking to the r0 is preferrable, since it generates smaller
7059 ;; code. Obvious r0 reloads can then be eliminated with a peephole on SH2A.
7060 (define_insn "*mov<mode>"
7061 [(set (match_operand:QIHI 0 "general_movdst_operand"
7062 "=r,r,r,Snd,r, Sdd,z, r,l")
7063 (match_operand:QIHI 1 "general_movsrc_operand"
7064 "Q,r,i,r, Snd,z, Sdd,l,r"))]
7065 "TARGET_SH1
7066 && (arith_reg_operand (operands[0], <MODE>mode)
7067 || arith_reg_operand (operands[1], <MODE>mode))"
7068 "@
7069 mov.<bw> %1,%0
7070 mov %1,%0
7071 mov %1,%0
7072 mov.<bw> %1,%0
7073 mov.<bw> %1,%0
7074 mov.<bw> %1,%0
7075 mov.<bw> %1,%0
7076 sts %1,%0
7077 lds %1,%0"
7078 [(set_attr "type" "pcload,move,movi8,store,load,store,load,prget,prset")
7079 (set (attr "length")
7080 (cond [(and (match_operand 0 "displacement_mem_operand")
7081 (not (match_operand 0 "short_displacement_mem_operand")))
7082 (const_int 4)
7083 (and (match_operand 1 "displacement_mem_operand")
7084 (not (match_operand 1 "short_displacement_mem_operand")))
7085 (const_int 4)]
7086 (const_int 2)))])
7087
7088 (define_insn "*movqi_media"
7089 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
7090 (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
7091 "TARGET_SHMEDIA
7092 && (arith_reg_operand (operands[0], QImode)
7093 || extend_reg_or_0_operand (operands[1], QImode))"
7094 "@
7095 add.l %1, r63, %0
7096 movi %1, %0
7097 ld%M1.ub %m1, %0
7098 st%M0.b %m0, %N1"
7099 [(set_attr "type" "arith_media,arith_media,load_media,store_media")
7100 (set (attr "highpart")
7101 (cond [(match_test "sh_contains_memref_p (insn)")
7102 (const_string "user")]
7103 (const_string "ignore")))])
7104
7105 (define_expand "reload_inqi"
7106 [(set (match_operand:SI 2 "" "=&r")
7107 (match_operand:QI 1 "inqhi_operand" ""))
7108 (set (match_operand:QI 0 "arith_reg_operand" "=r")
7109 (truncate:QI (match_dup 3)))]
7110 "TARGET_SHMEDIA"
7111 {
7112 rtx inner = XEXP (operands[1], 0);
7113 int regno = REGNO (inner);
7114
7115 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
7116 operands[1] = gen_rtx_REG (SImode, regno);
7117 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7118 })
7119
7120 (define_insn "*movhi_media"
7121 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m")
7122 (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
7123 "TARGET_SHMEDIA
7124 && (arith_reg_operand (operands[0], HImode)
7125 || arith_reg_or_0_operand (operands[1], HImode))"
7126 "@
7127 add.l %1, r63, %0
7128 movi %1, %0
7129 #
7130 ld%M1.w %m1, %0
7131 st%M0.w %m0, %N1"
7132 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
7133 (set (attr "highpart")
7134 (cond [(match_test "sh_contains_memref_p (insn)")
7135 (const_string "user")]
7136 (const_string "ignore")))])
7137
7138 (define_split
7139 [(set (match_operand:HI 0 "register_operand" "")
7140 (match_operand:HI 1 "immediate_operand" ""))]
7141 "TARGET_SHMEDIA && reload_completed
7142 && ! satisfies_constraint_I16 (operands[1])"
7143 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
7144
7145 (define_expand "reload_inhi"
7146 [(set (match_operand:SI 2 "" "=&r")
7147 (match_operand:HI 1 "inqhi_operand" ""))
7148 (set (match_operand:HI 0 "arith_reg_operand" "=r")
7149 (truncate:HI (match_dup 3)))]
7150 "TARGET_SHMEDIA"
7151 {
7152 rtx inner = XEXP (operands[1], 0);
7153 int regno = REGNO (inner);
7154
7155 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
7156 operands[1] = gen_rtx_REG (SImode, regno);
7157 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7158 })
7159
7160 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
7161 ;; compiled with -m2 -ml -O3 -funroll-loops
7162 (define_insn "*movdi_i"
7163 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
7164 (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
7165 "TARGET_SH1
7166 && (arith_reg_operand (operands[0], DImode)
7167 || arith_reg_operand (operands[1], DImode))"
7168 {
7169 return output_movedouble (insn, operands, DImode);
7170 }
7171 [(set_attr "length" "4")
7172 (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
7173
7174 ;; If the output is a register and the input is memory or a register, we have
7175 ;; to be careful and see which word needs to be loaded first.
7176 (define_split
7177 [(set (match_operand:DI 0 "general_movdst_operand" "")
7178 (match_operand:DI 1 "general_movsrc_operand" ""))]
7179 "TARGET_SH1 && reload_completed"
7180 [(set (match_dup 2) (match_dup 3))
7181 (set (match_dup 4) (match_dup 5))]
7182 {
7183 int regno;
7184
7185 if ((MEM_P (operands[0])
7186 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
7187 || (MEM_P (operands[1])
7188 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7189 FAIL;
7190
7191 switch (GET_CODE (operands[0]))
7192 {
7193 case REG:
7194 regno = REGNO (operands[0]);
7195 break;
7196 case SUBREG:
7197 regno = subreg_regno (operands[0]);
7198 break;
7199 case MEM:
7200 regno = -1;
7201 break;
7202 default:
7203 gcc_unreachable ();
7204 }
7205
7206 if (regno == -1
7207 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
7208 {
7209 operands[2] = operand_subword (operands[0], 0, 0, DImode);
7210 operands[3] = operand_subword (operands[1], 0, 0, DImode);
7211 operands[4] = operand_subword (operands[0], 1, 0, DImode);
7212 operands[5] = operand_subword (operands[1], 1, 0, DImode);
7213 }
7214 else
7215 {
7216 operands[2] = operand_subword (operands[0], 1, 0, DImode);
7217 operands[3] = operand_subword (operands[1], 1, 0, DImode);
7218 operands[4] = operand_subword (operands[0], 0, 0, DImode);
7219 operands[5] = operand_subword (operands[1], 0, 0, DImode);
7220 }
7221
7222 if (operands[2] == 0 || operands[3] == 0
7223 || operands[4] == 0 || operands[5] == 0)
7224 FAIL;
7225 })
7226
7227 ;; The '?'s in the following constraints may not reflect the time taken
7228 ;; to perform the move. They are there to discourage the use of floating-
7229 ;; point registers for storing integer values.
7230 (define_insn "*movdi_media"
7231 [(set (match_operand:DI 0 "general_movdst_operand"
7232 "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
7233 (match_operand:DI 1 "general_movsrc_operand"
7234 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
7235 "TARGET_SHMEDIA_FPU
7236 && (register_operand (operands[0], DImode)
7237 || sh_register_operand (operands[1], DImode))"
7238 "@
7239 add %1, r63, %0
7240 movi %1, %0
7241 #
7242 ld%M1.q %m1, %0
7243 st%M0.q %m0, %N1
7244 fld%M1.d %m1, %0
7245 fst%M0.d %m0, %1
7246 fmov.qd %N1, %0
7247 fmov.dq %1, %0
7248 fmov.d %1, %0
7249 ptabs %1, %0
7250 gettr %1, %0
7251 pt %1, %0"
7252 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7253 fload_media,fstore_media,fload_media,dfpconv_media,
7254 fmove_media,ptabs_media,gettr_media,pt_media")
7255 (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
7256
7257 (define_insn "*movdi_media_nofpu"
7258 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
7259 (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
7260 "TARGET_SHMEDIA
7261 && (register_operand (operands[0], DImode)
7262 || sh_register_operand (operands[1], DImode))"
7263 "@
7264 add %1, r63, %0
7265 movi %1, %0
7266 #
7267 ld%M1.q %m1, %0
7268 st%M0.q %m0, %N1
7269 ptabs %1, %0
7270 gettr %1, %0
7271 pt %1, %0"
7272 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7273 ptabs_media,gettr_media,pt_media")
7274 (set_attr "length" "4,4,16,4,4,4,4,*")])
7275
7276 (define_insn "*movdi_media_I16"
7277 [(set (match_operand:DI 0 "ext_dest_operand" "=r")
7278 (match_operand:DI 1 "const_int_operand" "I16"))]
7279 "TARGET_SHMEDIA && reload_completed"
7280 "movi %1, %0"
7281 [(set_attr "type" "arith_media")
7282 (set_attr "length" "4")])
7283
7284 (define_split
7285 [(set (match_operand:DI 0 "arith_reg_dest" "")
7286 (match_operand:DI 1 "immediate_operand" ""))]
7287 "TARGET_SHMEDIA && reload_completed
7288 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7289 [(set (match_dup 0) (match_dup 1))]
7290 {
7291 rtx insn;
7292
7293 if (TARGET_SHMEDIA64)
7294 insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
7295 else
7296 insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
7297
7298 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
7299
7300 DONE;
7301 })
7302
7303 (define_expand "movdi_const"
7304 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7305 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7306 (const_int 48)] UNSPEC_EXTRACT_S16)))
7307 (set (match_dup 0)
7308 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7309 (const:DI (unspec:DI [(match_dup 1)
7310 (const_int 32)] UNSPEC_EXTRACT_U16))))
7311 (set (match_dup 0)
7312 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7313 (const:DI (unspec:DI [(match_dup 1)
7314 (const_int 16)] UNSPEC_EXTRACT_U16))))
7315 (set (match_dup 0)
7316 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7317 (const:DI (unspec:DI [(match_dup 1)
7318 (const_int 0)] UNSPEC_EXTRACT_U16))))]
7319 "TARGET_SHMEDIA64 && reload_completed
7320 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7321 {
7322 sh_mark_label (operands[1], 4);
7323 })
7324
7325 (define_expand "movdi_const_32bit"
7326 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7327 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7328 (const_int 16)] UNSPEC_EXTRACT_S16)))
7329 (set (match_dup 0)
7330 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7331 (const:DI (unspec:DI [(match_dup 1)
7332 (const_int 0)] UNSPEC_EXTRACT_U16))))]
7333 "TARGET_SHMEDIA32 && reload_completed
7334 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7335 {
7336 sh_mark_label (operands[1], 2);
7337 })
7338
7339 (define_expand "movdi_const_16bit"
7340 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7341 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7342 (const_int 0)] UNSPEC_EXTRACT_S16)))]
7343 "TARGET_SHMEDIA && flag_pic && reload_completed
7344 && GET_CODE (operands[1]) == SYMBOL_REF"
7345 "")
7346
7347 (define_split
7348 [(set (match_operand:DI 0 "ext_dest_operand" "")
7349 (match_operand:DI 1 "immediate_operand" ""))]
7350 "TARGET_SHMEDIA && reload_completed
7351 && CONST_INT_P (operands[1])
7352 && ! satisfies_constraint_I16 (operands[1])"
7353 [(set (match_dup 0) (match_dup 2))
7354 (match_dup 1)]
7355 {
7356 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
7357 unsigned HOST_WIDE_INT low = val;
7358 unsigned HOST_WIDE_INT high = val;
7359 unsigned HOST_WIDE_INT sign;
7360 unsigned HOST_WIDE_INT val2 = val ^ (val-1);
7361
7362 /* Zero-extend the 16 least-significant bits. */
7363 low &= 0xffff;
7364
7365 /* Arithmetic shift right the word by 16 bits. */
7366 high >>= 16;
7367 if (GET_CODE (operands[0]) == SUBREG
7368 && GET_MODE (SUBREG_REG (operands[0])) == SImode)
7369 {
7370 high &= 0xffff;
7371 high ^= 0x8000;
7372 high -= 0x8000;
7373 }
7374 else
7375 {
7376 sign = 1;
7377 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7378 high ^= sign;
7379 high -= sign;
7380 }
7381 do
7382 {
7383 /* If we can't generate the constant with a two-insn movi / shori
7384 sequence, try some other strategies. */
7385 if (! CONST_OK_FOR_I16 (high))
7386 {
7387 /* Try constant load / left shift. We know VAL != 0. */
7388 val2 = val ^ (val-1);
7389 if (val2 > 0x1ffff)
7390 {
7391 int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
7392
7393 if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
7394 || (! CONST_OK_FOR_I16 (high >> 16)
7395 && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
7396 {
7397 val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
7398 operands[1] = gen_ashldi3_media (operands[0], operands[0],
7399 GEN_INT (trailing_zeroes));
7400 break;
7401 }
7402 }
7403 /* Try constant load / right shift. */
7404 val2 = (val >> 15) + 1;
7405 if (val2 == (val2 & -val2))
7406 {
7407 int shift = 49 - exact_log2 (val2);
7408
7409 val2 = trunc_int_for_mode (val << shift, DImode);
7410 if (CONST_OK_FOR_I16 (val2))
7411 {
7412 operands[1] = gen_lshrdi3_media (operands[0], operands[0],
7413 GEN_INT (shift));
7414 break;
7415 }
7416 }
7417 /* Try mperm.w . */
7418 val2 = val & 0xffff;
7419 if ((val >> 16 & 0xffff) == val2
7420 && (val >> 32 & 0xffff) == val2
7421 && (val >> 48 & 0xffff) == val2)
7422 {
7423 val2 = (HOST_WIDE_INT) val >> 48;
7424 operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
7425 operands[1] = gen_mperm_w0 (operands[1], operands[1]);
7426 break;
7427 }
7428 /* Try movi / mshflo.l */
7429 val2 = (HOST_WIDE_INT) val >> 32;
7430 if (val2 == ((unsigned HOST_WIDE_INT)
7431 trunc_int_for_mode (val, SImode)))
7432 {
7433 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7434 operands[0]);
7435 break;
7436 }
7437 /* Try movi / mshflo.l w/ r63. */
7438 val2 = val + ((HOST_WIDE_INT) -1 << 32);
7439 if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
7440 {
7441 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7442 const0_rtx);
7443 break;
7444 }
7445 }
7446 val2 = high;
7447 operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
7448 }
7449 while (0);
7450 operands[2] = GEN_INT (val2);
7451 })
7452
7453 (define_split
7454 [(set (match_operand:DI 0 "ext_dest_operand" "")
7455 (match_operand:DI 1 "immediate_operand" ""))]
7456 "TARGET_SHMEDIA && reload_completed
7457 && GET_CODE (operands[1]) == CONST_DOUBLE"
7458 [(set (match_dup 0) (match_dup 2))
7459 (set (match_dup 0)
7460 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
7461 {
7462 unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
7463 unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
7464 unsigned HOST_WIDE_INT val = low;
7465 unsigned HOST_WIDE_INT sign;
7466
7467 /* Zero-extend the 16 least-significant bits. */
7468 val &= 0xffff;
7469 operands[1] = GEN_INT (val);
7470
7471 /* Arithmetic shift right the double-word by 16 bits. */
7472 low >>= 16;
7473 low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
7474 high >>= 16;
7475 sign = 1;
7476 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7477 high ^= sign;
7478 high -= sign;
7479
7480 /* This will only be true if high is a sign-extension of low, i.e.,
7481 it must be either 0 or (unsigned)-1, and be zero iff the
7482 most-significant bit of low is set. */
7483 if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
7484 operands[2] = GEN_INT (low);
7485 else
7486 operands[2] = immed_double_const (low, high, DImode);
7487 })
7488
7489 (define_insn "shori_media"
7490 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
7491 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
7492 (const_int 16))
7493 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
7494 "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
7495 "@
7496 shori %u2, %0
7497 #"
7498 [(set_attr "type" "arith_media,*")])
7499
7500 (define_insn "*shori_media_si"
7501 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
7502 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
7503 (const_int 16))
7504 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
7505 "TARGET_SHMEDIA"
7506 "shori %u2, %0")
7507
7508 (define_expand "movdi"
7509 [(set (match_operand:DI 0 "general_movdst_operand" "")
7510 (match_operand:DI 1 "general_movsrc_operand" ""))]
7511 ""
7512 {
7513 prepare_move_operands (operands, DImode);
7514 })
7515
7516 (define_insn "movdf_media"
7517 [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
7518 (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
7519 "TARGET_SHMEDIA_FPU
7520 && (register_operand (operands[0], DFmode)
7521 || sh_register_operand (operands[1], DFmode))"
7522 "@
7523 fmov.d %1, %0
7524 fmov.qd %N1, %0
7525 fmov.dq %1, %0
7526 add %1, r63, %0
7527 #
7528 fld%M1.d %m1, %0
7529 fst%M0.d %m0, %1
7530 ld%M1.q %m1, %0
7531 st%M0.q %m0, %N1"
7532 [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,
7533 fload_media,fstore_media,load_media,store_media")])
7534
7535 (define_insn "movdf_media_nofpu"
7536 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7537 (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
7538 "TARGET_SHMEDIA
7539 && (register_operand (operands[0], DFmode)
7540 || sh_register_operand (operands[1], DFmode))"
7541 "@
7542 add %1, r63, %0
7543 #
7544 ld%M1.q %m1, %0
7545 st%M0.q %m0, %N1"
7546 [(set_attr "type" "arith_media,*,load_media,store_media")])
7547
7548 (define_split
7549 [(set (match_operand:DF 0 "arith_reg_dest" "")
7550 (match_operand:DF 1 "immediate_operand" ""))]
7551 "TARGET_SHMEDIA && reload_completed"
7552 [(set (match_dup 3) (match_dup 2))]
7553 {
7554 int endian = WORDS_BIG_ENDIAN ? 1 : 0;
7555 long values[2];
7556 REAL_VALUE_TYPE value;
7557
7558 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
7559 REAL_VALUE_TO_TARGET_DOUBLE (value, values);
7560
7561 if (HOST_BITS_PER_WIDE_INT >= 64)
7562 operands[2] = immed_double_const ((unsigned long) values[endian]
7563 | ((HOST_WIDE_INT) values[1 - endian]
7564 << 32), 0, DImode);
7565 else
7566 {
7567 gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
7568 operands[2] = immed_double_const (values[endian], values[1 - endian],
7569 DImode);
7570 }
7571
7572 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
7573 })
7574
7575 ;; FIXME: This should be a define_insn_and_split.
7576 (define_insn "movdf_k"
7577 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7578 (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
7579 "TARGET_SH1
7580 && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
7581 /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
7582 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
7583 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
7584 && (arith_reg_operand (operands[0], DFmode)
7585 || arith_reg_operand (operands[1], DFmode))"
7586 {
7587 return output_movedouble (insn, operands, DFmode);
7588 }
7589 [(set_attr "length" "4")
7590 (set_attr "type" "move,pcload,load,store")])
7591
7592 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
7593 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
7594 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
7595 ;; the d/m/c/X alternative, which is split later into single-precision
7596 ;; instructions. And when not optimizing, no splits are done before fixing
7597 ;; up pcloads, so we need usable length information for that.
7598 (define_insn "movdf_i4"
7599 [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
7600 (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
7601 (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
7602 (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
7603 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
7604 && (arith_reg_operand (operands[0], DFmode)
7605 || arith_reg_operand (operands[1], DFmode))"
7606 {
7607 switch (which_alternative)
7608 {
7609 case 0:
7610 if (TARGET_FMOVD)
7611 return "fmov %1,%0";
7612 else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
7613 return "fmov %R1,%R0" "\n"
7614 " fmov %S1,%S0";
7615 else
7616 return "fmov %S1,%S0" "\n"
7617 " fmov %R1,%R0";
7618 case 3:
7619 case 4:
7620 return "fmov.d %1,%0";
7621 default:
7622 return "#";
7623 }
7624 }
7625 [(set_attr_alternative "length"
7626 [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
7627 (const_int 4)
7628 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7629 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7630 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7631 (const_int 4)
7632 (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
7633 ;; We can't use 4-byte push/pop on SHcompact, so we have to
7634 ;; increment or decrement r15 explicitly.
7635 (if_then_else
7636 (match_test "TARGET_SHCOMPACT")
7637 (const_int 10) (const_int 8))
7638 (if_then_else
7639 (match_test "TARGET_SHCOMPACT")
7640 (const_int 10) (const_int 8))])
7641 (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
7642 (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
7643 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
7644 (const_string "double")
7645 (const_string "none")))])
7646
7647 ;; Moving DFmode between fp/general registers through memory
7648 ;; (the top of the stack) is faster than moving through fpul even for
7649 ;; little endian. Because the type of an instruction is important for its
7650 ;; scheduling, it is beneficial to split these operations, rather than
7651 ;; emitting them in one single chunk, even if this will expose a stack
7652 ;; use that will prevent scheduling of other stack accesses beyond this
7653 ;; instruction.
7654 (define_split
7655 [(set (match_operand:DF 0 "register_operand" "")
7656 (match_operand:DF 1 "register_operand" ""))
7657 (use (match_operand:PSI 2 "fpscr_operand" ""))
7658 (clobber (match_scratch:SI 3 "=X"))]
7659 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
7660 && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
7661 [(const_int 0)]
7662 {
7663 rtx insn, tos;
7664
7665 if (TARGET_SH5 && true_regnum (operands[1]) < 16)
7666 {
7667 emit_move_insn (stack_pointer_rtx,
7668 plus_constant (Pmode, stack_pointer_rtx, -8));
7669 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
7670 }
7671 else
7672 tos = gen_tmp_stack_mem (DFmode,
7673 gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
7674 insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
7675 if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
7676 add_reg_note (insn, REG_INC, stack_pointer_rtx);
7677 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
7678 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
7679 else
7680 tos = gen_tmp_stack_mem (DFmode,
7681 gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
7682 insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
7683 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
7684 emit_move_insn (stack_pointer_rtx,
7685 plus_constant (Pmode, stack_pointer_rtx, 8));
7686 else
7687 add_reg_note (insn, REG_INC, stack_pointer_rtx);
7688 DONE;
7689 })
7690
7691 ;; local-alloc sometimes allocates scratch registers even when not required,
7692 ;; so we must be prepared to handle these.
7693
7694 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
7695 (define_split
7696 [(set (match_operand:DF 0 "general_movdst_operand" "")
7697 (match_operand:DF 1 "general_movsrc_operand" ""))
7698 (use (match_operand:PSI 2 "fpscr_operand" ""))
7699 (clobber (match_scratch:SI 3 ""))]
7700 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
7701 && reload_completed
7702 && true_regnum (operands[0]) < 16
7703 && true_regnum (operands[1]) < 16"
7704 [(set (match_dup 0) (match_dup 1))]
7705 {
7706 /* If this was a reg <-> mem operation with base + index reg addressing,
7707 we have to handle this in a special way. */
7708 rtx mem = operands[0];
7709 int store_p = 1;
7710 if (! memory_operand (mem, DFmode))
7711 {
7712 mem = operands[1];
7713 store_p = 0;
7714 }
7715 if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
7716 mem = SUBREG_REG (mem);
7717 if (MEM_P (mem))
7718 {
7719 rtx addr = XEXP (mem, 0);
7720 if (GET_CODE (addr) == PLUS
7721 && REG_P (XEXP (addr, 0))
7722 && REG_P (XEXP (addr, 1)))
7723 {
7724 int offset;
7725 rtx reg0 = gen_rtx_REG (Pmode, 0);
7726 rtx regop = operands[store_p], word0 ,word1;
7727
7728 if (GET_CODE (regop) == SUBREG)
7729 alter_subreg (&regop, true);
7730 if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
7731 offset = 2;
7732 else
7733 offset = 4;
7734 mem = copy_rtx (mem);
7735 PUT_MODE (mem, SImode);
7736 word0 = gen_rtx_SUBREG (SImode, regop, 0);
7737 alter_subreg (&word0, true);
7738 word1 = gen_rtx_SUBREG (SImode, regop, 4);
7739 alter_subreg (&word1, true);
7740 if (store_p || ! refers_to_regno_p (REGNO (word0),
7741 REGNO (word0) + 1, addr, 0))
7742 {
7743 emit_insn (store_p
7744 ? gen_movsi_ie (mem, word0)
7745 : gen_movsi_ie (word0, mem));
7746 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7747 mem = copy_rtx (mem);
7748 emit_insn (store_p
7749 ? gen_movsi_ie (mem, word1)
7750 : gen_movsi_ie (word1, mem));
7751 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7752 }
7753 else
7754 {
7755 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7756 emit_insn (gen_movsi_ie (word1, mem));
7757 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7758 mem = copy_rtx (mem);
7759 emit_insn (gen_movsi_ie (word0, mem));
7760 }
7761 DONE;
7762 }
7763 }
7764 })
7765
7766 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
7767 (define_split
7768 [(set (match_operand:DF 0 "register_operand" "")
7769 (match_operand:DF 1 "memory_operand" ""))
7770 (use (match_operand:PSI 2 "fpscr_operand" ""))
7771 (clobber (reg:SI R0_REG))]
7772 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
7773 [(parallel [(set (match_dup 0) (match_dup 1))
7774 (use (match_dup 2))
7775 (clobber (scratch:SI))])]
7776 "")
7777
7778 (define_expand "reload_indf__frn"
7779 [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
7780 (match_operand:DF 1 "immediate_operand" "FQ"))
7781 (use (reg:PSI FPSCR_REG))
7782 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
7783 "TARGET_SH1"
7784 "")
7785
7786 (define_expand "reload_outdf__RnFRm"
7787 [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
7788 (match_operand:DF 1 "register_operand" "af,r"))
7789 (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
7790 "TARGET_SH1"
7791 "")
7792
7793 ;; Simplify no-op moves.
7794 (define_split
7795 [(set (match_operand:SF 0 "register_operand" "")
7796 (match_operand:SF 1 "register_operand" ""))
7797 (use (match_operand:PSI 2 "fpscr_operand" ""))
7798 (clobber (match_scratch:SI 3 ""))]
7799 "TARGET_SH2E && reload_completed
7800 && true_regnum (operands[0]) == true_regnum (operands[1])"
7801 [(set (match_dup 0) (match_dup 0))]
7802 "")
7803
7804 ;; fmovd substitute post-reload splits
7805 (define_split
7806 [(set (match_operand:DF 0 "register_operand" "")
7807 (match_operand:DF 1 "register_operand" ""))
7808 (use (match_operand:PSI 2 "fpscr_operand" ""))
7809 (clobber (match_scratch:SI 3 ""))]
7810 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
7811 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7812 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
7813 [(const_int 0)]
7814 {
7815 int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
7816 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
7817 gen_rtx_REG (SFmode, src), operands[2]));
7818 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
7819 gen_rtx_REG (SFmode, src + 1), operands[2]));
7820 DONE;
7821 })
7822
7823 (define_split
7824 [(set (match_operand:DF 0 "register_operand" "")
7825 (mem:DF (match_operand:SI 1 "register_operand" "")))
7826 (use (match_operand:PSI 2 "fpscr_operand" ""))
7827 (clobber (match_scratch:SI 3 ""))]
7828 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7829 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7830 && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
7831 [(const_int 0)]
7832 {
7833 int regno = true_regnum (operands[0]);
7834 rtx insn;
7835 rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
7836 rtx mem2
7837 = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
7838 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
7839 regno + SH_REG_MSW_OFFSET),
7840 mem2, operands[2]));
7841 add_reg_note (insn, REG_INC, operands[1]);
7842 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
7843 regno + SH_REG_LSW_OFFSET),
7844 change_address (mem, SFmode, NULL_RTX),
7845 operands[2]));
7846 DONE;
7847 })
7848
7849 (define_split
7850 [(set (match_operand:DF 0 "register_operand" "")
7851 (match_operand:DF 1 "memory_operand" ""))
7852 (use (match_operand:PSI 2 "fpscr_operand" ""))
7853 (clobber (match_scratch:SI 3 ""))]
7854 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7855 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
7856 [(const_int 0)]
7857 {
7858 int regno = true_regnum (operands[0]);
7859 rtx addr, insn;
7860 rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
7861 rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
7862 rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
7863
7864 operands[1] = copy_rtx (mem2);
7865 addr = XEXP (mem2, 0);
7866
7867 switch (GET_CODE (addr))
7868 {
7869 case REG:
7870 /* This is complicated. If the register is an arithmetic register
7871 we can just fall through to the REG+DISP case below. Otherwise
7872 we have to use a combination of POST_INC and REG addressing... */
7873 if (! arith_reg_operand (operands[1], SFmode))
7874 {
7875 XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
7876 insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
7877 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7878
7879 emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7880
7881 /* If we have modified the stack pointer, the value that we have
7882 read with post-increment might be modified by an interrupt,
7883 so write it back. */
7884 if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
7885 emit_insn (gen_push_e (reg0));
7886 else
7887 emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0),
7888 GEN_INT (-4)));
7889 break;
7890 }
7891 /* Fall through. */
7892
7893 case PLUS:
7894 emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
7895 operands[1] = copy_rtx (operands[1]);
7896 XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4);
7897 emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7898 break;
7899
7900 case POST_INC:
7901 insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
7902 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7903
7904 insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7905 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7906 break;
7907
7908 default:
7909 debug_rtx (addr);
7910 gcc_unreachable ();
7911 }
7912
7913 DONE;
7914 })
7915
7916 (define_split
7917 [(set (match_operand:DF 0 "memory_operand" "")
7918 (match_operand:DF 1 "register_operand" ""))
7919 (use (match_operand:PSI 2 "fpscr_operand" ""))
7920 (clobber (match_scratch:SI 3 ""))]
7921 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7922 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
7923 [(const_int 0)]
7924 {
7925 int regno = true_regnum (operands[1]);
7926 rtx insn, addr;
7927 rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
7928 rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
7929
7930 operands[0] = copy_rtx (operands[0]);
7931 PUT_MODE (operands[0], SFmode);
7932 addr = XEXP (operands[0], 0);
7933
7934 switch (GET_CODE (addr))
7935 {
7936 case REG:
7937 /* This is complicated. If the register is an arithmetic register
7938 we can just fall through to the REG+DISP case below. Otherwise
7939 we have to use a combination of REG and PRE_DEC addressing... */
7940 if (! arith_reg_operand (operands[0], SFmode))
7941 {
7942 emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
7943 emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7944
7945 operands[0] = copy_rtx (operands[0]);
7946 XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
7947
7948 insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7949 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7950 break;
7951 }
7952 /* Fall through. */
7953
7954 case PLUS:
7955 /* Since REG+DISP addressing has already been decided upon by gcc
7956 we can rely upon it having chosen an arithmetic register as the
7957 register component of the address. Just emit the lower numbered
7958 register first, to the lower address, then the higher numbered
7959 register to the higher address. */
7960 emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7961
7962 operands[0] = copy_rtx (operands[0]);
7963 XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4);
7964
7965 emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7966 break;
7967
7968 case PRE_DEC:
7969 /* This is easy. Output the word to go to the higher address
7970 first (ie the word in the higher numbered register) then the
7971 word to go to the lower address. */
7972
7973 insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7974 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7975
7976 insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7977 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7978 break;
7979
7980 default:
7981 /* FAIL; */
7982 debug_rtx (addr);
7983 gcc_unreachable ();
7984 }
7985
7986 DONE;
7987 })
7988
7989 ;; If the output is a register and the input is memory or a register, we have
7990 ;; to be careful and see which word needs to be loaded first.
7991 (define_split
7992 [(set (match_operand:DF 0 "general_movdst_operand" "")
7993 (match_operand:DF 1 "general_movsrc_operand" ""))]
7994 "TARGET_SH1 && reload_completed"
7995 [(set (match_dup 2) (match_dup 3))
7996 (set (match_dup 4) (match_dup 5))]
7997 {
7998 int regno;
7999
8000 if ((MEM_P (operands[0])
8001 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
8002 || (MEM_P (operands[1])
8003 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
8004 FAIL;
8005
8006 switch (GET_CODE (operands[0]))
8007 {
8008 case REG:
8009 regno = REGNO (operands[0]);
8010 break;
8011 case SUBREG:
8012 regno = subreg_regno (operands[0]);
8013 break;
8014 case MEM:
8015 regno = -1;
8016 break;
8017 default:
8018 gcc_unreachable ();
8019 }
8020
8021 if (regno == -1
8022 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
8023 {
8024 operands[2] = operand_subword (operands[0], 0, 0, DFmode);
8025 operands[3] = operand_subword (operands[1], 0, 0, DFmode);
8026 operands[4] = operand_subword (operands[0], 1, 0, DFmode);
8027 operands[5] = operand_subword (operands[1], 1, 0, DFmode);
8028 }
8029 else
8030 {
8031 operands[2] = operand_subword (operands[0], 1, 0, DFmode);
8032 operands[3] = operand_subword (operands[1], 1, 0, DFmode);
8033 operands[4] = operand_subword (operands[0], 0, 0, DFmode);
8034 operands[5] = operand_subword (operands[1], 0, 0, DFmode);
8035 }
8036
8037 if (operands[2] == 0 || operands[3] == 0
8038 || operands[4] == 0 || operands[5] == 0)
8039 FAIL;
8040 })
8041
8042 (define_expand "movdf"
8043 [(set (match_operand:DF 0 "general_movdst_operand" "")
8044 (match_operand:DF 1 "general_movsrc_operand" ""))]
8045 ""
8046 {
8047 prepare_move_operands (operands, DFmode);
8048 if (TARGET_SHMEDIA)
8049 {
8050 if (TARGET_SHMEDIA_FPU)
8051 emit_insn (gen_movdf_media (operands[0], operands[1]));
8052 else
8053 emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
8054 DONE;
8055 }
8056 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
8057 {
8058 emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
8059 DONE;
8060 }
8061 })
8062
8063 ;;This is incompatible with the way gcc uses subregs.
8064 ;;(define_insn "movv2sf_i"
8065 ;; [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
8066 ;; (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
8067 ;; "TARGET_SHMEDIA_FPU
8068 ;; && (fp_arith_reg_operand (operands[0], V2SFmode)
8069 ;; || fp_arith_reg_operand (operands[1], V2SFmode))"
8070 ;; "@
8071 ;; #
8072 ;; fld%M1.p %m1, %0
8073 ;; fst%M0.p %m0, %1"
8074 ;; [(set_attr "type" "*,fload_media,fstore_media")])
8075 (define_insn_and_split "movv2sf_i"
8076 [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
8077 (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
8078 "TARGET_SHMEDIA_FPU"
8079 "#"
8080 "TARGET_SHMEDIA_FPU && reload_completed"
8081 [(set (match_dup 0) (match_dup 1))]
8082 {
8083 operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
8084 operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
8085 })
8086
8087 (define_expand "movv2sf"
8088 [(set (match_operand:V2SF 0 "general_movdst_operand" "")
8089 (match_operand:V2SF 1 "nonimmediate_operand" ""))]
8090 "TARGET_SHMEDIA_FPU"
8091 {
8092 prepare_move_operands (operands, V2SFmode);
8093 })
8094
8095 (define_expand "addv2sf3"
8096 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8097 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8098 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8099 "TARGET_SHMEDIA_FPU"
8100 {
8101 sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
8102 DONE;
8103 })
8104
8105 (define_expand "subv2sf3"
8106 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8107 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8108 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8109 "TARGET_SHMEDIA_FPU"
8110 {
8111 sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
8112 DONE;
8113 })
8114
8115 (define_expand "mulv2sf3"
8116 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8117 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8118 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8119 "TARGET_SHMEDIA_FPU"
8120 {
8121 sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
8122 DONE;
8123 })
8124
8125 (define_expand "divv2sf3"
8126 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8127 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8128 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8129 "TARGET_SHMEDIA_FPU"
8130 {
8131 sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
8132 DONE;
8133 })
8134
8135 (define_insn_and_split "*movv4sf_i"
8136 [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
8137 (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
8138 "TARGET_SHMEDIA_FPU"
8139 "#"
8140 "&& reload_completed"
8141 [(const_int 0)]
8142 {
8143 for (int i = 0; i < 4/2; i++)
8144 {
8145 rtx x, y;
8146
8147 if (MEM_P (operands[0]))
8148 x = adjust_address (operands[0], V2SFmode,
8149 i * GET_MODE_SIZE (V2SFmode));
8150 else
8151 x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
8152
8153 if (MEM_P (operands[1]))
8154 y = adjust_address (operands[1], V2SFmode,
8155 i * GET_MODE_SIZE (V2SFmode));
8156 else
8157 y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
8158
8159 emit_insn (gen_movv2sf_i (x, y));
8160 }
8161
8162 DONE;
8163 }
8164 [(set_attr "length" "8")])
8165
8166 (define_expand "movv4sf"
8167 [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
8168 (match_operand:V4SF 1 "general_operand" ""))]
8169 "TARGET_SHMEDIA_FPU"
8170 {
8171 prepare_move_operands (operands, V4SFmode);
8172 })
8173
8174 (define_insn_and_split "*movv16sf_i"
8175 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8176 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8177 "TARGET_SHMEDIA_FPU"
8178 "#"
8179 "&& reload_completed"
8180 [(const_int 0)]
8181 {
8182 for (int i = 0; i < 16/2; i++)
8183 {
8184 rtx x, y;
8185
8186 if (MEM_P (operands[0]))
8187 x = adjust_address (operands[0], V2SFmode,
8188 i * GET_MODE_SIZE (V2SFmode));
8189 else
8190 {
8191 x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
8192 alter_subreg (&x, true);
8193 }
8194
8195 if (MEM_P (operands[1]))
8196 y = adjust_address (operands[1], V2SFmode,
8197 i * GET_MODE_SIZE (V2SFmode));
8198 else
8199 {
8200 y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
8201 alter_subreg (&y, true);
8202 }
8203
8204 emit_insn (gen_movv2sf_i (x, y));
8205 }
8206
8207 DONE;
8208 }
8209 [(set_attr "length" "32")])
8210
8211 (define_expand "movv16sf"
8212 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8213 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8214 "TARGET_SHMEDIA_FPU"
8215 {
8216 prepare_move_operands (operands, V16SFmode);
8217 })
8218
8219 (define_insn "movsf_media"
8220 [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
8221 (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
8222 "TARGET_SHMEDIA_FPU
8223 && (register_operand (operands[0], SFmode)
8224 || sh_register_operand (operands[1], SFmode))"
8225 "@
8226 fmov.s %1, %0
8227 fmov.ls %N1, %0
8228 fmov.sl %1, %0
8229 add.l %1, r63, %0
8230 #
8231 fld%M1.s %m1, %0
8232 fst%M0.s %m0, %1
8233 ld%M1.l %m1, %0
8234 st%M0.l %m0, %N1"
8235 [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
8236 (set (attr "highpart")
8237 (cond [(match_test "sh_contains_memref_p (insn)")
8238 (const_string "user")]
8239 (const_string "ignore")))])
8240
8241 (define_insn "movsf_media_nofpu"
8242 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
8243 (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
8244 "TARGET_SHMEDIA
8245 && (register_operand (operands[0], SFmode)
8246 || sh_register_operand (operands[1], SFmode))"
8247 "@
8248 add.l %1, r63, %0
8249 #
8250 ld%M1.l %m1, %0
8251 st%M0.l %m0, %N1"
8252 [(set_attr "type" "arith_media,*,load_media,store_media")
8253 (set (attr "highpart")
8254 (cond [(match_test "sh_contains_memref_p (insn)")
8255 (const_string "user")]
8256 (const_string "ignore")))])
8257
8258 (define_split
8259 [(set (match_operand:SF 0 "arith_reg_dest" "")
8260 (match_operand:SF 1 "immediate_operand" ""))]
8261 "TARGET_SHMEDIA && reload_completed
8262 && ! FP_REGISTER_P (true_regnum (operands[0]))"
8263 [(set (match_dup 3) (match_dup 2))]
8264 {
8265 long values;
8266 REAL_VALUE_TYPE value;
8267
8268 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
8269 REAL_VALUE_TO_TARGET_SINGLE (value, values);
8270 operands[2] = GEN_INT (values);
8271
8272 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
8273 })
8274
8275 (define_insn "movsf_i"
8276 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
8277 (match_operand:SF 1 "general_movsrc_operand" "r,G,FQ,mr,r,r,l"))]
8278 "TARGET_SH1
8279 && (! TARGET_SH2E
8280 /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
8281 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
8282 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
8283 && (arith_reg_operand (operands[0], SFmode)
8284 || arith_reg_operand (operands[1], SFmode))"
8285 "@
8286 mov %1,%0
8287 mov #0,%0
8288 mov.l %1,%0
8289 mov.l %1,%0
8290 mov.l %1,%0
8291 lds %1,%0
8292 sts %1,%0"
8293 [(set_attr "type" "move,move,pcload,load,store,move,move")])
8294
8295 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
8296 ;; update_flow_info would not know where to put REG_EQUAL notes
8297 ;; when the destination changes mode.
8298 (define_insn "movsf_ie"
8299 [(set (match_operand:SF 0 "general_movdst_operand"
8300 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
8301 (match_operand:SF 1 "general_movsrc_operand"
8302 "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
8303 (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c"))
8304 (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
8305 "TARGET_SH2E
8306 && (arith_reg_operand (operands[0], SFmode) || fpul_operand (operands[0], SFmode)
8307 || arith_reg_operand (operands[1], SFmode) || fpul_operand (operands[1], SFmode)
8308 || arith_reg_operand (operands[3], SImode))"
8309 "@
8310 fmov %1,%0
8311 mov %1,%0
8312 fldi0 %0
8313 fldi1 %0
8314 #
8315 fmov.s %1,%0
8316 fmov.s %1,%0
8317 mov.l %1,%0
8318 mov.l %1,%0
8319 mov.l %1,%0
8320 fsts fpul,%0
8321 flds %1,fpul
8322 lds.l %1,%0
8323 #
8324 sts %1,%0
8325 lds %1,%0
8326 sts.l %1,%0
8327 lds.l %1,%0
8328 ! move optimized away"
8329 [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,
8330 store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
8331 (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
8332 (set_attr_alternative "length"
8333 [(const_int 2)
8334 (const_int 2)
8335 (const_int 2)
8336 (const_int 2)
8337 (const_int 4)
8338 (if_then_else
8339 (match_test "TARGET_SH2A")
8340 (const_int 4) (const_int 2))
8341 (if_then_else
8342 (match_test "TARGET_SH2A")
8343 (const_int 4) (const_int 2))
8344 (const_int 2)
8345 (if_then_else
8346 (match_test "TARGET_SH2A")
8347 (const_int 4) (const_int 2))
8348 (if_then_else
8349 (match_test "TARGET_SH2A")
8350 (const_int 4) (const_int 2))
8351 (const_int 2)
8352 (const_int 2)
8353 (const_int 2)
8354 (const_int 4)
8355 (const_int 2)
8356 (const_int 2)
8357 (const_int 2)
8358 (const_int 2)
8359 (const_int 0)])
8360 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
8361 (const_string "single")
8362 (const_string "single")))])
8363
8364 (define_split
8365 [(set (match_operand:SF 0 "register_operand" "")
8366 (match_operand:SF 1 "register_operand" ""))
8367 (use (match_operand:PSI 2 "fpscr_operand" ""))
8368 (clobber (reg:SI FPUL_REG))]
8369 "TARGET_SH1"
8370 [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
8371 (use (match_dup 2))
8372 (clobber (scratch:SI))])
8373 (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
8374 (use (match_dup 2))
8375 (clobber (scratch:SI))])]
8376 "")
8377
8378 (define_expand "movsf"
8379 [(set (match_operand:SF 0 "general_movdst_operand" "")
8380 (match_operand:SF 1 "general_movsrc_operand" ""))]
8381 ""
8382 {
8383 prepare_move_operands (operands, SFmode);
8384 if (TARGET_SHMEDIA)
8385 {
8386 if (TARGET_SHMEDIA_FPU)
8387 emit_insn (gen_movsf_media (operands[0], operands[1]));
8388 else
8389 emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
8390 DONE;
8391 }
8392 if (TARGET_SH2E)
8393 {
8394 emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
8395 DONE;
8396 }
8397 })
8398
8399 (define_insn "mov_nop"
8400 [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
8401 "TARGET_SH2E"
8402 ""
8403 [(set_attr "length" "0")
8404 (set_attr "type" "nil")])
8405
8406 (define_expand "reload_insf__frn"
8407 [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
8408 (match_operand:SF 1 "immediate_operand" "FQ"))
8409 (use (reg:PSI FPSCR_REG))
8410 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8411 "TARGET_SH1"
8412 "")
8413
8414 (define_expand "reload_insi__i_fpul"
8415 [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
8416 (match_operand:SI 1 "immediate_operand" "i"))
8417 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8418 "TARGET_SH1"
8419 "")
8420
8421 (define_expand "ptabs"
8422 [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
8423 "TARGET_SHMEDIA"
8424 {
8425 if (!TARGET_PT_FIXED)
8426 {
8427 rtx eq = operands[1];
8428
8429 /* ??? For canonical RTL we really should remove any CONST from EQ
8430 before wrapping it in the AND, and finally wrap the EQ into a
8431 const if is constant. However, for reload we must expose the
8432 input register or symbolic constant, and we can't have
8433 different insn structures outside of the operands for different
8434 alternatives of the same pattern. */
8435 eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
8436 GEN_INT (3));
8437 operands[1]
8438 = (gen_rtx_IF_THEN_ELSE
8439 (PDImode,
8440 eq,
8441 gen_rtx_MEM (PDImode, operands[1]),
8442 gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
8443 PDImode, operands[1])));
8444 }
8445 })
8446
8447 ;; expanded by ptabs expander.
8448 (define_insn "*extendsipdi_media"
8449 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8450 (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
8451 "r,Csy")
8452 (const_int 3))
8453 (const_int 3))
8454 (mem:PDI (match_dup 1))
8455 (sign_extend:PDI (match_dup 1))))]
8456 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8457 "@
8458 ptabs %1, %0
8459 pt %1, %0"
8460 [(set_attr "type" "ptabs_media,pt_media")
8461 (set_attr "length" "4,*")])
8462
8463 (define_insn "*truncdipdi_media"
8464 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8465 (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
8466 "r,Csy")
8467 (const_int 3))
8468 (const_int 3))
8469 (mem:PDI (match_dup 1))
8470 (truncate:PDI (match_dup 1))))]
8471 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8472 "@
8473 ptabs %1, %0
8474 pt %1, %0"
8475 [(set_attr "type" "ptabs_media,pt_media")
8476 (set_attr "length" "4,*")])
8477
8478 (define_insn "*movsi_y"
8479 [(set (match_operand:SI 0 "register_operand" "=y,y")
8480 (match_operand:SI 1 "immediate_operand" "Qi,I08"))
8481 (clobber (match_scratch:SI 2 "=&z,r"))]
8482 "TARGET_SH2E
8483 && (reload_in_progress || reload_completed)"
8484 "#"
8485 [(set_attr "length" "4")
8486 (set_attr "type" "pcload,move")])
8487
8488 (define_split
8489 [(set (match_operand:SI 0 "register_operand" "")
8490 (match_operand:SI 1 "immediate_operand" ""))
8491 (clobber (match_operand:SI 2 "register_operand" ""))]
8492 "TARGET_SH1"
8493 [(set (match_dup 2) (match_dup 1))
8494 (set (match_dup 0) (match_dup 2))]
8495 "")
8496 \f
8497 ;; ------------------------------------------------------------------------
8498 ;; Define the real conditional branch instructions.
8499 ;; ------------------------------------------------------------------------
8500
8501 (define_expand "branch_true"
8502 [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
8503 (label_ref (match_operand 0))
8504 (pc)))]
8505 "TARGET_SH1")
8506
8507 (define_expand "branch_false"
8508 [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8509 (label_ref (match_operand 0))
8510 (pc)))]
8511 "TARGET_SH1")
8512
8513 (define_insn_and_split "*cbranch_t"
8514 [(set (pc) (if_then_else (match_operand 1 "cbranch_treg_value")
8515 (label_ref (match_operand 0))
8516 (pc)))]
8517 "TARGET_SH1"
8518 {
8519 return output_branch (sh_eval_treg_value (operands[1]), insn, operands);
8520 }
8521 "&& 1"
8522 [(const_int 0)]
8523 {
8524 /* Try to canonicalize the branch condition if it is not one of:
8525 (ne (reg:SI T_REG) (const_int 0))
8526 (eq (reg:SI T_REG) (const_int 0))
8527
8528 Instead of splitting out a new insn, we modify the current insn's
8529 operands as needed. This preserves things such as REG_DEAD notes. */
8530
8531 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
8532 && REG_P (XEXP (operands[1], 0)) && REGNO (XEXP (operands[1], 0)) == T_REG
8533 && XEXP (operands[1], 1) == const0_rtx)
8534 DONE;
8535
8536 int branch_cond = sh_eval_treg_value (operands[1]);
8537 rtx new_cond_rtx = NULL_RTX;
8538
8539 if (branch_cond == 0)
8540 new_cond_rtx = gen_rtx_EQ (VOIDmode, get_t_reg_rtx (), const0_rtx);
8541 else if (branch_cond == 1)
8542 new_cond_rtx = gen_rtx_NE (VOIDmode, get_t_reg_rtx (), const0_rtx);
8543
8544 if (new_cond_rtx != NULL_RTX)
8545 validate_change (curr_insn, &XEXP (XEXP (PATTERN (curr_insn), 1), 0),
8546 new_cond_rtx, false);
8547 DONE;
8548 }
8549 [(set_attr "type" "cbranch")])
8550
8551 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
8552 ;; which destination is too far away.
8553 ;; The const_int_operand is distinct for each branch target; it avoids
8554 ;; unwanted matches with redundant_insn.
8555 (define_insn "block_branch_redirect"
8556 [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
8557 "TARGET_SH1"
8558 ""
8559 [(set_attr "length" "0")])
8560
8561 ;; This one has the additional purpose to record a possible scratch register
8562 ;; for the following branch.
8563 ;; ??? Unfortunately, just setting the scratch register is not good enough,
8564 ;; because the insn then might be deemed dead and deleted. And we can't
8565 ;; make the use in the jump insn explicit because that would disable
8566 ;; delay slot scheduling from the target.
8567 (define_insn "indirect_jump_scratch"
8568 [(set (match_operand:SI 0 "register_operand" "=r")
8569 (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
8570 (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
8571 "TARGET_SH1"
8572 ""
8573 [(set_attr "length" "0")])
8574
8575 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
8576 ;; being pulled into the delay slot of a condbranch that has been made to
8577 ;; jump around the unconditional jump because it was out of range.
8578 (define_insn "stuff_delay_slot"
8579 [(set (pc)
8580 (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
8581 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
8582 "TARGET_SH1"
8583 ""
8584 [(set_attr "length" "0")
8585 (set_attr "cond_delay_slot" "yes")])
8586 \f
8587 ;; Conditional branch insns
8588
8589 (define_expand "cbranchint4_media"
8590 [(set (pc)
8591 (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
8592 [(match_operand 1 "" "")
8593 (match_operand 2 "" "")])
8594 (match_operand 3 "" "")
8595 (pc)))]
8596 "TARGET_SHMEDIA"
8597 {
8598 enum machine_mode mode = GET_MODE (operands[1]);
8599 if (mode == VOIDmode)
8600 mode = GET_MODE (operands[2]);
8601 if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
8602 {
8603 operands[1] = force_reg (mode, operands[1]);
8604 if (CONSTANT_P (operands[2])
8605 && (! satisfies_constraint_I06 (operands[2])))
8606 operands[2] = force_reg (mode, operands[2]);
8607 }
8608 else
8609 {
8610 if (operands[1] != const0_rtx)
8611 operands[1] = force_reg (mode, operands[1]);
8612 if (operands[2] != const0_rtx)
8613 operands[2] = force_reg (mode, operands[2]);
8614 }
8615 switch (GET_CODE (operands[0]))
8616 {
8617 case LEU:
8618 case LE:
8619 case LTU:
8620 case LT:
8621 operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
8622 VOIDmode, operands[2], operands[1]);
8623 operands[1] = XEXP (operands[0], 0);
8624 operands[2] = XEXP (operands[0], 1);
8625 break;
8626 default:
8627 operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
8628 VOIDmode, operands[1], operands[2]);
8629 break;
8630 }
8631 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
8632 })
8633
8634 (define_expand "cbranchfp4_media"
8635 [(set (pc)
8636 (if_then_else (match_operator 0 "sh_float_comparison_operator"
8637 [(match_operand 1 "" "")
8638 (match_operand 2 "" "")])
8639 (match_operand 3 "" "")
8640 (pc)))]
8641 "TARGET_SHMEDIA"
8642 {
8643 rtx tmp = gen_reg_rtx (SImode);
8644 rtx cmp;
8645 if (GET_CODE (operands[0]) == NE)
8646 cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
8647 else
8648 cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
8649 operands[1], operands[2]);
8650
8651 emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
8652
8653 if (GET_CODE (cmp) == GET_CODE (operands[0]))
8654 operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
8655 else
8656 operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
8657 operands[1] = tmp;
8658 operands[2] = const0_rtx;
8659 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
8660 })
8661
8662 (define_insn "*beq_media_i"
8663 [(set (pc)
8664 (if_then_else (match_operator 3 "equality_comparison_operator"
8665 [(match_operand:DI 1 "arith_reg_operand" "r,r")
8666 (match_operand:DI 2 "arith_operand" "r,I06")])
8667 (match_operand 0 "target_operand" "b,b")
8668 (pc)))]
8669 "TARGET_SHMEDIA"
8670 "@
8671 b%o3%' %1, %2, %0%>
8672 b%o3i%' %1, %2, %0%>"
8673 [(set_attr "type" "cbranch_media")])
8674
8675 (define_insn "*beq_media_i32"
8676 [(set (pc)
8677 (if_then_else (match_operator 3 "equality_comparison_operator"
8678 [(match_operand:SI 1 "arith_reg_operand" "r,r")
8679 (match_operand:SI 2 "arith_operand" "r,I06")])
8680 (match_operand 0 "target_operand" "b,b")
8681 (pc)))]
8682 "TARGET_SHMEDIA"
8683 "@
8684 b%o3%' %1, %2, %0%>
8685 b%o3i%' %1, %2, %0%>"
8686 [(set_attr "type" "cbranch_media")])
8687
8688 (define_insn "*bgt_media_i"
8689 [(set (pc)
8690 (if_then_else (match_operator 3 "greater_comparison_operator"
8691 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8692 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
8693 (match_operand 0 "target_operand" "b")
8694 (pc)))]
8695 "TARGET_SHMEDIA"
8696 "b%o3%' %N1, %N2, %0%>"
8697 [(set_attr "type" "cbranch_media")])
8698
8699 (define_insn "*bgt_media_i32"
8700 [(set (pc)
8701 (if_then_else (match_operator 3 "greater_comparison_operator"
8702 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8703 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8704 (match_operand 0 "target_operand" "b")
8705 (pc)))]
8706 "TARGET_SHMEDIA"
8707 "b%o3%' %N1, %N2, %0%>"
8708 [(set_attr "type" "cbranch_media")])
8709
8710 ;; These are only needed to make invert_jump() happy - otherwise, jump
8711 ;; optimization will be silently disabled.
8712 (define_insn "*blt_media_i"
8713 [(set (pc)
8714 (if_then_else (match_operator 3 "less_comparison_operator"
8715 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8716 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
8717 (match_operand 0 "target_operand" "b")
8718 (pc)))]
8719 "TARGET_SHMEDIA"
8720 "b%o3%' %N2, %N1, %0%>"
8721 [(set_attr "type" "cbranch_media")])
8722
8723 (define_insn "*blt_media_i32"
8724 [(set (pc)
8725 (if_then_else (match_operator 3 "less_comparison_operator"
8726 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8727 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8728 (match_operand 0 "target_operand" "b")
8729 (pc)))]
8730 "TARGET_SHMEDIA"
8731 "b%o3%' %N2, %N1, %0%>"
8732 [(set_attr "type" "cbranch_media")])
8733
8734 ;; combiner splitter for test-and-branch on single bit in register. This
8735 ;; is endian dependent because the non-paradoxical subreg looks different
8736 ;; on big endian.
8737 (define_split
8738 [(set (pc)
8739 (if_then_else
8740 (match_operator 3 "equality_comparison_operator"
8741 [(subreg:SI
8742 (zero_extract:DI
8743 (subreg:DI (match_operand:SI 1 "extend_reg_operand" "") 0)
8744 (const_int 1)
8745 (match_operand 2 "const_int_operand" "")) 0)
8746 (const_int 0)])
8747 (match_operand 0 "target_operand" "")
8748 (pc)))
8749 (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
8750 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
8751 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
8752 (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
8753 {
8754 operands[5] = GEN_INT (31 - INTVAL (operands[2]));
8755 operands[6] = (GET_CODE (operands[3]) == EQ
8756 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
8757 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
8758 })
8759
8760 ; operand 0 is the loop count pseudo register
8761 ; operand 1 is the label to jump to at the top of the loop
8762 (define_expand "doloop_end"
8763 [(parallel [(set (pc)
8764 (if_then_else (ne:SI (match_operand:SI 0 "" "")
8765 (const_int 1))
8766 (label_ref (match_operand 1 "" ""))
8767 (pc)))
8768 (set (match_dup 0)
8769 (plus:SI (match_dup 0) (const_int -1)))
8770 (clobber (reg:SI T_REG))])]
8771 "TARGET_SH2"
8772 {
8773 if (GET_MODE (operands[0]) != SImode)
8774 FAIL;
8775 emit_jump_insn (gen_doloop_end_split (operands[0], operands[1], operands[0]));
8776 DONE;
8777 })
8778
8779 (define_insn_and_split "doloop_end_split"
8780 [(set (pc)
8781 (if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0")
8782 (const_int 1))
8783 (label_ref (match_operand 1 "" ""))
8784 (pc)))
8785 (set (match_operand:SI 0 "arith_reg_dest" "=r")
8786 (plus:SI (match_dup 2) (const_int -1)))
8787 (clobber (reg:SI T_REG))]
8788 "TARGET_SH2"
8789 "#"
8790 ""
8791 [(parallel [(set (reg:SI T_REG)
8792 (eq:SI (match_dup 2) (const_int 1)))
8793 (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
8794 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8795 (label_ref (match_dup 1))
8796 (pc)))]
8797 ""
8798 [(set_attr "type" "cbranch")])
8799 \f
8800 ;; ------------------------------------------------------------------------
8801 ;; Jump and linkage insns
8802 ;; ------------------------------------------------------------------------
8803
8804 (define_insn "jump_compact"
8805 [(set (pc)
8806 (label_ref (match_operand 0 "" "")))]
8807 "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
8808 {
8809 /* The length is 16 if the delay slot is unfilled. */
8810 if (get_attr_length(insn) > 4)
8811 return output_far_jump(insn, operands[0]);
8812 else
8813 return "bra %l0%#";
8814 }
8815 [(set_attr "type" "jump")
8816 (set_attr "needs_delay_slot" "yes")])
8817
8818 ;; ??? It would be much saner to explicitly use the scratch register
8819 ;; in the jump insn, and have indirect_jump_scratch only set it,
8820 ;; but fill_simple_delay_slots would refuse to do delay slot filling
8821 ;; from the target then, as it uses simplejump_p.
8822 ;;(define_insn "jump_compact_far"
8823 ;; [(set (pc)
8824 ;; (label_ref (match_operand 0 "" "")))
8825 ;; (use (match_operand 1 "register_operand" "r")]
8826 ;; "TARGET_SH1"
8827 ;; "* return output_far_jump(insn, operands[0], operands[1]);"
8828 ;; [(set_attr "type" "jump")
8829 ;; (set_attr "needs_delay_slot" "yes")])
8830
8831 (define_insn "jump_media"
8832 [(set (pc)
8833 (match_operand 0 "target_operand" "b"))]
8834 "TARGET_SHMEDIA"
8835 "blink %0, r63%>"
8836 [(set_attr "type" "jump_media")])
8837
8838 (define_expand "jump"
8839 [(set (pc)
8840 (label_ref (match_operand 0 "" "")))]
8841 ""
8842 {
8843 if (TARGET_SH1)
8844 emit_jump_insn (gen_jump_compact (operands[0]));
8845 else if (TARGET_SHMEDIA)
8846 {
8847 if (reload_in_progress || reload_completed)
8848 FAIL;
8849 emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode, operands[0])));
8850 }
8851 DONE;
8852 })
8853
8854 (define_insn "force_mode_for_call"
8855 [(use (reg:PSI FPSCR_REG))]
8856 "TARGET_SHCOMPACT"
8857 ""
8858 [(set_attr "length" "0")
8859 (set (attr "fp_mode")
8860 (if_then_else (eq_attr "fpu_single" "yes")
8861 (const_string "single") (const_string "double")))])
8862
8863 (define_insn "calli"
8864 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8865 (match_operand 1 "" ""))
8866 (use (reg:PSI FPSCR_REG))
8867 (clobber (reg:SI PR_REG))]
8868 "TARGET_SH1"
8869 {
8870 if (TARGET_SH2A && (dbr_sequence_length () == 0))
8871 return "jsr/n @%0";
8872 else
8873 return "jsr @%0%#";
8874 }
8875 [(set_attr "type" "call")
8876 (set (attr "fp_mode")
8877 (if_then_else (eq_attr "fpu_single" "yes")
8878 (const_string "single") (const_string "double")))
8879 (set_attr "needs_delay_slot" "yes")
8880 (set_attr "fp_set" "unknown")])
8881
8882 ;; This is TBR relative jump instruction for SH2A architecture.
8883 ;; Its use is enabled by assigning an attribute "function_vector"
8884 ;; and the vector number to a function during its declaration.
8885 (define_insn "calli_tbr_rel"
8886 [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
8887 (match_operand 1 "" ""))
8888 (use (reg:PSI FPSCR_REG))
8889 (clobber (reg:SI PR_REG))]
8890 "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
8891 {
8892 unsigned HOST_WIDE_INT vect_num;
8893 vect_num = sh2a_get_function_vector_number (operands[0]);
8894 operands[2] = GEN_INT (vect_num * 4);
8895
8896 return "jsr/n @@(%O2,tbr)";
8897 }
8898 [(set_attr "type" "call")
8899 (set (attr "fp_mode")
8900 (if_then_else (eq_attr "fpu_single" "yes")
8901 (const_string "single") (const_string "double")))
8902 (set_attr "needs_delay_slot" "no")
8903 (set_attr "fp_set" "unknown")])
8904
8905 ;; This is a pc-rel call, using bsrf, for use with PIC.
8906 (define_insn "calli_pcrel"
8907 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8908 (match_operand 1 "" ""))
8909 (use (reg:PSI FPSCR_REG))
8910 (use (reg:SI PIC_REG))
8911 (use (match_operand 2 "" ""))
8912 (clobber (reg:SI PR_REG))]
8913 "TARGET_SH2"
8914 {
8915 return "bsrf %0" "\n"
8916 "%O2:%#";
8917 }
8918 [(set_attr "type" "call")
8919 (set (attr "fp_mode")
8920 (if_then_else (eq_attr "fpu_single" "yes")
8921 (const_string "single") (const_string "double")))
8922 (set_attr "needs_delay_slot" "yes")
8923 (set_attr "fp_set" "unknown")])
8924
8925 (define_insn_and_split "call_pcrel"
8926 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
8927 (match_operand 1 "" ""))
8928 (use (reg:PSI FPSCR_REG))
8929 (use (reg:SI PIC_REG))
8930 (clobber (reg:SI PR_REG))
8931 (clobber (match_scratch:SI 2 "=r"))]
8932 "TARGET_SH2"
8933 "#"
8934 "reload_completed"
8935 [(const_int 0)]
8936 {
8937 rtx lab = PATTERN (gen_call_site ());
8938
8939 if (SYMBOL_REF_LOCAL_P (operands[0]))
8940 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
8941 else
8942 emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
8943 emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
8944 DONE;
8945 }
8946 [(set_attr "type" "call")
8947 (set (attr "fp_mode")
8948 (if_then_else (eq_attr "fpu_single" "yes")
8949 (const_string "single") (const_string "double")))
8950 (set_attr "needs_delay_slot" "yes")
8951 (set_attr "fp_set" "unknown")])
8952
8953 (define_insn "call_compact"
8954 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8955 (match_operand 1 "" ""))
8956 (match_operand 2 "immediate_operand" "n")
8957 (use (reg:SI R0_REG))
8958 (use (reg:SI R1_REG))
8959 (use (reg:PSI FPSCR_REG))
8960 (clobber (reg:SI PR_REG))]
8961 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8962 "jsr @%0%#"
8963 [(set_attr "type" "call")
8964 (set (attr "fp_mode")
8965 (if_then_else (eq_attr "fpu_single" "yes")
8966 (const_string "single") (const_string "double")))
8967 (set_attr "needs_delay_slot" "yes")])
8968
8969 (define_insn "call_compact_rettramp"
8970 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8971 (match_operand 1 "" ""))
8972 (match_operand 2 "immediate_operand" "n")
8973 (use (reg:SI R0_REG))
8974 (use (reg:SI R1_REG))
8975 (use (reg:PSI FPSCR_REG))
8976 (clobber (reg:SI R10_REG))
8977 (clobber (reg:SI PR_REG))]
8978 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8979 "jsr @%0%#"
8980 [(set_attr "type" "call")
8981 (set (attr "fp_mode")
8982 (if_then_else (eq_attr "fpu_single" "yes")
8983 (const_string "single") (const_string "double")))
8984 (set_attr "needs_delay_slot" "yes")])
8985
8986 (define_insn "call_media"
8987 [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
8988 (match_operand 1 "" ""))
8989 (clobber (reg:DI PR_MEDIA_REG))]
8990 "TARGET_SHMEDIA"
8991 "blink %0, r18"
8992 [(set_attr "type" "jump_media")])
8993
8994 (define_insn "call_valuei"
8995 [(set (match_operand 0 "" "=rf")
8996 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8997 (match_operand 2 "" "")))
8998 (use (reg:PSI FPSCR_REG))
8999 (clobber (reg:SI PR_REG))]
9000 "TARGET_SH1"
9001 {
9002 if (TARGET_SH2A && (dbr_sequence_length () == 0))
9003 return "jsr/n @%1";
9004 else
9005 return "jsr @%1%#";
9006 }
9007 [(set_attr "type" "call")
9008 (set (attr "fp_mode")
9009 (if_then_else (eq_attr "fpu_single" "yes")
9010 (const_string "single") (const_string "double")))
9011 (set_attr "needs_delay_slot" "yes")
9012 (set_attr "fp_set" "unknown")])
9013
9014 ;; This is TBR relative jump instruction for SH2A architecture.
9015 ;; Its use is enabled by assigning an attribute "function_vector"
9016 ;; and the vector number to a function during its declaration.
9017 (define_insn "call_valuei_tbr_rel"
9018 [(set (match_operand 0 "" "=rf")
9019 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9020 (match_operand 2 "" "")))
9021 (use (reg:PSI FPSCR_REG))
9022 (clobber (reg:SI PR_REG))]
9023 "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
9024 {
9025 unsigned HOST_WIDE_INT vect_num;
9026 vect_num = sh2a_get_function_vector_number (operands[1]);
9027 operands[3] = GEN_INT (vect_num * 4);
9028
9029 return "jsr/n @@(%O3,tbr)";
9030 }
9031 [(set_attr "type" "call")
9032 (set (attr "fp_mode")
9033 (if_then_else (eq_attr "fpu_single" "yes")
9034 (const_string "single") (const_string "double")))
9035 (set_attr "needs_delay_slot" "no")
9036 (set_attr "fp_set" "unknown")])
9037
9038 (define_insn "call_valuei_pcrel"
9039 [(set (match_operand 0 "" "=rf")
9040 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9041 (match_operand 2 "" "")))
9042 (use (reg:PSI FPSCR_REG))
9043 (use (reg:SI PIC_REG))
9044 (use (match_operand 3 "" ""))
9045 (clobber (reg:SI PR_REG))]
9046 "TARGET_SH2"
9047 {
9048 return "bsrf %1" "\n"
9049 "%O3:%#";
9050 }
9051 [(set_attr "type" "call")
9052 (set (attr "fp_mode")
9053 (if_then_else (eq_attr "fpu_single" "yes")
9054 (const_string "single") (const_string "double")))
9055 (set_attr "needs_delay_slot" "yes")
9056 (set_attr "fp_set" "unknown")])
9057
9058 (define_insn_and_split "call_value_pcrel"
9059 [(set (match_operand 0 "" "=rf")
9060 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9061 (match_operand 2 "" "")))
9062 (use (reg:PSI FPSCR_REG))
9063 (use (reg:SI PIC_REG))
9064 (clobber (reg:SI PR_REG))
9065 (clobber (match_scratch:SI 3 "=r"))]
9066 "TARGET_SH2"
9067 "#"
9068 "reload_completed"
9069 [(const_int 0)]
9070 {
9071 rtx lab = PATTERN (gen_call_site ());
9072
9073 if (SYMBOL_REF_LOCAL_P (operands[1]))
9074 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
9075 else
9076 emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
9077 emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
9078 operands[2], copy_rtx (lab)));
9079 DONE;
9080 }
9081 [(set_attr "type" "call")
9082 (set (attr "fp_mode")
9083 (if_then_else (eq_attr "fpu_single" "yes")
9084 (const_string "single") (const_string "double")))
9085 (set_attr "needs_delay_slot" "yes")
9086 (set_attr "fp_set" "unknown")])
9087
9088 (define_insn "call_value_compact"
9089 [(set (match_operand 0 "" "=rf")
9090 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9091 (match_operand 2 "" "")))
9092 (match_operand 3 "immediate_operand" "n")
9093 (use (reg:SI R0_REG))
9094 (use (reg:SI R1_REG))
9095 (use (reg:PSI FPSCR_REG))
9096 (clobber (reg:SI PR_REG))]
9097 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9098 "jsr @%1%#"
9099 [(set_attr "type" "call")
9100 (set (attr "fp_mode")
9101 (if_then_else (eq_attr "fpu_single" "yes")
9102 (const_string "single") (const_string "double")))
9103 (set_attr "needs_delay_slot" "yes")])
9104
9105 (define_insn "call_value_compact_rettramp"
9106 [(set (match_operand 0 "" "=rf")
9107 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9108 (match_operand 2 "" "")))
9109 (match_operand 3 "immediate_operand" "n")
9110 (use (reg:SI R0_REG))
9111 (use (reg:SI R1_REG))
9112 (use (reg:PSI FPSCR_REG))
9113 (clobber (reg:SI R10_REG))
9114 (clobber (reg:SI PR_REG))]
9115 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9116 "jsr @%1%#"
9117 [(set_attr "type" "call")
9118 (set (attr "fp_mode")
9119 (if_then_else (eq_attr "fpu_single" "yes")
9120 (const_string "single") (const_string "double")))
9121 (set_attr "needs_delay_slot" "yes")])
9122
9123 (define_insn "call_value_media"
9124 [(set (match_operand 0 "" "=rf")
9125 (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
9126 (match_operand 2 "" "")))
9127 (clobber (reg:DI PR_MEDIA_REG))]
9128 "TARGET_SHMEDIA"
9129 "blink %1, r18"
9130 [(set_attr "type" "jump_media")])
9131
9132 (define_expand "call"
9133 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9134 (match_operand 1 "" ""))
9135 (match_operand 2 "" "")
9136 (use (reg:PSI FPSCR_REG))
9137 (clobber (reg:SI PR_REG))])]
9138 ""
9139 {
9140 if (TARGET_SHMEDIA)
9141 {
9142 operands[0] = shmedia_prepare_call_address (operands[0], 0);
9143 emit_call_insn (gen_call_media (operands[0], operands[1]));
9144 DONE;
9145 }
9146 else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
9147 {
9148 rtx cookie_rtx = operands[2];
9149 long cookie = INTVAL (cookie_rtx);
9150 rtx func = XEXP (operands[0], 0);
9151 rtx r0, r1;
9152
9153 if (flag_pic)
9154 {
9155 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9156 {
9157 rtx reg = gen_reg_rtx (Pmode);
9158
9159 emit_insn (gen_symGOTPLT2reg (reg, func));
9160 func = reg;
9161 }
9162 else
9163 func = legitimize_pic_address (func, Pmode, 0);
9164 }
9165
9166 r0 = gen_rtx_REG (SImode, R0_REG);
9167 r1 = gen_rtx_REG (SImode, R1_REG);
9168
9169 /* Since such a call function may use all call-clobbered
9170 registers, we force a mode switch earlier, so that we don't
9171 run out of registers when adjusting fpscr for the call. */
9172 emit_insn (gen_force_mode_for_call ());
9173
9174 operands[0]
9175 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9176 operands[0] = force_reg (SImode, operands[0]);
9177
9178 emit_move_insn (r0, func);
9179 emit_move_insn (r1, cookie_rtx);
9180
9181 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9182 emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
9183 operands[2]));
9184 else
9185 emit_call_insn (gen_call_compact (operands[0], operands[1],
9186 operands[2]));
9187
9188 DONE;
9189 }
9190 else if (TARGET_SHCOMPACT && flag_pic
9191 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9192 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9193 {
9194 rtx reg = gen_reg_rtx (Pmode);
9195
9196 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
9197 XEXP (operands[0], 0) = reg;
9198 }
9199 if (!flag_pic && TARGET_SH2A
9200 && MEM_P (operands[0])
9201 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9202 {
9203 if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
9204 {
9205 emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
9206 operands[1]));
9207 DONE;
9208 }
9209 }
9210 if (flag_pic && TARGET_SH2
9211 && MEM_P (operands[0])
9212 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9213 {
9214 emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
9215 DONE;
9216 }
9217 else
9218 {
9219 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9220 operands[1] = operands[2];
9221 }
9222
9223 emit_call_insn (gen_calli (operands[0], operands[1]));
9224 DONE;
9225 })
9226
9227 (define_insn "call_pop_compact"
9228 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9229 (match_operand 1 "" ""))
9230 (match_operand 2 "immediate_operand" "n")
9231 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9232 (match_operand 3 "immediate_operand" "n")))
9233 (use (reg:SI R0_REG))
9234 (use (reg:SI R1_REG))
9235 (use (reg:PSI FPSCR_REG))
9236 (clobber (reg:SI PR_REG))]
9237 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9238 "jsr @%0%#"
9239 [(set_attr "type" "call")
9240 (set (attr "fp_mode")
9241 (if_then_else (eq_attr "fpu_single" "yes")
9242 (const_string "single") (const_string "double")))
9243 (set_attr "needs_delay_slot" "yes")])
9244
9245 (define_insn "call_pop_compact_rettramp"
9246 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9247 (match_operand 1 "" ""))
9248 (match_operand 2 "immediate_operand" "n")
9249 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9250 (match_operand 3 "immediate_operand" "n")))
9251 (use (reg:SI R0_REG))
9252 (use (reg:SI R1_REG))
9253 (use (reg:PSI FPSCR_REG))
9254 (clobber (reg:SI R10_REG))
9255 (clobber (reg:SI PR_REG))]
9256 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9257 "jsr @%0%#"
9258 [(set_attr "type" "call")
9259 (set (attr "fp_mode")
9260 (if_then_else (eq_attr "fpu_single" "yes")
9261 (const_string "single") (const_string "double")))
9262 (set_attr "needs_delay_slot" "yes")])
9263
9264 (define_expand "call_pop"
9265 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9266 (match_operand 1 "" ""))
9267 (match_operand 2 "" "")
9268 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9269 (match_operand 3 "" "")))])]
9270 "TARGET_SHCOMPACT"
9271 {
9272 rtx cookie_rtx;
9273 long cookie;
9274 rtx func;
9275 rtx r0, r1;
9276
9277 gcc_assert (operands[2] && INTVAL (operands[2]));
9278 cookie_rtx = operands[2];
9279 cookie = INTVAL (cookie_rtx);
9280 func = XEXP (operands[0], 0);
9281
9282 if (flag_pic)
9283 {
9284 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9285 {
9286 rtx reg = gen_reg_rtx (Pmode);
9287 emit_insn (gen_symGOTPLT2reg (reg, func));
9288 func = reg;
9289 }
9290 else
9291 func = legitimize_pic_address (func, Pmode, 0);
9292 }
9293
9294 r0 = gen_rtx_REG (SImode, R0_REG);
9295 r1 = gen_rtx_REG (SImode, R1_REG);
9296
9297 /* Since such a call function may use all call-clobbered
9298 registers, we force a mode switch earlier, so that we don't
9299 run out of registers when adjusting fpscr for the call. */
9300 emit_insn (gen_force_mode_for_call ());
9301
9302 operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9303 SFUNC_GOT);
9304 operands[0] = force_reg (SImode, operands[0]);
9305
9306 emit_move_insn (r0, func);
9307 emit_move_insn (r1, cookie_rtx);
9308
9309 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9310 emit_call_insn (gen_call_pop_compact_rettramp
9311 (operands[0], operands[1], operands[2], operands[3]));
9312 else
9313 emit_call_insn (gen_call_pop_compact
9314 (operands[0], operands[1], operands[2], operands[3]));
9315
9316 DONE;
9317 })
9318
9319 (define_expand "call_value"
9320 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9321 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9322 (match_operand 2 "" "")))
9323 (match_operand 3 "" "")
9324 (use (reg:PSI FPSCR_REG))
9325 (clobber (reg:SI PR_REG))])]
9326 ""
9327 {
9328 if (TARGET_SHMEDIA)
9329 {
9330 operands[1] = shmedia_prepare_call_address (operands[1], 0);
9331 emit_call_insn (gen_call_value_media (operands[0], operands[1],
9332 operands[2]));
9333 DONE;
9334 }
9335 else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
9336 {
9337 rtx cookie_rtx = operands[3];
9338 long cookie = INTVAL (cookie_rtx);
9339 rtx func = XEXP (operands[1], 0);
9340 rtx r0, r1;
9341
9342 if (flag_pic)
9343 {
9344 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9345 {
9346 rtx reg = gen_reg_rtx (Pmode);
9347
9348 emit_insn (gen_symGOTPLT2reg (reg, func));
9349 func = reg;
9350 }
9351 else
9352 func = legitimize_pic_address (func, Pmode, 0);
9353 }
9354
9355 r0 = gen_rtx_REG (SImode, R0_REG);
9356 r1 = gen_rtx_REG (SImode, R1_REG);
9357
9358 /* Since such a call function may use all call-clobbered
9359 registers, we force a mode switch earlier, so that we don't
9360 run out of registers when adjusting fpscr for the call. */
9361 emit_insn (gen_force_mode_for_call ());
9362
9363 operands[1]
9364 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9365 operands[1] = force_reg (SImode, operands[1]);
9366
9367 emit_move_insn (r0, func);
9368 emit_move_insn (r1, cookie_rtx);
9369
9370 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9371 emit_call_insn (gen_call_value_compact_rettramp (operands[0],
9372 operands[1],
9373 operands[2],
9374 operands[3]));
9375 else
9376 emit_call_insn (gen_call_value_compact (operands[0], operands[1],
9377 operands[2], operands[3]));
9378
9379 DONE;
9380 }
9381 else if (TARGET_SHCOMPACT && flag_pic
9382 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9383 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9384 {
9385 rtx reg = gen_reg_rtx (Pmode);
9386
9387 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
9388 XEXP (operands[1], 0) = reg;
9389 }
9390 if (!flag_pic && TARGET_SH2A
9391 && MEM_P (operands[1])
9392 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9393 {
9394 if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
9395 {
9396 emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
9397 XEXP (operands[1], 0), operands[2]));
9398 DONE;
9399 }
9400 }
9401 if (flag_pic && TARGET_SH2
9402 && MEM_P (operands[1])
9403 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9404 {
9405 emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
9406 operands[2]));
9407 DONE;
9408 }
9409 else
9410 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9411
9412 emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
9413 DONE;
9414 })
9415
9416 (define_insn "sibcalli"
9417 [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
9418 (match_operand 1 "" ""))
9419 (use (reg:PSI FPSCR_REG))
9420 (return)]
9421 "TARGET_SH1"
9422 "jmp @%0%#"
9423 [(set_attr "needs_delay_slot" "yes")
9424 (set (attr "fp_mode")
9425 (if_then_else (eq_attr "fpu_single" "yes")
9426 (const_string "single") (const_string "double")))
9427 (set_attr "type" "jump_ind")])
9428
9429 (define_insn "sibcalli_pcrel"
9430 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
9431 (match_operand 1 "" ""))
9432 (use (match_operand 2 "" ""))
9433 (use (reg:PSI FPSCR_REG))
9434 (return)]
9435 "TARGET_SH2"
9436 {
9437 return "braf %0" "\n"
9438 "%O2:%#";
9439 }
9440 [(set_attr "needs_delay_slot" "yes")
9441 (set (attr "fp_mode")
9442 (if_then_else (eq_attr "fpu_single" "yes")
9443 (const_string "single") (const_string "double")))
9444 (set_attr "type" "jump_ind")])
9445
9446 ;; This uses an unspec to describe that the symbol_ref is very close.
9447 (define_insn "sibcalli_thunk"
9448 [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
9449 UNSPEC_THUNK))
9450 (match_operand 1 "" ""))
9451 (use (reg:PSI FPSCR_REG))
9452 (return)]
9453 "TARGET_SH1"
9454 "bra %O0"
9455 [(set_attr "needs_delay_slot" "yes")
9456 (set (attr "fp_mode")
9457 (if_then_else (eq_attr "fpu_single" "yes")
9458 (const_string "single") (const_string "double")))
9459 (set_attr "type" "jump")
9460 (set_attr "length" "2")])
9461
9462 (define_insn_and_split "sibcall_pcrel"
9463 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
9464 (match_operand 1 "" ""))
9465 (use (reg:PSI FPSCR_REG))
9466 (clobber (match_scratch:SI 2 "=k"))
9467 (return)]
9468 "TARGET_SH2"
9469 "#"
9470 "reload_completed"
9471 [(const_int 0)]
9472 {
9473 rtx lab = PATTERN (gen_call_site ());
9474 rtx call_insn;
9475
9476 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
9477 call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
9478 copy_rtx (lab)));
9479 SIBLING_CALL_P (call_insn) = 1;
9480 DONE;
9481 }
9482 [(set_attr "needs_delay_slot" "yes")
9483 (set (attr "fp_mode")
9484 (if_then_else (eq_attr "fpu_single" "yes")
9485 (const_string "single") (const_string "double")))
9486 (set_attr "type" "jump_ind")])
9487
9488 (define_insn "sibcall_compact"
9489 [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
9490 (match_operand 1 "" ""))
9491 (return)
9492 (use (match_operand:SI 2 "register_operand" "z,x"))
9493 (use (reg:SI R1_REG))
9494 (use (reg:PSI FPSCR_REG))
9495 ;; We want to make sure the `x' above will only match MACH_REG
9496 ;; because sibcall_epilogue may clobber MACL_REG.
9497 (clobber (reg:SI MACL_REG))]
9498 "TARGET_SHCOMPACT"
9499 {
9500 static const char* alt[] =
9501 {
9502 "jmp @%0%#",
9503
9504 "jmp @%0" "\n"
9505 " sts %2,r0"
9506 };
9507 return alt[which_alternative];
9508 }
9509 [(set_attr "needs_delay_slot" "yes,no")
9510 (set_attr "length" "2,4")
9511 (set (attr "fp_mode") (const_string "single"))
9512 (set_attr "type" "jump_ind")])
9513
9514 (define_insn "sibcall_media"
9515 [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
9516 (match_operand 1 "" ""))
9517 (use (reg:SI PR_MEDIA_REG))
9518 (return)]
9519 "TARGET_SHMEDIA"
9520 "blink %0, r63"
9521 [(set_attr "type" "jump_media")])
9522
9523 (define_expand "sibcall"
9524 [(parallel
9525 [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9526 (match_operand 1 "" ""))
9527 (match_operand 2 "" "")
9528 (use (reg:PSI FPSCR_REG))
9529 (return)])]
9530 ""
9531 {
9532 if (TARGET_SHMEDIA)
9533 {
9534 operands[0] = shmedia_prepare_call_address (operands[0], 1);
9535 emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
9536 DONE;
9537 }
9538 else if (TARGET_SHCOMPACT && operands[2]
9539 && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9540 {
9541 rtx cookie_rtx = operands[2];
9542 long cookie = INTVAL (cookie_rtx);
9543 rtx func = XEXP (operands[0], 0);
9544 rtx mach, r1;
9545
9546 if (flag_pic)
9547 {
9548 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9549 {
9550 rtx reg = gen_reg_rtx (Pmode);
9551
9552 emit_insn (gen_symGOT2reg (reg, func));
9553 func = reg;
9554 }
9555 else
9556 func = legitimize_pic_address (func, Pmode, 0);
9557 }
9558
9559 /* FIXME: if we could tell whether all argument registers are
9560 already taken, we could decide whether to force the use of
9561 MACH_REG or to stick to R0_REG. Unfortunately, there's no
9562 simple way to tell. We could use the CALL_COOKIE, but we
9563 can't currently tell a register used for regular argument
9564 passing from one that is unused. If we leave it up to reload
9565 to decide which register to use, it seems to always choose
9566 R0_REG, which leaves no available registers in SIBCALL_REGS
9567 to hold the address of the trampoline. */
9568 mach = gen_rtx_REG (SImode, MACH_REG);
9569 r1 = gen_rtx_REG (SImode, R1_REG);
9570
9571 /* Since such a call function may use all call-clobbered
9572 registers, we force a mode switch earlier, so that we don't
9573 run out of registers when adjusting fpscr for the call. */
9574 emit_insn (gen_force_mode_for_call ());
9575
9576 operands[0]
9577 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9578 operands[0] = force_reg (SImode, operands[0]);
9579
9580 /* We don't need a return trampoline, since the callee will
9581 return directly to the upper caller. */
9582 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9583 {
9584 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9585 cookie_rtx = GEN_INT (cookie);
9586 }
9587
9588 emit_move_insn (mach, func);
9589 emit_move_insn (r1, cookie_rtx);
9590
9591 emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
9592 DONE;
9593 }
9594 else if (TARGET_SHCOMPACT && flag_pic
9595 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9596 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9597 {
9598 rtx reg = gen_reg_rtx (Pmode);
9599
9600 emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
9601 XEXP (operands[0], 0) = reg;
9602 }
9603 if (flag_pic && TARGET_SH2
9604 && MEM_P (operands[0])
9605 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9606 /* The PLT needs the PIC register, but the epilogue would have
9607 to restore it, so we can only use PC-relative PIC calls for
9608 static functions. */
9609 && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9610 {
9611 emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
9612 DONE;
9613 }
9614 else
9615 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9616
9617 emit_call_insn (gen_sibcalli (operands[0], operands[1]));
9618 DONE;
9619 })
9620
9621 (define_insn "sibcall_valuei"
9622 [(set (match_operand 0 "" "=rf")
9623 (call (mem:SI (match_operand:SI 1 "register_operand" "k"))
9624 (match_operand 2 "" "")))
9625 (use (reg:PSI FPSCR_REG))
9626 (return)]
9627 "TARGET_SH1"
9628 "jmp @%1%#"
9629 [(set_attr "needs_delay_slot" "yes")
9630 (set (attr "fp_mode")
9631 (if_then_else (eq_attr "fpu_single" "yes")
9632 (const_string "single") (const_string "double")))
9633 (set_attr "type" "jump_ind")])
9634
9635 (define_insn "sibcall_valuei_pcrel"
9636 [(set (match_operand 0 "" "=rf")
9637 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
9638 (match_operand 2 "" "")))
9639 (use (match_operand 3 "" ""))
9640 (use (reg:PSI FPSCR_REG))
9641 (return)]
9642 "TARGET_SH2"
9643 {
9644 return "braf %1" "\n"
9645 "%O3:%#";
9646 }
9647 [(set_attr "needs_delay_slot" "yes")
9648 (set (attr "fp_mode")
9649 (if_then_else (eq_attr "fpu_single" "yes")
9650 (const_string "single") (const_string "double")))
9651 (set_attr "type" "jump_ind")])
9652
9653 (define_insn_and_split "sibcall_value_pcrel"
9654 [(set (match_operand 0 "" "=rf")
9655 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9656 (match_operand 2 "" "")))
9657 (use (reg:PSI FPSCR_REG))
9658 (clobber (match_scratch:SI 3 "=k"))
9659 (return)]
9660 "TARGET_SH2"
9661 "#"
9662 "reload_completed"
9663 [(const_int 0)]
9664 {
9665 rtx lab = PATTERN (gen_call_site ());
9666 rtx call_insn;
9667
9668 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
9669 call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
9670 operands[3],
9671 operands[2],
9672 copy_rtx (lab)));
9673 SIBLING_CALL_P (call_insn) = 1;
9674 DONE;
9675 }
9676 [(set_attr "needs_delay_slot" "yes")
9677 (set (attr "fp_mode")
9678 (if_then_else (eq_attr "fpu_single" "yes")
9679 (const_string "single") (const_string "double")))
9680 (set_attr "type" "jump_ind")])
9681
9682 (define_insn "sibcall_value_compact"
9683 [(set (match_operand 0 "" "=rf,rf")
9684 (call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
9685 (match_operand 2 "" "")))
9686 (return)
9687 (use (match_operand:SI 3 "register_operand" "z,x"))
9688 (use (reg:SI R1_REG))
9689 (use (reg:PSI FPSCR_REG))
9690 ;; We want to make sure the `x' above will only match MACH_REG
9691 ;; because sibcall_epilogue may clobber MACL_REG.
9692 (clobber (reg:SI MACL_REG))]
9693 "TARGET_SHCOMPACT"
9694 {
9695 static const char* alt[] =
9696 {
9697 "jmp @%1%#",
9698
9699 "jmp @%1" "\n"
9700 " sts %3,r0"
9701 };
9702 return alt[which_alternative];
9703 }
9704 [(set_attr "needs_delay_slot" "yes,no")
9705 (set_attr "length" "2,4")
9706 (set (attr "fp_mode") (const_string "single"))
9707 (set_attr "type" "jump_ind")])
9708
9709 (define_insn "sibcall_value_media"
9710 [(set (match_operand 0 "" "=rf")
9711 (call (mem:DI (match_operand 1 "target_reg_operand" "k"))
9712 (match_operand 2 "" "")))
9713 (use (reg:SI PR_MEDIA_REG))
9714 (return)]
9715 "TARGET_SHMEDIA"
9716 "blink %1, r63"
9717 [(set_attr "type" "jump_media")])
9718
9719 (define_expand "sibcall_value"
9720 [(parallel
9721 [(set (match_operand 0 "arith_reg_operand" "")
9722 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9723 (match_operand 2 "" "")))
9724 (match_operand 3 "" "")
9725 (use (reg:PSI FPSCR_REG))
9726 (return)])]
9727 ""
9728 {
9729 if (TARGET_SHMEDIA)
9730 {
9731 operands[1] = shmedia_prepare_call_address (operands[1], 1);
9732 emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
9733 operands[2]));
9734 DONE;
9735 }
9736 else if (TARGET_SHCOMPACT && operands[3]
9737 && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9738 {
9739 rtx cookie_rtx = operands[3];
9740 long cookie = INTVAL (cookie_rtx);
9741 rtx func = XEXP (operands[1], 0);
9742 rtx mach, r1;
9743
9744 if (flag_pic)
9745 {
9746 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9747 {
9748 rtx reg = gen_reg_rtx (Pmode);
9749
9750 emit_insn (gen_symGOT2reg (reg, func));
9751 func = reg;
9752 }
9753 else
9754 func = legitimize_pic_address (func, Pmode, 0);
9755 }
9756
9757 /* FIXME: if we could tell whether all argument registers are
9758 already taken, we could decide whether to force the use of
9759 MACH_REG or to stick to R0_REG. Unfortunately, there's no
9760 simple way to tell. We could use the CALL_COOKIE, but we
9761 can't currently tell a register used for regular argument
9762 passing from one that is unused. If we leave it up to reload
9763 to decide which register to use, it seems to always choose
9764 R0_REG, which leaves no available registers in SIBCALL_REGS
9765 to hold the address of the trampoline. */
9766 mach = gen_rtx_REG (SImode, MACH_REG);
9767 r1 = gen_rtx_REG (SImode, R1_REG);
9768
9769 /* Since such a call function may use all call-clobbered
9770 registers, we force a mode switch earlier, so that we don't
9771 run out of registers when adjusting fpscr for the call. */
9772 emit_insn (gen_force_mode_for_call ());
9773
9774 operands[1]
9775 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9776 operands[1] = force_reg (SImode, operands[1]);
9777
9778 /* We don't need a return trampoline, since the callee will
9779 return directly to the upper caller. */
9780 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9781 {
9782 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9783 cookie_rtx = GEN_INT (cookie);
9784 }
9785
9786 emit_move_insn (mach, func);
9787 emit_move_insn (r1, cookie_rtx);
9788
9789 emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
9790 operands[2], mach));
9791 DONE;
9792 }
9793 else if (TARGET_SHCOMPACT && flag_pic
9794 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9795 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9796 {
9797 rtx reg = gen_reg_rtx (Pmode);
9798
9799 emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
9800 XEXP (operands[1], 0) = reg;
9801 }
9802 if (flag_pic && TARGET_SH2
9803 && MEM_P (operands[1])
9804 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9805 /* The PLT needs the PIC register, but the epilogue would have
9806 to restore it, so we can only use PC-relative PIC calls for
9807 static functions. */
9808 && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9809 {
9810 emit_call_insn (gen_sibcall_value_pcrel (operands[0],
9811 XEXP (operands[1], 0),
9812 operands[2]));
9813 DONE;
9814 }
9815 else
9816 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9817
9818 emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
9819 DONE;
9820 })
9821
9822 (define_insn "call_value_pop_compact"
9823 [(set (match_operand 0 "" "=rf")
9824 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9825 (match_operand 2 "" "")))
9826 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9827 (match_operand 4 "immediate_operand" "n")))
9828 (match_operand 3 "immediate_operand" "n")
9829 (use (reg:SI R0_REG))
9830 (use (reg:SI R1_REG))
9831 (use (reg:PSI FPSCR_REG))
9832 (clobber (reg:SI PR_REG))]
9833 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9834 "jsr @%1%#"
9835 [(set_attr "type" "call")
9836 (set (attr "fp_mode")
9837 (if_then_else (eq_attr "fpu_single" "yes")
9838 (const_string "single") (const_string "double")))
9839 (set_attr "needs_delay_slot" "yes")])
9840
9841 (define_insn "call_value_pop_compact_rettramp"
9842 [(set (match_operand 0 "" "=rf")
9843 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9844 (match_operand 2 "" "")))
9845 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9846 (match_operand 4 "immediate_operand" "n")))
9847 (match_operand 3 "immediate_operand" "n")
9848 (use (reg:SI R0_REG))
9849 (use (reg:SI R1_REG))
9850 (use (reg:PSI FPSCR_REG))
9851 (clobber (reg:SI R10_REG))
9852 (clobber (reg:SI PR_REG))]
9853 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9854 "jsr @%1%#"
9855 [(set_attr "type" "call")
9856 (set (attr "fp_mode")
9857 (if_then_else (eq_attr "fpu_single" "yes")
9858 (const_string "single") (const_string "double")))
9859 (set_attr "needs_delay_slot" "yes")])
9860
9861 (define_expand "call_value_pop"
9862 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9863 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9864 (match_operand 2 "" "")))
9865 (match_operand 3 "" "")
9866 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9867 (match_operand 4 "" "")))])]
9868 "TARGET_SHCOMPACT"
9869 {
9870 rtx cookie_rtx;
9871 long cookie;
9872 rtx func;
9873 rtx r0, r1;
9874
9875 gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
9876 cookie_rtx = operands[3];
9877 cookie = INTVAL (cookie_rtx);
9878 func = XEXP (operands[1], 0);
9879
9880 if (flag_pic)
9881 {
9882 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9883 {
9884 rtx reg = gen_reg_rtx (Pmode);
9885
9886 emit_insn (gen_symGOTPLT2reg (reg, func));
9887 func = reg;
9888 }
9889 else
9890 func = legitimize_pic_address (func, Pmode, 0);
9891 }
9892
9893 r0 = gen_rtx_REG (SImode, R0_REG);
9894 r1 = gen_rtx_REG (SImode, R1_REG);
9895
9896 /* Since such a call function may use all call-clobbered
9897 registers, we force a mode switch earlier, so that we don't
9898 run out of registers when adjusting fpscr for the call. */
9899 emit_insn (gen_force_mode_for_call ());
9900
9901 operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9902 SFUNC_GOT);
9903 operands[1] = force_reg (SImode, operands[1]);
9904
9905 emit_move_insn (r0, func);
9906 emit_move_insn (r1, cookie_rtx);
9907
9908 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9909 emit_call_insn (gen_call_value_pop_compact_rettramp
9910 (operands[0], operands[1], operands[2],
9911 operands[3], operands[4]));
9912 else
9913 emit_call_insn (gen_call_value_pop_compact
9914 (operands[0], operands[1], operands[2],
9915 operands[3], operands[4]));
9916
9917 DONE;
9918 })
9919
9920 (define_expand "sibcall_epilogue"
9921 [(return)]
9922 ""
9923 {
9924 sh_expand_epilogue (true);
9925 if (TARGET_SHCOMPACT)
9926 {
9927 rtx insn, set;
9928
9929 /* If epilogue clobbers r0, preserve it in macl. */
9930 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
9931 if ((set = single_set (insn))
9932 && REG_P (SET_DEST (set))
9933 && REGNO (SET_DEST (set)) == R0_REG)
9934 {
9935 rtx r0 = gen_rtx_REG (SImode, R0_REG);
9936 rtx tmp = gen_rtx_REG (SImode, MACL_REG);
9937
9938 /* We can't tell at this point whether the sibcall is a
9939 sibcall_compact and, if it is, whether it uses r0 or
9940 mach as operand 2, so let the instructions that
9941 preserve r0 be optimized away if r0 turns out to be
9942 dead. */
9943 emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
9944 emit_move_insn (r0, tmp);
9945 break;
9946 }
9947 }
9948 DONE;
9949 })
9950
9951 (define_insn "indirect_jump_compact"
9952 [(set (pc)
9953 (match_operand:SI 0 "arith_reg_operand" "r"))]
9954 "TARGET_SH1"
9955 "jmp @%0%#"
9956 [(set_attr "needs_delay_slot" "yes")
9957 (set_attr "type" "jump_ind")])
9958
9959 (define_expand "indirect_jump"
9960 [(set (pc)
9961 (match_operand 0 "register_operand" ""))]
9962 ""
9963 {
9964 if (GET_MODE (operands[0]) != Pmode)
9965 operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
9966 })
9967
9968 ;; The use of operand 1 / 2 helps us distinguish case table jumps
9969 ;; which can be present in structured code from indirect jumps which can not
9970 ;; be present in structured code. This allows -fprofile-arcs to work.
9971
9972 ;; For SH1 processors.
9973 (define_insn "casesi_jump_1"
9974 [(set (pc)
9975 (match_operand:SI 0 "register_operand" "r"))
9976 (use (label_ref (match_operand 1 "" "")))]
9977 "TARGET_SH1"
9978 "jmp @%0%#"
9979 [(set_attr "needs_delay_slot" "yes")
9980 (set_attr "type" "jump_ind")])
9981
9982 ;; For all later processors.
9983 (define_insn "casesi_jump_2"
9984 [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
9985 (label_ref (match_operand 1 "" ""))))
9986 (use (label_ref (match_operand 2 "" "")))]
9987 "TARGET_SH2
9988 && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
9989 "braf %0%#"
9990 [(set_attr "needs_delay_slot" "yes")
9991 (set_attr "type" "jump_ind")])
9992
9993 (define_insn "casesi_jump_media"
9994 [(set (pc) (match_operand 0 "target_reg_operand" "b"))
9995 (use (label_ref (match_operand 1 "" "")))]
9996 "TARGET_SHMEDIA"
9997 "blink %0, r63"
9998 [(set_attr "type" "jump_media")])
9999
10000 ;; Call subroutine returning any type.
10001 ;; ??? This probably doesn't work.
10002 (define_expand "untyped_call"
10003 [(parallel [(call (match_operand 0 "" "")
10004 (const_int 0))
10005 (match_operand 1 "" "")
10006 (match_operand 2 "" "")])]
10007 "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
10008 {
10009 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
10010
10011 for (int i = 0; i < XVECLEN (operands[2], 0); i++)
10012 {
10013 rtx set = XVECEXP (operands[2], 0, i);
10014 emit_move_insn (SET_DEST (set), SET_SRC (set));
10015 }
10016
10017 /* The optimizer does not know that the call sets the function value
10018 registers we stored in the result block. We avoid problems by
10019 claiming that all hard registers are used and clobbered at this
10020 point. */
10021 emit_insn (gen_blockage ());
10022
10023 DONE;
10024 })
10025 \f
10026 ;; ------------------------------------------------------------------------
10027 ;; Misc insns
10028 ;; ------------------------------------------------------------------------
10029
10030 (define_insn "dect"
10031 [(set (reg:SI T_REG)
10032 (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
10033 (set (match_operand:SI 0 "arith_reg_dest" "=r")
10034 (plus:SI (match_dup 1) (const_int -1)))]
10035 "TARGET_SH2"
10036 "dt %0"
10037 [(set_attr "type" "arith")])
10038
10039 (define_insn "nop"
10040 [(const_int 0)]
10041 ""
10042 "nop")
10043
10044 ;; Load address of a label. This is only generated by the casesi expand,
10045 ;; and by machine_dependent_reorg (fixing up fp moves).
10046 ;; This must use unspec, because this only works for labels that are
10047 ;; within range.
10048 (define_insn "mova"
10049 [(set (reg:SI R0_REG)
10050 (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
10051 "TARGET_SH1"
10052 "mova %O0,r0"
10053 [(set_attr "in_delay_slot" "no")
10054 (set_attr "type" "arith")])
10055
10056 ;; machine_dependent_reorg will make this a `mova'.
10057 (define_insn "mova_const"
10058 [(set (reg:SI R0_REG)
10059 (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
10060 "TARGET_SH1"
10061 "#"
10062 [(set_attr "in_delay_slot" "no")
10063 (set_attr "type" "arith")])
10064
10065 (define_expand "GOTaddr2picreg"
10066 [(set (reg:SI R0_REG)
10067 (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
10068 UNSPEC_MOVA))
10069 (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
10070 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
10071 ""
10072 {
10073 if (TARGET_VXWORKS_RTP)
10074 {
10075 rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
10076 rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
10077 emit_insn (gen_vxworks_picreg (gott_base, gott_index));
10078 DONE;
10079 }
10080
10081 operands[0] = gen_rtx_REG (Pmode, PIC_REG);
10082 operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
10083
10084 if (TARGET_SHMEDIA)
10085 {
10086 rtx tr = gen_rtx_REG (Pmode, TR0_REG);
10087 rtx pic = operands[0];
10088 rtx lab = PATTERN (gen_call_site ());
10089 rtx insn, equiv;
10090
10091 equiv = operands[1];
10092 operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
10093 UNSPEC_PCREL_SYMOFF);
10094 operands[1] = gen_rtx_CONST (Pmode, operands[1]);
10095
10096 if (Pmode == SImode)
10097 {
10098 emit_insn (gen_movsi_const (pic, operands[1]));
10099 emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
10100 }
10101 else
10102 {
10103 emit_insn (gen_movdi_const (pic, operands[1]));
10104 emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
10105 }
10106
10107 insn = emit_move_insn (operands[0], tr);
10108
10109 set_unique_reg_note (insn, REG_EQUAL, equiv);
10110
10111 DONE;
10112 }
10113 })
10114
10115 ;; A helper for GOTaddr2picreg to finish up the initialization of the
10116 ;; PIC register.
10117 (define_expand "vxworks_picreg"
10118 [(set (reg:SI PIC_REG)
10119 (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
10120 (set (reg:SI R0_REG)
10121 (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
10122 (set (reg:SI PIC_REG)
10123 (mem:SI (reg:SI PIC_REG)))
10124 (set (reg:SI PIC_REG)
10125 (mem:SI (plus:SI (reg:SI PIC_REG)
10126 (reg:SI R0_REG))))]
10127 "TARGET_VXWORKS_RTP")
10128
10129 (define_insn "*ptb"
10130 [(set (match_operand 0 "target_reg_operand" "=b")
10131 (const (unspec [(match_operand 1 "" "Csy")]
10132 UNSPEC_DATALABEL)))]
10133 "TARGET_SHMEDIA && flag_pic
10134 && satisfies_constraint_Csy (operands[1])"
10135 "ptb/u datalabel %1, %0"
10136 [(set_attr "type" "ptabs_media")
10137 (set_attr "length" "*")])
10138
10139 (define_insn "ptrel_si"
10140 [(set (match_operand:SI 0 "target_reg_operand" "=b")
10141 (plus:SI (match_operand:SI 1 "register_operand" "r")
10142 (pc)))
10143 (match_operand:SI 2 "" "")]
10144 "TARGET_SHMEDIA"
10145 "%O2: ptrel/u %1, %0"
10146 [(set_attr "type" "ptabs_media")])
10147
10148 (define_insn "ptrel_di"
10149 [(set (match_operand:DI 0 "target_reg_operand" "=b")
10150 (plus:DI (match_operand:DI 1 "register_operand" "r")
10151 (pc)))
10152 (match_operand:DI 2 "" "")]
10153 "TARGET_SHMEDIA"
10154 "%O2: ptrel/u %1, %0"
10155 [(set_attr "type" "ptabs_media")])
10156
10157 (define_expand "builtin_setjmp_receiver"
10158 [(match_operand 0 "" "")]
10159 "flag_pic"
10160 {
10161 emit_insn (gen_GOTaddr2picreg ());
10162 DONE;
10163 })
10164
10165 (define_expand "call_site"
10166 [(unspec [(match_dup 0)] UNSPEC_CALLER)]
10167 "TARGET_SH1"
10168 {
10169 static HOST_WIDE_INT i = 0;
10170 operands[0] = GEN_INT (i);
10171 i++;
10172 })
10173
10174 ;; op0 = op1 + r12 but hide it before reload completed. See the comment
10175 ;; in symGOT_load expand.
10176 (define_insn_and_split "chk_guard_add"
10177 [(set (match_operand:SI 0 "register_operand" "=&r")
10178 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
10179 (reg:SI PIC_REG)]
10180 UNSPEC_CHKADD))]
10181 "TARGET_SH1"
10182 "#"
10183 "TARGET_SH1 && reload_completed"
10184 [(set (match_dup 0) (reg:SI PIC_REG))
10185 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
10186 ""
10187 [(set_attr "type" "arith")])
10188
10189 (define_expand "sym_label2reg"
10190 [(set (match_operand:SI 0 "" "")
10191 (const:SI (unspec:SI [(match_operand:SI 1 "" "")
10192 (const (plus:SI (match_operand:SI 2 "" "")
10193 (const_int 2)))]
10194 UNSPEC_SYMOFF)))]
10195 "TARGET_SH1" "")
10196
10197 (define_expand "symGOT_load"
10198 [(set (match_dup 2) (match_operand 1 "" ""))
10199 (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
10200 (set (match_operand 0 "" "") (mem (match_dup 3)))]
10201 ""
10202 {
10203 rtx mem;
10204
10205 operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10206 operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10207
10208 if (TARGET_SHMEDIA)
10209 {
10210 rtx reg = operands[2];
10211
10212 if (Pmode == DImode)
10213 {
10214 if (flag_pic > 1)
10215 emit_insn (gen_movdi_const_32bit (reg, operands[1]));
10216 else
10217 emit_insn (gen_movdi_const_16bit (reg, operands[1]));
10218 }
10219 else
10220 {
10221 if (flag_pic > 1)
10222 emit_insn (gen_movsi_const (reg, operands[1]));
10223 else
10224 emit_insn (gen_movsi_const_16bit (reg, operands[1]));
10225 }
10226 }
10227 else
10228 emit_move_insn (operands[2], operands[1]);
10229
10230 /* When stack protector inserts codes after the result is set to
10231 R0, @(rX, r12) will cause a spill failure for R0. Use a unspec
10232 insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
10233 when rX is a GOT address for the guard symbol. Ugly but doesn't
10234 matter because this is a rare situation. */
10235 if (!TARGET_SHMEDIA
10236 && flag_stack_protect
10237 && GET_CODE (operands[1]) == CONST
10238 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
10239 && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
10240 && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
10241 "__stack_chk_guard") == 0)
10242 emit_insn (gen_chk_guard_add (operands[3], operands[2]));
10243 else
10244 emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
10245 gen_rtx_REG (Pmode, PIC_REG)));
10246
10247 /* N.B. This is not constant for a GOTPLT relocation. */
10248 mem = gen_rtx_MEM (Pmode, operands[3]);
10249 MEM_NOTRAP_P (mem) = 1;
10250 /* ??? Should we have a special alias set for the GOT? */
10251 emit_move_insn (operands[0], mem);
10252
10253 DONE;
10254 })
10255
10256 (define_expand "sym2GOT"
10257 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
10258 ""
10259 "")
10260
10261 (define_expand "symGOT2reg"
10262 [(match_operand 0 "" "") (match_operand 1 "" "")]
10263 ""
10264 {
10265 rtx gotsym, insn;
10266
10267 gotsym = gen_sym2GOT (operands[1]);
10268 PUT_MODE (gotsym, Pmode);
10269 insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
10270
10271 MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
10272
10273 DONE;
10274 })
10275
10276 (define_expand "symGOTPLT2reg"
10277 [(match_operand 0 "" "") (match_operand 1 "" "")]
10278 ""
10279 {
10280 rtx pltsym = gen_rtx_CONST (Pmode,
10281 gen_rtx_UNSPEC (Pmode,
10282 gen_rtvec (1, operands[1]),
10283 UNSPEC_GOTPLT));
10284 emit_insn (gen_symGOT_load (operands[0], pltsym));
10285 DONE;
10286 })
10287
10288 (define_expand "sym2GOTOFF"
10289 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
10290 ""
10291 "")
10292
10293 (define_expand "symGOTOFF2reg"
10294 [(match_operand 0 "" "") (match_operand 1 "" "")]
10295 ""
10296 {
10297 rtx gotoffsym, insn;
10298 rtx t = (!can_create_pseudo_p ()
10299 ? operands[0]
10300 : gen_reg_rtx (GET_MODE (operands[0])));
10301
10302 gotoffsym = gen_sym2GOTOFF (operands[1]);
10303 PUT_MODE (gotoffsym, Pmode);
10304 emit_move_insn (t, gotoffsym);
10305 insn = emit_move_insn (operands[0],
10306 gen_rtx_PLUS (Pmode, t,
10307 gen_rtx_REG (Pmode, PIC_REG)));
10308
10309 set_unique_reg_note (insn, REG_EQUAL, operands[1]);
10310
10311 DONE;
10312 })
10313
10314 (define_expand "symPLT_label2reg"
10315 [(set (match_operand:SI 0 "" "")
10316 (const:SI
10317 (unspec:SI
10318 [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
10319 (const:SI (plus:SI (match_operand:SI 2 "" "")
10320 (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
10321 ;; Even though the PIC register is not really used by the call
10322 ;; sequence in which this is expanded, the PLT code assumes the PIC
10323 ;; register is set, so we must not skip its initialization. Since
10324 ;; we only use this expand as part of calling sequences, and never
10325 ;; to take the address of a function, this is the best point to
10326 ;; insert the (use). Using the PLT to take the address of a
10327 ;; function would be wrong, not only because the PLT entry could
10328 ;; then be called from a function that doesn't initialize the PIC
10329 ;; register to the proper GOT, but also because pointers to the
10330 ;; same function might not compare equal, should they be set by
10331 ;; different shared libraries.
10332 (use (reg:SI PIC_REG))]
10333 "TARGET_SH1"
10334 "")
10335
10336 (define_expand "sym2PIC"
10337 [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
10338 ""
10339 "")
10340
10341 ;; -------------------------------------------------------------------------
10342 ;; TLS code generation.
10343
10344 ;; FIXME: The multi-insn asm blocks should be converted to use
10345 ;; define_insn_and_split.
10346 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
10347 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
10348 ;; for details.
10349
10350 (define_insn "tls_global_dynamic"
10351 [(set (match_operand:SI 0 "register_operand" "=&z")
10352 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10353 UNSPEC_TLSGD))
10354 (const_int 0)))
10355 (use (reg:PSI FPSCR_REG))
10356 (use (reg:SI PIC_REG))
10357 (clobber (reg:SI PR_REG))
10358 (clobber (scratch:SI))]
10359 "TARGET_SH1"
10360 {
10361 return "mov.l 1f,r4" "\n"
10362 " mova 2f,r0" "\n"
10363 " mov.l 2f,r1" "\n"
10364 " add r0,r1" "\n"
10365 " jsr @r1" "\n"
10366 " add r12,r4" "\n"
10367 " bra 3f" "\n"
10368 " nop" "\n"
10369 " .align 2" "\n"
10370 "1: .long %a1@TLSGD" "\n"
10371 "2: .long __tls_get_addr@PLT" "\n"
10372 "3:";
10373 }
10374 [(set_attr "type" "tls_load")
10375 (set_attr "length" "26")])
10376
10377 (define_insn "tls_local_dynamic"
10378 [(set (match_operand:SI 0 "register_operand" "=&z")
10379 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10380 UNSPEC_TLSLDM))
10381 (const_int 0)))
10382 (use (reg:PSI FPSCR_REG))
10383 (use (reg:SI PIC_REG))
10384 (clobber (reg:SI PR_REG))
10385 (clobber (scratch:SI))]
10386 "TARGET_SH1"
10387 {
10388 return "mov.l 1f,r4" "\n"
10389 " mova 2f,r0" "\n"
10390 " mov.l 2f,r1" "\n"
10391 " add r0,r1" "\n"
10392 " jsr @r1" "\n"
10393 " add r12,r4" "\n"
10394 " bra 3f" "\n"
10395 " nop" "\n"
10396 " .align 2" "\n"
10397 "1: .long %a1@TLSLDM" "\n"
10398 "2: .long __tls_get_addr@PLT" "\n"
10399 "3:";
10400 }
10401 [(set_attr "type" "tls_load")
10402 (set_attr "length" "26")])
10403
10404 (define_expand "sym2DTPOFF"
10405 [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
10406 ""
10407 "")
10408
10409 (define_expand "symDTPOFF2reg"
10410 [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
10411 ""
10412 {
10413 rtx dtpoffsym;
10414 rtx t = (!can_create_pseudo_p ()
10415 ? operands[0]
10416 : gen_reg_rtx (GET_MODE (operands[0])));
10417
10418 dtpoffsym = gen_sym2DTPOFF (operands[1]);
10419 PUT_MODE (dtpoffsym, Pmode);
10420 emit_move_insn (t, dtpoffsym);
10421 emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
10422 DONE;
10423 })
10424
10425 (define_expand "sym2GOTTPOFF"
10426 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
10427 ""
10428 "")
10429
10430 (define_insn "tls_initial_exec"
10431 [(set (match_operand:SI 0 "register_operand" "=&r")
10432 (unspec:SI [(match_operand:SI 1 "" "")]
10433 UNSPEC_TLSIE))
10434 (use (reg:SI GBR_REG))
10435 (use (reg:SI PIC_REG))
10436 (clobber (reg:SI R0_REG))]
10437 ""
10438 {
10439 return "mov.l 1f,r0" "\n"
10440 " stc gbr,%0" "\n"
10441 " mov.l @(r0,r12),r0" "\n"
10442 " bra 2f" "\n"
10443 " add r0,%0" "\n"
10444 " .align 2" "\n"
10445 "1: .long %a1" "\n"
10446 "2:";
10447 }
10448 [(set_attr "type" "tls_load")
10449 (set_attr "length" "16")])
10450
10451 (define_expand "sym2TPOFF"
10452 [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
10453 ""
10454 "")
10455
10456 (define_expand "symTPOFF2reg"
10457 [(match_operand 0 "" "") (match_operand 1 "" "")]
10458 ""
10459 {
10460 rtx tpoffsym;
10461
10462 tpoffsym = gen_sym2TPOFF (operands[1]);
10463 PUT_MODE (tpoffsym, Pmode);
10464 emit_move_insn (operands[0], tpoffsym);
10465 DONE;
10466 })
10467
10468 ;;------------------------------------------------------------------------------
10469 ;; Thread pointer getter and setter.
10470 ;;
10471 ;; On SH the thread pointer is kept in the GBR.
10472 ;; These patterns are usually expanded from the respective built-in functions.
10473 (define_expand "get_thread_pointersi"
10474 [(set (match_operand:SI 0 "register_operand") (reg:SI GBR_REG))]
10475 "TARGET_SH1")
10476
10477 ;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses.
10478 (define_insn "store_gbr"
10479 [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))]
10480 ""
10481 "stc gbr,%0"
10482 [(set_attr "type" "tls_load")])
10483
10484 (define_expand "set_thread_pointersi"
10485 [(set (reg:SI GBR_REG)
10486 (unspec_volatile:SI [(match_operand:SI 0 "register_operand")]
10487 UNSPECV_GBR))]
10488 "TARGET_SH1")
10489
10490 (define_insn "load_gbr"
10491 [(set (reg:SI GBR_REG)
10492 (unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
10493 UNSPECV_GBR))]
10494 "TARGET_SH1"
10495 "ldc %0,gbr"
10496 [(set_attr "type" "move")])
10497
10498 ;;------------------------------------------------------------------------------
10499 ;; Thread pointer relative memory loads and stores.
10500 ;;
10501 ;; On SH there are GBR displacement address modes which can be utilized to
10502 ;; access memory behind the thread pointer.
10503 ;; Since we do not allow using GBR for general purpose memory accesses, these
10504 ;; GBR addressing modes are formed by the combine pass.
10505 ;; This could be done with fewer patterns than below by using a mem predicate
10506 ;; for the GBR mem, but then reload would try to reload addresses with a
10507 ;; zero displacement for some strange reason.
10508
10509 (define_insn "*mov<mode>_gbr_load"
10510 [(set (match_operand:QIHISI 0 "register_operand" "=z")
10511 (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10512 (match_operand:QIHISI 1 "gbr_displacement"))))]
10513 "TARGET_SH1"
10514 "mov.<bwl> @(%O1,gbr),%0"
10515 [(set_attr "type" "load")])
10516
10517 (define_insn "*mov<mode>_gbr_load"
10518 [(set (match_operand:QIHISI 0 "register_operand" "=z")
10519 (mem:QIHISI (reg:SI GBR_REG)))]
10520 "TARGET_SH1"
10521 "mov.<bwl> @(0,gbr),%0"
10522 [(set_attr "type" "load")])
10523
10524 (define_insn "*mov<mode>_gbr_load"
10525 [(set (match_operand:SI 0 "register_operand" "=z")
10526 (sign_extend:SI
10527 (mem:QIHI (plus:SI (reg:SI GBR_REG)
10528 (match_operand:QIHI 1 "gbr_displacement")))))]
10529 "TARGET_SH1"
10530 "mov.<bw> @(%O1,gbr),%0"
10531 [(set_attr "type" "load")])
10532
10533 (define_insn "*mov<mode>_gbr_load"
10534 [(set (match_operand:SI 0 "register_operand" "=z")
10535 (sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))]
10536 "TARGET_SH1"
10537 "mov.<bw> @(0,gbr),%0"
10538 [(set_attr "type" "load")])
10539
10540 (define_insn "*mov<mode>_gbr_store"
10541 [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10542 (match_operand:QIHISI 0 "gbr_displacement")))
10543 (match_operand:QIHISI 1 "register_operand" "z"))]
10544 "TARGET_SH1"
10545 "mov.<bwl> %1,@(%O0,gbr)"
10546 [(set_attr "type" "store")])
10547
10548 (define_insn "*mov<mode>_gbr_store"
10549 [(set (mem:QIHISI (reg:SI GBR_REG))
10550 (match_operand:QIHISI 0 "register_operand" "z"))]
10551 "TARGET_SH1"
10552 "mov.<bwl> %0,@(0,gbr)"
10553 [(set_attr "type" "store")])
10554
10555 ;; DImode memory accesses have to be split in two SImode accesses.
10556 ;; Split them before reload, so that it gets a better chance to figure out
10557 ;; how to deal with the R0 restriction for the individual SImode accesses.
10558 ;; Do not match this insn during or after reload because it can't be split
10559 ;; afterwards.
10560 (define_insn_and_split "*movdi_gbr_load"
10561 [(set (match_operand:DI 0 "register_operand")
10562 (match_operand:DI 1 "gbr_address_mem"))]
10563 "TARGET_SH1 && can_create_pseudo_p ()"
10564 "#"
10565 "&& 1"
10566 [(set (match_dup 3) (match_dup 5))
10567 (set (match_dup 4) (match_dup 6))]
10568 {
10569 /* Swap low/high part load order on little endian, so that the result reg
10570 of the second load can be used better. */
10571 int off = TARGET_LITTLE_ENDIAN ? 1 : 0;
10572 operands[3 + off] = gen_lowpart (SImode, operands[0]);
10573 operands[5 + off] = gen_lowpart (SImode, operands[1]);
10574 operands[4 - off] = gen_highpart (SImode, operands[0]);
10575 operands[6 - off] = gen_highpart (SImode, operands[1]);
10576 })
10577
10578 (define_insn_and_split "*movdi_gbr_store"
10579 [(set (match_operand:DI 0 "gbr_address_mem")
10580 (match_operand:DI 1 "register_operand"))]
10581 "TARGET_SH1 && can_create_pseudo_p ()"
10582 "#"
10583 "&& 1"
10584 [(set (match_dup 3) (match_dup 5))
10585 (set (match_dup 4) (match_dup 6))]
10586 {
10587 /* Swap low/high part store order on big endian, so that stores of function
10588 call results can save a reg copy. */
10589 int off = TARGET_LITTLE_ENDIAN ? 0 : 1;
10590 operands[3 + off] = gen_lowpart (SImode, operands[0]);
10591 operands[5 + off] = gen_lowpart (SImode, operands[1]);
10592 operands[4 - off] = gen_highpart (SImode, operands[0]);
10593 operands[6 - off] = gen_highpart (SImode, operands[1]);
10594 })
10595
10596 ;; Sometimes memory accesses do not get combined with the store_gbr insn,
10597 ;; in particular when the displacements are in the range of the regular move
10598 ;; insns. Thus, in the first split pass after the combine pass we search
10599 ;; for missed opportunities and try to fix them up ourselves.
10600 ;; If an equivalent GBR address can be determined the load / store is split
10601 ;; into one of the GBR load / store patterns.
10602 ;; All of that must happen before reload (GBR address modes use R0 as the
10603 ;; other operand) and there's no point of doing it if the GBR is not
10604 ;; referenced in a function at all.
10605 (define_split
10606 [(set (match_operand:QIHISIDI 0 "register_operand")
10607 (match_operand:QIHISIDI 1 "memory_operand"))]
10608 "TARGET_SH1 && !reload_in_progress && !reload_completed
10609 && df_regs_ever_live_p (GBR_REG)"
10610 [(set (match_dup 0) (match_dup 1))]
10611 {
10612 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10613 if (gbr_mem != NULL_RTX)
10614 operands[1] = replace_equiv_address (operands[1], gbr_mem);
10615 else
10616 FAIL;
10617 })
10618
10619 (define_split
10620 [(set (match_operand:SI 0 "register_operand")
10621 (sign_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10622 "TARGET_SH1 && !reload_in_progress && !reload_completed
10623 && df_regs_ever_live_p (GBR_REG)"
10624 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
10625 {
10626 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10627 if (gbr_mem != NULL_RTX)
10628 operands[1] = replace_equiv_address (operands[1], gbr_mem);
10629 else
10630 FAIL;
10631 })
10632
10633 ;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads.
10634 ;; Split those so that a GBR load can be used.
10635 (define_split
10636 [(set (match_operand:SI 0 "register_operand")
10637 (zero_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10638 "TARGET_SH2A && !reload_in_progress && !reload_completed
10639 && df_regs_ever_live_p (GBR_REG)"
10640 [(set (match_dup 2) (match_dup 1))
10641 (set (match_dup 0) (zero_extend:SI (match_dup 2)))]
10642 {
10643 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10644 if (gbr_mem != NULL_RTX)
10645 {
10646 operands[2] = gen_reg_rtx (GET_MODE (operands[1]));
10647 operands[1] = replace_equiv_address (operands[1], gbr_mem);
10648 }
10649 else
10650 FAIL;
10651 })
10652
10653 (define_split
10654 [(set (match_operand:QIHISIDI 0 "memory_operand")
10655 (match_operand:QIHISIDI 1 "register_operand"))]
10656 "TARGET_SH1 && !reload_in_progress && !reload_completed
10657 && df_regs_ever_live_p (GBR_REG)"
10658 [(set (match_dup 0) (match_dup 1))]
10659 {
10660 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]);
10661 if (gbr_mem != NULL_RTX)
10662 operands[0] = replace_equiv_address (operands[0], gbr_mem);
10663 else
10664 FAIL;
10665 })
10666
10667 ;;------------------------------------------------------------------------------
10668 ;; case instruction for switch statements.
10669
10670 ;; operand 0 is index
10671 ;; operand 1 is the minimum bound
10672 ;; operand 2 is the maximum bound - minimum bound + 1
10673 ;; operand 3 is CODE_LABEL for the table;
10674 ;; operand 4 is the CODE_LABEL to go to if index out of range.
10675 (define_expand "casesi"
10676 [(match_operand:SI 0 "arith_reg_operand" "")
10677 (match_operand:SI 1 "arith_reg_operand" "")
10678 (match_operand:SI 2 "arith_reg_operand" "")
10679 (match_operand 3 "" "") (match_operand 4 "" "")]
10680 ""
10681 {
10682 rtx reg = gen_reg_rtx (SImode);
10683 rtx reg2 = gen_reg_rtx (SImode);
10684 if (TARGET_SHMEDIA)
10685 {
10686 rtx reg = gen_reg_rtx (DImode);
10687 rtx reg2 = gen_reg_rtx (DImode);
10688 rtx reg3 = gen_reg_rtx (Pmode);
10689 rtx reg4 = gen_reg_rtx (Pmode);
10690 rtx reg5 = gen_reg_rtx (Pmode);
10691 rtx load, test;
10692
10693 operands[0] = convert_modes (DImode, SImode, operands[0], 0);
10694 operands[1] = convert_modes (DImode, SImode, operands[1], 0);
10695 operands[2] = convert_modes (DImode, SImode, operands[2], 1);
10696
10697 test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
10698 emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0],
10699 operands[4]));
10700 emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
10701 test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
10702 emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
10703 emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
10704 emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
10705 (Pmode, operands[3])));
10706 /* Messy: can we subreg to clean this up? */
10707 if (Pmode == DImode)
10708 load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
10709 else
10710 load = gen_casesi_load_media (reg4,
10711 gen_rtx_SUBREG (DImode, reg3, 0),
10712 reg2, operands[3]);
10713 PUT_MODE (SET_SRC (load), Pmode);
10714 emit_insn (load);
10715 /* ??? The following add could be eliminated if we used ptrel. */
10716 emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
10717 emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
10718 emit_barrier ();
10719 DONE;
10720 }
10721 operands[1] = copy_to_mode_reg (SImode, operands[1]);
10722 operands[2] = copy_to_mode_reg (SImode, operands[2]);
10723 /* If optimizing, casesi_worker depends on the mode of the instruction
10724 before label it 'uses' - operands[3]. */
10725 emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
10726 reg));
10727 emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
10728 if (TARGET_SH2)
10729 emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
10730 else
10731 emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
10732 /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
10733 operands[3], but to lab. We will fix this up in
10734 machine_dependent_reorg. */
10735 emit_barrier ();
10736 DONE;
10737 })
10738
10739 (define_expand "casesi_0"
10740 [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
10741 (set (match_dup 4) (minus:SI (match_dup 4)
10742 (match_operand:SI 1 "arith_operand" "")))
10743 (set (reg:SI T_REG)
10744 (gtu:SI (match_dup 4)
10745 (match_operand:SI 2 "arith_reg_operand" "")))
10746 (set (pc)
10747 (if_then_else (ne (reg:SI T_REG)
10748 (const_int 0))
10749 (label_ref (match_operand 3 "" ""))
10750 (pc)))]
10751 "TARGET_SH1"
10752 "")
10753
10754 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
10755 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
10756 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
10757 (define_insn "casesi_worker_0"
10758 [(set (match_operand:SI 0 "register_operand" "=r,r")
10759 (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
10760 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10761 (clobber (match_scratch:SI 3 "=X,1"))
10762 (clobber (match_scratch:SI 4 "=&z,z"))]
10763 "TARGET_SH1"
10764 "#")
10765
10766 (define_split
10767 [(set (match_operand:SI 0 "register_operand" "")
10768 (unspec:SI [(match_operand:SI 1 "register_operand" "")
10769 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10770 (clobber (match_scratch:SI 3 ""))
10771 (clobber (match_scratch:SI 4 ""))]
10772 "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
10773 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
10774 (parallel [(set (match_dup 0)
10775 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10776 (label_ref (match_dup 2))] UNSPEC_CASESI))
10777 (clobber (match_dup 3))])
10778 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
10779 {
10780 if (GET_CODE (operands[2]) == CODE_LABEL)
10781 LABEL_NUSES (operands[2])++;
10782 })
10783
10784 (define_split
10785 [(set (match_operand:SI 0 "register_operand" "")
10786 (unspec:SI [(match_operand:SI 1 "register_operand" "")
10787 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10788 (clobber (match_scratch:SI 3 ""))
10789 (clobber (match_scratch:SI 4 ""))]
10790 "TARGET_SH2 && reload_completed"
10791 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
10792 (parallel [(set (match_dup 0)
10793 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10794 (label_ref (match_dup 2))] UNSPEC_CASESI))
10795 (clobber (match_dup 3))])]
10796 {
10797 if (GET_CODE (operands[2]) == CODE_LABEL)
10798 LABEL_NUSES (operands[2])++;
10799 })
10800
10801 (define_insn "casesi_worker_1"
10802 [(set (match_operand:SI 0 "register_operand" "=r,r")
10803 (unspec:SI [(reg:SI R0_REG)
10804 (match_operand:SI 1 "register_operand" "0,r")
10805 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10806 (clobber (match_scratch:SI 3 "=X,1"))]
10807 "TARGET_SH1"
10808 {
10809 rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
10810
10811 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10812
10813 switch (GET_MODE (diff_vec))
10814 {
10815 case SImode:
10816 return "shll2 %1" "\n"
10817 " mov.l @(r0,%1),%0";
10818 case HImode:
10819 return "add %1,%1" "\n"
10820 " mov.w @(r0,%1),%0";
10821 case QImode:
10822 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10823 return "mov.b @(r0,%1),%0" "\n"
10824 " extu.b %0,%0";
10825 else
10826 return "mov.b @(r0,%1),%0";
10827
10828 default:
10829 gcc_unreachable ();
10830 }
10831 }
10832 [(set_attr "length" "4")])
10833
10834 (define_insn "casesi_worker_2"
10835 [(set (match_operand:SI 0 "register_operand" "=r,r")
10836 (unspec:SI [(reg:SI R0_REG)
10837 (match_operand:SI 1 "register_operand" "0,r")
10838 (label_ref (match_operand 2 "" ""))
10839 (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
10840 (clobber (match_operand:SI 4 "" "=X,1"))]
10841 "TARGET_SH2 && reload_completed && flag_pic"
10842 {
10843 rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
10844 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10845
10846 switch (GET_MODE (diff_vec))
10847 {
10848 case SImode:
10849 return "shll2 %1" "\n"
10850 " add r0,%1" "\n"
10851 " mova %O3,r0" "\n"
10852 " mov.l @(r0,%1),%0";
10853 case HImode:
10854 return "add %1,%1" "\n"
10855 " add r0,%1" "\n"
10856 " mova %O3,r0" "\n"
10857 " mov.w @(r0,%1),%0";
10858 case QImode:
10859 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10860 return "add r0,%1" "\n"
10861 " mova %O3,r0" "\n"
10862 " mov.b @(r0,%1),%0" "\n"
10863 " extu.b %0,%0";
10864 else
10865 return "add r0,%1" "\n"
10866 " mova %O3,r0" "\n"
10867 " mov.b @(r0,%1),%0";
10868 default:
10869 gcc_unreachable ();
10870 }
10871 }
10872 [(set_attr "length" "8")])
10873
10874 (define_insn "casesi_shift_media"
10875 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10876 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
10877 (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
10878 UNSPEC_CASESI)))]
10879 "TARGET_SHMEDIA"
10880 {
10881 rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
10882
10883 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10884
10885 switch (GET_MODE (diff_vec))
10886 {
10887 case SImode:
10888 return "shlli %1, 2, %0";
10889 case HImode:
10890 return "shlli %1, 1, %0";
10891 case QImode:
10892 if (rtx_equal_p (operands[0], operands[1]))
10893 return "";
10894 return "add %1, r63, %0";
10895 default:
10896 gcc_unreachable ();
10897 }
10898 }
10899 [(set_attr "type" "arith_media")])
10900
10901 (define_insn "casesi_load_media"
10902 [(set (match_operand 0 "any_arith_reg_dest" "=r")
10903 (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
10904 (match_operand:DI 2 "arith_reg_operand" "r")
10905 (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
10906 "TARGET_SHMEDIA"
10907 {
10908 rtx diff_vec = PATTERN (NEXT_INSN (operands[3]));
10909
10910 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10911
10912 switch (GET_MODE (diff_vec))
10913 {
10914 case SImode:
10915 return "ldx.l %1, %2, %0";
10916 case HImode:
10917 #if 0
10918 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10919 return "ldx.uw %1, %2, %0";
10920 #endif
10921 return "ldx.w %1, %2, %0";
10922 case QImode:
10923 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10924 return "ldx.ub %1, %2, %0";
10925 return "ldx.b %1, %2, %0";
10926 default:
10927 gcc_unreachable ();
10928 }
10929 }
10930 [(set_attr "type" "load_media")])
10931
10932 (define_expand "simple_return"
10933 [(simple_return)]
10934 "sh_can_use_simple_return_p ()")
10935
10936 (define_expand "return"
10937 [(return)]
10938 "reload_completed && epilogue_completed"
10939 {
10940 if (TARGET_SHMEDIA)
10941 {
10942 emit_jump_insn (gen_return_media ());
10943 DONE;
10944 }
10945
10946 if (TARGET_SHCOMPACT
10947 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
10948 {
10949 emit_jump_insn (gen_shcompact_return_tramp ());
10950 DONE;
10951 }
10952 })
10953
10954 (define_insn "*<code>_i"
10955 [(any_return)]
10956 "TARGET_SH1 && ! (TARGET_SHCOMPACT
10957 && (crtl->args.info.call_cookie
10958 & CALL_COOKIE_RET_TRAMP (1)))
10959 && reload_completed
10960 && ! sh_cfun_trap_exit_p ()"
10961 {
10962 if (TARGET_SH2A && (dbr_sequence_length () == 0)
10963 && !current_function_interrupt)
10964 return "rts/n";
10965 else
10966 return "%@ %#";
10967 }
10968 [(set_attr "type" "return")
10969 (set_attr "needs_delay_slot" "yes")])
10970
10971 ;; trapa has no delay slot.
10972 (define_insn "*return_trapa"
10973 [(return)]
10974 "TARGET_SH1 && !TARGET_SHCOMPACT
10975 && reload_completed"
10976 "%@"
10977 [(set_attr "type" "return")])
10978
10979 (define_expand "shcompact_return_tramp"
10980 [(return)]
10981 "TARGET_SHCOMPACT
10982 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
10983 {
10984 rtx reg = gen_rtx_REG (Pmode, R0_REG);
10985
10986 function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC);
10987 emit_jump_insn (gen_shcompact_return_tramp_i ());
10988 DONE;
10989 })
10990
10991 (define_insn "shcompact_return_tramp_i"
10992 [(parallel [(return) (use (reg:SI R0_REG))])]
10993 "TARGET_SHCOMPACT
10994 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
10995 "jmp @r0%#"
10996 [(set_attr "type" "jump_ind")
10997 (set_attr "needs_delay_slot" "yes")])
10998
10999 (define_insn "return_media_i"
11000 [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
11001 "TARGET_SHMEDIA && reload_completed"
11002 "blink %0, r63"
11003 [(set_attr "type" "jump_media")])
11004
11005 (define_insn "return_media_rte"
11006 [(return)]
11007 "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
11008 "rte"
11009 [(set_attr "type" "jump_media")])
11010
11011 (define_expand "return_media"
11012 [(return)]
11013 "TARGET_SHMEDIA && reload_completed"
11014 {
11015 int tr_regno = sh_media_register_for_return ();
11016 rtx tr;
11017
11018 if (current_function_interrupt)
11019 {
11020 emit_jump_insn (gen_return_media_rte ());
11021 DONE;
11022 }
11023 if (tr_regno < 0)
11024 {
11025 rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
11026
11027 gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
11028 tr_regno = TR0_REG;
11029 tr = gen_rtx_REG (Pmode, tr_regno);
11030 emit_move_insn (tr, r18);
11031 }
11032 else
11033 tr = gen_rtx_REG (Pmode, tr_regno);
11034
11035 emit_jump_insn (gen_return_media_i (tr));
11036 DONE;
11037 })
11038
11039 (define_insn "shcompact_preserve_incoming_args"
11040 [(set (match_operand:SI 0 "register_operand" "+r")
11041 (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
11042 "TARGET_SHCOMPACT"
11043 ""
11044 [(set_attr "length" "0")])
11045
11046 (define_insn "shcompact_incoming_args"
11047 [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
11048 (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
11049 (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
11050 (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
11051 (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
11052 (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
11053 (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
11054 (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
11055 (set (mem:BLK (reg:SI MACL_REG))
11056 (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
11057 (use (reg:SI R0_REG))
11058 (clobber (reg:SI R0_REG))
11059 (clobber (reg:SI MACL_REG))
11060 (clobber (reg:SI MACH_REG))
11061 (clobber (reg:SI PR_REG))]
11062 "TARGET_SHCOMPACT"
11063 "jsr @r0%#"
11064 [(set_attr "needs_delay_slot" "yes")])
11065
11066 (define_insn "shmedia_save_restore_regs_compact"
11067 [(set (reg:SI SP_REG)
11068 (plus:SI (reg:SI SP_REG)
11069 (match_operand:SI 0 "immediate_operand" "i")))
11070 (use (reg:SI R0_REG))
11071 (clobber (reg:SI PR_REG))]
11072 "TARGET_SHCOMPACT
11073 && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
11074 || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
11075 "jsr @r0%#"
11076 [(set_attr "needs_delay_slot" "yes")])
11077
11078 (define_expand "prologue"
11079 [(const_int 0)]
11080 ""
11081 {
11082 sh_expand_prologue ();
11083 DONE;
11084 })
11085
11086 (define_expand "epilogue"
11087 [(return)]
11088 ""
11089 {
11090 sh_expand_epilogue (false);
11091 if (TARGET_SHMEDIA
11092 || (TARGET_SHCOMPACT
11093 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))))
11094 {
11095 emit_jump_insn (gen_return ());
11096 DONE;
11097 }
11098 })
11099
11100 (define_expand "eh_return"
11101 [(use (match_operand 0 "register_operand" ""))]
11102 ""
11103 {
11104 rtx ra = operands[0];
11105
11106 if (TARGET_SHMEDIA64)
11107 emit_insn (gen_eh_set_ra_di (ra));
11108 else
11109 emit_insn (gen_eh_set_ra_si (ra));
11110
11111 DONE;
11112 })
11113
11114 ;; Clobber the return address on the stack. We can't expand this
11115 ;; until we know where it will be put in the stack frame.
11116
11117 (define_insn "eh_set_ra_si"
11118 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
11119 UNSPECV_EH_RETURN)
11120 (clobber (match_scratch:SI 1 "=&r"))]
11121 "! TARGET_SHMEDIA64"
11122 "#")
11123
11124 (define_insn "eh_set_ra_di"
11125 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
11126 UNSPECV_EH_RETURN)
11127 (clobber (match_scratch:DI 1 "=&r"))]
11128 "TARGET_SHMEDIA64"
11129 "#")
11130
11131 (define_split
11132 [(unspec_volatile [(match_operand 0 "register_operand" "")]
11133 UNSPECV_EH_RETURN)
11134 (clobber (match_scratch 1 ""))]
11135 "reload_completed"
11136 [(const_int 0)]
11137 {
11138 sh_set_return_address (operands[0], operands[1]);
11139 DONE;
11140 })
11141
11142 (define_insn "blockage"
11143 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
11144 ""
11145 ""
11146 [(set_attr "length" "0")])
11147 \f
11148 ;; Define movml instructions for SH2A target. Currently they are
11149 ;; used to push and pop all banked registers only.
11150
11151 (define_insn "movml_push_banked"
11152 [(set (match_operand:SI 0 "register_operand" "=r")
11153 (plus (match_dup 0) (const_int -32)))
11154 (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
11155 (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
11156 (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
11157 (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
11158 (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
11159 (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
11160 (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
11161 (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
11162 "TARGET_SH2A && REGNO (operands[0]) == 15"
11163 "movml.l r7,@-r15"
11164 [(set_attr "in_delay_slot" "no")])
11165
11166 (define_insn "movml_pop_banked"
11167 [(set (match_operand:SI 0 "register_operand" "=r")
11168 (plus (match_dup 0) (const_int 32)))
11169 (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
11170 (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
11171 (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
11172 (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
11173 (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
11174 (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
11175 (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
11176 (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
11177 "TARGET_SH2A && REGNO (operands[0]) == 15"
11178 "movml.l @r15+,r7"
11179 [(set_attr "in_delay_slot" "no")])
11180 \f
11181 ;; ------------------------------------------------------------------------
11182 ;; Scc instructions
11183 ;; ------------------------------------------------------------------------
11184
11185 (define_insn "movt"
11186 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11187 (match_operand:SI 1 "t_reg_operand"))]
11188 "TARGET_SH1"
11189 "movt %0"
11190 [(set_attr "type" "arith")])
11191
11192 (define_insn "movrt"
11193 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11194 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11195 "TARGET_SH2A"
11196 "movrt %0"
11197 [(set_attr "type" "arith")])
11198
11199 (define_expand "cstore4_media"
11200 [(set (match_operand:SI 0 "register_operand" "=r")
11201 (match_operator:SI 1 "sh_float_comparison_operator"
11202 [(match_operand 2 "logical_operand" "")
11203 (match_operand 3 "cmp_operand" "")]))]
11204 "TARGET_SHMEDIA"
11205 {
11206 enum machine_mode mode = GET_MODE (operands[2]);
11207 enum rtx_code code = GET_CODE (operands[1]);
11208 bool invert, swap;
11209 if (mode == VOIDmode)
11210 mode = GET_MODE (operands[3]);
11211 if (operands[2] == const0_rtx)
11212 {
11213 if (code == EQ || code == NE)
11214 operands[2] = operands[3], operands[3] = const0_rtx;
11215 }
11216 else
11217 operands[2] = force_reg (mode, operands[2]);
11218 if (operands[3] != const0_rtx)
11219 operands[3] = force_reg (mode, operands[3]);
11220
11221 switch (code)
11222 {
11223 case GEU:
11224 case GE:
11225 swap = invert = !FLOAT_MODE_P (mode);
11226 break;
11227
11228 case LEU:
11229 case LE:
11230 swap = FLOAT_MODE_P (mode), invert = !swap;
11231 break;
11232
11233 case LTU:
11234 case LT:
11235 swap = true, invert = false;
11236 break;
11237
11238 case GTU:
11239 case GT:
11240 case EQ:
11241 case UNORDERED:
11242 swap = invert = false;
11243 break;
11244
11245 case NE:
11246 swap = invert = true;
11247 break;
11248
11249 default:
11250 gcc_unreachable ();
11251 }
11252
11253 if (swap)
11254 {
11255 rtx tem = operands[2];
11256 operands[2] = operands[3];
11257 operands[3] = tem;
11258 code = swap_condition (code);
11259 }
11260
11261 if (invert)
11262 {
11263 rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
11264 code = reverse_condition (code);
11265 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11266 emit_insn (gen_cstore4_media (tem, operands[1],
11267 operands[2], operands[3]));
11268 code = EQ;
11269 operands[2] = tem;
11270 operands[3] = const0_rtx;
11271 }
11272
11273 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11274 })
11275
11276 (define_expand "cstoresi4"
11277 [(set (match_operand:SI 0 "register_operand" "=r")
11278 (match_operator:SI 1 "comparison_operator"
11279 [(match_operand:SI 2 "cmpsi_operand" "")
11280 (match_operand:SI 3 "arith_operand" "")]))]
11281 "TARGET_SH1 || TARGET_SHMEDIA"
11282 {
11283 if (TARGET_SHMEDIA)
11284 {
11285 emit_insn (gen_cstore4_media (operands[0], operands[1],
11286 operands[2], operands[3]));
11287 DONE;
11288 }
11289
11290 if (sh_expand_t_scc (operands))
11291 DONE;
11292
11293 if (! currently_expanding_to_rtl)
11294 FAIL;
11295
11296 sh_emit_compare_and_set (operands, SImode);
11297 DONE;
11298 })
11299
11300 (define_expand "cstoredi4"
11301 [(set (match_operand:SI 0 "register_operand" "=r")
11302 (match_operator:SI 1 "comparison_operator"
11303 [(match_operand:DI 2 "arith_operand" "")
11304 (match_operand:DI 3 "arith_operand" "")]))]
11305 "TARGET_SH2 || TARGET_SHMEDIA"
11306 {
11307 if (TARGET_SHMEDIA)
11308 {
11309 emit_insn (gen_cstore4_media (operands[0], operands[1],
11310 operands[2], operands[3]));
11311 DONE;
11312 }
11313
11314 if (sh_expand_t_scc (operands))
11315 DONE;
11316
11317 if (! currently_expanding_to_rtl)
11318 FAIL;
11319
11320 sh_emit_compare_and_set (operands, DImode);
11321 DONE;
11322 })
11323
11324 ;; Move the complement of the T reg to a reg.
11325 ;; On SH2A the movrt insn can be used.
11326 ;; On anything else than SH2A this has to be done with multiple instructions.
11327 ;; One obvious way would be:
11328 ;; cmp/eq ...
11329 ;; movt r0
11330 ;; xor #1,r0
11331 ;;
11332 ;; However, this puts pressure on r0 in most cases and thus the following is
11333 ;; more appealing:
11334 ;; cmp/eq ...
11335 ;; mov #-1,temp
11336 ;; negc temp,dest
11337 ;;
11338 ;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
11339 ;; becomes a one instruction operation. Moreover, care must be taken that
11340 ;; the insn can still be combined with inverted compare and branch code
11341 ;; around it. On the other hand, if a function returns the complement of
11342 ;; a previous comparison result in the T bit, the xor #1,r0 approach might
11343 ;; lead to better code.
11344 (define_expand "movnegt"
11345 [(set (match_operand:SI 0 "arith_reg_dest" "")
11346 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11347 "TARGET_SH1"
11348 {
11349 if (TARGET_SH2A)
11350 emit_insn (gen_movrt (operands[0], operands[1]));
11351 else
11352 {
11353 rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
11354 emit_insn (gen_movrt_negc (operands[0], operands[1], val));
11355 }
11356 DONE;
11357 })
11358
11359 (define_insn "movrt_negc"
11360 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11361 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11362 (set (reg:SI T_REG) (const_int 1))
11363 (use (match_operand:SI 2 "arith_reg_operand" "r"))]
11364 "TARGET_SH1"
11365 "negc %2,%0"
11366 [(set_attr "type" "arith")])
11367
11368 ;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the
11369 ;; pattern can be used by the combine pass. Using a scratch reg for the
11370 ;; -1 constant results in slightly better register allocations compared to
11371 ;; generating a pseudo reg before reload.
11372 (define_insn_and_split "*movrt_negc"
11373 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11374 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11375 (clobber (match_scratch:SI 2 "=r"))
11376 (clobber (reg:SI T_REG))]
11377 "TARGET_SH1 && ! TARGET_SH2A"
11378 "#"
11379 "&& reload_completed"
11380 [(set (match_dup 2) (const_int -1))
11381 (parallel
11382 [(set (match_dup 0) (xor:SI (match_dup 1) (const_int 1)))
11383 (set (reg:SI T_REG) (const_int 1))
11384 (use (match_dup 2))])])
11385
11386 ;; Store the negated T bit in a reg using r0 and xor. This one doesn't
11387 ;; clobber the T bit, which is useful when storing the T bit and the
11388 ;; negated T bit in parallel. On SH2A the movrt insn can be used for that.
11389 ;; Usually we don't want this insn to be matched, except for cases where the
11390 ;; T bit clobber is really not appreciated. Hence the extra use on T_REG.
11391 (define_insn_and_split "movrt_xor"
11392 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
11393 (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
11394 (use (reg:SI T_REG))]
11395 "TARGET_SH1 && !TARGET_SH2A"
11396 "#"
11397 "&& reload_completed"
11398 [(set (match_dup 0) (reg:SI T_REG))
11399 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))])
11400
11401 ;; Store the T bit and the negated T bit in two regs in parallel. There is
11402 ;; no real insn to do that, but specifying this pattern will give combine
11403 ;; some opportunities.
11404 (define_insn_and_split "*movt_movrt"
11405 [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11406 (match_operand:SI 1 "negt_reg_operand"))
11407 (set (match_operand:SI 2 "arith_reg_dest")
11408 (match_operand:SI 3 "t_reg_operand"))])]
11409 "TARGET_SH1"
11410 "#"
11411 "&& 1"
11412 [(const_int 0)]
11413 {
11414 rtx i = TARGET_SH2A
11415 ? gen_movrt (operands[0], get_t_reg_rtx ())
11416 : gen_movrt_xor (operands[0], get_t_reg_rtx ());
11417
11418 emit_insn (i);
11419 emit_insn (gen_movt (operands[2], get_t_reg_rtx ()));
11420 DONE;
11421 })
11422
11423 (define_insn_and_split "*movt_movrt"
11424 [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11425 (match_operand:SI 1 "t_reg_operand"))
11426 (set (match_operand:SI 2 "arith_reg_dest")
11427 (match_operand:SI 3 "negt_reg_operand"))])]
11428 "TARGET_SH1"
11429 "#"
11430 "&& 1"
11431 [(parallel [(set (match_dup 2) (match_dup 3))
11432 (set (match_dup 0) (match_dup 1))])])
11433
11434 ;; Use negc to store the T bit in a MSB of a reg in the following way:
11435 ;; T = 1: 0x80000000 -> reg
11436 ;; T = 0: 0x7FFFFFFF -> reg
11437 ;; This works because 0 - 0x80000000 = 0x80000000.
11438 ;;
11439 ;; This insn must not match again after it has been split into the constant
11440 ;; load and negc. This is accomplished by the special negc insn that
11441 ;; has a use on the operand.
11442 (define_insn_and_split "*mov_t_msb_neg"
11443 [(set (match_operand:SI 0 "arith_reg_dest")
11444 (minus:SI (const_int -2147483648) ;; 0x80000000
11445 (match_operand 1 "t_reg_operand")))
11446 (clobber (reg:SI T_REG))]
11447 "TARGET_SH1"
11448 "#"
11449 "&& can_create_pseudo_p ()"
11450 [(set (match_dup 2) (const_int -2147483648))
11451 (parallel [(set (match_dup 0) (minus:SI (neg:SI (match_dup 2))
11452 (reg:SI T_REG)))
11453 (clobber (reg:SI T_REG))
11454 (use (match_dup 2))])]
11455 {
11456 operands[2] = gen_reg_rtx (SImode);
11457 })
11458
11459 (define_insn "*mov_t_msb_neg_negc"
11460 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11461 (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
11462 (match_operand:SI 2 "t_reg_operand")))
11463 (clobber (reg:SI T_REG))
11464 (use (match_dup 1))]
11465 "TARGET_SH1"
11466 "negc %1,%0"
11467 [(set_attr "type" "arith")])
11468
11469 ;; These are essentially the same as above, but with the inverted T bit.
11470 ;; Combine recognizes the split patterns, but does not take them sometimes
11471 ;; if the T_REG clobber is specified. Instead it tries to split out the
11472 ;; T bit negation. Since these splits are supposed to be taken only by
11473 ;; combine, it will see the T_REG clobber of the *mov_t_msb_neg insn, so this
11474 ;; should be fine.
11475 (define_split
11476 [(set (match_operand:SI 0 "arith_reg_dest")
11477 (plus:SI (match_operand 1 "negt_reg_operand")
11478 (const_int 2147483647)))] ;; 0x7fffffff
11479 "TARGET_SH1 && can_create_pseudo_p ()"
11480 [(parallel [(set (match_dup 0)
11481 (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11482 (clobber (reg:SI T_REG))])])
11483
11484 (define_split
11485 [(set (match_operand:SI 0 "arith_reg_dest")
11486 (if_then_else:SI (match_operand 1 "t_reg_operand")
11487 (const_int 2147483647) ;; 0x7fffffff
11488 (const_int -2147483648)))] ;; 0x80000000
11489 "TARGET_SH1 && can_create_pseudo_p ()"
11490 [(parallel [(set (match_dup 0)
11491 (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11492 (clobber (reg:SI T_REG))])])
11493
11494 ;; The *negnegt pattern helps the combine pass to figure out how to fold
11495 ;; an explicit double T bit negation.
11496 (define_insn_and_split "*negnegt"
11497 [(set (reg:SI T_REG)
11498 (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
11499 "TARGET_SH1"
11500 "#"
11501 ""
11502 [(const_int 0)])
11503
11504 ;; Store T bit as all zeros or ones in a reg.
11505 (define_insn "mov_neg_si_t"
11506 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11507 (neg:SI (match_operand 1 "t_reg_operand" "")))]
11508 "TARGET_SH1"
11509 "subc %0,%0"
11510 [(set_attr "type" "arith")])
11511
11512 ;; Store negated T bit as all zeros or ones in a reg.
11513 ;; Use the following sequence:
11514 ;; subc Rn,Rn ! Rn = Rn - Rn - T; T = T
11515 ;; not Rn,Rn ! Rn = 0 - Rn
11516 (define_split
11517 [(set (match_operand:SI 0 "arith_reg_dest" "")
11518 (neg:SI (match_operand 1 "negt_reg_operand" "")))]
11519 "TARGET_SH1"
11520 [(set (match_dup 0) (neg:SI (reg:SI T_REG)))
11521 (set (match_dup 0) (not:SI (match_dup 0)))])
11522
11523 ;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
11524 (define_insn_and_split "*movtt"
11525 [(set (reg:SI T_REG)
11526 (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
11527 "TARGET_SH1"
11528 "#"
11529 ""
11530 [(const_int 0)])
11531
11532 ;; Invert the T bit.
11533 ;; On SH2A we can use the nott insn. On anything else this must be done with
11534 ;; multiple insns like:
11535 ;; movt Rn
11536 ;; tst Rn,Rn
11537 ;; This requires an additional pseudo. The SH specific sh_treg_combine RTL
11538 ;; pass will look for this insn. Disallow using it if pseudos can't be
11539 ;; created.
11540 (define_insn_and_split "nott"
11541 [(set (reg:SI T_REG)
11542 (xor:SI (match_operand:SI 0 "t_reg_operand") (const_int 1)))]
11543 "TARGET_SH2A || (TARGET_SH1 && can_create_pseudo_p ())"
11544 {
11545 gcc_assert (TARGET_SH2A);
11546 return "nott";
11547 }
11548 "! TARGET_SH2A && can_create_pseudo_p ()"
11549 [(set (match_dup 0) (reg:SI T_REG))
11550 (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
11551 {
11552 operands[0] = gen_reg_rtx (SImode);
11553 })
11554
11555 ;; Store T bit as MSB in a reg.
11556 ;; T = 0: 0x00000000 -> reg
11557 ;; T = 1: 0x80000000 -> reg
11558 (define_insn_and_split "*movt_msb"
11559 [(set (match_operand:SI 0 "arith_reg_dest")
11560 (mult:SI (match_operand:SI 1 "t_reg_operand")
11561 (const_int -2147483648))) ;; 0xffffffff80000000
11562 (clobber (reg:SI T_REG))]
11563 "TARGET_SH1"
11564 "#"
11565 "&& 1"
11566 [(set (match_dup 0) (ashift:SI (reg:SI T_REG) (const_int 31)))])
11567
11568 ;; Store inverted T bit as MSB in a reg.
11569 ;; T = 0: 0x80000000 -> reg
11570 ;; T = 1: 0x00000000 -> reg
11571 ;; On SH2A we can get away without clobbering the T_REG.
11572 (define_insn_and_split "*negt_msb"
11573 [(set (match_operand:SI 0 "arith_reg_dest")
11574 (match_operand:SI 1 "negt_reg_shl31_operand"))]
11575 "TARGET_SH2A"
11576 "#"
11577 "&& can_create_pseudo_p ()"
11578 [(const_int 0)]
11579 {
11580 rtx tmp = gen_reg_rtx (SImode);
11581 emit_insn (gen_movrt (tmp, get_t_reg_rtx ()));
11582 emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx));
11583 DONE;
11584 })
11585
11586 (define_insn_and_split "*negt_msb"
11587 [(set (match_operand:SI 0 "arith_reg_dest")
11588 (match_operand:SI 1 "negt_reg_shl31_operand"))
11589 (clobber (reg:SI T_REG))]
11590 "TARGET_SH1 && !TARGET_SH2A"
11591 "#"
11592 "&& can_create_pseudo_p ()"
11593 [(const_int 0)]
11594 {
11595 rtx tmp = gen_reg_rtx (SImode);
11596 emit_move_insn (tmp, get_t_reg_rtx ());
11597 emit_insn (gen_cmpeqsi_t (tmp, const0_rtx));
11598 emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ()));
11599 DONE;
11600 })
11601
11602 ;; The *cset_zero patterns convert optimizations such as
11603 ;; "if (test) x = 0;"
11604 ;; to
11605 ;; "x &= -(test == 0);"
11606 ;; back to conditional branch sequences if zero-displacement branches
11607 ;; are enabled.
11608 ;; FIXME: These patterns can be removed when conditional execution patterns
11609 ;; are implemented, since ifcvt will not perform these optimizations if
11610 ;; conditional execution is supported.
11611 (define_insn "*cset_zero"
11612 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11613 (and:SI (plus:SI (match_operand:SI 1 "t_reg_operand")
11614 (const_int -1))
11615 (match_operand:SI 2 "arith_reg_operand" "0")))]
11616 "TARGET_SH1 && TARGET_ZDCBRANCH"
11617 {
11618 return "bf 0f" "\n"
11619 " mov #0,%0" "\n"
11620 "0:";
11621 }
11622 [(set_attr "type" "arith") ;; poor approximation
11623 (set_attr "length" "4")])
11624
11625 (define_insn "*cset_zero"
11626 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11627 (if_then_else:SI (match_operand:SI 1 "t_reg_operand")
11628 (match_operand:SI 2 "arith_reg_operand" "0")
11629 (const_int 0)))]
11630 "TARGET_SH1 && TARGET_ZDCBRANCH"
11631 {
11632 return "bt 0f" "\n"
11633 " mov #0,%0" "\n"
11634 "0:";
11635 }
11636 [(set_attr "type" "arith") ;; poor approximation
11637 (set_attr "length" "4")])
11638
11639 (define_expand "cstoresf4"
11640 [(set (match_operand:SI 0 "register_operand" "=r")
11641 (match_operator:SI 1 "sh_float_comparison_operator"
11642 [(match_operand:SF 2 "arith_operand" "")
11643 (match_operand:SF 3 "arith_operand" "")]))]
11644 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11645 {
11646 if (TARGET_SHMEDIA)
11647 {
11648 emit_insn (gen_cstore4_media (operands[0], operands[1],
11649 operands[2], operands[3]));
11650 DONE;
11651 }
11652
11653 if (! currently_expanding_to_rtl)
11654 FAIL;
11655
11656 sh_emit_compare_and_set (operands, SFmode);
11657 DONE;
11658 })
11659
11660 (define_expand "cstoredf4"
11661 [(set (match_operand:SI 0 "register_operand" "=r")
11662 (match_operator:SI 1 "sh_float_comparison_operator"
11663 [(match_operand:DF 2 "arith_operand" "")
11664 (match_operand:DF 3 "arith_operand" "")]))]
11665 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11666 {
11667 if (TARGET_SHMEDIA)
11668 {
11669 emit_insn (gen_cstore4_media (operands[0], operands[1],
11670 operands[2], operands[3]));
11671 DONE;
11672 }
11673
11674 if (! currently_expanding_to_rtl)
11675 FAIL;
11676
11677 sh_emit_compare_and_set (operands, DFmode);
11678 DONE;
11679 })
11680
11681 ;; -------------------------------------------------------------------------
11682 ;; Instructions to cope with inline literal tables
11683 ;; -------------------------------------------------------------------------
11684
11685 ;; 2 byte integer in line
11686 (define_insn "consttable_2"
11687 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11688 (match_operand 1 "" "")]
11689 UNSPECV_CONST2)]
11690 ""
11691 {
11692 if (operands[1] != const0_rtx)
11693 assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
11694 return "";
11695 }
11696 [(set_attr "length" "2")
11697 (set_attr "in_delay_slot" "no")])
11698
11699 ;; 4 byte integer in line
11700 (define_insn "consttable_4"
11701 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11702 (match_operand 1 "" "")]
11703 UNSPECV_CONST4)]
11704 ""
11705 {
11706 if (operands[1] != const0_rtx)
11707 {
11708 assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
11709 mark_symbol_refs_as_used (operands[0]);
11710 }
11711 return "";
11712 }
11713 [(set_attr "length" "4")
11714 (set_attr "in_delay_slot" "no")])
11715
11716 ;; 8 byte integer in line
11717 (define_insn "consttable_8"
11718 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11719 (match_operand 1 "" "")]
11720 UNSPECV_CONST8)]
11721 ""
11722 {
11723 if (operands[1] != const0_rtx)
11724 assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
11725 return "";
11726 }
11727 [(set_attr "length" "8")
11728 (set_attr "in_delay_slot" "no")])
11729
11730 ;; 4 byte floating point
11731 (define_insn "consttable_sf"
11732 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
11733 (match_operand 1 "" "")]
11734 UNSPECV_CONST4)]
11735 ""
11736 {
11737 if (operands[1] != const0_rtx)
11738 {
11739 REAL_VALUE_TYPE d;
11740 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11741 assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
11742 }
11743 return "";
11744 }
11745 [(set_attr "length" "4")
11746 (set_attr "in_delay_slot" "no")])
11747
11748 ;; 8 byte floating point
11749 (define_insn "consttable_df"
11750 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
11751 (match_operand 1 "" "")]
11752 UNSPECV_CONST8)]
11753 ""
11754 {
11755 if (operands[1] != const0_rtx)
11756 {
11757 REAL_VALUE_TYPE d;
11758 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11759 assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
11760 }
11761 return "";
11762 }
11763 [(set_attr "length" "8")
11764 (set_attr "in_delay_slot" "no")])
11765
11766 ;; Alignment is needed for some constant tables; it may also be added for
11767 ;; Instructions at the start of loops, or after unconditional branches.
11768 ;; ??? We would get more accurate lengths if we did instruction
11769 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
11770 ;; here is too conservative.
11771
11772 ;; align to a two byte boundary
11773 (define_expand "align_2"
11774 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
11775 ""
11776 "")
11777
11778 ;; Align to a four byte boundary.
11779 ;; align_4 and align_log are instructions for the starts of loops, or
11780 ;; after unconditional branches, which may take up extra room.
11781 (define_expand "align_4"
11782 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
11783 ""
11784 "")
11785
11786 ;; Align to a cache line boundary.
11787 (define_insn "align_log"
11788 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
11789 ""
11790 ""
11791 [(set_attr "length" "0")
11792 (set_attr "in_delay_slot" "no")])
11793
11794 ;; Emitted at the end of the literal table, used to emit the
11795 ;; 32bit branch labels if needed.
11796 (define_insn "consttable_end"
11797 [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
11798 ""
11799 {
11800 return output_jump_label_table ();
11801 }
11802 [(set_attr "in_delay_slot" "no")])
11803
11804 ;; Emitted at the end of the window in the literal table.
11805 (define_insn "consttable_window_end"
11806 [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
11807 ""
11808 ""
11809 [(set_attr "length" "0")
11810 (set_attr "in_delay_slot" "no")])
11811
11812 ;; -------------------------------------------------------------------------
11813 ;; Minimum / maximum operations.
11814 ;; -------------------------------------------------------------------------
11815
11816 ;; The SH2A clips.b and clips.w insns do a signed min-max function. If smin
11817 ;; and smax standard name patterns are defined, they will be used during
11818 ;; initial expansion and combine will then be able to form the actual min-max
11819 ;; pattern.
11820 ;; The clips.b and clips.w set the SR.CS bit if the value in the register is
11821 ;; clipped, but there is currently no way of making use of this information.
11822 ;; The only way to read or reset the SR.CS bit is by accessing the SR.
11823 (define_expand "<code>si3"
11824 [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11825 (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand")
11826 (match_operand 2 "const_int_operand")))
11827 (clobber (reg:SI T_REG))])]
11828 "TARGET_SH2A"
11829 {
11830 /* Force the comparison value into a register, because greater-than
11831 comparisons can work only on registers. Combine will be able to pick up
11832 the constant value from the REG_EQUAL note when trying to form a min-max
11833 pattern. */
11834 operands[2] = force_reg (SImode, operands[2]);
11835 })
11836
11837 ;; Convert
11838 ;; smax (smin (...))
11839 ;; to
11840 ;; smin (smax (...))
11841 (define_insn_and_split "*clips"
11842 [(set (match_operand:SI 0 "arith_reg_dest")
11843 (smax:SI (smin:SI (match_operand:SI 1 "arith_reg_operand")
11844 (match_operand 2 "clips_max_const_int"))
11845 (match_operand 3 "clips_min_const_int")))]
11846 "TARGET_SH2A"
11847 "#"
11848 "&& 1"
11849 [(set (match_dup 0)
11850 (smin:SI (smax:SI (match_dup 1) (match_dup 3)) (match_dup 2)))])
11851
11852 (define_insn "*clips"
11853 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11854 (smin:SI (smax:SI (match_operand:SI 1 "arith_reg_operand" "0")
11855 (match_operand 2 "clips_min_const_int"))
11856 (match_operand 3 "clips_max_const_int")))]
11857 "TARGET_SH2A"
11858 {
11859 if (INTVAL (operands[3]) == 127)
11860 return "clips.b %0";
11861 else if (INTVAL (operands[3]) == 32767)
11862 return "clips.w %0";
11863 else
11864 gcc_unreachable ();
11865 }
11866 [(set_attr "type" "arith")])
11867
11868 ;; If the expanded smin or smax patterns were not combined, split them into
11869 ;; a compare and branch sequence, because there are no real smin or smax
11870 ;; insns.
11871 (define_insn_and_split "*<code>si3"
11872 [(set (match_operand:SI 0 "arith_reg_dest")
11873 (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand")
11874 (match_operand:SI 2 "arith_reg_or_0_or_1_operand")))
11875 (clobber (reg:SI T_REG))]
11876 "TARGET_SH2A && can_create_pseudo_p ()"
11877 "#"
11878 "&& 1"
11879 [(const_int 0)]
11880 {
11881 rtx skip_label = gen_label_rtx ();
11882 emit_move_insn (operands[0], operands[1]);
11883
11884 rtx cmp_val = operands[2];
11885 if (satisfies_constraint_M (cmp_val))
11886 cmp_val = const0_rtx;
11887
11888 emit_insn (gen_cmpgtsi_t (operands[0], cmp_val));
11889 emit_jump_insn (<CODE> == SMIN
11890 ? gen_branch_false (skip_label)
11891 : gen_branch_true (skip_label));
11892
11893 emit_label_after (skip_label, emit_move_insn (operands[0], operands[2]));
11894 DONE;
11895 })
11896
11897 ;; The SH2A clipu.b and clipu.w insns can be used to implement a min function
11898 ;; with a register and a constant.
11899 ;; The clipu.b and clipu.w set the SR.CS bit if the value in the register is
11900 ;; clipped, but there is currently no way of making use of this information.
11901 ;; The only way to read or reset the SR.CS bit is by accessing the SR.
11902 (define_expand "uminsi3"
11903 [(set (match_operand:SI 0 "arith_reg_dest")
11904 (umin:SI (match_operand:SI 1 "arith_reg_operand")
11905 (match_operand 2 "const_int_operand")))]
11906 "TARGET_SH2A"
11907 {
11908 if (INTVAL (operands[2]) == 1)
11909 {
11910 emit_insn (gen_clipu_one (operands[0], operands[1]));
11911 DONE;
11912 }
11913 else if (! clipu_max_const_int (operands[2], VOIDmode))
11914 FAIL;
11915 })
11916
11917 (define_insn "*clipu"
11918 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11919 (umin:SI (match_operand:SI 1 "arith_reg_operand" "0")
11920 (match_operand 2 "clipu_max_const_int")))]
11921 "TARGET_SH2A"
11922 {
11923 if (INTVAL (operands[2]) == 255)
11924 return "clipu.b %0";
11925 else if (INTVAL (operands[2]) == 65535)
11926 return "clipu.w %0";
11927 else
11928 gcc_unreachable ();
11929 }
11930 [(set_attr "type" "arith")])
11931
11932 (define_insn_and_split "clipu_one"
11933 [(set (match_operand:SI 0 "arith_reg_dest")
11934 (umin:SI (match_operand:SI 1 "arith_reg_operand") (const_int 1)))
11935 (clobber (reg:SI T_REG))]
11936 "TARGET_SH2A"
11937 "#"
11938 "&& can_create_pseudo_p ()"
11939 [(const_int 0)]
11940 {
11941 emit_insn (gen_cmpeqsi_t (operands[1], const0_rtx));
11942 emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
11943 DONE;
11944 })
11945
11946 ;; -------------------------------------------------------------------------
11947 ;; Misc
11948 ;; -------------------------------------------------------------------------
11949
11950 ;; String/block move insn.
11951
11952 (define_expand "movmemsi"
11953 [(parallel [(set (mem:BLK (match_operand:BLK 0))
11954 (mem:BLK (match_operand:BLK 1)))
11955 (use (match_operand:SI 2 "nonmemory_operand"))
11956 (use (match_operand:SI 3 "immediate_operand"))
11957 (clobber (reg:SI PR_REG))
11958 (clobber (reg:SI R4_REG))
11959 (clobber (reg:SI R5_REG))
11960 (clobber (reg:SI R0_REG))])]
11961 "TARGET_SH1 && ! TARGET_SH5"
11962 {
11963 if (expand_block_move (operands))
11964 DONE;
11965 else
11966 FAIL;
11967 })
11968
11969 (define_insn "block_move_real"
11970 [(parallel [(set (mem:BLK (reg:SI R4_REG))
11971 (mem:BLK (reg:SI R5_REG)))
11972 (use (match_operand:SI 0 "arith_reg_operand" "r"))
11973 (clobber (reg:SI PR_REG))
11974 (clobber (reg:SI R0_REG))])]
11975 "TARGET_SH1 && ! TARGET_HARD_SH4"
11976 "jsr @%0%#"
11977 [(set_attr "type" "sfunc")
11978 (set_attr "needs_delay_slot" "yes")])
11979
11980 (define_insn "block_lump_real"
11981 [(parallel [(set (mem:BLK (reg:SI R4_REG))
11982 (mem:BLK (reg:SI R5_REG)))
11983 (use (match_operand:SI 0 "arith_reg_operand" "r"))
11984 (use (reg:SI R6_REG))
11985 (clobber (reg:SI PR_REG))
11986 (clobber (reg:SI T_REG))
11987 (clobber (reg:SI R4_REG))
11988 (clobber (reg:SI R5_REG))
11989 (clobber (reg:SI R6_REG))
11990 (clobber (reg:SI R0_REG))])]
11991 "TARGET_SH1 && ! TARGET_HARD_SH4"
11992 "jsr @%0%#"
11993 [(set_attr "type" "sfunc")
11994 (set_attr "needs_delay_slot" "yes")])
11995
11996 (define_insn "block_move_real_i4"
11997 [(parallel [(set (mem:BLK (reg:SI R4_REG))
11998 (mem:BLK (reg:SI R5_REG)))
11999 (use (match_operand:SI 0 "arith_reg_operand" "r"))
12000 (clobber (reg:SI PR_REG))
12001 (clobber (reg:SI R0_REG))
12002 (clobber (reg:SI R1_REG))
12003 (clobber (reg:SI R2_REG))])]
12004 "TARGET_HARD_SH4"
12005 "jsr @%0%#"
12006 [(set_attr "type" "sfunc")
12007 (set_attr "needs_delay_slot" "yes")])
12008
12009 (define_insn "block_lump_real_i4"
12010 [(parallel [(set (mem:BLK (reg:SI R4_REG))
12011 (mem:BLK (reg:SI R5_REG)))
12012 (use (match_operand:SI 0 "arith_reg_operand" "r"))
12013 (use (reg:SI R6_REG))
12014 (clobber (reg:SI PR_REG))
12015 (clobber (reg:SI T_REG))
12016 (clobber (reg:SI R4_REG))
12017 (clobber (reg:SI R5_REG))
12018 (clobber (reg:SI R6_REG))
12019 (clobber (reg:SI R0_REG))
12020 (clobber (reg:SI R1_REG))
12021 (clobber (reg:SI R2_REG))
12022 (clobber (reg:SI R3_REG))])]
12023 "TARGET_HARD_SH4"
12024 "jsr @%0%#"
12025 [(set_attr "type" "sfunc")
12026 (set_attr "needs_delay_slot" "yes")])
12027
12028 ;; byte compare pattern
12029 ;; temp = a ^ b;
12030 ;; !((temp & 0xF000) && (temp & 0x0F00) && (temp & 0x00F0) && (temp & 0x000F))
12031 (define_insn "cmpstr_t"
12032 [(set (reg:SI T_REG)
12033 (eq:SI (and:SI
12034 (and:SI
12035 (and:SI
12036 (zero_extract:SI
12037 (xor:SI (match_operand:SI 0 "arith_reg_operand" "r")
12038 (match_operand:SI 1 "arith_reg_operand" "r"))
12039 (const_int 8) (const_int 0))
12040 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12041 (const_int 8) (const_int 8)))
12042 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12043 (const_int 8) (const_int 16)))
12044 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12045 (const_int 8) (const_int 24)))
12046 (const_int 0)))]
12047 "TARGET_SH1"
12048 "cmp/str %0,%1"
12049 [(set_attr "type" "mt_group")])
12050
12051 (define_expand "cmpstrsi"
12052 [(set (match_operand:SI 0 "register_operand")
12053 (compare:SI (match_operand:BLK 1 "memory_operand")
12054 (match_operand:BLK 2 "memory_operand")))
12055 (use (match_operand 3 "immediate_operand"))]
12056 "TARGET_SH1 && optimize"
12057 {
12058 if (! optimize_insn_for_size_p () && sh_expand_cmpstr (operands))
12059 DONE;
12060 else
12061 FAIL;
12062 })
12063
12064 (define_expand "cmpstrnsi"
12065 [(set (match_operand:SI 0 "register_operand")
12066 (compare:SI (match_operand:BLK 1 "memory_operand")
12067 (match_operand:BLK 2 "memory_operand")))
12068 (use (match_operand:SI 3 "immediate_operand"))
12069 (use (match_operand:SI 4 "immediate_operand"))]
12070 "TARGET_SH1 && optimize"
12071 {
12072 if (! optimize_insn_for_size_p () && sh_expand_cmpnstr (operands))
12073 DONE;
12074 else
12075 FAIL;
12076 })
12077
12078 (define_expand "strlensi"
12079 [(set (match_operand:SI 0 "register_operand")
12080 (unspec:SI [(match_operand:BLK 1 "memory_operand")
12081 (match_operand:SI 2 "immediate_operand")
12082 (match_operand:SI 3 "immediate_operand")]
12083 UNSPEC_BUILTIN_STRLEN))]
12084 "TARGET_SH1 && optimize"
12085 {
12086 if (! optimize_insn_for_size_p () && sh_expand_strlen (operands))
12087 DONE;
12088 else
12089 FAIL;
12090 })
12091
12092 \f
12093 ;; -------------------------------------------------------------------------
12094 ;; Floating point instructions.
12095 ;; -------------------------------------------------------------------------
12096
12097 ;; ??? All patterns should have a type attribute.
12098
12099 (define_expand "movpsi"
12100 [(set (match_operand:PSI 0 "register_operand" "")
12101 (match_operand:PSI 1 "general_movsrc_operand" ""))]
12102 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12103 "")
12104
12105 ;; The c / m alternative is a fake to guide reload to load directly into
12106 ;; fpscr, since reload doesn't know how to use post-increment.
12107 ;; TARGET_LEGITIMATE_ADDRESS_P guards about bogus addresses before reload,
12108 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
12109 ;; predicate after reload.
12110 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
12111 ;; like a mac -> gpr move.
12112 (define_insn "fpu_switch"
12113 [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
12114 (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
12115 "TARGET_SH2E
12116 && (! reload_completed
12117 || true_regnum (operands[0]) != FPSCR_REG
12118 || !MEM_P (operands[1])
12119 || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
12120 "@
12121 ! precision stays the same
12122 lds.l %1,fpscr
12123 mov.l %1,%0
12124 #
12125 lds %1,fpscr
12126 mov %1,%0
12127 mov.l %1,%0
12128 sts fpscr,%0
12129 sts.l fpscr,%0"
12130 [(set_attr "length" "0,2,2,4,2,2,2,2,2")
12131 (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,
12132 mac_gp,fstore")])
12133
12134 (define_peephole2
12135 [(set (reg:PSI FPSCR_REG)
12136 (mem:PSI (match_operand:SI 0 "register_operand" "")))]
12137 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
12138 [(const_int 0)]
12139 {
12140 rtx fpscr, mem, new_insn;
12141
12142 fpscr = SET_DEST (PATTERN (curr_insn));
12143 mem = SET_SRC (PATTERN (curr_insn));
12144 mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
12145
12146 new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
12147 add_reg_note (new_insn, REG_INC, operands[0]);
12148 DONE;
12149 })
12150
12151 (define_split
12152 [(set (reg:PSI FPSCR_REG)
12153 (mem:PSI (match_operand:SI 0 "register_operand" "")))]
12154 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
12155 && (flag_peephole2 ? epilogue_completed : reload_completed)"
12156 [(const_int 0)]
12157 {
12158 rtx fpscr, mem, new_insn;
12159
12160 fpscr = SET_DEST (PATTERN (curr_insn));
12161 mem = SET_SRC (PATTERN (curr_insn));
12162 mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
12163
12164 new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
12165 add_reg_note (new_insn, REG_INC, operands[0]);
12166
12167 if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
12168 emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
12169 DONE;
12170 })
12171
12172 ;; ??? This uses the fp unit, but has no type indicating that.
12173 ;; If we did that, this would either give a bogus latency or introduce
12174 ;; a bogus FIFO constraint.
12175 ;; Since this insn is currently only used for prologues/epilogues,
12176 ;; it is probably best to claim no function unit, which matches the
12177 ;; current setting.
12178 (define_insn "toggle_sz"
12179 [(set (reg:PSI FPSCR_REG)
12180 (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
12181 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12182 "fschg"
12183 [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
12184
12185 ;; There's no way we can use it today, since optimize mode switching
12186 ;; doesn't enable us to know from which mode we're switching to the
12187 ;; mode it requests, to tell whether we can use a relative mode switch
12188 ;; (like toggle_pr) or an absolute switch (like loading fpscr from
12189 ;; memory).
12190 (define_insn "toggle_pr"
12191 [(set (reg:PSI FPSCR_REG)
12192 (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
12193 "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
12194 "fpchg"
12195 [(set_attr "type" "fpscr_toggle")])
12196
12197 (define_expand "addsf3"
12198 [(set (match_operand:SF 0 "fp_arith_reg_operand")
12199 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand")
12200 (match_operand:SF 2 "fp_arith_reg_operand")))]
12201 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12202 {
12203 if (TARGET_SH2E)
12204 {
12205 expand_sf_binop (&gen_addsf3_i, operands);
12206 DONE;
12207 }
12208 })
12209
12210 (define_insn "*addsf3_media"
12211 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12212 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12213 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12214 "TARGET_SHMEDIA_FPU"
12215 "fadd.s %1, %2, %0"
12216 [(set_attr "type" "fparith_media")])
12217
12218 (define_insn_and_split "unary_sf_op"
12219 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12220 (vec_select:V2SF
12221 (vec_concat:V2SF
12222 (vec_select:SF
12223 (match_dup 0)
12224 (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
12225 (match_operator:SF 2 "unary_float_operator"
12226 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12227 (parallel [(match_operand 4
12228 "const_int_operand" "n")]))]))
12229 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
12230 "TARGET_SHMEDIA_FPU"
12231 "#"
12232 "TARGET_SHMEDIA_FPU && reload_completed"
12233 [(set (match_dup 5) (match_dup 6))]
12234 {
12235 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12236 rtx op1 = gen_rtx_REG (SFmode,
12237 (true_regnum (operands[1])
12238 + (INTVAL (operands[4]) ^ endian)));
12239
12240 operands[7] = gen_rtx_REG (SFmode,
12241 (true_regnum (operands[0])
12242 + (INTVAL (operands[3]) ^ endian)));
12243 operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
12244 }
12245 [(set_attr "type" "fparith_media")])
12246
12247 (define_insn_and_split "binary_sf_op0"
12248 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12249 (vec_concat:V2SF
12250 (match_operator:SF 3 "binary_float_operator"
12251 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12252 (parallel [(const_int 0)]))
12253 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
12254 (parallel [(const_int 0)]))])
12255 (vec_select:SF
12256 (match_dup 0)
12257 (parallel [(const_int 1)]))))]
12258 "TARGET_SHMEDIA_FPU"
12259 "#"
12260 "&& reload_completed"
12261 [(set (match_dup 4) (match_dup 5))]
12262 {
12263 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12264 rtx op1 = gen_rtx_REG (SFmode,
12265 true_regnum (operands[1]) + endian);
12266 rtx op2 = gen_rtx_REG (SFmode,
12267 true_regnum (operands[2]) + endian);
12268
12269 operands[4] = gen_rtx_REG (SFmode,
12270 true_regnum (operands[0]) + endian);
12271 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
12272 }
12273 [(set_attr "type" "fparith_media")])
12274
12275 (define_insn_and_split "binary_sf_op1"
12276 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12277 (vec_concat:V2SF
12278 (vec_select:SF
12279 (match_dup 0)
12280 (parallel [(const_int 0)]))
12281 (match_operator:SF 3 "binary_float_operator"
12282 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12283 (parallel [(const_int 1)]))
12284 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
12285 (parallel [(const_int 1)]))])))]
12286 "TARGET_SHMEDIA_FPU"
12287 "#"
12288 "&& reload_completed"
12289 [(set (match_dup 4) (match_dup 5))]
12290 {
12291 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12292 rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian));
12293 rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian));
12294
12295 operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian));
12296 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
12297 }
12298 [(set_attr "type" "fparith_media")])
12299
12300 (define_insn "addsf3_i"
12301 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12302 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
12303 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12304 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12305 "TARGET_SH2E"
12306 "fadd %2,%0"
12307 [(set_attr "type" "fp")
12308 (set_attr "fp_mode" "single")])
12309
12310 (define_expand "subsf3"
12311 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12312 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12313 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
12314 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12315 {
12316 if (TARGET_SH2E)
12317 {
12318 expand_sf_binop (&gen_subsf3_i, operands);
12319 DONE;
12320 }
12321 })
12322
12323 (define_insn "*subsf3_media"
12324 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12325 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12326 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12327 "TARGET_SHMEDIA_FPU"
12328 "fsub.s %1, %2, %0"
12329 [(set_attr "type" "fparith_media")])
12330
12331 (define_insn "subsf3_i"
12332 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12333 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
12334 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12335 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12336 "TARGET_SH2E"
12337 "fsub %2,%0"
12338 [(set_attr "type" "fp")
12339 (set_attr "fp_mode" "single")])
12340
12341 (define_expand "mulsf3"
12342 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12343 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12344 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
12345 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12346 {
12347 if (TARGET_SH2E)
12348 {
12349 emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2],
12350 get_fpscr_rtx ()));
12351 DONE;
12352 }
12353 })
12354
12355 (define_insn "*mulsf3_media"
12356 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12357 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12358 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12359 "TARGET_SHMEDIA_FPU"
12360 "fmul.s %1, %2, %0"
12361 [(set_attr "type" "fparith_media")])
12362
12363 (define_insn "mulsf3_i"
12364 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12365 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
12366 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12367 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12368 "TARGET_SH2E"
12369 "fmul %2,%0"
12370 [(set_attr "type" "fp")
12371 (set_attr "fp_mode" "single")])
12372
12373 ;; FMA (fused multiply-add) patterns
12374 (define_expand "fmasf4"
12375 [(set (match_operand:SF 0 "fp_arith_reg_operand")
12376 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand")
12377 (match_operand:SF 2 "fp_arith_reg_operand")
12378 (match_operand:SF 3 "fp_arith_reg_operand")))]
12379 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12380 {
12381 if (TARGET_SH2E)
12382 {
12383 emit_sf_insn (gen_fmasf4_i (operands[0], operands[1], operands[2],
12384 operands[3], get_fpscr_rtx ()));
12385 DONE;
12386 }
12387 })
12388
12389 (define_insn "fmasf4_i"
12390 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12391 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w")
12392 (match_operand:SF 2 "fp_arith_reg_operand" "f")
12393 (match_operand:SF 3 "fp_arith_reg_operand" "0")))
12394 (use (match_operand:PSI 4 "fpscr_operand" "c"))]
12395 "TARGET_SH2E"
12396 "fmac %1,%2,%0"
12397 [(set_attr "type" "fp")
12398 (set_attr "fp_mode" "single")])
12399
12400 (define_insn "fmasf4_media"
12401 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12402 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12403 (match_operand:SF 2 "fp_arith_reg_operand" "f")
12404 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
12405 "TARGET_SHMEDIA_FPU"
12406 "fmac.s %1, %2, %0"
12407 [(set_attr "type" "fparith_media")])
12408
12409 ;; For some cases such as 'a * b + a' the FMA pattern is not generated by
12410 ;; previous transformations. If FMA is generally allowed, let the combine
12411 ;; pass utilize it.
12412 (define_insn_and_split "*fmasf4"
12413 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12414 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
12415 (match_operand:SF 2 "fp_arith_reg_operand" "f"))
12416 (match_operand:SF 3 "arith_reg_operand" "0")))
12417 (use (match_operand:PSI 4 "fpscr_operand"))]
12418 "TARGET_SH2E && flag_fp_contract_mode != FP_CONTRACT_OFF"
12419 "fmac %1,%2,%0"
12420 "&& can_create_pseudo_p ()"
12421 [(parallel [(set (match_dup 0)
12422 (fma:SF (match_dup 1) (match_dup 2) (match_dup 3)))
12423 (use (match_dup 4))])]
12424 {
12425 /* Change 'b * a + a' into 'a * b + a'.
12426 This is better for register allocation. */
12427 if (REGNO (operands[2]) == REGNO (operands[3]))
12428 {
12429 rtx tmp = operands[1];
12430 operands[1] = operands[2];
12431 operands[2] = tmp;
12432 }
12433 }
12434 [(set_attr "type" "fp")
12435 (set_attr "fp_mode" "single")])
12436
12437 (define_insn "*fmasf4_media"
12438 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12439 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12440 (match_operand:SF 2 "fp_arith_reg_operand" "f"))
12441 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
12442 "TARGET_SHMEDIA_FPU && flag_fp_contract_mode != FP_CONTRACT_OFF"
12443 "fmac.s %1, %2, %0"
12444 [(set_attr "type" "fparith_media")])
12445
12446 (define_expand "divsf3"
12447 [(set (match_operand:SF 0 "fp_arith_reg_operand")
12448 (div:SF (match_operand:SF 1 "fp_arith_reg_operand")
12449 (match_operand:SF 2 "fp_arith_reg_operand")))]
12450 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12451 {
12452 if (TARGET_SH2E)
12453 {
12454 expand_sf_binop (&gen_divsf3_i, operands);
12455 DONE;
12456 }
12457 })
12458
12459 (define_insn "*divsf3_media"
12460 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12461 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12462 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12463 "TARGET_SHMEDIA_FPU"
12464 "fdiv.s %1, %2, %0"
12465 [(set_attr "type" "fdiv_media")])
12466
12467 (define_insn "divsf3_i"
12468 [(set (match_operand:SF 0 "fp_arith_reg_dest" "=f")
12469 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
12470 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12471 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12472 "TARGET_SH2E"
12473 "fdiv %2,%0"
12474 [(set_attr "type" "fdiv")
12475 (set_attr "fp_mode" "single")])
12476
12477 (define_insn "floatdisf2"
12478 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12479 (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
12480 "TARGET_SHMEDIA_FPU"
12481 "float.qs %1, %0"
12482 [(set_attr "type" "fpconv_media")])
12483
12484 (define_expand "floatsisf2"
12485 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12486 (float:SF (match_operand:SI 1 "fpul_operand" "")))]
12487 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12488 {
12489 if (TARGET_SH4 || TARGET_SH2A_SINGLE)
12490 {
12491 emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1],
12492 get_fpscr_rtx ()));
12493 DONE;
12494 }
12495 })
12496
12497 (define_insn "*floatsisf2_media"
12498 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12499 (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
12500 "TARGET_SHMEDIA_FPU"
12501 "float.ls %1, %0"
12502 [(set_attr "type" "fpconv_media")])
12503
12504 (define_insn "floatsisf2_i4"
12505 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12506 (float:SF (match_operand:SI 1 "fpul_operand" "y")))
12507 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12508 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12509 "float %1,%0"
12510 [(set_attr "type" "fp")
12511 (set_attr "fp_mode" "single")])
12512
12513 (define_insn "*floatsisf2_ie"
12514 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12515 (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
12516 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12517 "float %1,%0"
12518 [(set_attr "type" "fp")])
12519
12520 (define_insn "fix_truncsfdi2"
12521 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
12522 (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12523 "TARGET_SHMEDIA_FPU"
12524 "ftrc.sq %1, %0"
12525 [(set_attr "type" "fpconv_media")])
12526
12527 (define_expand "fix_truncsfsi2"
12528 [(set (match_operand:SI 0 "fpul_operand" "=y")
12529 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12530 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12531 {
12532 if (TARGET_SH4 || TARGET_SH2A_SINGLE)
12533 {
12534 emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1],
12535 get_fpscr_rtx ()));
12536 DONE;
12537 }
12538 })
12539
12540 (define_insn "*fix_truncsfsi2_media"
12541 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
12542 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12543 "TARGET_SHMEDIA_FPU"
12544 "ftrc.sl %1, %0"
12545 [(set_attr "type" "fpconv_media")])
12546
12547 (define_insn "fix_truncsfsi2_i4"
12548 [(set (match_operand:SI 0 "fpul_operand" "=y")
12549 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12550 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12551 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12552 "ftrc %1,%0"
12553 [(set_attr "type" "ftrc_s")
12554 (set_attr "fp_mode" "single")])
12555
12556 ;; ??? This pattern is used nowhere. fix_truncsfsi2 always expands to
12557 ;; fix_truncsfsi2_i4.
12558 ;; (define_insn "fix_truncsfsi2_i4_2"
12559 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12560 ;; (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
12561 ;; (use (reg:PSI FPSCR_REG))
12562 ;; (clobber (reg:SI FPUL_REG))]
12563 ;; "TARGET_SH4"
12564 ;; "#"
12565 ;; [(set_attr "length" "4")
12566 ;; (set_attr "fp_mode" "single")])
12567
12568 ;;(define_split
12569 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12570 ;; (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
12571 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
12572 ;; (clobber (reg:SI FPUL_REG))]
12573 ;; "TARGET_SH4"
12574 ;; [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
12575 ;; (use (match_dup 2))])
12576 ;; (set (match_dup 0) (reg:SI FPUL_REG))])
12577
12578 (define_insn "*fixsfsi"
12579 [(set (match_operand:SI 0 "fpul_operand" "=y")
12580 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12581 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12582 "ftrc %1,%0"
12583 [(set_attr "type" "fp")])
12584
12585 (define_insn "cmpgtsf_t"
12586 [(set (reg:SI T_REG)
12587 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12588 (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12589 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12590 "fcmp/gt %1,%0"
12591 [(set_attr "type" "fp_cmp")
12592 (set_attr "fp_mode" "single")])
12593
12594 (define_insn "cmpeqsf_t"
12595 [(set (reg:SI T_REG)
12596 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12597 (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12598 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12599 "fcmp/eq %1,%0"
12600 [(set_attr "type" "fp_cmp")
12601 (set_attr "fp_mode" "single")])
12602
12603 (define_insn "ieee_ccmpeqsf_t"
12604 [(set (reg:SI T_REG)
12605 (ior:SI (reg:SI T_REG)
12606 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12607 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
12608 "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12609 {
12610 return output_ieee_ccmpeq (insn, operands);
12611 }
12612 [(set_attr "length" "4")])
12613
12614
12615 (define_insn "cmpgtsf_t_i4"
12616 [(set (reg:SI T_REG)
12617 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12618 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12619 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12620 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12621 "fcmp/gt %1,%0"
12622 [(set_attr "type" "fp_cmp")
12623 (set_attr "fp_mode" "single")])
12624
12625 (define_insn "cmpeqsf_t_i4"
12626 [(set (reg:SI T_REG)
12627 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12628 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12629 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12630 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12631 "fcmp/eq %1,%0"
12632 [(set_attr "type" "fp_cmp")
12633 (set_attr "fp_mode" "single")])
12634
12635 (define_insn "*ieee_ccmpeqsf_t_4"
12636 [(set (reg:SI T_REG)
12637 (ior:SI (reg:SI T_REG)
12638 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12639 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
12640 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12641 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12642 {
12643 return output_ieee_ccmpeq (insn, operands);
12644 }
12645 [(set_attr "length" "4")
12646 (set_attr "fp_mode" "single")])
12647
12648 (define_insn "cmpeqsf_media"
12649 [(set (match_operand:SI 0 "register_operand" "=r")
12650 (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12651 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12652 "TARGET_SHMEDIA_FPU"
12653 "fcmpeq.s %1, %2, %0"
12654 [(set_attr "type" "fcmp_media")])
12655
12656 (define_insn "cmpgtsf_media"
12657 [(set (match_operand:SI 0 "register_operand" "=r")
12658 (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12659 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12660 "TARGET_SHMEDIA_FPU"
12661 "fcmpgt.s %1, %2, %0"
12662 [(set_attr "type" "fcmp_media")])
12663
12664 (define_insn "cmpgesf_media"
12665 [(set (match_operand:SI 0 "register_operand" "=r")
12666 (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12667 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12668 "TARGET_SHMEDIA_FPU"
12669 "fcmpge.s %1, %2, %0"
12670 [(set_attr "type" "fcmp_media")])
12671
12672 (define_insn "cmpunsf_media"
12673 [(set (match_operand:SI 0 "register_operand" "=r")
12674 (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12675 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12676 "TARGET_SHMEDIA_FPU"
12677 "fcmpun.s %1, %2, %0"
12678 [(set_attr "type" "fcmp_media")])
12679
12680 (define_expand "cbranchsf4"
12681 [(set (pc)
12682 (if_then_else (match_operator 0 "sh_float_comparison_operator"
12683 [(match_operand:SF 1 "arith_operand" "")
12684 (match_operand:SF 2 "arith_operand" "")])
12685 (match_operand 3 "" "")
12686 (pc)))]
12687 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12688 {
12689 if (TARGET_SHMEDIA)
12690 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
12691 operands[3]));
12692 else
12693 sh_emit_compare_and_branch (operands, SFmode);
12694 DONE;
12695 })
12696
12697 (define_expand "negsf2"
12698 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12699 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12700 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12701 {
12702 if (TARGET_SH2E)
12703 {
12704 expand_sf_unop (&gen_negsf2_i, operands);
12705 DONE;
12706 }
12707 })
12708
12709 (define_insn "*negsf2_media"
12710 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12711 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12712 "TARGET_SHMEDIA_FPU"
12713 "fneg.s %1, %0"
12714 [(set_attr "type" "fmove_media")])
12715
12716 (define_insn "negsf2_i"
12717 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12718 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12719 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12720 "TARGET_SH2E"
12721 "fneg %0"
12722 [(set_attr "type" "fmove")
12723 (set_attr "fp_mode" "single")])
12724
12725 (define_expand "sqrtsf2"
12726 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12727 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12728 "TARGET_SH3E || TARGET_SHMEDIA_FPU"
12729 {
12730 if (TARGET_SH3E)
12731 {
12732 expand_sf_unop (&gen_sqrtsf2_i, operands);
12733 DONE;
12734 }
12735 })
12736
12737 (define_insn "*sqrtsf2_media"
12738 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12739 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12740 "TARGET_SHMEDIA_FPU"
12741 "fsqrt.s %1, %0"
12742 [(set_attr "type" "fdiv_media")])
12743
12744 (define_insn "sqrtsf2_i"
12745 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12746 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12747 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12748 "TARGET_SH3E"
12749 "fsqrt %0"
12750 [(set_attr "type" "fdiv")
12751 (set_attr "fp_mode" "single")])
12752
12753 (define_insn "rsqrtsf2"
12754 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12755 (div:SF (match_operand:SF 1 "immediate_operand" "i")
12756 (sqrt:SF (match_operand:SF 2 "fp_arith_reg_operand" "0"))))
12757 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12758 "TARGET_FPU_ANY && TARGET_FSRRA
12759 && operands[1] == CONST1_RTX (SFmode)"
12760 "fsrra %0"
12761 [(set_attr "type" "fsrra")
12762 (set_attr "fp_mode" "single")])
12763
12764 ;; When the sincos pattern is defined, the builtin functions sin and cos
12765 ;; will be expanded to the sincos pattern and one of the output values will
12766 ;; remain unused.
12767 (define_expand "sincossf3"
12768 [(set (match_operand:SF 0 "nonimmediate_operand")
12769 (unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand")] UNSPEC_FCOSA))
12770 (set (match_operand:SF 1 "nonimmediate_operand")
12771 (unspec:SF [(match_dup 2)] UNSPEC_FSINA))]
12772 "TARGET_FPU_ANY && TARGET_FSCA"
12773 {
12774 rtx scaled = gen_reg_rtx (SFmode);
12775 rtx truncated = gen_reg_rtx (SImode);
12776 rtx fsca = gen_reg_rtx (V2SFmode);
12777 rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
12778
12779 emit_sf_insn (gen_mulsf3 (scaled, operands[2], scale_reg));
12780 emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
12781 emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
12782 get_fpscr_rtx ()));
12783
12784 emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
12785 emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 0));
12786 DONE;
12787 })
12788
12789 (define_insn_and_split "fsca"
12790 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12791 (vec_concat:V2SF
12792 (unspec:SF [(mult:SF
12793 (float:SF (match_operand:SI 1 "fpul_fsca_operand" "y"))
12794 (match_operand:SF 2 "fsca_scale_factor" "i"))
12795 ] UNSPEC_FSINA)
12796 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
12797 ] UNSPEC_FCOSA)))
12798 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12799 "TARGET_FPU_ANY && TARGET_FSCA"
12800 "fsca fpul,%d0"
12801 "&& !fpul_operand (operands[1], SImode)"
12802 [(const_int 0)]
12803 {
12804 /* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it
12805 to a simple reg, otherwise reload will have trouble reloading the
12806 pseudo into fpul. */
12807 rtx x = XEXP (operands[1], 0);
12808 while (x != NULL_RTX && !fpul_operand (x, SImode))
12809 {
12810 gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT);
12811 x = XEXP (x, 0);
12812 }
12813
12814 gcc_assert (x != NULL_RTX && fpul_operand (x, SImode));
12815 emit_insn (gen_fsca (operands[0], x, operands[2], operands[3]));
12816 DONE;
12817 }
12818 [(set_attr "type" "fsca")
12819 (set_attr "fp_mode" "single")])
12820
12821 (define_expand "abssf2"
12822 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12823 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12824 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12825 {
12826 if (TARGET_SH2E)
12827 {
12828 expand_sf_unop (&gen_abssf2_i, operands);
12829 DONE;
12830 }
12831 })
12832
12833 (define_insn "*abssf2_media"
12834 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12835 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12836 "TARGET_SHMEDIA_FPU"
12837 "fabs.s %1, %0"
12838 [(set_attr "type" "fmove_media")])
12839
12840 (define_insn "abssf2_i"
12841 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12842 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12843 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12844 "TARGET_SH2E"
12845 "fabs %0"
12846 [(set_attr "type" "fmove")
12847 (set_attr "fp_mode" "single")])
12848
12849 (define_expand "adddf3"
12850 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12851 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12852 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12853 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12854 {
12855 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12856 {
12857 expand_df_binop (&gen_adddf3_i, operands);
12858 DONE;
12859 }
12860 })
12861
12862 (define_insn "*adddf3_media"
12863 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12864 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12865 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12866 "TARGET_SHMEDIA_FPU"
12867 "fadd.d %1, %2, %0"
12868 [(set_attr "type" "dfparith_media")])
12869
12870 (define_insn "adddf3_i"
12871 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12872 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12873 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12874 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12875 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12876 "fadd %2,%0"
12877 [(set_attr "type" "dfp_arith")
12878 (set_attr "fp_mode" "double")])
12879
12880 (define_expand "subdf3"
12881 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12882 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12883 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12884 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12885 {
12886 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12887 {
12888 expand_df_binop (&gen_subdf3_i, operands);
12889 DONE;
12890 }
12891 })
12892
12893 (define_insn "*subdf3_media"
12894 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12895 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12896 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12897 "TARGET_SHMEDIA_FPU"
12898 "fsub.d %1, %2, %0"
12899 [(set_attr "type" "dfparith_media")])
12900
12901 (define_insn "subdf3_i"
12902 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12903 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12904 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12905 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12906 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12907 "fsub %2,%0"
12908 [(set_attr "type" "dfp_arith")
12909 (set_attr "fp_mode" "double")])
12910
12911 (define_expand "muldf3"
12912 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12913 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12914 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12915 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12916 {
12917 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12918 {
12919 expand_df_binop (&gen_muldf3_i, operands);
12920 DONE;
12921 }
12922 })
12923
12924 (define_insn "*muldf3_media"
12925 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12926 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12927 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12928 "TARGET_SHMEDIA_FPU"
12929 "fmul.d %1, %2, %0"
12930 [(set_attr "type" "dfmul_media")])
12931
12932 (define_insn "muldf3_i"
12933 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12934 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12935 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12936 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12937 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12938 "fmul %2,%0"
12939 [(set_attr "type" "dfp_mul")
12940 (set_attr "fp_mode" "double")])
12941
12942 (define_expand "divdf3"
12943 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12944 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12945 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12946 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12947 {
12948 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12949 {
12950 expand_df_binop (&gen_divdf3_i, operands);
12951 DONE;
12952 }
12953 })
12954
12955 (define_insn "*divdf3_media"
12956 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12957 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12958 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12959 "TARGET_SHMEDIA_FPU"
12960 "fdiv.d %1, %2, %0"
12961 [(set_attr "type" "dfdiv_media")])
12962
12963 (define_insn "divdf3_i"
12964 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12965 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12966 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12967 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12968 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12969 "fdiv %2,%0"
12970 [(set_attr "type" "dfdiv")
12971 (set_attr "fp_mode" "double")])
12972
12973 (define_insn "floatdidf2"
12974 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12975 (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
12976 "TARGET_SHMEDIA_FPU"
12977 "float.qd %1, %0"
12978 [(set_attr "type" "dfpconv_media")])
12979
12980 (define_expand "floatsidf2"
12981 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12982 (float:DF (match_operand:SI 1 "fpul_operand" "")))]
12983 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12984 {
12985 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12986 {
12987 emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
12988 get_fpscr_rtx ()));
12989 DONE;
12990 }
12991 })
12992
12993 (define_insn "*floatsidf2_media"
12994 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12995 (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
12996 "TARGET_SHMEDIA_FPU"
12997 "float.ld %1, %0"
12998 [(set_attr "type" "dfpconv_media")])
12999
13000 (define_insn "floatsidf2_i"
13001 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13002 (float:DF (match_operand:SI 1 "fpul_operand" "y")))
13003 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13004 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13005 "float %1,%0"
13006 [(set_attr "type" "dfp_conv")
13007 (set_attr "fp_mode" "double")])
13008
13009 (define_insn "fix_truncdfdi2"
13010 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
13011 (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13012 "TARGET_SHMEDIA_FPU"
13013 "ftrc.dq %1, %0"
13014 [(set_attr "type" "dfpconv_media")])
13015
13016 (define_expand "fix_truncdfsi2"
13017 [(set (match_operand:SI 0 "fpul_operand" "")
13018 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
13019 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13020 {
13021 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13022 {
13023 emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
13024 get_fpscr_rtx ()));
13025 DONE;
13026 }
13027 })
13028
13029 (define_insn "*fix_truncdfsi2_media"
13030 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
13031 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13032 "TARGET_SHMEDIA_FPU"
13033 "ftrc.dl %1, %0"
13034 [(set_attr "type" "dfpconv_media")])
13035
13036 (define_insn "fix_truncdfsi2_i"
13037 [(set (match_operand:SI 0 "fpul_operand" "=y")
13038 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13039 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13040 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13041 "ftrc %1,%0"
13042 [(set_attr "type" "dfp_conv")
13043 (set_attr "dfp_comp" "no")
13044 (set_attr "fp_mode" "double")])
13045
13046 ;; ??? This pattern is used nowhere. fix_truncdfsi2 always expands to
13047 ;; fix_truncdfsi2_i.
13048 ;; (define_insn "fix_truncdfsi2_i4"
13049 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
13050 ;; (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
13051 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
13052 ;; (clobber (reg:SI FPUL_REG))]
13053 ;; "TARGET_SH4"
13054 ;; "#"
13055 ;; [(set_attr "length" "4")
13056 ;; (set_attr "fp_mode" "double")])
13057 ;;
13058 ;; (define_split
13059 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
13060 ;; (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
13061 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
13062 ;; (clobber (reg:SI FPUL_REG))]
13063 ;; "TARGET_SH4"
13064 ;; [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
13065 ;; (use (match_dup 2))])
13066 ;; (set (match_dup 0) (reg:SI FPUL_REG))])
13067
13068 (define_insn "cmpgtdf_t"
13069 [(set (reg:SI T_REG)
13070 (gt:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13071 (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13072 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13073 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13074 "fcmp/gt %1,%0"
13075 [(set_attr "type" "dfp_cmp")
13076 (set_attr "fp_mode" "double")])
13077
13078 (define_insn "cmpeqdf_t"
13079 [(set (reg:SI T_REG)
13080 (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13081 (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13082 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13083 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13084 "fcmp/eq %1,%0"
13085 [(set_attr "type" "dfp_cmp")
13086 (set_attr "fp_mode" "double")])
13087
13088 (define_insn "*ieee_ccmpeqdf_t"
13089 [(set (reg:SI T_REG)
13090 (ior:SI (reg:SI T_REG)
13091 (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13092 (match_operand:DF 1 "fp_arith_reg_operand" "f"))))
13093 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13094 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13095 {
13096 return output_ieee_ccmpeq (insn, operands);
13097 }
13098 [(set_attr "length" "4")
13099 (set_attr "fp_mode" "double")])
13100
13101 (define_insn "cmpeqdf_media"
13102 [(set (match_operand:SI 0 "register_operand" "=r")
13103 (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13104 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13105 "TARGET_SHMEDIA_FPU"
13106 "fcmpeq.d %1,%2,%0"
13107 [(set_attr "type" "fcmp_media")])
13108
13109 (define_insn "cmpgtdf_media"
13110 [(set (match_operand:SI 0 "register_operand" "=r")
13111 (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13112 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13113 "TARGET_SHMEDIA_FPU"
13114 "fcmpgt.d %1,%2,%0"
13115 [(set_attr "type" "fcmp_media")])
13116
13117 (define_insn "cmpgedf_media"
13118 [(set (match_operand:SI 0 "register_operand" "=r")
13119 (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13120 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13121 "TARGET_SHMEDIA_FPU"
13122 "fcmpge.d %1,%2,%0"
13123 [(set_attr "type" "fcmp_media")])
13124
13125 (define_insn "cmpundf_media"
13126 [(set (match_operand:SI 0 "register_operand" "=r")
13127 (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13128 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13129 "TARGET_SHMEDIA_FPU"
13130 "fcmpun.d %1,%2,%0"
13131 [(set_attr "type" "fcmp_media")])
13132
13133 (define_expand "cbranchdf4"
13134 [(set (pc)
13135 (if_then_else (match_operator 0 "sh_float_comparison_operator"
13136 [(match_operand:DF 1 "arith_operand" "")
13137 (match_operand:DF 2 "arith_operand" "")])
13138 (match_operand 3 "" "")
13139 (pc)))]
13140 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13141 {
13142 if (TARGET_SHMEDIA)
13143 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
13144 operands[3]));
13145 else
13146 sh_emit_compare_and_branch (operands, DFmode);
13147 DONE;
13148 })
13149
13150 (define_expand "negdf2"
13151 [(set (match_operand:DF 0 "fp_arith_reg_operand")
13152 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13153 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13154 {
13155 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13156 {
13157 expand_df_unop (&gen_negdf2_i, operands);
13158 DONE;
13159 }
13160 })
13161
13162 (define_insn "*negdf2_media"
13163 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13164 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13165 "TARGET_SHMEDIA_FPU"
13166 "fneg.d %1, %0"
13167 [(set_attr "type" "fmove_media")])
13168
13169 (define_insn "negdf2_i"
13170 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13171 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
13172 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13173 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13174 "fneg %0"
13175 [(set_attr "type" "fmove")
13176 (set_attr "fp_mode" "double")])
13177
13178 (define_expand "sqrtdf2"
13179 [(set (match_operand:DF 0 "fp_arith_reg_operand")
13180 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13181 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13182 {
13183 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13184 {
13185 expand_df_unop (&gen_sqrtdf2_i, operands);
13186 DONE;
13187 }
13188 })
13189
13190 (define_insn "*sqrtdf2_media"
13191 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13192 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13193 "TARGET_SHMEDIA_FPU"
13194 "fsqrt.d %1, %0"
13195 [(set_attr "type" "dfdiv_media")])
13196
13197 (define_insn "sqrtdf2_i"
13198 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13199 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
13200 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13201 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13202 "fsqrt %0"
13203 [(set_attr "type" "dfdiv")
13204 (set_attr "fp_mode" "double")])
13205
13206 (define_expand "absdf2"
13207 [(set (match_operand:DF 0 "fp_arith_reg_operand")
13208 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13209 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13210 {
13211 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13212 {
13213 expand_df_unop (&gen_absdf2_i, operands);
13214 DONE;
13215 }
13216 })
13217
13218 (define_insn "*absdf2_media"
13219 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13220 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13221 "TARGET_SHMEDIA_FPU"
13222 "fabs.d %1, %0"
13223 [(set_attr "type" "fmove_media")])
13224
13225 (define_insn "absdf2_i"
13226 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13227 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
13228 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13229 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13230 "fabs %0"
13231 [(set_attr "type" "fmove")
13232 (set_attr "fp_mode" "double")])
13233
13234 (define_expand "extendsfdf2"
13235 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13236 (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
13237 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13238 {
13239 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13240 {
13241 emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
13242 get_fpscr_rtx ()));
13243 DONE;
13244 }
13245 })
13246
13247 (define_insn "*extendsfdf2_media"
13248 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13249 (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13250 "TARGET_SHMEDIA_FPU"
13251 "fcnv.sd %1, %0"
13252 [(set_attr "type" "dfpconv_media")])
13253
13254 (define_insn "extendsfdf2_i4"
13255 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13256 (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
13257 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13258 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13259 "fcnvsd %1,%0"
13260 [(set_attr "type" "fp")
13261 (set_attr "fp_mode" "double")])
13262
13263 (define_expand "truncdfsf2"
13264 [(set (match_operand:SF 0 "fpul_operand" "")
13265 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
13266 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13267 {
13268 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13269 {
13270 emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
13271 get_fpscr_rtx ()));
13272 DONE;
13273 }
13274 })
13275
13276 (define_insn "*truncdfsf2_media"
13277 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13278 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13279 "TARGET_SHMEDIA_FPU"
13280 "fcnv.ds %1, %0"
13281 [(set_attr "type" "dfpconv_media")])
13282
13283 (define_insn "truncdfsf2_i4"
13284 [(set (match_operand:SF 0 "fpul_operand" "=y")
13285 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13286 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13287 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13288 "fcnvds %1,%0"
13289 [(set_attr "type" "fp")
13290 (set_attr "fp_mode" "double")])
13291 \f
13292 ;; -------------------------------------------------------------------------
13293 ;; Bit field extract patterns.
13294 ;; -------------------------------------------------------------------------
13295
13296 ;; These give better code for packed bitfields, because they allow
13297 ;; auto-increment addresses to be generated.
13298
13299 (define_expand "insv"
13300 [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
13301 (match_operand:SI 1 "immediate_operand" "")
13302 (match_operand:SI 2 "immediate_operand" ""))
13303 (match_operand:SI 3 "general_operand" ""))]
13304 "TARGET_SH1 && TARGET_BIG_ENDIAN"
13305 {
13306 rtx addr_target, orig_address, shift_reg, qi_val;
13307 HOST_WIDE_INT bitsize, size, v = 0;
13308 rtx x = operands[3];
13309
13310 if (TARGET_SH2A && TARGET_BITOPS
13311 && (satisfies_constraint_Sbw (operands[0])
13312 || satisfies_constraint_Sbv (operands[0]))
13313 && satisfies_constraint_M (operands[1])
13314 && satisfies_constraint_K03 (operands[2]))
13315 {
13316 if (satisfies_constraint_N (operands[3]))
13317 {
13318 emit_insn (gen_bclr_m2a (operands[0], operands[2]));
13319 DONE;
13320 }
13321 else if (satisfies_constraint_M (operands[3]))
13322 {
13323 emit_insn (gen_bset_m2a (operands[0], operands[2]));
13324 DONE;
13325 }
13326 else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
13327 && satisfies_constraint_M (operands[1]))
13328 {
13329 emit_insn (gen_bst_m2a (operands[0], operands[2]));
13330 DONE;
13331 }
13332 else if (REG_P (operands[3])
13333 && satisfies_constraint_M (operands[1]))
13334 {
13335 emit_insn (gen_bld_reg (operands[3], const0_rtx));
13336 emit_insn (gen_bst_m2a (operands[0], operands[2]));
13337 DONE;
13338 }
13339 }
13340 /* ??? expmed doesn't care for non-register predicates. */
13341 if (! memory_operand (operands[0], VOIDmode)
13342 || ! immediate_operand (operands[1], VOIDmode)
13343 || ! immediate_operand (operands[2], VOIDmode)
13344 || ! general_operand (x, VOIDmode))
13345 FAIL;
13346 /* If this isn't a 16 / 24 / 32 bit field, or if
13347 it doesn't start on a byte boundary, then fail. */
13348 bitsize = INTVAL (operands[1]);
13349 if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
13350 || (INTVAL (operands[2]) % 8) != 0)
13351 FAIL;
13352
13353 size = bitsize / 8;
13354 orig_address = XEXP (operands[0], 0);
13355 shift_reg = gen_reg_rtx (SImode);
13356 if (CONST_INT_P (x))
13357 {
13358 v = INTVAL (x);
13359 qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
13360 }
13361 else
13362 {
13363 emit_insn (gen_movsi (shift_reg, operands[3]));
13364 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13365 }
13366 addr_target = copy_addr_to_reg (plus_constant (Pmode,
13367 orig_address, size - 1));
13368
13369 operands[0] = replace_equiv_address (operands[0], addr_target);
13370 emit_insn (gen_movqi (operands[0], qi_val));
13371
13372 while (size -= 1)
13373 {
13374 if (CONST_INT_P (x))
13375 qi_val
13376 = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
13377 else
13378 {
13379 emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
13380 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13381 }
13382 emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
13383 emit_insn (gen_movqi (operands[0], qi_val));
13384 }
13385
13386 DONE;
13387 })
13388
13389 (define_insn "movua"
13390 [(set (match_operand:SI 0 "register_operand" "=z")
13391 (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
13392 UNSPEC_MOVUA))]
13393 "TARGET_SH4A_ARCH"
13394 "movua.l %1,%0"
13395 [(set_attr "type" "movua")])
13396
13397 ;; We shouldn't need this, but cse replaces increments with references
13398 ;; to other regs before flow has a chance to create post_inc
13399 ;; addressing modes, and only postreload's cse_move2add brings the
13400 ;; increments back to a usable form.
13401 (define_peephole2
13402 [(set (match_operand:SI 0 "register_operand" "")
13403 (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
13404 (const_int 32) (const_int 0)))
13405 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
13406 "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
13407 [(set (match_operand:SI 0 "register_operand" "")
13408 (sign_extract:SI (mem:SI (post_inc:SI
13409 (match_operand:SI 1 "register_operand" "")))
13410 (const_int 32) (const_int 0)))]
13411 "")
13412
13413 (define_expand "extv"
13414 [(set (match_operand:SI 0 "register_operand" "")
13415 (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
13416 (match_operand 2 "const_int_operand" "")
13417 (match_operand 3 "const_int_operand" "")))]
13418 "TARGET_SH4A_ARCH || TARGET_SH2A"
13419 {
13420 if (TARGET_SH2A && TARGET_BITOPS
13421 && (satisfies_constraint_Sbw (operands[1])
13422 || satisfies_constraint_Sbv (operands[1]))
13423 && satisfies_constraint_M (operands[2])
13424 && satisfies_constraint_K03 (operands[3]))
13425 {
13426 emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
13427 if (REGNO (operands[0]) != T_REG)
13428 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
13429 DONE;
13430 }
13431 if (TARGET_SH4A_ARCH
13432 && INTVAL (operands[2]) == 32
13433 && INTVAL (operands[3]) == 0
13434 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
13435 {
13436 rtx src = adjust_address (operands[1], BLKmode, 0);
13437 set_mem_size (src, 4);
13438 emit_insn (gen_movua (operands[0], src));
13439 DONE;
13440 }
13441
13442 FAIL;
13443 })
13444
13445 (define_expand "extzv"
13446 [(set (match_operand:SI 0 "register_operand" "")
13447 (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
13448 (match_operand 2 "const_int_operand" "")
13449 (match_operand 3 "const_int_operand" "")))]
13450 "TARGET_SH4A_ARCH || TARGET_SH2A"
13451 {
13452 if (TARGET_SH2A && TARGET_BITOPS
13453 && (satisfies_constraint_Sbw (operands[1])
13454 || satisfies_constraint_Sbv (operands[1]))
13455 && satisfies_constraint_M (operands[2])
13456 && satisfies_constraint_K03 (operands[3]))
13457 {
13458 emit_insn (gen_bld_m2a (operands[1], operands[3]));
13459 if (REGNO (operands[0]) != T_REG)
13460 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
13461 DONE;
13462 }
13463 if (TARGET_SH4A_ARCH
13464 && INTVAL (operands[2]) == 32
13465 && INTVAL (operands[3]) == 0
13466 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
13467 {
13468 rtx src = adjust_address (operands[1], BLKmode, 0);
13469 set_mem_size (src, 4);
13470 emit_insn (gen_movua (operands[0], src));
13471 DONE;
13472 }
13473
13474 FAIL;
13475 })
13476
13477 ;; SH2A instructions for bitwise operations.
13478 ;; FIXME: Convert multiple instruction insns to insn_and_split.
13479 ;; FIXME: Use iterators to fold at least and,xor,or insn variations.
13480
13481 ;; Clear a bit in a memory location.
13482 (define_insn "bclr_m2a"
13483 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13484 (and:QI
13485 (not:QI (ashift:QI (const_int 1)
13486 (match_operand:QI 1 "const_int_operand" "K03,K03")))
13487 (match_dup 0)))]
13488 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13489 "@
13490 bclr.b %1,%0
13491 bclr.b %1,@(0,%t0)"
13492 [(set_attr "length" "4,4")])
13493
13494 (define_insn "bclrmem_m2a"
13495 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13496 (and:QI (match_dup 0)
13497 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
13498 "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
13499 "@
13500 bclr.b %W1,%0
13501 bclr.b %W1,@(0,%t0)"
13502 [(set_attr "length" "4,4")])
13503
13504 ;; Set a bit in a memory location.
13505 (define_insn "bset_m2a"
13506 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13507 (ior:QI
13508 (ashift:QI (const_int 1)
13509 (match_operand:QI 1 "const_int_operand" "K03,K03"))
13510 (match_dup 0)))]
13511 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13512 "@
13513 bset.b %1,%0
13514 bset.b %1,@(0,%t0)"
13515 [(set_attr "length" "4,4")])
13516
13517 (define_insn "bsetmem_m2a"
13518 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13519 (ior:QI (match_dup 0)
13520 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
13521 "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
13522 "@
13523 bset.b %V1,%0
13524 bset.b %V1,@(0,%t0)"
13525 [(set_attr "length" "4,4")])
13526
13527 ;;; Transfer the contents of the T bit to a specified bit of memory.
13528 (define_insn "bst_m2a"
13529 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
13530 (if_then_else (eq (reg:SI T_REG) (const_int 0))
13531 (and:QI
13532 (not:QI (ashift:QI (const_int 1)
13533 (match_operand:QI 1 "const_int_operand" "K03,K03")))
13534 (match_dup 0))
13535 (ior:QI
13536 (ashift:QI (const_int 1) (match_dup 1))
13537 (match_dup 0))))]
13538 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13539 "@
13540 bst.b %1,%0
13541 bst.b %1,@(0,%t0)"
13542 [(set_attr "length" "4")])
13543
13544 ;; Store a specified bit of memory in the T bit.
13545 (define_insn "bld_m2a"
13546 [(set (reg:SI T_REG)
13547 (zero_extract:SI
13548 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
13549 (const_int 1)
13550 (match_operand 1 "const_int_operand" "K03,K03")))]
13551 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13552 "@
13553 bld.b %1,%0
13554 bld.b %1,@(0,%t0)"
13555 [(set_attr "length" "4,4")])
13556
13557 ;; Store a specified bit of memory in the T bit.
13558 (define_insn "bldsign_m2a"
13559 [(set (reg:SI T_REG)
13560 (sign_extract:SI
13561 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13562 (const_int 1)
13563 (match_operand 1 "const_int_operand" "K03,K03")))]
13564 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13565 "@
13566 bld.b %1,%0
13567 bld.b %1,@(0,%t0)"
13568 [(set_attr "length" "4,4")])
13569
13570 ;; Store a specified bit of the LSB 8 bits of a register in the T bit.
13571 (define_insn "bld_reg"
13572 [(set (reg:SI T_REG)
13573 (zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
13574 (const_int 1)
13575 (match_operand 1 "const_int_operand" "K03")))]
13576 "TARGET_SH2A && satisfies_constraint_K03 (operands[1])"
13577 "bld %1,%0")
13578
13579 (define_insn "*bld_regqi"
13580 [(set (reg:SI T_REG)
13581 (zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
13582 (const_int 1)
13583 (match_operand 1 "const_int_operand" "K03")))]
13584 "TARGET_SH2A && satisfies_constraint_K03 (operands[1])"
13585 "bld %1,%0")
13586
13587 ;; Take logical and of a specified bit of memory with the T bit and
13588 ;; store its result in the T bit.
13589 (define_insn "band_m2a"
13590 [(set (reg:SI T_REG)
13591 (and:SI (reg:SI T_REG)
13592 (zero_extract:SI
13593 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13594 (const_int 1)
13595 (match_operand 1 "const_int_operand" "K03,K03"))))]
13596 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13597 "@
13598 band.b %1,%0
13599 band.b %1,@(0,%t0)"
13600 [(set_attr "length" "4,4")])
13601
13602 (define_insn "bandreg_m2a"
13603 [(set (match_operand:SI 0 "register_operand" "=r,r")
13604 (and:SI (zero_extract:SI
13605 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13606 (const_int 1)
13607 (match_operand 2 "const_int_operand" "K03,K03"))
13608 (match_operand:SI 3 "register_operand" "r,r")))]
13609 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13610 {
13611 static const char* alt[] =
13612 {
13613 "band.b %2,%1" "\n"
13614 " movt %0",
13615
13616 "band.b %2,@(0,%t1)" "\n"
13617 " movt %0"
13618 };
13619 return alt[which_alternative];
13620 }
13621 [(set_attr "length" "6,6")])
13622
13623 ;; Take logical or of a specified bit of memory with the T bit and
13624 ;; store its result in the T bit.
13625 (define_insn "bor_m2a"
13626 [(set (reg:SI T_REG)
13627 (ior:SI (reg:SI T_REG)
13628 (zero_extract:SI
13629 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13630 (const_int 1)
13631 (match_operand 1 "const_int_operand" "K03,K03"))))]
13632 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13633 "@
13634 bor.b %1,%0
13635 bor.b %1,@(0,%t0)"
13636 [(set_attr "length" "4,4")])
13637
13638 (define_insn "borreg_m2a"
13639 [(set (match_operand:SI 0 "register_operand" "=r,r")
13640 (ior:SI (zero_extract:SI
13641 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13642 (const_int 1)
13643 (match_operand 2 "const_int_operand" "K03,K03"))
13644 (match_operand:SI 3 "register_operand" "=r,r")))]
13645 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13646 {
13647 static const char* alt[] =
13648 {
13649 "bor.b %2,%1" "\n"
13650 " movt %0",
13651
13652 "bor.b %2,@(0,%t1)" "\n"
13653 " movt %0"
13654 };
13655 return alt[which_alternative];
13656 }
13657 [(set_attr "length" "6,6")])
13658
13659 ;; Take exclusive or of a specified bit of memory with the T bit and
13660 ;; store its result in the T bit.
13661 (define_insn "bxor_m2a"
13662 [(set (reg:SI T_REG)
13663 (xor:SI (reg:SI T_REG)
13664 (zero_extract:SI
13665 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13666 (const_int 1)
13667 (match_operand 1 "const_int_operand" "K03,K03"))))]
13668 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13669 "@
13670 bxor.b %1,%0
13671 bxor.b %1,@(0,%t0)"
13672 [(set_attr "length" "4,4")])
13673
13674 (define_insn "bxorreg_m2a"
13675 [(set (match_operand:SI 0 "register_operand" "=r,r")
13676 (xor:SI (zero_extract:SI
13677 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13678 (const_int 1)
13679 (match_operand 2 "const_int_operand" "K03,K03"))
13680 (match_operand:SI 3 "register_operand" "=r,r")))]
13681 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13682 {
13683 static const char* alt[] =
13684 {
13685 "bxor.b %2,%1" "\n"
13686 " movt %0",
13687
13688 "bxor.b %2,@(0,%t1)" "\n"
13689 " movt %0"
13690 };
13691 return alt[which_alternative];
13692 }
13693 [(set_attr "length" "6,6")])
13694 \f
13695 ;; -------------------------------------------------------------------------
13696 ;; Peepholes
13697 ;; -------------------------------------------------------------------------
13698 ;; This matches cases where the bit in a memory location is set.
13699 (define_peephole2
13700 [(set (match_operand:SI 0 "register_operand")
13701 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand")))
13702 (set (match_dup 0)
13703 (ior:SI (match_dup 0)
13704 (match_operand:SI 2 "const_int_operand")))
13705 (set (match_dup 1)
13706 (match_operand 3 "arith_reg_operand"))]
13707 "TARGET_SH2A && TARGET_BITOPS
13708 && satisfies_constraint_Pso (operands[2])
13709 && REGNO (operands[0]) == REGNO (operands[3])"
13710 [(set (match_dup 1)
13711 (ior:QI (match_dup 1) (match_dup 2)))]
13712 "")
13713
13714 ;; This matches cases where the bit in a memory location is cleared.
13715 (define_peephole2
13716 [(set (match_operand:SI 0 "register_operand")
13717 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand")))
13718 (set (match_dup 0)
13719 (and:SI (match_dup 0)
13720 (match_operand:SI 2 "const_int_operand")))
13721 (set (match_dup 1)
13722 (match_operand 3 "arith_reg_operand"))]
13723 "TARGET_SH2A && TARGET_BITOPS
13724 && satisfies_constraint_Psz (operands[2])
13725 && REGNO (operands[0]) == REGNO (operands[3])"
13726 [(set (match_dup 1)
13727 (and:QI (match_dup 1) (match_dup 2)))]
13728 "")
13729
13730 ;; This matches cases where a stack pointer increment at the start of the
13731 ;; epilogue combines with a stack slot read loading the return value.
13732 (define_peephole
13733 [(set (match_operand:SI 0 "arith_reg_operand" "")
13734 (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
13735 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
13736 "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
13737 "mov.l @%1+,%0")
13738
13739 ;; See the comment on the dt combiner pattern above.
13740 (define_peephole
13741 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
13742 (plus:SI (match_dup 0)
13743 (const_int -1)))
13744 (set (reg:SI T_REG)
13745 (eq:SI (match_dup 0) (const_int 0)))]
13746 "TARGET_SH2"
13747 "dt %0")
13748
13749 ;; The following peepholes fold load sequences for which reload was not
13750 ;; able to generate a displacement addressing move insn.
13751 ;; This can happen when reload has to transform a move insn
13752 ;; without displacement into one with displacement. Or when reload can't
13753 ;; fit a displacement into the insn's constraints. In the latter case, the
13754 ;; load destination reg remains at r0, which reload compensates by inserting
13755 ;; another mov insn.
13756
13757 ;; Fold sequence:
13758 ;; mov #54,r0
13759 ;; mov.{b,w} @(r0,r15),r0
13760 ;; mov r0,r3
13761 ;; into:
13762 ;; mov.{b,w} @(54,r15),r3
13763 ;;
13764 (define_peephole2
13765 [(set (match_operand:SI 0 "arith_reg_dest" "")
13766 (match_operand:SI 1 "const_int_operand" ""))
13767 (set (match_operand:SI 2 "arith_reg_dest" "")
13768 (sign_extend:SI
13769 (mem:QI (plus:SI (match_dup 0)
13770 (match_operand:SI 3 "arith_reg_operand" "")))))
13771 (set (match_operand:QI 4 "arith_reg_dest" "")
13772 (match_operand:QI 5 "arith_reg_operand" ""))]
13773 "TARGET_SH2A
13774 && sh_legitimate_index_p (QImode, operands[1], true, true)
13775 && REGNO (operands[2]) == REGNO (operands[5])
13776 && peep2_reg_dead_p (3, operands[5])"
13777 [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))]
13778 "")
13779
13780 (define_peephole2
13781 [(set (match_operand:SI 0 "arith_reg_dest" "")
13782 (match_operand:SI 1 "const_int_operand" ""))
13783 (set (match_operand:SI 2 "arith_reg_dest" "")
13784 (sign_extend:SI
13785 (mem:HI (plus:SI (match_dup 0)
13786 (match_operand:SI 3 "arith_reg_operand" "")))))
13787 (set (match_operand:HI 4 "arith_reg_dest" "")
13788 (match_operand:HI 5 "arith_reg_operand" ""))]
13789 "TARGET_SH2A
13790 && sh_legitimate_index_p (HImode, operands[1], true, true)
13791 && REGNO (operands[2]) == REGNO (operands[5])
13792 && peep2_reg_dead_p (3, operands[5])"
13793 [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))]
13794 "")
13795
13796 ;; Fold sequence:
13797 ;; mov #54,r0
13798 ;; mov.{b,w} @(r0,r15),r1
13799 ;; into:
13800 ;; mov.{b,w} @(54,r15),r1
13801 ;;
13802 (define_peephole2
13803 [(set (match_operand:SI 0 "arith_reg_dest" "")
13804 (match_operand:SI 1 "const_int_operand" ""))
13805 (set (match_operand:SI 2 "arith_reg_dest" "")
13806 (sign_extend:SI
13807 (mem:QI (plus:SI (match_dup 0)
13808 (match_operand:SI 3 "arith_reg_operand" "")))))]
13809 "TARGET_SH2A
13810 && sh_legitimate_index_p (QImode, operands[1], true, true)
13811 && (peep2_reg_dead_p (2, operands[0])
13812 || REGNO (operands[0]) == REGNO (operands[2]))"
13813 [(set (match_dup 2)
13814 (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))]
13815 "")
13816
13817 (define_peephole2
13818 [(set (match_operand:SI 0 "arith_reg_dest" "")
13819 (match_operand:SI 1 "const_int_operand" ""))
13820 (set (match_operand:SI 2 "arith_reg_dest" "")
13821 (sign_extend:SI
13822 (mem:HI (plus:SI (match_dup 0)
13823 (match_operand:SI 3 "arith_reg_operand" "")))))]
13824 "TARGET_SH2A
13825 && sh_legitimate_index_p (HImode, operands[1], true, true)
13826 && (peep2_reg_dead_p (2, operands[0])
13827 || REGNO (operands[0]) == REGNO (operands[2]))"
13828 [(set (match_dup 2)
13829 (sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))]
13830 "")
13831
13832 ;; Fold sequence:
13833 ;; mov.{b,w} @(r0,r15),r0
13834 ;; mov r0,r3
13835 ;; into:
13836 ;; mov.{b,w} @(r0,r15),r3
13837 ;;
13838 ;; This can happen when initially a displacement address is picked, where
13839 ;; the destination reg is fixed to r0, and then the address is transformed
13840 ;; into 'r0 + reg'.
13841 (define_peephole2
13842 [(set (match_operand:SI 0 "arith_reg_dest" "")
13843 (sign_extend:SI
13844 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13845 (match_operand:SI 2 "arith_reg_operand" "")))))
13846 (set (match_operand:QI 3 "arith_reg_dest" "")
13847 (match_operand:QI 4 "arith_reg_operand" ""))]
13848 "TARGET_SH1
13849 && REGNO (operands[0]) == REGNO (operands[4])
13850 && peep2_reg_dead_p (2, operands[0])"
13851 [(set (match_dup 3)
13852 (mem:QI (plus:SI (match_dup 1) (match_dup 2))))]
13853 "")
13854
13855 (define_peephole2
13856 [(set (match_operand:SI 0 "arith_reg_dest" "")
13857 (sign_extend:SI
13858 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13859 (match_operand:SI 2 "arith_reg_operand" "")))))
13860 (set (match_operand:HI 3 "arith_reg_dest" "")
13861 (match_operand:HI 4 "arith_reg_operand" ""))]
13862 "TARGET_SH1
13863 && REGNO (operands[0]) == REGNO (operands[4])
13864 && peep2_reg_dead_p (2, operands[0])"
13865 [(set (match_dup 3)
13866 (mem:HI (plus:SI (match_dup 1) (match_dup 2))))]
13867 "")
13868
13869 (define_peephole
13870 [(set (match_operand:SI 0 "register_operand" "=r")
13871 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13872 (set (mem:SF (match_dup 0))
13873 (match_operand:SF 2 "general_movsrc_operand" ""))]
13874 "TARGET_SH1 && REGNO (operands[0]) == 0
13875 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
13876 || (GET_CODE (operands[2]) == SUBREG
13877 && REGNO (SUBREG_REG (operands[2])) < 16))
13878 && reg_unused_after (operands[0], insn)"
13879 "mov.l %2,@(%0,%1)")
13880
13881 (define_peephole
13882 [(set (match_operand:SI 0 "register_operand" "=r")
13883 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13884 (set (match_operand:SF 2 "general_movdst_operand" "")
13885
13886 (mem:SF (match_dup 0)))]
13887 "TARGET_SH1 && REGNO (operands[0]) == 0
13888 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
13889 || (GET_CODE (operands[2]) == SUBREG
13890 && REGNO (SUBREG_REG (operands[2])) < 16))
13891 && reg_unused_after (operands[0], insn)"
13892 "mov.l @(%0,%1),%2")
13893
13894 (define_peephole
13895 [(set (match_operand:SI 0 "register_operand" "=r")
13896 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13897 (set (mem:SF (match_dup 0))
13898 (match_operand:SF 2 "general_movsrc_operand" ""))]
13899 "TARGET_SH2E && REGNO (operands[0]) == 0
13900 && ((REG_P (operands[2])
13901 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
13902 || (GET_CODE (operands[2]) == SUBREG
13903 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
13904 && reg_unused_after (operands[0], insn)"
13905 "fmov{.s|} %2,@(%0,%1)")
13906
13907 (define_peephole
13908 [(set (match_operand:SI 0 "register_operand" "=r")
13909 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13910 (set (match_operand:SF 2 "general_movdst_operand" "")
13911
13912 (mem:SF (match_dup 0)))]
13913 "TARGET_SH2E && REGNO (operands[0]) == 0
13914 && ((REG_P (operands[2])
13915 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
13916 || (GET_CODE (operands[2]) == SUBREG
13917 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
13918 && reg_unused_after (operands[0], insn)"
13919 "fmov{.s|} @(%0,%1),%2")
13920
13921 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).
13922 (define_insn "sp_switch_1"
13923 [(set (reg:SI SP_REG) (unspec_volatile [(match_operand:SI 0 "" "")]
13924 UNSPECV_SP_SWITCH_B))]
13925 "TARGET_SH1"
13926 {
13927 return "mov.l r0,@-r15" "\n"
13928 " mov.l %0,r0" "\n"
13929 " mov.l @r0,r0" "\n"
13930 " mov.l r15,@-r0" "\n"
13931 " mov r0,r15";
13932 }
13933 [(set_attr "length" "10")])
13934
13935 ;; Switch back to the original stack for interrupt functions with the
13936 ;; sp_switch attribute.
13937 (define_insn "sp_switch_2"
13938 [(unspec_volatile [(const_int 0)]
13939 UNSPECV_SP_SWITCH_E)]
13940 "TARGET_SH1"
13941 {
13942 return "mov.l @r15,r15" "\n"
13943 " mov.l @r15+,r0";
13944 }
13945 [(set_attr "length" "4")])
13946
13947 ;; -------------------------------------------------------------------------
13948 ;; Integer vector moves
13949 ;; -------------------------------------------------------------------------
13950
13951 (define_expand "movv8qi"
13952 [(set (match_operand:V8QI 0 "general_movdst_operand" "")
13953 (match_operand:V8QI 1 "general_movsrc_operand" ""))]
13954 "TARGET_SHMEDIA"
13955 {
13956 prepare_move_operands (operands, V8QImode);
13957 })
13958
13959 (define_insn "movv8qi_i"
13960 [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
13961 (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13962 "TARGET_SHMEDIA
13963 && (register_operand (operands[0], V8QImode)
13964 || sh_register_operand (operands[1], V8QImode))"
13965 "@
13966 add %1, r63, %0
13967 movi %1, %0
13968 #
13969 ld%M1.q %m1, %0
13970 st%M0.q %m0, %N1"
13971 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
13972 (set_attr "length" "4,4,16,4,4")])
13973
13974 (define_split
13975 [(set (match_operand:V8QI 0 "arith_reg_dest" "")
13976 (subreg:V8QI (const_int 0) 0))]
13977 "TARGET_SHMEDIA"
13978 [(set (match_dup 0)
13979 (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
13980 (const_int 0) (const_int 0) (const_int 0)
13981 (const_int 0) (const_int 0)]))])
13982
13983 (define_split
13984 [(set (match_operand 0 "arith_reg_dest" "")
13985 (match_operand 1 "sh_rep_vec" ""))]
13986 "TARGET_SHMEDIA && reload_completed
13987 && GET_MODE (operands[0]) == GET_MODE (operands[1])
13988 && sh_vector_mode_supported_p (GET_MODE (operands[0]))
13989 && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
13990 && (XVECEXP (operands[1], 0, 0) != const0_rtx
13991 || XVECEXP (operands[1], 0, 1) != const0_rtx)
13992 && (XVECEXP (operands[1], 0, 0) != constm1_rtx
13993 || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
13994 [(set (match_dup 0) (match_dup 1))
13995 (match_dup 2)]
13996 {
13997 int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
13998 rtx elt1 = XVECEXP (operands[1], 0, 1);
13999
14000 if (unit_size > 2)
14001 operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
14002 else
14003 {
14004 if (unit_size < 2)
14005 operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
14006 operands[2] = gen_mperm_w0 (operands[0], operands[0]);
14007 }
14008 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
14009 operands[1] = XVECEXP (operands[1], 0, 0);
14010 if (unit_size < 2)
14011 {
14012 if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
14013 operands[1]
14014 = GEN_INT (TARGET_LITTLE_ENDIAN
14015 ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
14016 : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
14017 else
14018 {
14019 operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
14020 operands[1]
14021 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
14022 }
14023 }
14024 })
14025
14026 (define_split
14027 [(set (match_operand 0 "arith_reg_dest" "")
14028 (match_operand 1 "sh_const_vec" ""))]
14029 "TARGET_SHMEDIA && reload_completed
14030 && GET_MODE (operands[0]) == GET_MODE (operands[1])
14031 && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
14032 [(set (match_dup 0) (match_dup 1))]
14033 {
14034 rtx v = operands[1];
14035 enum machine_mode new_mode
14036 = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
14037
14038 operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
14039 operands[1]
14040 = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
14041 })
14042
14043 (define_expand "movv2hi"
14044 [(set (match_operand:V2HI 0 "general_movdst_operand" "")
14045 (match_operand:V2HI 1 "general_movsrc_operand" ""))]
14046 "TARGET_SHMEDIA"
14047 {
14048 prepare_move_operands (operands, V2HImode);
14049 })
14050
14051 (define_insn "movv2hi_i"
14052 [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
14053 (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
14054 "TARGET_SHMEDIA
14055 && (register_operand (operands[0], V2HImode)
14056 || sh_register_operand (operands[1], V2HImode))"
14057 "@
14058 add.l %1, r63, %0
14059 movi %1, %0
14060 #
14061 ld%M1.l %m1, %0
14062 st%M0.l %m0, %N1"
14063 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
14064 (set_attr "length" "4,4,16,4,4")
14065 (set (attr "highpart")
14066 (cond [(match_test "sh_contains_memref_p (insn)")
14067 (const_string "user")]
14068 (const_string "ignore")))])
14069
14070 (define_expand "movv4hi"
14071 [(set (match_operand:V4HI 0 "general_movdst_operand" "")
14072 (match_operand:V4HI 1 "general_movsrc_operand" ""))]
14073 "TARGET_SHMEDIA"
14074 {
14075 prepare_move_operands (operands, V4HImode);
14076 })
14077
14078 (define_insn "movv4hi_i"
14079 [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
14080 (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
14081 "TARGET_SHMEDIA
14082 && (register_operand (operands[0], V4HImode)
14083 || sh_register_operand (operands[1], V4HImode))"
14084 "@
14085 add %1, r63, %0
14086 movi %1, %0
14087 #
14088 ld%M1.q %m1, %0
14089 st%M0.q %m0, %N1"
14090 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
14091 (set_attr "length" "4,4,16,4,4")
14092 (set_attr "highpart" "depend")])
14093
14094 (define_expand "movv2si"
14095 [(set (match_operand:V2SI 0 "general_movdst_operand" "")
14096 (match_operand:V2SI 1 "general_movsrc_operand" ""))]
14097 "TARGET_SHMEDIA"
14098 {
14099 prepare_move_operands (operands, V2SImode);
14100 })
14101
14102 (define_insn "movv2si_i"
14103 [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
14104 (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
14105 "TARGET_SHMEDIA
14106 && (register_operand (operands[0], V2SImode)
14107 || sh_register_operand (operands[1], V2SImode))"
14108 "@
14109 add %1, r63, %0
14110 #
14111 #
14112 ld%M1.q %m1, %0
14113 st%M0.q %m0, %N1"
14114 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
14115 (set_attr "length" "4,4,16,4,4")
14116 (set_attr "highpart" "depend")])
14117
14118 ;; -------------------------------------------------------------------------
14119 ;; Multimedia Intrinsics
14120 ;; -------------------------------------------------------------------------
14121
14122 (define_insn "absv2si2"
14123 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14124 (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
14125 "TARGET_SHMEDIA"
14126 "mabs.l %1, %0"
14127 [(set_attr "type" "mcmp_media")
14128 (set_attr "highpart" "depend")])
14129
14130 (define_insn "absv4hi2"
14131 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14132 (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
14133 "TARGET_SHMEDIA"
14134 "mabs.w %1, %0"
14135 [(set_attr "type" "mcmp_media")
14136 (set_attr "highpart" "depend")])
14137
14138 (define_insn "addv2si3"
14139 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14140 (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
14141 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14142 "TARGET_SHMEDIA"
14143 "madd.l %1, %2, %0"
14144 [(set_attr "type" "arith_media")
14145 (set_attr "highpart" "depend")])
14146
14147 (define_insn "addv4hi3"
14148 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14149 (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
14150 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14151 "TARGET_SHMEDIA"
14152 "madd.w %1, %2, %0"
14153 [(set_attr "type" "arith_media")
14154 (set_attr "highpart" "depend")])
14155
14156 (define_insn_and_split "addv2hi3"
14157 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
14158 (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
14159 (match_operand:V2HI 2 "extend_reg_operand" "r")))]
14160 "TARGET_SHMEDIA"
14161 "#"
14162 "TARGET_SHMEDIA"
14163 [(const_int 0)]
14164 {
14165 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
14166 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
14167 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
14168 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
14169 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
14170
14171 emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
14172 emit_insn (gen_truncdisi2 (si_dst, di_dst));
14173 DONE;
14174 }
14175 [(set_attr "highpart" "must_split")])
14176
14177 (define_insn "ssaddv2si3"
14178 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14179 (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
14180 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14181 "TARGET_SHMEDIA"
14182 "madds.l %1, %2, %0"
14183 [(set_attr "type" "mcmp_media")
14184 (set_attr "highpart" "depend")])
14185
14186 (define_insn "usaddv8qi3"
14187 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14188 (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
14189 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
14190 "TARGET_SHMEDIA"
14191 "madds.ub %1, %2, %0"
14192 [(set_attr "type" "mcmp_media")
14193 (set_attr "highpart" "depend")])
14194
14195 (define_insn "ssaddv4hi3"
14196 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14197 (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
14198 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14199 "TARGET_SHMEDIA"
14200 "madds.w %1, %2, %0"
14201 [(set_attr "type" "mcmp_media")
14202 (set_attr "highpart" "depend")])
14203
14204 (define_insn "negcmpeqv8qi"
14205 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14206 (neg:V8QI (eq:V8QI
14207 (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
14208 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
14209 "TARGET_SHMEDIA"
14210 "mcmpeq.b %N1, %N2, %0"
14211 [(set_attr "type" "mcmp_media")
14212 (set_attr "highpart" "depend")])
14213
14214 (define_insn "negcmpeqv2si"
14215 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14216 (neg:V2SI (eq:V2SI
14217 (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
14218 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
14219 "TARGET_SHMEDIA"
14220 "mcmpeq.l %N1, %N2, %0"
14221 [(set_attr "type" "mcmp_media")
14222 (set_attr "highpart" "depend")])
14223
14224 (define_insn "negcmpeqv4hi"
14225 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14226 (neg:V4HI (eq:V4HI
14227 (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
14228 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14229 "TARGET_SHMEDIA"
14230 "mcmpeq.w %N1, %N2, %0"
14231 [(set_attr "type" "mcmp_media")
14232 (set_attr "highpart" "depend")])
14233
14234 (define_insn "negcmpgtuv8qi"
14235 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14236 (neg:V8QI (gtu:V8QI
14237 (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
14238 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
14239 "TARGET_SHMEDIA"
14240 "mcmpgt.ub %N1, %N2, %0"
14241 [(set_attr "type" "mcmp_media")
14242 (set_attr "highpart" "depend")])
14243
14244 (define_insn "negcmpgtv2si"
14245 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14246 (neg:V2SI (gt:V2SI
14247 (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
14248 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
14249 "TARGET_SHMEDIA"
14250 "mcmpgt.l %N1, %N2, %0"
14251 [(set_attr "type" "mcmp_media")
14252 (set_attr "highpart" "depend")])
14253
14254 (define_insn "negcmpgtv4hi"
14255 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14256 (neg:V4HI (gt:V4HI
14257 (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
14258 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14259 "TARGET_SHMEDIA"
14260 "mcmpgt.w %N1, %N2, %0"
14261 [(set_attr "type" "mcmp_media")
14262 (set_attr "highpart" "depend")])
14263
14264 (define_insn "mcmv"
14265 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14266 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14267 (match_operand:DI 2 "arith_reg_operand" "r"))
14268 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
14269 (not:DI (match_dup 2)))))]
14270 "TARGET_SHMEDIA"
14271 "mcmv %N1, %2, %0"
14272 [(set_attr "type" "arith_media")
14273 (set_attr "highpart" "depend")])
14274
14275 (define_insn "mcnvs_lw"
14276 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14277 (vec_concat:V4HI
14278 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
14279 (ss_truncate:V2HI
14280 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
14281 "TARGET_SHMEDIA"
14282 "mcnvs.lw %N1, %N2, %0"
14283 [(set_attr "type" "mcmp_media")])
14284
14285 (define_insn "mcnvs_wb"
14286 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14287 (vec_concat:V8QI
14288 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
14289 (ss_truncate:V4QI
14290 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14291 "TARGET_SHMEDIA"
14292 "mcnvs.wb %N1, %N2, %0"
14293 [(set_attr "type" "mcmp_media")])
14294
14295 (define_insn "mcnvs_wub"
14296 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14297 (vec_concat:V8QI
14298 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
14299 (us_truncate:V4QI
14300 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14301 "TARGET_SHMEDIA"
14302 "mcnvs.wub %N1, %N2, %0"
14303 [(set_attr "type" "mcmp_media")])
14304
14305 (define_insn "mextr_rl"
14306 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14307 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14308 (match_operand:HI 3 "mextr_bit_offset" "i"))
14309 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14310 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
14311 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
14312 {
14313 static char templ[21];
14314 sprintf (templ, "mextr%d %%N1, %%N2, %%0",
14315 (int) INTVAL (operands[3]) >> 3);
14316 return templ;
14317 }
14318 [(set_attr "type" "arith_media")])
14319
14320 (define_insn "*mextr_lr"
14321 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14322 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14323 (match_operand:HI 3 "mextr_bit_offset" "i"))
14324 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14325 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
14326 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
14327 {
14328 static char templ[21];
14329 sprintf (templ, "mextr%d %%N2, %%N1, %%0",
14330 (int) INTVAL (operands[4]) >> 3);
14331 return templ;
14332 }
14333 [(set_attr "type" "arith_media")])
14334
14335 ; mextrN can be modelled with vec_select / vec_concat, but the selection
14336 ; vector then varies depending on endianness.
14337 (define_expand "mextr1"
14338 [(match_operand:DI 0 "arith_reg_dest" "")
14339 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14340 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14341 "TARGET_SHMEDIA"
14342 {
14343 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14344 GEN_INT (1 * 8), GEN_INT (7 * 8)));
14345 DONE;
14346 })
14347
14348 (define_expand "mextr2"
14349 [(match_operand:DI 0 "arith_reg_dest" "")
14350 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14351 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14352 "TARGET_SHMEDIA"
14353 {
14354 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14355 GEN_INT (2 * 8), GEN_INT (6 * 8)));
14356 DONE;
14357 })
14358
14359 (define_expand "mextr3"
14360 [(match_operand:DI 0 "arith_reg_dest" "")
14361 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14362 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14363 "TARGET_SHMEDIA"
14364 {
14365 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14366 GEN_INT (3 * 8), GEN_INT (5 * 8)));
14367 DONE;
14368 })
14369
14370 (define_expand "mextr4"
14371 [(match_operand:DI 0 "arith_reg_dest" "")
14372 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14373 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14374 "TARGET_SHMEDIA"
14375 {
14376 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14377 GEN_INT (4 * 8), GEN_INT (4 * 8)));
14378 DONE;
14379 })
14380
14381 (define_expand "mextr5"
14382 [(match_operand:DI 0 "arith_reg_dest" "")
14383 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14384 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14385 "TARGET_SHMEDIA"
14386 {
14387 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14388 GEN_INT (5 * 8), GEN_INT (3 * 8)));
14389 DONE;
14390 })
14391
14392 (define_expand "mextr6"
14393 [(match_operand:DI 0 "arith_reg_dest" "")
14394 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14395 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14396 "TARGET_SHMEDIA"
14397 {
14398 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14399 GEN_INT (6 * 8), GEN_INT (2 * 8)));
14400 DONE;
14401 })
14402
14403 (define_expand "mextr7"
14404 [(match_operand:DI 0 "arith_reg_dest" "")
14405 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14406 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14407 "TARGET_SHMEDIA"
14408 {
14409 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14410 GEN_INT (7 * 8), GEN_INT (1 * 8)));
14411 DONE;
14412 })
14413
14414 (define_expand "mmacfx_wl"
14415 [(match_operand:V2SI 0 "arith_reg_dest" "")
14416 (match_operand:V2HI 1 "extend_reg_operand" "")
14417 (match_operand:V2HI 2 "extend_reg_operand" "")
14418 (match_operand:V2SI 3 "arith_reg_operand" "")]
14419 "TARGET_SHMEDIA"
14420 {
14421 emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
14422 operands[1], operands[2]));
14423 DONE;
14424 })
14425
14426 ;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
14427 ;; is depend
14428 (define_insn "mmacfx_wl_i"
14429 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14430 (ss_plus:V2SI
14431 (match_operand:V2SI 1 "arith_reg_operand" "0")
14432 (ss_truncate:V2SI
14433 (ashift:V2DI
14434 (sign_extend:V2DI
14435 (mult:V2SI
14436 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
14437 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
14438 (const_int 1)))))]
14439 "TARGET_SHMEDIA"
14440 "mmacfx.wl %2, %3, %0"
14441 [(set_attr "type" "mac_media")
14442 (set_attr "highpart" "depend")])
14443
14444 (define_expand "mmacnfx_wl"
14445 [(match_operand:V2SI 0 "arith_reg_dest" "")
14446 (match_operand:V2HI 1 "extend_reg_operand" "")
14447 (match_operand:V2HI 2 "extend_reg_operand" "")
14448 (match_operand:V2SI 3 "arith_reg_operand" "")]
14449 "TARGET_SHMEDIA"
14450 {
14451 emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
14452 operands[1], operands[2]));
14453 DONE;
14454 })
14455
14456 (define_insn "mmacnfx_wl_i"
14457 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14458 (ss_minus:V2SI
14459 (match_operand:V2SI 1 "arith_reg_operand" "0")
14460 (ss_truncate:V2SI
14461 (ashift:V2DI
14462 (sign_extend:V2DI
14463 (mult:V2SI
14464 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
14465 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
14466 (const_int 1)))))]
14467 "TARGET_SHMEDIA"
14468 "mmacnfx.wl %2, %3, %0"
14469 [(set_attr "type" "mac_media")
14470 (set_attr "highpart" "depend")])
14471
14472 (define_insn "mulv2si3"
14473 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14474 (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14475 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14476 "TARGET_SHMEDIA"
14477 "mmul.l %1, %2, %0"
14478 [(set_attr "type" "d2mpy_media")
14479 (set_attr "highpart" "depend")])
14480
14481 (define_insn "mulv4hi3"
14482 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14483 (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14484 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14485 "TARGET_SHMEDIA"
14486 "mmul.w %1, %2, %0"
14487 [(set_attr "type" "dmpy_media")
14488 (set_attr "highpart" "depend")])
14489
14490 (define_insn "mmulfx_l"
14491 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14492 (ss_truncate:V2SI
14493 (ashiftrt:V2DI
14494 (mult:V2DI
14495 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14496 (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
14497 (const_int 31))))]
14498 "TARGET_SHMEDIA"
14499 "mmulfx.l %1, %2, %0"
14500 [(set_attr "type" "d2mpy_media")
14501 (set_attr "highpart" "depend")])
14502
14503 (define_insn "mmulfx_w"
14504 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14505 (ss_truncate:V4HI
14506 (ashiftrt:V4SI
14507 (mult:V4SI
14508 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14509 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14510 (const_int 15))))]
14511 "TARGET_SHMEDIA"
14512 "mmulfx.w %1, %2, %0"
14513 [(set_attr "type" "dmpy_media")
14514 (set_attr "highpart" "depend")])
14515
14516 (define_insn "mmulfxrp_w"
14517 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14518 (ss_truncate:V4HI
14519 (ashiftrt:V4SI
14520 (plus:V4SI
14521 (mult:V4SI
14522 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14523 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14524 (const_int 16384))
14525 (const_int 15))))]
14526 "TARGET_SHMEDIA"
14527 "mmulfxrp.w %1, %2, %0"
14528 [(set_attr "type" "dmpy_media")
14529 (set_attr "highpart" "depend")])
14530
14531
14532 (define_expand "mmulhi_wl"
14533 [(match_operand:V2SI 0 "arith_reg_dest" "")
14534 (match_operand:V4HI 1 "arith_reg_operand" "")
14535 (match_operand:V4HI 2 "arith_reg_operand" "")]
14536 "TARGET_SHMEDIA"
14537 {
14538 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
14539 (operands[0], operands[1], operands[2]));
14540 DONE;
14541 })
14542
14543 (define_expand "mmullo_wl"
14544 [(match_operand:V2SI 0 "arith_reg_dest" "")
14545 (match_operand:V4HI 1 "arith_reg_operand" "")
14546 (match_operand:V4HI 2 "arith_reg_operand" "")]
14547 "TARGET_SHMEDIA"
14548 {
14549 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
14550 (operands[0], operands[1], operands[2]));
14551 DONE;
14552 })
14553
14554 (define_insn "mmul23_wl"
14555 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14556 (vec_select:V2SI
14557 (mult:V4SI
14558 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14559 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14560 (parallel [(const_int 2) (const_int 3)])))]
14561 "TARGET_SHMEDIA"
14562 {
14563 return (TARGET_LITTLE_ENDIAN
14564 ? "mmulhi.wl %1, %2, %0"
14565 : "mmullo.wl %1, %2, %0");
14566 }
14567 [(set_attr "type" "dmpy_media")
14568 (set (attr "highpart")
14569 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14570 (const_string "user")))])
14571
14572 (define_insn "mmul01_wl"
14573 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14574 (vec_select:V2SI
14575 (mult:V4SI
14576 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14577 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14578 (parallel [(const_int 0) (const_int 1)])))]
14579 "TARGET_SHMEDIA"
14580 {
14581 return (TARGET_LITTLE_ENDIAN
14582 ? "mmullo.wl %1, %2, %0"
14583 : "mmulhi.wl %1, %2, %0");
14584 }
14585 [(set_attr "type" "dmpy_media")
14586 (set (attr "highpart")
14587 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14588 (const_string "user")))])
14589
14590
14591 (define_expand "mmulsum_wq"
14592 [(match_operand:DI 0 "arith_reg_dest" "")
14593 (match_operand:V4HI 1 "arith_reg_operand" "")
14594 (match_operand:V4HI 2 "arith_reg_operand" "")
14595 (match_operand:DI 3 "arith_reg_operand" "")]
14596 "TARGET_SHMEDIA"
14597 {
14598 emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
14599 operands[1], operands[2]));
14600 DONE;
14601 })
14602
14603 (define_insn "mmulsum_wq_i"
14604 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14605 (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
14606 (plus:DI
14607 (plus:DI
14608 (vec_select:DI
14609 (mult:V4DI
14610 (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
14611 (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
14612 (parallel [(const_int 0)]))
14613 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14614 (sign_extend:V4DI (match_dup 3)))
14615 (parallel [(const_int 1)])))
14616 (plus:DI
14617 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14618 (sign_extend:V4DI (match_dup 3)))
14619 (parallel [(const_int 2)]))
14620 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14621 (sign_extend:V4DI (match_dup 3)))
14622 (parallel [(const_int 3)]))))))]
14623 "TARGET_SHMEDIA"
14624 "mmulsum.wq %2, %3, %0"
14625 [(set_attr "type" "mac_media")])
14626
14627 (define_expand "mperm_w"
14628 [(match_operand:V4HI 0 "arith_reg_dest" "=r")
14629 (match_operand:V4HI 1 "arith_reg_operand" "r")
14630 (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
14631 "TARGET_SHMEDIA"
14632 {
14633 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
14634 (operands[0], operands[1], operands[2]));
14635 DONE;
14636 })
14637
14638 ; This use of vec_select isn't exactly correct according to rtl.texi
14639 ; (because not constant), but it seems a straightforward extension.
14640 (define_insn "mperm_w_little"
14641 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14642 (vec_select:V4HI
14643 (match_operand:V4HI 1 "arith_reg_operand" "r")
14644 (parallel
14645 [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
14646 (const_int 2) (const_int 0))
14647 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
14648 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
14649 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
14650 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
14651 "mperm.w %1, %N2, %0"
14652 [(set_attr "type" "arith_media")])
14653
14654 (define_insn "mperm_w_big"
14655 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14656 (vec_select:V4HI
14657 (match_operand:V4HI 1 "arith_reg_operand" "r")
14658 (parallel
14659 [(zero_extract:QI (not:QI (match_operand:QI 2
14660 "extend_reg_or_0_operand" "rZ"))
14661 (const_int 2) (const_int 0))
14662 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
14663 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
14664 (zero_extract:QI (not:QI (match_dup 2))
14665 (const_int 2) (const_int 6))])))]
14666 "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
14667 "mperm.w %1, %N2, %0"
14668 [(set_attr "type" "arith_media")])
14669
14670 (define_insn "mperm_w0"
14671 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14672 (vec_duplicate:V4HI (truncate:HI (match_operand 1
14673 "trunc_hi_operand" "r"))))]
14674 "TARGET_SHMEDIA"
14675 "mperm.w %1, r63, %0"
14676 [(set_attr "type" "arith_media")
14677 (set_attr "highpart" "ignore")])
14678
14679 (define_expand "msad_ubq"
14680 [(match_operand:DI 0 "arith_reg_dest" "")
14681 (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
14682 (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
14683 (match_operand:DI 3 "arith_reg_operand" "")]
14684 "TARGET_SHMEDIA"
14685 {
14686 emit_insn (gen_msad_ubq_i (operands[0], operands[3],
14687 operands[1], operands[2]));
14688 DONE;
14689 })
14690
14691 (define_insn "msad_ubq_i"
14692 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14693 (plus:DI
14694 (plus:DI
14695 (plus:DI
14696 (plus:DI
14697 (match_operand:DI 1 "arith_reg_operand" "0")
14698 (abs:DI (vec_select:DI
14699 (minus:V8DI
14700 (zero_extend:V8DI
14701 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14702 (zero_extend:V8DI
14703 (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
14704 (parallel [(const_int 0)]))))
14705 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14706 (zero_extend:V8DI (match_dup 3)))
14707 (parallel [(const_int 1)]))))
14708 (plus:DI
14709 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14710 (zero_extend:V8DI (match_dup 3)))
14711 (parallel [(const_int 2)])))
14712 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14713 (zero_extend:V8DI (match_dup 3)))
14714 (parallel [(const_int 3)])))))
14715 (plus:DI
14716 (plus:DI
14717 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14718 (zero_extend:V8DI (match_dup 3)))
14719 (parallel [(const_int 4)])))
14720 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14721 (zero_extend:V8DI (match_dup 3)))
14722 (parallel [(const_int 5)]))))
14723 (plus:DI
14724 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14725 (zero_extend:V8DI (match_dup 3)))
14726 (parallel [(const_int 6)])))
14727 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14728 (zero_extend:V8DI (match_dup 3)))
14729 (parallel [(const_int 7)])))))))]
14730 "TARGET_SHMEDIA"
14731 "msad.ubq %N2, %N3, %0"
14732 [(set_attr "type" "mac_media")])
14733
14734 (define_insn "mshalds_l"
14735 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14736 (ss_truncate:V2SI
14737 (ashift:V2DI
14738 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14739 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14740 (const_int 31)))))]
14741 "TARGET_SHMEDIA"
14742 "mshalds.l %1, %2, %0"
14743 [(set_attr "type" "mcmp_media")
14744 (set_attr "highpart" "depend")])
14745
14746 (define_insn "mshalds_w"
14747 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14748 (ss_truncate:V4HI
14749 (ashift:V4SI
14750 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14751 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14752 (const_int 15)))))]
14753 "TARGET_SHMEDIA"
14754 "mshalds.w %1, %2, %0"
14755 [(set_attr "type" "mcmp_media")
14756 (set_attr "highpart" "depend")])
14757
14758 (define_insn "ashrv2si3"
14759 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14760 (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14761 (match_operand:DI 2 "arith_reg_operand" "r")))]
14762 "TARGET_SHMEDIA"
14763 "mshard.l %1, %2, %0"
14764 [(set_attr "type" "arith_media")
14765 (set_attr "highpart" "depend")])
14766
14767 (define_insn "ashrv4hi3"
14768 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14769 (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14770 (match_operand:DI 2 "arith_reg_operand" "r")))]
14771 "TARGET_SHMEDIA"
14772 "mshard.w %1, %2, %0"
14773 [(set_attr "type" "arith_media")
14774 (set_attr "highpart" "depend")])
14775
14776 (define_insn "mshards_q"
14777 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
14778 (ss_truncate:HI
14779 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
14780 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
14781 "TARGET_SHMEDIA"
14782 "mshards.q %1, %N2, %0"
14783 [(set_attr "type" "mcmp_media")])
14784
14785 (define_expand "mshfhi_b"
14786 [(match_operand:V8QI 0 "arith_reg_dest" "")
14787 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14788 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
14789 "TARGET_SHMEDIA"
14790 {
14791 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
14792 (operands[0], operands[1], operands[2]));
14793 DONE;
14794 })
14795
14796 (define_expand "mshflo_b"
14797 [(match_operand:V8QI 0 "arith_reg_dest" "")
14798 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14799 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
14800 "TARGET_SHMEDIA"
14801 {
14802 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
14803 (operands[0], operands[1], operands[2]));
14804 DONE;
14805 })
14806
14807 (define_insn "mshf4_b"
14808 [(set
14809 (match_operand:V8QI 0 "arith_reg_dest" "=r")
14810 (vec_select:V8QI
14811 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14812 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14813 (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
14814 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
14815 "TARGET_SHMEDIA"
14816 {
14817 return (TARGET_LITTLE_ENDIAN
14818 ? "mshfhi.b %N1, %N2, %0"
14819 : "mshflo.b %N1, %N2, %0");
14820 }
14821 [(set_attr "type" "arith_media")
14822 (set (attr "highpart")
14823 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14824 (const_string "user")))])
14825
14826 (define_insn "mshf0_b"
14827 [(set
14828 (match_operand:V8QI 0 "arith_reg_dest" "=r")
14829 (vec_select:V8QI
14830 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14831 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14832 (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
14833 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
14834 "TARGET_SHMEDIA"
14835 {
14836 return (TARGET_LITTLE_ENDIAN
14837 ? "mshflo.b %N1, %N2, %0"
14838 : "mshfhi.b %N1, %N2, %0");
14839 }
14840 [(set_attr "type" "arith_media")
14841 (set (attr "highpart")
14842 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14843 (const_string "user")))])
14844
14845 (define_expand "mshfhi_l"
14846 [(match_operand:V2SI 0 "arith_reg_dest" "")
14847 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14848 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
14849 "TARGET_SHMEDIA"
14850 {
14851 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
14852 (operands[0], operands[1], operands[2]));
14853 DONE;
14854 })
14855
14856 (define_expand "mshflo_l"
14857 [(match_operand:V2SI 0 "arith_reg_dest" "")
14858 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14859 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
14860 "TARGET_SHMEDIA"
14861 {
14862 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
14863 (operands[0], operands[1], operands[2]));
14864 DONE;
14865 })
14866
14867 (define_insn "mshf4_l"
14868 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14869 (vec_select:V2SI
14870 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14871 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
14872 (parallel [(const_int 1) (const_int 3)])))]
14873 "TARGET_SHMEDIA"
14874 {
14875 return (TARGET_LITTLE_ENDIAN
14876 ? "mshfhi.l %N1, %N2, %0"
14877 : "mshflo.l %N1, %N2, %0");
14878 }
14879 [(set_attr "type" "arith_media")
14880 (set (attr "highpart")
14881 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14882 (const_string "user")))])
14883
14884 (define_insn "mshf0_l"
14885 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14886 (vec_select:V2SI
14887 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14888 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
14889 (parallel [(const_int 0) (const_int 2)])))]
14890 "TARGET_SHMEDIA"
14891 {
14892 return (TARGET_LITTLE_ENDIAN
14893 ? "mshflo.l %N1, %N2, %0"
14894 : "mshfhi.l %N1, %N2, %0");
14895 }
14896 [(set_attr "type" "arith_media")
14897 (set (attr "highpart")
14898 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14899 (const_string "user")))])
14900
14901 (define_expand "mshfhi_w"
14902 [(match_operand:V4HI 0 "arith_reg_dest" "")
14903 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14904 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
14905 "TARGET_SHMEDIA"
14906 {
14907 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
14908 (operands[0], operands[1], operands[2]));
14909 DONE;
14910 })
14911
14912 (define_expand "mshflo_w"
14913 [(match_operand:V4HI 0 "arith_reg_dest" "")
14914 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14915 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
14916 "TARGET_SHMEDIA"
14917 {
14918 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
14919 (operands[0], operands[1], operands[2]));
14920 DONE;
14921 })
14922
14923 (define_insn "mshf4_w"
14924 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14925 (vec_select:V4HI
14926 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14927 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
14928 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
14929 "TARGET_SHMEDIA"
14930 {
14931 return (TARGET_LITTLE_ENDIAN
14932 ? "mshfhi.w %N1, %N2, %0"
14933 : "mshflo.w %N1, %N2, %0");
14934 }
14935 [(set_attr "type" "arith_media")
14936 (set (attr "highpart")
14937 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14938 (const_string "user")))])
14939
14940 (define_insn "mshf0_w"
14941 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14942 (vec_select:V4HI
14943 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14944 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
14945 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
14946 "TARGET_SHMEDIA"
14947 {
14948 return (TARGET_LITTLE_ENDIAN
14949 ? "mshflo.w %N1, %N2, %0"
14950 : "mshfhi.w %N1, %N2, %0");
14951 }
14952 [(set_attr "type" "arith_media")
14953 (set (attr "highpart")
14954 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14955 (const_string "user")))])
14956
14957 (define_insn "mshflo_w_x"
14958 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14959 (vec_select:V4HI
14960 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
14961 (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
14962 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
14963 "TARGET_SHMEDIA"
14964 "mshflo.w %N1, %N2, %0"
14965 [(set_attr "type" "arith_media")
14966 (set_attr "highpart" "ignore")])
14967
14968 ;; These are useful to expand ANDs and as combiner patterns.
14969 (define_insn_and_split "mshfhi_l_di"
14970 [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
14971 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
14972 (const_int 32))
14973 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
14974 (const_int -4294967296))))]
14975 "TARGET_SHMEDIA"
14976 "@
14977 mshfhi.l %N1, %N2, %0
14978 #"
14979 "TARGET_SHMEDIA && reload_completed
14980 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
14981 [(set (match_dup 3) (match_dup 4))
14982 (set (match_dup 5) (match_dup 6))]
14983 {
14984 operands[3] = gen_lowpart (SImode, operands[0]);
14985 operands[4] = gen_highpart (SImode, operands[1]);
14986 operands[5] = gen_highpart (SImode, operands[0]);
14987 operands[6] = gen_highpart (SImode, operands[2]);
14988 }
14989 [(set_attr "type" "arith_media")])
14990
14991 (define_insn "*mshfhi_l_di_rev"
14992 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14993 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14994 (const_int -4294967296))
14995 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14996 (const_int 32))))]
14997 "TARGET_SHMEDIA"
14998 "mshfhi.l %N2, %N1, %0"
14999 [(set_attr "type" "arith_media")])
15000
15001 (define_split
15002 [(set (match_operand:DI 0 "arith_reg_dest" "")
15003 (ior:DI (zero_extend:DI (match_operand:SI 1
15004 "extend_reg_or_0_operand" ""))
15005 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
15006 (const_int -4294967296))))
15007 (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
15008 "TARGET_SHMEDIA"
15009 [(const_int 0)]
15010 {
15011 emit_insn (gen_ashldi3_media (operands[3],
15012 simplify_gen_subreg (DImode, operands[1],
15013 SImode, 0),
15014 GEN_INT (32)));
15015 emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
15016 DONE;
15017 })
15018
15019 (define_insn "mshflo_l_di"
15020 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15021 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15022 (const_int 4294967295))
15023 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15024 (const_int 32))))]
15025
15026 "TARGET_SHMEDIA"
15027 "mshflo.l %N1, %N2, %0"
15028 [(set_attr "type" "arith_media")
15029 (set_attr "highpart" "ignore")])
15030
15031 (define_insn "*mshflo_l_di_rev"
15032 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15033 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15034 (const_int 32))
15035 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15036 (const_int 4294967295))))]
15037
15038 "TARGET_SHMEDIA"
15039 "mshflo.l %N2, %N1, %0"
15040 [(set_attr "type" "arith_media")
15041 (set_attr "highpart" "ignore")])
15042
15043 ;; Combiner pattern for trampoline initialization.
15044 (define_insn_and_split "*double_shori"
15045 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15046 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
15047 (const_int 32))
15048 (match_operand:DI 2 "const_int_operand" "n")))]
15049 "TARGET_SHMEDIA
15050 && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
15051 "#"
15052 "rtx_equal_p (operands[0], operands[1])"
15053 [(const_int 0)]
15054 {
15055 HOST_WIDE_INT v = INTVAL (operands[2]);
15056
15057 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
15058 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
15059 DONE;
15060 }
15061 [(set_attr "highpart" "ignore")])
15062
15063 (define_insn "*mshflo_l_di_x"
15064 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15065 (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
15066 "rZ"))
15067 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15068 (const_int 32))))]
15069 "TARGET_SHMEDIA"
15070 "mshflo.l %N1, %N2, %0"
15071 [(set_attr "type" "arith_media")
15072 (set_attr "highpart" "ignore")])
15073
15074 (define_insn_and_split "concat_v2sf"
15075 [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
15076 ;; (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
15077 (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
15078 (match_operand:SF 2 "register_operand" "rZ,f,f")))]
15079 "TARGET_SHMEDIA"
15080 "@
15081 mshflo.l %N1, %N2, %0
15082 #
15083 #"
15084 "TARGET_SHMEDIA && reload_completed
15085 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
15086 [(set (match_dup 3) (match_dup 1))
15087 (set (match_dup 4) (match_dup 2))]
15088 {
15089 operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
15090 operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
15091 }
15092 [(set_attr "type" "arith_media")
15093 (set_attr "highpart" "ignore")])
15094
15095 (define_insn "*mshflo_l_di_x_rev"
15096 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15097 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15098 (const_int 32))
15099 (zero_extend:DI
15100 (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
15101 "TARGET_SHMEDIA"
15102 "mshflo.l %N2, %N1, %0"
15103 [(set_attr "type" "arith_media")
15104 (set_attr "highpart" "ignore")])
15105
15106 (define_insn "ashlv2si3"
15107 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15108 (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
15109 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15110 "TARGET_SHMEDIA"
15111 "mshlld.l %1, %2, %0"
15112 [(set_attr "type" "arith_media")
15113 (set_attr "highpart" "depend")])
15114
15115 (define_split
15116 [(set (match_operand 0 "any_register_operand" "")
15117 (match_operator 3 "shift_operator"
15118 [(match_operand 1 "any_register_operand" "")
15119 (match_operand 2 "shift_count_reg_operand" "")]))]
15120 "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
15121 [(set (match_dup 0) (match_dup 3))]
15122 {
15123 rtx count = operands[2];
15124 enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
15125
15126 while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
15127 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
15128 || GET_CODE (count) == TRUNCATE)
15129 count = XEXP (count, 0);
15130 inner_mode = GET_MODE (count);
15131 count = simplify_gen_subreg (outer_mode, count, inner_mode,
15132 subreg_lowpart_offset (outer_mode, inner_mode));
15133 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
15134 operands[1], count);
15135 })
15136
15137 (define_insn "ashlv4hi3"
15138 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15139 (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
15140 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15141 "TARGET_SHMEDIA"
15142 "mshlld.w %1, %2, %0"
15143 [(set_attr "type" "arith_media")
15144 (set_attr "highpart" "depend")])
15145
15146 (define_insn "lshrv2si3"
15147 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15148 (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
15149 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15150 "TARGET_SHMEDIA"
15151 "mshlrd.l %1, %2, %0"
15152 [(set_attr "type" "arith_media")
15153 (set_attr "highpart" "depend")])
15154
15155 (define_insn "lshrv4hi3"
15156 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15157 (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
15158 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15159 "TARGET_SHMEDIA"
15160 "mshlrd.w %1, %2, %0"
15161 [(set_attr "type" "arith_media")
15162 (set_attr "highpart" "depend")])
15163
15164 (define_insn "subv2si3"
15165 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15166 (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15167 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15168 "TARGET_SHMEDIA"
15169 "msub.l %N1, %2, %0"
15170 [(set_attr "type" "arith_media")
15171 (set_attr "highpart" "depend")])
15172
15173 (define_insn "subv4hi3"
15174 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15175 (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15176 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15177 "TARGET_SHMEDIA"
15178 "msub.w %N1, %2, %0"
15179 [(set_attr "type" "arith_media")
15180 (set_attr "highpart" "depend")])
15181
15182 (define_insn_and_split "subv2hi3"
15183 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
15184 (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
15185 (match_operand:V2HI 2 "arith_reg_operand" "r")))]
15186 "TARGET_SHMEDIA"
15187 "#"
15188 "TARGET_SHMEDIA"
15189 [(const_int 0)]
15190 {
15191 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
15192 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
15193 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
15194 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
15195 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
15196
15197 emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
15198 emit_insn (gen_truncdisi2 (si_dst, di_dst));
15199 DONE;
15200 }
15201 [(set_attr "highpart" "must_split")])
15202
15203 (define_insn "sssubv2si3"
15204 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15205 (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15206 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15207 "TARGET_SHMEDIA"
15208 "msubs.l %N1, %2, %0"
15209 [(set_attr "type" "mcmp_media")
15210 (set_attr "highpart" "depend")])
15211
15212 (define_insn "ussubv8qi3"
15213 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15214 (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
15215 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
15216 "TARGET_SHMEDIA"
15217 "msubs.ub %N1, %2, %0"
15218 [(set_attr "type" "mcmp_media")
15219 (set_attr "highpart" "depend")])
15220
15221 (define_insn "sssubv4hi3"
15222 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15223 (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15224 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15225 "TARGET_SHMEDIA"
15226 "msubs.w %N1, %2, %0"
15227 [(set_attr "type" "mcmp_media")
15228 (set_attr "highpart" "depend")])
15229
15230 ;; -------------------------------------------------------------------------
15231 ;; Floating Point Intrinsics
15232 ;; -------------------------------------------------------------------------
15233
15234 (define_insn "fcosa_s"
15235 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15236 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
15237 UNSPEC_FCOSA))]
15238 "TARGET_SHMEDIA"
15239 "fcosa.s %1, %0"
15240 [(set_attr "type" "atrans_media")])
15241
15242 (define_insn "fsina_s"
15243 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15244 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
15245 UNSPEC_FSINA))]
15246 "TARGET_SHMEDIA"
15247 "fsina.s %1, %0"
15248 [(set_attr "type" "atrans_media")])
15249
15250 (define_insn "fipr"
15251 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15252 (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
15253 "fp_arith_reg_operand" "f")
15254 (match_operand:V4SF 2
15255 "fp_arith_reg_operand" "f"))
15256 (parallel [(const_int 0)]))
15257 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
15258 (parallel [(const_int 1)])))
15259 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
15260 (parallel [(const_int 2)]))
15261 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
15262 (parallel [(const_int 3)])))))]
15263 "TARGET_SHMEDIA"
15264 "fipr.s %1, %2, %0"
15265 [(set_attr "type" "fparith_media")])
15266
15267 (define_insn "fsrra_s"
15268 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15269 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
15270 UNSPEC_FSRRA))]
15271 "TARGET_SHMEDIA"
15272 "fsrra.s %1, %0"
15273 [(set_attr "type" "atrans_media")])
15274
15275 (define_insn "ftrv"
15276 [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
15277 (plus:V4SF
15278 (plus:V4SF
15279 (mult:V4SF
15280 (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
15281 (parallel [(const_int 0) (const_int 5)
15282 (const_int 10) (const_int 15)]))
15283 (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
15284 (mult:V4SF
15285 (vec_select:V4SF (match_dup 1)
15286 (parallel [(const_int 4) (const_int 9)
15287 (const_int 14) (const_int 3)]))
15288 (vec_select:V4SF (match_dup 2)
15289 (parallel [(const_int 1) (const_int 2)
15290 (const_int 3) (const_int 0)]))))
15291 (plus:V4SF
15292 (mult:V4SF
15293 (vec_select:V4SF (match_dup 1)
15294 (parallel [(const_int 8) (const_int 13)
15295 (const_int 2) (const_int 7)]))
15296 (vec_select:V4SF (match_dup 2)
15297 (parallel [(const_int 2) (const_int 3)
15298 (const_int 0) (const_int 1)])))
15299 (mult:V4SF
15300 (vec_select:V4SF (match_dup 1)
15301 (parallel [(const_int 12) (const_int 1)
15302 (const_int 6) (const_int 11)]))
15303 (vec_select:V4SF (match_dup 2)
15304 (parallel [(const_int 3) (const_int 0)
15305 (const_int 1) (const_int 2)]))))))]
15306 "TARGET_SHMEDIA"
15307 "ftrv.s %1, %2, %0"
15308 [(set_attr "type" "fparith_media")])
15309
15310 (define_insn "ldhi_l"
15311 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15312 (zero_extract:SI
15313 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
15314 (const_int 3))
15315 (const_int -3)))
15316 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
15317 (const_int 0)))]
15318 "TARGET_SHMEDIA32"
15319 "ldhi.l %U1, %0"
15320 [(set_attr "type" "load_media")])
15321
15322 (define_insn "ldhi_q"
15323 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15324 (zero_extract:DI
15325 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
15326 (const_int 7))
15327 (const_int -7)))
15328 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
15329 (const_int 0)))]
15330 "TARGET_SHMEDIA32"
15331 "ldhi.q %U1, %0"
15332 [(set_attr "type" "load_media")])
15333
15334 (define_insn_and_split "*ldhi_q_comb0"
15335 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15336 (zero_extract:DI
15337 (mem:DI (plus:SI (ior:SI (plus:SI
15338 (match_operand:SI 1 "register_operand" "r")
15339 (match_operand:SI 2 "ua_offset" "I06"))
15340 (const_int 7))
15341 (const_int -7)))
15342 (plus:SI (and:SI (match_dup 1) (const_int 7))
15343 (const_int 1))
15344 (const_int 0)))]
15345 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
15346 "#"
15347 ""
15348 [(pc)]
15349 {
15350 emit_insn (gen_ldhi_q (operands[0],
15351 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15352 DONE;
15353 })
15354
15355 (define_insn_and_split "*ldhi_q_comb1"
15356 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15357 (zero_extract:DI
15358 (mem:DI (plus:SI (ior:SI (plus:SI
15359 (match_operand:SI 1 "register_operand" "r")
15360 (match_operand:SI 2 "ua_offset" "I06"))
15361 (const_int 7))
15362 (const_int -7)))
15363 (plus:SI (and:SI (plus:SI (match_dup 1)
15364 (match_operand:SI 3 "ua_offset" "I06"))
15365 (const_int 7))
15366 (const_int 1))
15367 (const_int 0)))]
15368 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
15369 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
15370 "#"
15371 ""
15372 [(pc)]
15373 {
15374 emit_insn (gen_ldhi_q (operands[0],
15375 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15376 DONE;
15377 })
15378
15379 (define_insn "ldlo_l"
15380 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15381 (zero_extract:SI
15382 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
15383 (const_int -4)))
15384 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
15385 (and:SI (match_dup 1) (const_int 3))))]
15386 "TARGET_SHMEDIA32"
15387 "ldlo.l %U1, %0"
15388 [(set_attr "type" "load_media")])
15389
15390 (define_insn "ldlo_q"
15391 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15392 (zero_extract:DI
15393 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
15394 (const_int -8)))
15395 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
15396 (and:SI (match_dup 1) (const_int 7))))]
15397 "TARGET_SHMEDIA32"
15398 "ldlo.q %U1, %0"
15399 [(set_attr "type" "load_media")])
15400
15401 (define_insn_and_split "*ldlo_q_comb0"
15402 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15403 (zero_extract:DI
15404 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
15405 (match_operand:SI 2 "ua_offset" "I06"))
15406 (const_int -8)))
15407 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
15408 (and:SI (match_dup 1) (const_int 7))))]
15409 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
15410 "#"
15411 ""
15412 [(pc)]
15413 {
15414 emit_insn (gen_ldlo_q (operands[0],
15415 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15416 DONE;
15417 })
15418
15419 (define_insn_and_split "*ldlo_q_comb1"
15420 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15421 (zero_extract:DI
15422 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
15423 (match_operand:SI 2 "ua_offset" "I06"))
15424 (const_int -8)))
15425 (minus:SI (const_int 8)
15426 (and:SI (plus:SI (match_dup 1)
15427 (match_operand:SI 3 "ua_offset" "I06"))
15428 (const_int 7)))
15429 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
15430 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
15431 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
15432 "#"
15433 ""
15434 [(pc)]
15435 {
15436 emit_insn (gen_ldlo_q (operands[0],
15437 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15438 DONE;
15439 })
15440
15441 (define_insn "sthi_l"
15442 [(set (zero_extract:SI
15443 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
15444 (const_int 3))
15445 (const_int -3)))
15446 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
15447 (const_int 0))
15448 (match_operand:SI 1 "arith_reg_operand" "r"))]
15449 "TARGET_SHMEDIA32"
15450 "sthi.l %U0, %1"
15451 [(set_attr "type" "ustore_media")])
15452
15453 ;; All unaligned stores are considered to be 'narrow' because they typically
15454 ;; operate on less that a quadword, and when they operate on a full quadword,
15455 ;; the vanilla store high / store low sequence will cause a stall if not
15456 ;; scheduled apart.
15457 (define_insn "sthi_q"
15458 [(set (zero_extract:DI
15459 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
15460 (const_int 7))
15461 (const_int -7)))
15462 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
15463 (const_int 0))
15464 (match_operand:DI 1 "arith_reg_operand" "r"))]
15465 "TARGET_SHMEDIA32"
15466 "sthi.q %U0, %1"
15467 [(set_attr "type" "ustore_media")])
15468
15469 (define_insn_and_split "*sthi_q_comb0"
15470 [(set (zero_extract:DI
15471 (mem:DI (plus:SI (ior:SI (plus:SI
15472 (match_operand:SI 0 "register_operand" "r")
15473 (match_operand:SI 1 "ua_offset" "I06"))
15474 (const_int 7))
15475 (const_int -7)))
15476 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
15477 (const_int 0))
15478 (match_operand:DI 2 "arith_reg_operand" "r"))]
15479 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15480 "#"
15481 ""
15482 [(pc)]
15483 {
15484 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15485 operands[2]));
15486 DONE;
15487 })
15488
15489 (define_insn_and_split "*sthi_q_comb1"
15490 [(set (zero_extract:DI
15491 (mem:DI (plus:SI (ior:SI (plus:SI
15492 (match_operand:SI 0 "register_operand" "r")
15493 (match_operand:SI 1 "ua_offset" "I06"))
15494 (const_int 7))
15495 (const_int -7)))
15496 (plus:SI (and:SI (plus:SI (match_dup 0)
15497 (match_operand:SI 2 "ua_offset" "I06"))
15498 (const_int 7))
15499 (const_int 1))
15500 (const_int 0))
15501 (match_operand:DI 3 "arith_reg_operand" "r"))]
15502 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
15503 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15504 "#"
15505 ""
15506 [(pc)]
15507 {
15508 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15509 operands[3]));
15510 DONE;
15511 })
15512
15513 ;; This is highpart user because the address is used as full 64 bit.
15514 (define_insn "stlo_l"
15515 [(set (zero_extract:SI
15516 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
15517 (const_int -4)))
15518 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
15519 (and:SI (match_dup 0) (const_int 3)))
15520 (match_operand:SI 1 "arith_reg_operand" "r"))]
15521 "TARGET_SHMEDIA32"
15522 "stlo.l %U0, %1"
15523 [(set_attr "type" "ustore_media")])
15524
15525 (define_insn "stlo_q"
15526 [(set (zero_extract:DI
15527 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
15528 (const_int -8)))
15529 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
15530 (and:SI (match_dup 0) (const_int 7)))
15531 (match_operand:DI 1 "arith_reg_operand" "r"))]
15532 "TARGET_SHMEDIA32"
15533 "stlo.q %U0, %1"
15534 [(set_attr "type" "ustore_media")])
15535
15536 (define_insn_and_split "*stlo_q_comb0"
15537 [(set (zero_extract:DI
15538 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15539 (match_operand:SI 1 "ua_offset" "I06"))
15540 (const_int -8)))
15541 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
15542 (and:SI (match_dup 0) (const_int 7)))
15543 (match_operand:DI 2 "arith_reg_operand" "r"))]
15544 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15545 "#"
15546 ""
15547 [(pc)]
15548 {
15549 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15550 operands[2]));
15551 DONE;
15552 })
15553
15554 (define_insn_and_split "*stlo_q_comb1"
15555 [(set (zero_extract:DI
15556 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15557 (match_operand:SI 1 "ua_offset" "I06"))
15558 (const_int -8)))
15559 (minus:SI (const_int 8)
15560 (and:SI (plus:SI (match_dup 0)
15561 (match_operand:SI 2 "ua_offset" "I06"))
15562 (const_int 7)))
15563 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
15564 (match_operand:DI 3 "arith_reg_operand" "r"))]
15565 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15566 "#"
15567 ""
15568 [(pc)]
15569 {
15570 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15571 operands[3]));
15572 DONE;
15573 })
15574
15575 (define_insn "ldhi_l64"
15576 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15577 (zero_extract:SI
15578 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15579 (const_int 3))
15580 (const_int -3)))
15581 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
15582 (const_int 0)))]
15583 "TARGET_SHMEDIA64"
15584 "ldhi.l %U1, %0"
15585 [(set_attr "type" "load_media")])
15586
15587 (define_insn "ldhi_q64"
15588 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15589 (zero_extract:DI
15590 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15591 (const_int 7))
15592 (const_int -7)))
15593 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
15594 (const_int 0)))]
15595 "TARGET_SHMEDIA64"
15596 "ldhi.q %U1, %0"
15597 [(set_attr "type" "load_media")])
15598
15599 (define_insn "ldlo_l64"
15600 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15601 (zero_extract:SI
15602 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15603 (const_int -4)))
15604 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
15605 (and:DI (match_dup 1) (const_int 3))))]
15606 "TARGET_SHMEDIA64"
15607 "ldlo.l %U1, %0"
15608 [(set_attr "type" "load_media")])
15609
15610 (define_insn "ldlo_q64"
15611 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15612 (zero_extract:DI
15613 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15614 (const_int -8)))
15615 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
15616 (and:DI (match_dup 1) (const_int 7))))]
15617 "TARGET_SHMEDIA64"
15618 "ldlo.q %U1, %0"
15619 [(set_attr "type" "load_media")])
15620
15621 (define_insn "sthi_l64"
15622 [(set (zero_extract:SI
15623 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15624 (const_int 3))
15625 (const_int -3)))
15626 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
15627 (const_int 0))
15628 (match_operand:SI 1 "arith_reg_operand" "r"))]
15629 "TARGET_SHMEDIA64"
15630 "sthi.l %U0, %1"
15631 [(set_attr "type" "ustore_media")])
15632
15633 (define_insn "sthi_q64"
15634 [(set (zero_extract:DI
15635 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15636 (const_int 7))
15637 (const_int -7)))
15638 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
15639 (const_int 0))
15640 (match_operand:DI 1 "arith_reg_operand" "r"))]
15641 "TARGET_SHMEDIA64"
15642 "sthi.q %U0, %1"
15643 [(set_attr "type" "ustore_media")])
15644
15645 (define_insn "stlo_l64"
15646 [(set (zero_extract:SI
15647 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15648 (const_int -4)))
15649 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
15650 (and:DI (match_dup 0) (const_int 3)))
15651 (match_operand:SI 1 "arith_reg_operand" "r"))]
15652 "TARGET_SHMEDIA64"
15653 "stlo.l %U0, %1"
15654 [(set_attr "type" "ustore_media")])
15655
15656 (define_insn "stlo_q64"
15657 [(set (zero_extract:DI
15658 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15659 (const_int -8)))
15660 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
15661 (and:DI (match_dup 0) (const_int 7)))
15662 (match_operand:DI 1 "arith_reg_operand" "r"))]
15663 "TARGET_SHMEDIA64"
15664 "stlo.q %U0, %1"
15665 [(set_attr "type" "ustore_media")])
15666
15667 (define_insn "nsb"
15668 [(set (match_operand:QI 0 "arith_reg_dest" "=r")
15669 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15670 UNSPEC_NSB))]
15671 "TARGET_SHMEDIA"
15672 "nsb %1, %0"
15673 [(set_attr "type" "arith_media")])
15674
15675 (define_insn "nsbsi"
15676 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15677 (zero_extend:SI
15678 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15679 UNSPEC_NSB)))]
15680 "TARGET_SHMEDIA"
15681 "nsb %1, %0"
15682 [(set_attr "type" "arith_media")])
15683
15684 (define_insn "nsbdi"
15685 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15686 (zero_extend:DI
15687 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15688 UNSPEC_NSB)))]
15689 "TARGET_SHMEDIA"
15690 "nsb %1, %0"
15691 [(set_attr "type" "arith_media")])
15692
15693 (define_expand "ffsdi2"
15694 [(set (match_operand:DI 0 "arith_reg_dest" "")
15695 (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
15696 "TARGET_SHMEDIA"
15697 {
15698 rtx scratch = gen_reg_rtx (DImode);
15699 rtx last;
15700
15701 emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
15702 emit_insn (gen_xordi3 (scratch, operands[1], scratch));
15703 emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
15704 emit_insn (gen_nsbdi (scratch, scratch));
15705 emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
15706 emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
15707 last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
15708 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
15709
15710 DONE;
15711 })
15712
15713 (define_expand "ffssi2"
15714 [(set (match_operand:SI 0 "arith_reg_dest" "")
15715 (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
15716 "TARGET_SHMEDIA"
15717 {
15718 rtx scratch = gen_reg_rtx (SImode);
15719 rtx discratch = gen_reg_rtx (DImode);
15720 rtx last;
15721
15722 emit_insn (gen_adddi3 (discratch,
15723 simplify_gen_subreg (DImode, operands[1], SImode, 0),
15724 constm1_rtx));
15725 emit_insn (gen_andcdi3 (discratch,
15726 simplify_gen_subreg (DImode, operands[1], SImode, 0),
15727 discratch));
15728 emit_insn (gen_nsbsi (scratch, discratch));
15729 last = emit_insn (gen_subsi3 (operands[0],
15730 force_reg (SImode, GEN_INT (63)), scratch));
15731 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
15732
15733 DONE;
15734 })
15735
15736 (define_insn "byterev"
15737 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15738 (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
15739 (parallel [(const_int 7) (const_int 6) (const_int 5)
15740 (const_int 4) (const_int 3) (const_int 2)
15741 (const_int 1) (const_int 0)])))]
15742 "TARGET_SHMEDIA"
15743 "byterev %1, %0"
15744 [(set_attr "type" "arith_media")])
15745
15746 ;; In user mode, the "pref" instruction will raise a RADDERR exception
15747 ;; for accesses to [0x80000000,0xffffffff]. This makes it an unsuitable
15748 ;; implementation of __builtin_prefetch for VxWorks RTPs.
15749 (define_expand "prefetch"
15750 [(prefetch (match_operand 0 "address_operand" "")
15751 (match_operand:SI 1 "const_int_operand" "")
15752 (match_operand:SI 2 "const_int_operand" ""))]
15753 "(TARGET_SH2A || TARGET_SH3 || TARGET_SH5)
15754 && (TARGET_SHMEDIA || ! TARGET_VXWORKS_RTP)")
15755
15756 (define_insn "*prefetch"
15757 [(prefetch (match_operand:SI 0 "register_operand" "r")
15758 (match_operand:SI 1 "const_int_operand" "n")
15759 (match_operand:SI 2 "const_int_operand" "n"))]
15760 "(TARGET_SH2A || TARGET_SH3 || TARGET_SHCOMPACT) && ! TARGET_VXWORKS_RTP"
15761 "pref @%0"
15762 [(set_attr "type" "other")])
15763
15764 (define_insn "*prefetch_media"
15765 [(prefetch (match_operand:QI 0 "address_operand" "p")
15766 (match_operand:SI 1 "const_int_operand" "n")
15767 (match_operand:SI 2 "const_int_operand" "n"))]
15768 "TARGET_SHMEDIA"
15769 {
15770 operands[0] = gen_rtx_MEM (QImode, operands[0]);
15771 output_asm_insn ("ld%M0.b %m0,r63", operands);
15772 return "";
15773 }
15774 [(set_attr "type" "other")])
15775
15776 (define_insn "alloco_i"
15777 [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
15778 (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
15779 "TARGET_SHMEDIA32"
15780 {
15781 rtx xops[2];
15782
15783 if (GET_CODE (operands[0]) == PLUS)
15784 {
15785 xops[0] = XEXP (operands[0], 0);
15786 xops[1] = XEXP (operands[0], 1);
15787 }
15788 else
15789 {
15790 xops[0] = operands[0];
15791 xops[1] = const0_rtx;
15792 }
15793 output_asm_insn ("alloco %0, %1", xops);
15794 return "";
15795 }
15796 [(set_attr "type" "other")])
15797
15798 (define_split
15799 [(set (match_operand 0 "any_register_operand" "")
15800 (match_operand 1 "" ""))]
15801 "TARGET_SHMEDIA && reload_completed"
15802 [(set (match_dup 0) (match_dup 1))]
15803 {
15804 int n_changes = 0;
15805
15806 for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
15807 if (!n_changes)
15808 FAIL;
15809 })
15810
15811 ;; -------------------------------------------------------------------------
15812 ;; Stack Protector Patterns
15813 ;; -------------------------------------------------------------------------
15814
15815 (define_expand "stack_protect_set"
15816 [(set (match_operand 0 "memory_operand" "")
15817 (match_operand 1 "memory_operand" ""))]
15818 ""
15819 {
15820 if (TARGET_SHMEDIA)
15821 {
15822 if (TARGET_SHMEDIA64)
15823 emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
15824 else
15825 emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
15826 }
15827 else
15828 emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
15829
15830 DONE;
15831 })
15832
15833 (define_insn "stack_protect_set_si"
15834 [(set (match_operand:SI 0 "memory_operand" "=m")
15835 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15836 (set (match_scratch:SI 2 "=&r") (const_int 0))]
15837 "!TARGET_SHMEDIA"
15838 {
15839 return "mov.l %1,%2" "\n"
15840 " mov.l %2,%0" "\n"
15841 " mov #0,%2";
15842 }
15843 [(set_attr "type" "other")
15844 (set_attr "length" "6")])
15845
15846 (define_insn "stack_protect_set_si_media"
15847 [(set (match_operand:SI 0 "memory_operand" "=m")
15848 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15849 (set (match_scratch:SI 2 "=&r") (const_int 0))]
15850 "TARGET_SHMEDIA"
15851 {
15852 return "ld%M1.l %m1,%2" "\n"
15853 " st%M0.l %m0,%2" "\n"
15854 " movi 0,%2";
15855 }
15856 [(set_attr "type" "other")
15857 (set_attr "length" "12")])
15858
15859 (define_insn "stack_protect_set_di_media"
15860 [(set (match_operand:DI 0 "memory_operand" "=m")
15861 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15862 (set (match_scratch:DI 2 "=&r") (const_int 0))]
15863 "TARGET_SHMEDIA64"
15864 {
15865 return "ld%M1.q %m1,%2" "\n"
15866 " st%M0.q %m0,%2" "\n"
15867 " movi 0,%2";
15868 }
15869 [(set_attr "type" "other")
15870 (set_attr "length" "12")])
15871
15872 (define_expand "stack_protect_test"
15873 [(match_operand 0 "memory_operand" "")
15874 (match_operand 1 "memory_operand" "")
15875 (match_operand 2 "" "")]
15876 ""
15877 {
15878 if (TARGET_SHMEDIA)
15879 {
15880 rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
15881 rtx test;
15882
15883 test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
15884 if (TARGET_SHMEDIA64)
15885 {
15886 emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
15887 operands[1]));
15888 emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
15889 }
15890 else
15891 {
15892 emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
15893 operands[1]));
15894 emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
15895 }
15896 }
15897 else
15898 {
15899 emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
15900 emit_jump_insn (gen_branch_true (operands[2]));
15901 }
15902
15903 DONE;
15904 })
15905
15906 (define_insn "stack_protect_test_si"
15907 [(set (reg:SI T_REG)
15908 (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
15909 (match_operand:SI 1 "memory_operand" "m")]
15910 UNSPEC_SP_TEST))
15911 (set (match_scratch:SI 2 "=&r") (const_int 0))
15912 (set (match_scratch:SI 3 "=&r") (const_int 0))]
15913 "!TARGET_SHMEDIA"
15914 {
15915 return "mov.l %0,%2" "\n"
15916 " mov.l %1,%3" "\n"
15917 " cmp/eq %2,%3" "\n"
15918 " mov #0,%2" "\n"
15919 " mov #0,%3";
15920 }
15921 [(set_attr "type" "other")
15922 (set_attr "length" "10")])
15923
15924 (define_insn "stack_protect_test_si_media"
15925 [(set (match_operand:SI 0 "register_operand" "=&r")
15926 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
15927 (match_operand:SI 2 "memory_operand" "m")]
15928 UNSPEC_SP_TEST))
15929 (set (match_scratch:SI 3 "=&r") (const_int 0))]
15930 "TARGET_SHMEDIA"
15931 {
15932 return "ld%M1.l %m1,%0" "\n"
15933 " ld%M2.l %m2,%3" "\n"
15934 " cmpeq %0,%3,%0" "\n"
15935 " movi 0,%3";
15936 }
15937 [(set_attr "type" "other")
15938 (set_attr "length" "16")])
15939
15940 (define_insn "stack_protect_test_di_media"
15941 [(set (match_operand:DI 0 "register_operand" "=&r")
15942 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
15943 (match_operand:DI 2 "memory_operand" "m")]
15944 UNSPEC_SP_TEST))
15945 (set (match_scratch:DI 3 "=&r") (const_int 0))]
15946 "TARGET_SHMEDIA64"
15947 {
15948 return "ld%M1.q %m1,%0" "\n"
15949 " ld%M2.q %m2,%3" "\n"
15950 " cmpeq %0,%3,%0" "\n"
15951 " movi 0,%3";
15952 }
15953 [(set_attr "type" "other")
15954 (set_attr "length" "16")])
15955
15956 ;; -------------------------------------------------------------------------
15957 ;; Atomic operations
15958 ;; -------------------------------------------------------------------------
15959
15960 (include "sync.md")