b5add4be0f3ac8b23ea83207556c56b7474ee730
[gcc.git] / gcc / config / sh / sh.md
1 ;;- Machine description for Renesas / SuperH SH.
2 ;; Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3 ;; 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 ;; Free Software Foundation, Inc.
5 ;; Contributed by Steve Chamberlain (sac@cygnus.com).
6 ;; Improved by Jim Wilson (wilson@cygnus.com).
7
8 ;; This file is part of GCC.
9
10 ;; GCC is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 3, or (at your option)
13 ;; any later version.
14
15 ;; GCC is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING3. If not see
22 ;; <http://www.gnu.org/licenses/>.
23
24
25 ;; ??? Should prepend a * to all pattern names which are not used.
26 ;; This will make the compiler smaller, and rebuilds after changes faster.
27
28 ;; ??? Should be enhanced to include support for many more GNU superoptimizer
29 ;; sequences. Especially the sequences for arithmetic right shifts.
30
31 ;; ??? Should check all DImode patterns for consistency and usefulness.
32
33 ;; ??? The MAC.W and MAC.L instructions are not supported. There is no
34 ;; way to generate them.
35
36 ;; ??? The cmp/str instruction is not supported. Perhaps it can be used
37 ;; for a str* inline function.
38
39 ;; BSR is not generated by the compiler proper, but when relaxing, it
40 ;; generates .uses pseudo-ops that allow linker relaxation to create
41 ;; BSR. This is actually implemented in bfd/{coff,elf32}-sh.c
42
43 ;; Special constraints for SH machine description:
44 ;;
45 ;; t -- T
46 ;; x -- mac
47 ;; l -- pr
48 ;; z -- r0
49 ;;
50 ;; Special formats used for outputting SH instructions:
51 ;;
52 ;; %. -- print a .s if insn needs delay slot
53 ;; %@ -- print rte/rts if is/isn't an interrupt function
54 ;; %# -- output a nop if there is nothing to put in the delay slot
55 ;; %O -- print a constant without the #
56 ;; %R -- print the lsw reg of a double
57 ;; %S -- print the msw reg of a double
58 ;; %T -- print next word of a double REG or MEM
59 ;;
60 ;; Special predicates:
61 ;;
62 ;; arith_operand -- operand is valid source for arithmetic op
63 ;; arith_reg_operand -- operand is valid register for arithmetic op
64 ;; general_movdst_operand -- operand is valid move destination
65 ;; general_movsrc_operand -- operand is valid move source
66 ;; logical_operand -- operand is valid source for logical op
67
68 ;; -------------------------------------------------------------------------
69 ;; Constants
70 ;; -------------------------------------------------------------------------
71
72 (define_constants [
73 (AP_REG 145)
74 (PR_REG 146)
75 (T_REG 147)
76 (GBR_REG 144)
77 (MACH_REG 148)
78 (MACL_REG 149)
79 (FPUL_REG 150)
80 (RAP_REG 152)
81
82 (FPSCR_REG 151)
83
84 (PIC_REG 12)
85 (FP_REG 14)
86 (SP_REG 15)
87
88 (PR_MEDIA_REG 18)
89 (T_MEDIA_REG 19)
90
91 (R0_REG 0)
92 (R1_REG 1)
93 (R2_REG 2)
94 (R3_REG 3)
95 (R4_REG 4)
96 (R5_REG 5)
97 (R6_REG 6)
98 (R7_REG 7)
99 (R8_REG 8)
100 (R9_REG 9)
101 (R10_REG 10)
102 (R20_REG 20)
103 (R21_REG 21)
104 (R22_REG 22)
105 (R23_REG 23)
106
107 (DR0_REG 64)
108 (DR2_REG 66)
109 (DR4_REG 68)
110 (FR23_REG 87)
111
112 (TR0_REG 128)
113 (TR1_REG 129)
114 (TR2_REG 130)
115
116 (XD0_REG 136)
117
118 ;; These are used with unspec.
119 (UNSPEC_COMPACT_ARGS 0)
120 (UNSPEC_MOVA 1)
121 (UNSPEC_CASESI 2)
122 (UNSPEC_DATALABEL 3)
123 (UNSPEC_BBR 4)
124 (UNSPEC_SFUNC 5)
125 (UNSPEC_PIC 6)
126 (UNSPEC_GOT 7)
127 (UNSPEC_GOTOFF 8)
128 (UNSPEC_PLT 9)
129 (UNSPEC_CALLER 10)
130 (UNSPEC_GOTPLT 11)
131 (UNSPEC_ICACHE 12)
132 (UNSPEC_INIT_TRAMP 13)
133 (UNSPEC_FCOSA 14)
134 (UNSPEC_FSRRA 15)
135 (UNSPEC_FSINA 16)
136 (UNSPEC_NSB 17)
137 (UNSPEC_ALLOCO 18)
138 (UNSPEC_TLSGD 20)
139 (UNSPEC_TLSLDM 21)
140 (UNSPEC_TLSIE 22)
141 (UNSPEC_DTPOFF 23)
142 (UNSPEC_GOTTPOFF 24)
143 (UNSPEC_TPOFF 25)
144 (UNSPEC_RA 26)
145 (UNSPEC_DIV_INV_M0 30)
146 (UNSPEC_DIV_INV_M1 31)
147 (UNSPEC_DIV_INV_M2 32)
148 (UNSPEC_DIV_INV_M3 33)
149 (UNSPEC_DIV_INV20 34)
150 (UNSPEC_DIV_INV_TABLE 37)
151 (UNSPEC_ASHIFTRT 35)
152 (UNSPEC_THUNK 36)
153 (UNSPEC_CHKADD 38)
154 (UNSPEC_SP_SET 40)
155 (UNSPEC_SP_TEST 41)
156 (UNSPEC_MOVUA 42)
157
158 ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT).
159 ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent.
160 (UNSPEC_EXTRACT_S16 43)
161 (UNSPEC_EXTRACT_U16 44)
162
163 ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR.
164 (UNSPEC_SYMOFF 45)
165
166 ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
167 (UNSPEC_PCREL_SYMOFF 46)
168
169 ;; These are used with unspec_volatile.
170 (UNSPECV_BLOCKAGE 0)
171 (UNSPECV_ALIGN 1)
172 (UNSPECV_CONST2 2)
173 (UNSPECV_CONST4 4)
174 (UNSPECV_CONST8 6)
175 (UNSPECV_WINDOW_END 10)
176 (UNSPECV_CONST_END 11)
177 (UNSPECV_EH_RETURN 12)
178 ])
179
180 ;; -------------------------------------------------------------------------
181 ;; Attributes
182 ;; -------------------------------------------------------------------------
183
184 ;; Target CPU.
185
186 (define_attr "cpu"
187 "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
188 (const (symbol_ref "sh_cpu_attr")))
189
190 (define_attr "endian" "big,little"
191 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
192 (const_string "little") (const_string "big"))))
193
194 ;; Indicate if the default fpu mode is single precision.
195 (define_attr "fpu_single" "yes,no"
196 (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
197 (const_string "yes") (const_string "no"))))
198
199 (define_attr "fmovd" "yes,no"
200 (const (if_then_else (symbol_ref "TARGET_FMOVD")
201 (const_string "yes") (const_string "no"))))
202 ;; pipeline model
203 (define_attr "pipe_model" "sh1,sh4,sh5media"
204 (const
205 (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
206 (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
207 (const_string "sh1"))))
208
209 ;; cbranch conditional branch instructions
210 ;; jump unconditional jumps
211 ;; arith ordinary arithmetic
212 ;; arith3 a compound insn that behaves similarly to a sequence of
213 ;; three insns of type arith
214 ;; arith3b like above, but might end with a redirected branch
215 ;; load from memory
216 ;; load_si Likewise, SImode variant for general register.
217 ;; fload Likewise, but load to fp register.
218 ;; store to memory
219 ;; fstore floating point register to memory
220 ;; move general purpose register to register
221 ;; movi8 8-bit immediate to general purpose register
222 ;; mt_group other sh4 mt instructions
223 ;; fmove register to register, floating point
224 ;; smpy word precision integer multiply
225 ;; dmpy longword or doublelongword precision integer multiply
226 ;; return rts
227 ;; pload load of pr reg, which can't be put into delay slot of rts
228 ;; prset copy register to pr reg, ditto
229 ;; pstore store of pr reg, which can't be put into delay slot of jsr
230 ;; prget copy pr to register, ditto
231 ;; pcload pc relative load of constant value
232 ;; pcfload Likewise, but load to fp register.
233 ;; pcload_si Likewise, SImode variant for general register.
234 ;; rte return from exception
235 ;; sfunc special function call with known used registers
236 ;; call function call
237 ;; fp floating point
238 ;; fpscr_toggle toggle a bit in the fpscr
239 ;; fdiv floating point divide (or square root)
240 ;; gp_fpul move from general purpose register to fpul
241 ;; fpul_gp move from fpul to general purpose register
242 ;; mac_gp move from mac[lh] to general purpose register
243 ;; gp_mac move from general purpose register to mac[lh]
244 ;; mac_mem move from mac[lh] to memory
245 ;; mem_mac move from memory to mac[lh]
246 ;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv
247 ;; ftrc_s fix_truncsfsi2_i4
248 ;; dfdiv double precision floating point divide (or square root)
249 ;; cwb ic_invalidate_line_i
250 ;; movua SH4a unaligned load
251 ;; fsrra square root reciprocal approximate
252 ;; fsca sine and cosine approximate
253 ;; tls_load load TLS related address
254 ;; arith_media SHmedia arithmetic, logical, and shift instructions
255 ;; cbranch_media SHmedia conditional branch instructions
256 ;; cmp_media SHmedia compare instructions
257 ;; dfdiv_media SHmedia double precision divide and square root
258 ;; dfmul_media SHmedia double precision multiply instruction
259 ;; dfparith_media SHmedia double precision floating point arithmetic
260 ;; dfpconv_media SHmedia double precision floating point conversions
261 ;; dmpy_media SHmedia longword multiply
262 ;; fcmp_media SHmedia floating point compare instructions
263 ;; fdiv_media SHmedia single precision divide and square root
264 ;; fload_media SHmedia floating point register load instructions
265 ;; fmove_media SHmedia floating point register moves (inc. fabs and fneg)
266 ;; fparith_media SHmedia single precision floating point arithmetic
267 ;; fpconv_media SHmedia single precision floating point conversions
268 ;; fstore_media SHmedia floating point register store instructions
269 ;; gettr_media SHmedia gettr instruction
270 ;; invalidate_line_media SHmedia invalidate_line sequence
271 ;; jump_media SHmedia unconditional branch instructions
272 ;; load_media SHmedia general register load instructions
273 ;; pt_media SHmedia pt instruction (expanded by assembler)
274 ;; ptabs_media SHmedia ptabs instruction
275 ;; store_media SHmedia general register store instructions
276 ;; mcmp_media SHmedia multimedia compare, absolute, saturating ops
277 ;; mac_media SHmedia mac-style fixed point operations
278 ;; d2mpy_media SHmedia: two 32-bit integer multiplies
279 ;; atrans_media SHmedia approximate transcendental functions
280 ;; ustore_media SHmedia unaligned stores
281 ;; nil no-op move, will be deleted.
282
283 (define_attr "type"
284 "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s,dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,gp_mac,mac_mem,mem_mac,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load,arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,d2mpy_media,atrans_media,ustore_media,nil,other"
285 (const_string "other"))
286
287 ;; We define a new attribute namely "insn_class".We use
288 ;; this for the DFA based pipeline description.
289 ;;
290 ;; mt_group SH4 "mt" group instructions.
291 ;;
292 ;; ex_group SH4 "ex" group instructions.
293 ;;
294 ;; ls_group SH4 "ls" group instructions.
295 ;;
296
297 (define_attr "insn_class"
298 "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
299 (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
300 (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group")
301 (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,store,fstore,gp_fpul,fpul_gp") (const_string "ls_group")
302 (eq_attr "type" "cbranch,jump") (const_string "br_group")
303 (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
304 (const_string "fe_group")
305 (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb,gp_mac,mac_mem,mem_mac") (const_string "co_group")]
306 (const_string "none")))
307 ;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
308 ;; so these do not belong in an insn group, although they are modeled
309 ;; with their own define_insn_reservations.
310
311 ;; Indicate what precision must be selected in fpscr for this insn, if any.
312
313 (define_attr "fp_mode" "single,double,none" (const_string "none"))
314
315 ;; Indicate if the fpu mode is set by this instruction
316 ;; "unknown" must have the value as "none" in fp_mode, and means
317 ;; that the instruction/abi has left the processor in an unknown
318 ;; state.
319 ;; "none" means that nothing has changed and no mode is set.
320 ;; This attribute is only used for the Renesas ABI.
321 (define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
322
323 ; If a conditional branch destination is within -252..258 bytes away
324 ; from the instruction it can be 2 bytes long. Something in the
325 ; range -4090..4100 bytes can be 6 bytes long. All other conditional
326 ; branches are initially assumed to be 16 bytes long.
327 ; In machine_dependent_reorg, we split all branches that are longer than
328 ; 2 bytes.
329
330 ;; The maximum range used for SImode constant pool entries is 1018. A final
331 ;; instruction can add 8 bytes while only being 4 bytes in size, thus we
332 ;; can have a total of 1022 bytes in the pool. Add 4 bytes for a branch
333 ;; instruction around the pool table, 2 bytes of alignment before the table,
334 ;; and 30 bytes of alignment after the table. That gives a maximum total
335 ;; pool size of 1058 bytes.
336 ;; Worst case code/pool content size ratio is 1:2 (using asms).
337 ;; Thus, in the worst case, there is one instruction in front of a maximum
338 ;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
339 ;; code. For the last n bytes of code, there are 2n + 36 bytes of pool.
340 ;; If we have a forward branch, the initial table will be put after the
341 ;; unconditional branch.
342 ;;
343 ;; ??? We could do much better by keeping track of the actual pcloads within
344 ;; the branch range and in the pcload range in front of the branch range.
345
346 ;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
347 ;; inside an le.
348 (define_attr "short_cbranch_p" "no,yes"
349 (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
350 (const_string "no")
351 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
352 (const_string "yes")
353 (match_test "NEXT_INSN (PREV_INSN (insn)) != insn")
354 (const_string "no")
355 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
356 (const_string "yes")
357 ] (const_string "no")))
358
359 (define_attr "med_branch_p" "no,yes"
360 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
361 (const_int 1988))
362 (const_string "yes")
363 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
364 (const_string "no")
365 (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
366 (const_int 8186))
367 (const_string "yes")
368 ] (const_string "no")))
369
370 (define_attr "med_cbranch_p" "no,yes"
371 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
372 (const_int 1986))
373 (const_string "yes")
374 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
375 (const_string "no")
376 (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
377 (const_int 8184))
378 (const_string "yes")
379 ] (const_string "no")))
380
381 (define_attr "braf_branch_p" "no,yes"
382 (cond [(match_test "! TARGET_SH2")
383 (const_string "no")
384 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
385 (const_int 20660))
386 (const_string "yes")
387 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
388 (const_string "no")
389 (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
390 (const_int 65530))
391 (const_string "yes")
392 ] (const_string "no")))
393
394 (define_attr "braf_cbranch_p" "no,yes"
395 (cond [(match_test "! TARGET_SH2")
396 (const_string "no")
397 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
398 (const_int 20658))
399 (const_string "yes")
400 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
401 (const_string "no")
402 (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
403 (const_int 65528))
404 (const_string "yes")
405 ] (const_string "no")))
406
407 ; An unconditional jump in the range -4092..4098 can be 2 bytes long.
408 ; For wider ranges, we need a combination of a code and a data part.
409 ; If we can get a scratch register for a long range jump, the code
410 ; part can be 4 bytes long; otherwise, it must be 8 bytes long.
411 ; If the jump is in the range -32764..32770, the data part can be 2 bytes
412 ; long; otherwise, it must be 6 bytes long.
413
414 ; All other instructions are two bytes long by default.
415
416 ;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
417 ;; but getattrtab doesn't understand this.
418 (define_attr "length" ""
419 (cond [(eq_attr "type" "cbranch")
420 (cond [(eq_attr "short_cbranch_p" "yes")
421 (const_int 2)
422 (eq_attr "med_cbranch_p" "yes")
423 (const_int 6)
424 (eq_attr "braf_cbranch_p" "yes")
425 (const_int 12)
426 ;; ??? using pc is not computed transitively.
427 (ne (match_dup 0) (match_dup 0))
428 (const_int 14)
429 (match_test "flag_pic")
430 (const_int 24)
431 ] (const_int 16))
432 (eq_attr "type" "jump")
433 (cond [(eq_attr "med_branch_p" "yes")
434 (const_int 2)
435 (and (match_test "prev_nonnote_insn (insn)")
436 (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))") (symbol_ref "INSN"))
437 (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))") (symbol_ref "code_for_indirect_jump_scratch"))))
438 (cond [(eq_attr "braf_branch_p" "yes")
439 (const_int 6)
440 (not (match_test "flag_pic"))
441 (const_int 10)
442 (match_test "TARGET_SH2")
443 (const_int 10)] (const_int 18))
444 (eq_attr "braf_branch_p" "yes")
445 (const_int 10)
446 ;; ??? using pc is not computed transitively.
447 (ne (match_dup 0) (match_dup 0))
448 (const_int 12)
449 (match_test "flag_pic")
450 (const_int 22)
451 ] (const_int 14))
452 (eq_attr "type" "pt_media")
453 (if_then_else (match_test "TARGET_SHMEDIA64")
454 (const_int 20) (const_int 12))
455 (and (eq_attr "type" "jump_media")
456 (match_test "TARGET_SH5_CUT2_WORKAROUND"))
457 (const_int 8)
458 ] (if_then_else (match_test "TARGET_SHMEDIA")
459 (const_int 4)
460 (const_int 2))))
461
462 ;; DFA descriptions for the pipelines
463
464 (include "sh1.md")
465 (include "shmedia.md")
466 (include "sh4.md")
467
468 (include "predicates.md")
469 (include "constraints.md")
470
471 ;; Definitions for filling delay slots
472
473 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
474
475 (define_attr "banked" "yes,no"
476 (cond [(match_test "sh_loads_bankedreg_p (insn)")
477 (const_string "yes")]
478 (const_string "no")))
479
480 ;; ??? This should be (nil) instead of (const_int 0)
481 (define_attr "hit_stack" "yes,no"
482 (cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)"))
483 (const_string "no")]
484 (const_string "yes")))
485
486 (define_attr "interrupt_function" "no,yes"
487 (const (symbol_ref "current_function_interrupt")))
488
489 (define_attr "in_delay_slot" "yes,no"
490 (cond [(eq_attr "type" "cbranch") (const_string "no")
491 (eq_attr "type" "pcload,pcload_si") (const_string "no")
492 (eq_attr "needs_delay_slot" "yes") (const_string "no")
493 (eq_attr "length" "2") (const_string "yes")
494 ] (const_string "no")))
495
496 (define_attr "cond_delay_slot" "yes,no"
497 (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
498 ] (const_string "no")))
499
500 (define_attr "is_sfunc" ""
501 (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
502
503 (define_attr "is_mac_media" ""
504 (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
505
506 (define_attr "branch_zero" "yes,no"
507 (cond [(eq_attr "type" "!cbranch") (const_string "no")
508 (ne (symbol_ref "(next_active_insn (insn)\
509 == (prev_active_insn\
510 (XEXP (SET_SRC (PATTERN (insn)), 1))))\
511 && get_attr_length (next_active_insn (insn)) == 2")
512 (const_int 0))
513 (const_string "yes")]
514 (const_string "no")))
515
516 ;; SH4 Double-precision computation with double-precision result -
517 ;; the two halves are ready at different times.
518 (define_attr "dfp_comp" "yes,no"
519 (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
520 (const_string "no")))
521
522 ;; Insns for which the latency of a preceding fp insn is decreased by one.
523 (define_attr "late_fp_use" "yes,no" (const_string "no"))
524 ;; And feeding insns for which this relevant.
525 (define_attr "any_fp_comp" "yes,no"
526 (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
527 (const_string "yes")]
528 (const_string "no")))
529
530 (define_attr "any_int_load" "yes,no"
531 (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
532 (const_string "yes")]
533 (const_string "no")))
534
535 (define_attr "highpart" "user, ignore, extend, depend, must_split"
536 (const_string "user"))
537
538 (define_delay
539 (eq_attr "needs_delay_slot" "yes")
540 [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
541
542 ;; On the SH and SH2, the rte instruction reads the return pc from the stack,
543 ;; and thus we can't put a pop instruction in its delay slot.
544 ;; ??? On the SH3, the rte instruction does not use the stack, so a pop
545 ;; instruction can go in the delay slot.
546
547 ;; Since a normal return (rts) implicitly uses the PR register,
548 ;; we can't allow PR register loads in an rts delay slot.
549
550 (define_delay
551 (eq_attr "type" "return")
552 [(and (eq_attr "in_delay_slot" "yes")
553 (ior (and (eq_attr "interrupt_function" "no")
554 (eq_attr "type" "!pload,prset"))
555 (and (eq_attr "interrupt_function" "yes")
556 (ior
557 (not (match_test "TARGET_SH3"))
558 (eq_attr "hit_stack" "no")
559 (eq_attr "banked" "no"))))) (nil) (nil)])
560
561 ;; Since a call implicitly uses the PR register, we can't allow
562 ;; a PR register store in a jsr delay slot.
563
564 (define_delay
565 (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
566 [(and (eq_attr "in_delay_slot" "yes")
567 (eq_attr "type" "!pstore,prget")) (nil) (nil)])
568
569 ;; Say that we have annulled true branches, since this gives smaller and
570 ;; faster code when branches are predicted as not taken.
571
572 ;; ??? The non-annulled condition should really be "in_delay_slot",
573 ;; but insns that can be filled in non-annulled get priority over insns
574 ;; that can only be filled in anulled.
575
576 (define_delay
577 (and (eq_attr "type" "cbranch")
578 (match_test "TARGET_SH2"))
579 ;; SH2e has a hardware bug that pretty much prohibits the use of
580 ;; annulled delay slots.
581 [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
582 (not (eq_attr "cpu" "sh2e"))) (nil)])
583 \f
584 ;; -------------------------------------------------------------------------
585 ;; SImode signed integer comparisons
586 ;; -------------------------------------------------------------------------
587
588 ;; Various patterns to generate the TST #imm, R0 instruction.
589 ;; Although this adds some pressure on the R0 register, it can potentially
590 ;; result in faster code, even if the operand has to be moved to R0 first.
591 ;; This is because on SH4 TST #imm, R0 and MOV Rm, Rn are both MT group
592 ;; instructions and thus will be executed in parallel. On SH4A TST #imm, R0
593 ;; is an EX group instruction but still can be executed in parallel with the
594 ;; MT group MOV Rm, Rn instruction.
595
596 ;; Usual TST #imm, R0 patterns for SI, HI and QI
597 ;; This is usually used for bit patterns other than contiguous bits
598 ;; and single bits.
599
600 (define_insn "tstsi_t"
601 [(set (reg:SI T_REG)
602 (eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r")
603 (match_operand:SI 1 "logical_operand" "K08,r"))
604 (const_int 0)))]
605 "TARGET_SH1"
606 "tst %1,%0"
607 [(set_attr "type" "mt_group")])
608
609 (define_insn "tsthi_t"
610 [(set (reg:SI T_REG)
611 (eq:SI (subreg:SI (and:HI (match_operand:HI 0 "logical_operand" "%z")
612 (match_operand 1 "const_int_operand")) 0)
613 (const_int 0)))]
614 "TARGET_SH1
615 && CONST_OK_FOR_K08 (INTVAL (operands[1]))"
616 "tst %1,%0"
617 [(set_attr "type" "mt_group")])
618
619 (define_insn "tstqi_t"
620 [(set (reg:SI T_REG)
621 (eq:SI (subreg:SI (and:QI (match_operand:QI 0 "logical_operand" "%z")
622 (match_operand 1 "const_int_operand")) 0)
623 (const_int 0)))]
624 "TARGET_SH1
625 && (CONST_OK_FOR_K08 (INTVAL (operands[1]))
626 || CONST_OK_FOR_I08 (INTVAL (operands[1])))"
627 {
628 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
629 return "tst %1,%0";
630 }
631 [(set_attr "type" "mt_group")])
632
633 ;; Test low QI subreg against zero.
634 ;; This avoids unnecessary zero extension before the test.
635
636 (define_insn "tstqi_t_zero"
637 [(set (reg:SI T_REG)
638 (eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))]
639 "TARGET_SH1"
640 "tst #255,%0"
641 [(set_attr "type" "mt_group")])
642
643 ;; Extract LSB, negate and store in T bit.
644
645 (define_insn "tstsi_t_and_not"
646 [(set (reg:SI T_REG)
647 (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z"))
648 (const_int 1)))]
649 "TARGET_SH1"
650 "tst #1,%0"
651 [(set_attr "type" "mt_group")])
652
653 ;; Extract contiguous bits and compare them against zero.
654
655 (define_insn "tstsi_t_zero_extract_eq"
656 [(set (reg:SI T_REG)
657 (eq:SI (zero_extract:SI (match_operand 0 "logical_operand" "z")
658 (match_operand:SI 1 "const_int_operand")
659 (match_operand:SI 2 "const_int_operand"))
660 (const_int 0)))]
661 "TARGET_SH1
662 && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))"
663 {
664 operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
665 return "tst %1,%0";
666 }
667 [(set_attr "type" "mt_group")])
668
669 ;; This split is required when testing bits in a QI subreg.
670
671 (define_split
672 [(set (reg:SI T_REG)
673 (eq:SI (if_then_else:SI (zero_extract:SI
674 (match_operand 0 "logical_operand" "")
675 (match_operand 1 "const_int_operand")
676 (match_operand 2 "const_int_operand"))
677 (match_operand 3 "const_int_operand")
678 (const_int 0))
679 (const_int 0)))]
680 "TARGET_SH1
681 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
682 && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
683 [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3))
684 (const_int 0)))]
685 {
686 if (GET_MODE (operands[0]) == QImode)
687 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
688 })
689
690 ;; Extract single bit, negate and store it in the T bit.
691 ;; Not used for SH4A.
692
693 (define_insn "tstsi_t_zero_extract_xor"
694 [(set (reg:SI T_REG)
695 (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
696 (match_operand:SI 3 "const_int_operand"))
697 (match_operand:SI 1 "const_int_operand")
698 (match_operand:SI 2 "const_int_operand")))]
699 "TARGET_SH1
700 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
701 && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
702 "tst %3,%0"
703 [(set_attr "type" "mt_group")])
704
705 ;; Extract single bit, negate and store it in the T bit.
706 ;; Used for SH4A little endian.
707
708 (define_insn "tstsi_t_zero_extract_subreg_xor_little"
709 [(set (reg:SI T_REG)
710 (zero_extract:SI
711 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
712 (match_operand:SI 3 "const_int_operand")) 0)
713 (match_operand:SI 1 "const_int_operand")
714 (match_operand:SI 2 "const_int_operand")))]
715 "TARGET_SH1 && TARGET_LITTLE_ENDIAN
716 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
717 == (INTVAL (operands[3]) & 255)
718 && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
719 {
720 operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
721 return "tst %3,%0";
722 }
723 [(set_attr "type" "mt_group")])
724
725 ;; Extract single bit, negate and store it in the T bit.
726 ;; Used for SH4A big endian.
727
728 (define_insn "tstsi_t_zero_extract_subreg_xor_big"
729 [(set (reg:SI T_REG)
730 (zero_extract:SI
731 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
732 (match_operand:SI 3 "const_int_operand")) 3)
733 (match_operand:SI 1 "const_int_operand")
734 (match_operand:SI 2 "const_int_operand")))]
735 "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN
736 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
737 == (INTVAL (operands[3]) & 255)
738 && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
739 {
740 operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
741 return "tst %3,%0";
742 }
743 [(set_attr "type" "mt_group")])
744
745 ;; ??? Perhaps should only accept reg/constant if the register is reg 0.
746 ;; That would still allow reload to create cmpi instructions, but would
747 ;; perhaps allow forcing the constant into a register when that is better.
748 ;; Probably should use r0 for mem/imm compares, but force constant into a
749 ;; register for pseudo/imm compares.
750
751 (define_insn "cmpeqsi_t"
752 [(set (reg:SI T_REG)
753 (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
754 (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
755 "TARGET_SH1"
756 "@
757 tst %0,%0
758 cmp/eq %1,%0
759 cmp/eq %1,%0"
760 [(set_attr "type" "mt_group")])
761
762 (define_insn "cmpgtsi_t"
763 [(set (reg:SI T_REG)
764 (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
765 (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
766 "TARGET_SH1"
767 "@
768 cmp/gt %1,%0
769 cmp/pl %0"
770 [(set_attr "type" "mt_group")])
771
772 (define_insn "cmpgesi_t"
773 [(set (reg:SI T_REG)
774 (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
775 (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
776 "TARGET_SH1"
777 "@
778 cmp/ge %1,%0
779 cmp/pz %0"
780 [(set_attr "type" "mt_group")])
781
782 ;; -------------------------------------------------------------------------
783 ;; SImode compare and branch
784 ;; -------------------------------------------------------------------------
785
786 (define_expand "cbranchsi4"
787 [(set (pc)
788 (if_then_else (match_operator 0 "comparison_operator"
789 [(match_operand:SI 1 "arith_operand" "")
790 (match_operand:SI 2 "arith_operand" "")])
791 (label_ref (match_operand 3 "" ""))
792 (pc)))
793 (clobber (reg:SI T_REG))]
794 ""
795 {
796 if (TARGET_SHMEDIA)
797 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
798 operands[2], operands[3]));
799 else if (TARGET_CBRANCHDI4)
800 expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
801 else
802 sh_emit_compare_and_branch (operands, SImode);
803 DONE;
804 })
805
806 ;; -------------------------------------------------------------------------
807 ;; SImode unsigned integer comparisons
808 ;; -------------------------------------------------------------------------
809
810 (define_insn_and_split "cmpgeusi_t"
811 [(set (reg:SI T_REG)
812 (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
813 (match_operand:SI 1 "arith_reg_or_0_operand" "rN")))]
814 "TARGET_SH1"
815 "cmp/hs %1,%0"
816 "&& operands[1] == CONST0_RTX (SImode)"
817 [(pc)]
818 {
819 emit_insn (gen_sett ());
820 DONE;
821 }
822 [(set_attr "type" "mt_group")])
823
824 (define_insn "cmpgtusi_t"
825 [(set (reg:SI T_REG)
826 (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
827 (match_operand:SI 1 "arith_reg_operand" "r")))]
828 "TARGET_SH1"
829 "cmp/hi %1,%0"
830 [(set_attr "type" "mt_group")])
831
832 \f
833 ;; -------------------------------------------------------------------------
834 ;; DImode compare and branch
835 ;; -------------------------------------------------------------------------
836
837
838 ;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
839 ;; Therefore, we aim to have a set of three branches that go straight to the
840 ;; destination, i.e. only one of them is taken at any one time.
841 ;; This mechanism should also be slightly better for the sh4-200.
842
843 (define_expand "cbranchdi4"
844 [(set (pc)
845 (if_then_else (match_operator 0 "comparison_operator"
846 [(match_operand:DI 1 "arith_operand" "")
847 (match_operand:DI 2 "arith_operand" "")])
848 (label_ref (match_operand 3 "" ""))
849 (pc)))
850 (clobber (match_dup 4))
851 (clobber (reg:SI T_REG))]
852 "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
853 {
854 enum rtx_code comparison;
855
856 if (TARGET_SHMEDIA)
857 {
858 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
859 operands[2], operands[3]));
860 DONE;
861 }
862
863 else if (!TARGET_CBRANCHDI4)
864 {
865 sh_emit_compare_and_branch (operands, DImode);
866 DONE;
867 }
868
869 else
870 {
871 if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
872 DONE;
873
874 comparison = prepare_cbranch_operands (operands, DImode,
875 LAST_AND_UNUSED_RTX_CODE);
876 if (comparison != GET_CODE (operands[0]))
877 operands[0]
878 = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
879 operands[4] = gen_rtx_SCRATCH (SImode);
880 }
881 })
882
883 (define_insn_and_split "cbranchdi4_i"
884 [(set (pc)
885 (if_then_else (match_operator 0 "comparison_operator"
886 [(match_operand:DI 1 "arith_operand" "r,r")
887 (match_operand:DI 2 "arith_operand" "rN,I08")])
888 (label_ref (match_operand 3 "" ""))
889 (pc)))
890 (clobber (match_scratch:SI 4 "=X,&r"))
891 (clobber (reg:SI T_REG))]
892 "TARGET_CBRANCHDI4"
893 "#"
894 "&& reload_completed"
895 [(pc)]
896 {
897 if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
898 FAIL;
899 DONE;
900 })
901
902 ;; -------------------------------------------------------------------------
903 ;; DImode signed integer comparisons
904 ;; -------------------------------------------------------------------------
905
906 (define_insn ""
907 [(set (reg:SI T_REG)
908 (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
909 (match_operand:DI 1 "arith_operand" "r"))
910 (const_int 0)))]
911 "TARGET_SH1"
912 {
913 return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0",
914 insn, operands);
915 }
916 [(set_attr "length" "6")
917 (set_attr "type" "arith3b")])
918
919 (define_insn "cmpeqdi_t"
920 [(set (reg:SI T_REG)
921 (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
922 (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
923 "TARGET_SH1"
924 "@
925 tst %S0,%S0\;bf %,Ldi%=\;tst %R0,%R0\\n%,Ldi%=:
926 cmp/eq %S1,%S0\;bf %,Ldi%=\;cmp/eq %R1,%R0\\n%,Ldi%=:"
927 [(set_attr "length" "6")
928 (set_attr "type" "arith3b")])
929
930 (define_split
931 [(set (reg:SI T_REG)
932 (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
933 (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
934 ;; If we applied this split when not optimizing, it would only be
935 ;; applied during the machine-dependent reorg, when no new basic blocks
936 ;; may be created.
937 "TARGET_SH1 && reload_completed && optimize"
938 [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
939 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
940 (label_ref (match_dup 6))
941 (pc)))
942 (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
943 (match_dup 6)]
944 {
945 operands[2] = gen_highpart (SImode, operands[0]);
946 operands[3] = operands[1] == const0_rtx
947 ? const0_rtx
948 : gen_highpart (SImode, operands[1]);
949 operands[4] = gen_lowpart (SImode, operands[0]);
950 operands[5] = gen_lowpart (SImode, operands[1]);
951 operands[6] = gen_label_rtx ();
952 })
953
954 (define_insn "cmpgtdi_t"
955 [(set (reg:SI T_REG)
956 (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
957 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
958 "TARGET_SH2"
959 "@
960 cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:
961 tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"
962 [(set_attr "length" "8")
963 (set_attr "type" "arith3")])
964
965 (define_insn "cmpgedi_t"
966 [(set (reg:SI T_REG)
967 (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
968 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
969 "TARGET_SH2"
970 "@
971 cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:
972 cmp/pz\\t%S0"
973 [(set_attr "length" "8,2")
974 (set_attr "type" "arith3,mt_group")])
975 \f
976 ;; -------------------------------------------------------------------------
977 ;; DImode unsigned integer comparisons
978 ;; -------------------------------------------------------------------------
979
980 (define_insn "cmpgeudi_t"
981 [(set (reg:SI T_REG)
982 (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
983 (match_operand:DI 1 "arith_reg_operand" "r")))]
984 "TARGET_SH2"
985 "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"
986 [(set_attr "length" "8")
987 (set_attr "type" "arith3")])
988
989 (define_insn "cmpgtudi_t"
990 [(set (reg:SI T_REG)
991 (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
992 (match_operand:DI 1 "arith_reg_operand" "r")))]
993 "TARGET_SH2"
994 "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"
995 [(set_attr "length" "8")
996 (set_attr "type" "arith3")])
997
998 (define_insn "cmpeqsi_media"
999 [(set (match_operand:SI 0 "register_operand" "=r")
1000 (eq:SI (match_operand:SI 1 "logical_operand" "%r")
1001 (match_operand:SI 2 "cmp_operand" "Nr")))]
1002 "TARGET_SHMEDIA"
1003 "cmpeq %1, %N2, %0"
1004 [(set_attr "type" "cmp_media")])
1005
1006 (define_insn "cmpeqdi_media"
1007 [(set (match_operand:SI 0 "register_operand" "=r")
1008 (eq:SI (match_operand:DI 1 "register_operand" "%r")
1009 (match_operand:DI 2 "cmp_operand" "Nr")))]
1010 "TARGET_SHMEDIA"
1011 "cmpeq %1, %N2, %0"
1012 [(set_attr "type" "cmp_media")])
1013
1014 (define_insn "cmpgtsi_media"
1015 [(set (match_operand:SI 0 "register_operand" "=r")
1016 (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
1017 (match_operand:SI 2 "cmp_operand" "rN")))]
1018 "TARGET_SHMEDIA"
1019 "cmpgt %N1, %N2, %0"
1020 [(set_attr "type" "cmp_media")])
1021
1022 (define_insn "cmpgtdi_media"
1023 [(set (match_operand:SI 0 "register_operand" "=r")
1024 (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1025 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1026 "TARGET_SHMEDIA"
1027 "cmpgt %N1, %N2, %0"
1028 [(set_attr "type" "cmp_media")])
1029
1030 (define_insn "cmpgtusi_media"
1031 [(set (match_operand:SI 0 "register_operand" "=r")
1032 (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
1033 (match_operand:SI 2 "cmp_operand" "rN")))]
1034 "TARGET_SHMEDIA"
1035 "cmpgtu %N1, %N2, %0"
1036 [(set_attr "type" "cmp_media")])
1037
1038 (define_insn "cmpgtudi_media"
1039 [(set (match_operand:SI 0 "register_operand" "=r")
1040 (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1041 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1042 "TARGET_SHMEDIA"
1043 "cmpgtu %N1, %N2, %0"
1044 [(set_attr "type" "cmp_media")])
1045
1046 ; These two patterns are for combine.
1047 (define_insn "*cmpne0sisi_media"
1048 [(set (match_operand:SI 0 "register_operand" "=r")
1049 (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
1050 "TARGET_SHMEDIA"
1051 "cmpgtu %1,r63,%0"
1052 [(set_attr "type" "cmp_media")])
1053
1054 ;; -------------------------------------------------------------------------
1055 ;; Conditional move instructions
1056 ;; -------------------------------------------------------------------------
1057
1058 ;; The insn names may seem reversed, but note that cmveq performs the move
1059 ;; if op1 == 0, and cmvne does it if op1 != 0.
1060
1061 (define_insn "movdicc_false"
1062 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1063 (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
1064 (const_int 0))
1065 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1066 (match_operand:DI 3 "arith_reg_operand" "0")))]
1067 "TARGET_SHMEDIA"
1068 "cmveq %1, %N2, %0"
1069 [(set_attr "type" "arith_media")])
1070
1071 (define_insn "movdicc_true"
1072 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1073 (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
1074 (const_int 0))
1075 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1076 (match_operand:DI 3 "arith_reg_operand" "0")))]
1077 "TARGET_SHMEDIA"
1078 "cmvne %1, %N2, %0"
1079 [(set_attr "type" "arith_media")])
1080
1081 (define_peephole2
1082 [(set (match_operand:DI 0 "arith_reg_dest" "")
1083 (if_then_else:DI (match_operator 3 "equality_comparison_operator"
1084 [(match_operand:DI 1 "arith_reg_operand" "")
1085 (const_int 0)])
1086 (match_operand:DI 2 "arith_reg_dest" "")
1087 (match_dup 0)))
1088 (set (match_dup 2) (match_dup 0))]
1089 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1090 [(set (match_dup 2)
1091 (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
1092 {
1093 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1094 VOIDmode, operands[1], CONST0_RTX (DImode));
1095 })
1096
1097 (define_peephole2
1098 [(set (match_operand:DI 0 "general_movdst_operand" "")
1099 (match_operand:DI 1 "arith_reg_or_0_operand" ""))
1100 (set (match_operand:DI 2 "arith_reg_dest" "")
1101 (if_then_else:DI (match_operator 4 "equality_comparison_operator"
1102 [(match_operand:DI 3 "arith_reg_operand" "")
1103 (const_int 0)])
1104 (match_dup 0)
1105 (match_dup 2)))]
1106 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1107 [(set (match_dup 2)
1108 (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
1109 "")
1110
1111 (define_expand "movdicc"
1112 [(set (match_operand:DI 0 "register_operand" "")
1113 (if_then_else:DI (match_operand 1 "comparison_operator" "")
1114 (match_operand:DI 2 "register_operand" "")
1115 (match_operand:DI 3 "register_operand" "")))]
1116 "TARGET_SHMEDIA"
1117 {
1118 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1119 && GET_MODE (XEXP (operands[1], 0)) == DImode
1120 && XEXP (operands[1], 1) == const0_rtx)
1121 ;
1122 else
1123 {
1124 if (!can_create_pseudo_p ())
1125 FAIL;
1126
1127 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1128 GET_CODE (operands[1]),
1129 XEXP (operands[1], 0),
1130 XEXP (operands[1], 1));
1131 if (!operands[1])
1132 FAIL;
1133 }
1134 })
1135
1136 ;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1137 ;; SImode to DImode.
1138 (define_insn "movsicc_false"
1139 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1140 (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1141 (const_int 0))
1142 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1143 (match_operand:SI 3 "arith_reg_operand" "0")))]
1144 "TARGET_SHMEDIA"
1145 "cmveq %1, %N2, %0"
1146 [(set_attr "type" "arith_media")])
1147
1148 (define_insn "movsicc_true"
1149 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1150 (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1151 (const_int 0))
1152 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1153 (match_operand:SI 3 "arith_reg_operand" "0")))]
1154 "TARGET_SHMEDIA"
1155 "cmvne %1, %N2, %0"
1156 [(set_attr "type" "arith_media")])
1157
1158 (define_peephole2
1159 [(set (match_operand:SI 0 "arith_reg_dest" "")
1160 (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1161 [(match_operand:SI 1 "arith_reg_operand" "")
1162 (const_int 0)])
1163 (match_operand:SI 2 "arith_reg_dest" "")
1164 (match_dup 0)))
1165 (set (match_dup 2) (match_dup 0))]
1166 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1167 [(set (match_dup 2)
1168 (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1169 {
1170 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1171 VOIDmode, operands[1], CONST0_RTX (SImode));
1172 })
1173
1174 (define_peephole2
1175 [(set (match_operand:SI 0 "general_movdst_operand" "")
1176 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1177 (set (match_operand:SI 2 "arith_reg_dest" "")
1178 (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1179 [(match_operand:SI 3 "arith_reg_operand" "")
1180 (const_int 0)])
1181 (match_dup 0)
1182 (match_dup 2)))]
1183 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1184 && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1185 [(set (match_dup 2)
1186 (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1187 {
1188 replace_rtx (operands[4], operands[0], operands[1]);
1189 })
1190
1191 (define_peephole2
1192 [(set (match_operand 0 "any_register_operand" "")
1193 (match_operand 1 "any_register_operand" ""))
1194 (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1195 (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1196 "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1197 <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1198 && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1199 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1200 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1201 && ! reg_overlap_mentioned_p (operands[0], operands[3])
1202 && ! reg_overlap_mentioned_p (operands[2], operands[0])
1203 && ! reg_overlap_mentioned_p (operands[0], operands[1])
1204 && (REGNO_REG_CLASS (REGNO (operands[0]))
1205 == REGNO_REG_CLASS (REGNO (operands[2])))
1206 && (REGNO_REG_CLASS (REGNO (operands[1]))
1207 == REGNO_REG_CLASS (REGNO (operands[0])))"
1208 [(set (match_dup 0) (match_dup 3))
1209 (set (match_dup 4) (match_dup 5))]
1210 {
1211 rtx set1, set2, insn2;
1212 rtx replacements[4];
1213
1214 /* We want to replace occurrences of operands[0] with operands[1] and
1215 operands[2] with operands[0] in operands[4]/operands[5].
1216 Doing just two replace_rtx calls naively would result in the second
1217 replacement undoing all that the first did if operands[1] and operands[2]
1218 are identical, so we must do this simultaneously. */
1219 replacements[0] = operands[0];
1220 replacements[1] = operands[1];
1221 replacements[2] = operands[2];
1222 replacements[3] = operands[0];
1223 if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1224 || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1225 || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1226 FAIL;
1227
1228 operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1229 replace_n_hard_rtx (operands[4], replacements, 2, 1);
1230 operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1231 /* The operands array is aliased to recog_data.operand, which gets
1232 clobbered by extract_insn, so finish with it now. */
1233 set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1234 set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1235 /* ??? The last insn might be a jump insn, but the generic peephole2 code
1236 always uses emit_insn. */
1237 /* Check that we don't violate matching constraints or earlyclobbers. */
1238 extract_insn (emit_insn (set1));
1239 if (! constrain_operands (1))
1240 goto failure;
1241 insn2 = emit (set2);
1242 if (GET_CODE (insn2) == BARRIER)
1243 goto failure;
1244 extract_insn (insn2);
1245 if (! constrain_operands (1))
1246 {
1247 rtx tmp;
1248 failure:
1249 tmp = replacements[0];
1250 replacements[0] = replacements[1];
1251 replacements[1] = tmp;
1252 tmp = replacements[2];
1253 replacements[2] = replacements[3];
1254 replacements[3] = tmp;
1255 replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1256 replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1257 replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1258 FAIL;
1259 }
1260 DONE;
1261 })
1262
1263 ;; The register allocator is rather clumsy in handling multi-way conditional
1264 ;; moves, so allow the combiner to make them, and we split them up after
1265 ;; reload. */
1266 (define_insn_and_split "*movsicc_umin"
1267 [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1268 (umin:SI (if_then_else:SI
1269 (eq (match_operand:SI 1 "arith_reg_operand" "r")
1270 (const_int 0))
1271 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1272 (match_operand:SI 3 "register_operand" "0"))
1273 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1274 (clobber (match_scratch:SI 5 "=&r"))]
1275 "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1276 "#"
1277 "TARGET_SHMEDIA && reload_completed"
1278 [(pc)]
1279 {
1280 emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1281 operands[3]));
1282 emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1283 emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1284 operands[0]));
1285 DONE;
1286 })
1287
1288 (define_insn "*movsicc_t_false"
1289 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1290 (if_then_else (eq (reg:SI T_REG) (const_int 0))
1291 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1292 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1293 "TARGET_PRETEND_CMOVE
1294 && (arith_reg_operand (operands[1], SImode)
1295 || (immediate_operand (operands[1], SImode)
1296 && satisfies_constraint_I08 (operands[1])))"
1297 "bt 0f\;mov %1,%0\\n0:"
1298 [(set_attr "type" "mt_group,arith") ;; poor approximation
1299 (set_attr "length" "4")])
1300
1301 (define_insn "*movsicc_t_true"
1302 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1303 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1304 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1305 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1306 "TARGET_PRETEND_CMOVE
1307 && (arith_reg_operand (operands[1], SImode)
1308 || (immediate_operand (operands[1], SImode)
1309 && satisfies_constraint_I08 (operands[1])))"
1310 "bf 0f\;mov %1,%0\\n0:"
1311 [(set_attr "type" "mt_group,arith") ;; poor approximation
1312 (set_attr "length" "4")])
1313
1314 (define_expand "movsicc"
1315 [(set (match_operand:SI 0 "arith_reg_dest" "")
1316 (if_then_else:SI (match_operand 1 "comparison_operator" "")
1317 (match_operand:SI 2 "arith_reg_or_0_operand" "")
1318 (match_operand:SI 3 "arith_reg_operand" "")))]
1319 "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1320 {
1321 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1322 && GET_MODE (XEXP (operands[1], 0)) == SImode
1323 && (TARGET_SHMEDIA
1324 || (REG_P (XEXP (operands[1], 0))
1325 && REGNO (XEXP (operands[1], 0)) == T_REG))
1326 && XEXP (operands[1], 1) == const0_rtx)
1327 ;
1328
1329 else if (TARGET_PRETEND_CMOVE)
1330 {
1331 enum rtx_code code = GET_CODE (operands[1]);
1332 enum rtx_code new_code = code;
1333 rtx op0 = XEXP (operands[1], 0);
1334 rtx op1 = XEXP (operands[1], 1);
1335
1336 if (! currently_expanding_to_rtl)
1337 FAIL;
1338 switch (code)
1339 {
1340 case LT: case LE: case LEU: case LTU:
1341 if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1342 break;
1343 case NE:
1344 new_code = reverse_condition (code);
1345 break;
1346 case EQ: case GT: case GE: case GEU: case GTU:
1347 break;
1348 default:
1349 FAIL;
1350 }
1351 sh_emit_scc_to_t (new_code, op0, op1);
1352 operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1353 gen_rtx_REG (SImode, T_REG), const0_rtx);
1354 }
1355 else
1356 {
1357 if (!can_create_pseudo_p ())
1358 FAIL;
1359
1360 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1361 GET_CODE (operands[1]),
1362 XEXP (operands[1], 0),
1363 XEXP (operands[1], 1));
1364 if (!operands[1])
1365 FAIL;
1366 }
1367 })
1368
1369 (define_expand "movqicc"
1370 [(set (match_operand:QI 0 "register_operand" "")
1371 (if_then_else:QI (match_operand 1 "comparison_operator" "")
1372 (match_operand:QI 2 "register_operand" "")
1373 (match_operand:QI 3 "register_operand" "")))]
1374 "TARGET_SHMEDIA"
1375 {
1376 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1377 operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1378 operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1379 emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1380 DONE;
1381 })
1382 \f
1383 ;; -------------------------------------------------------------------------
1384 ;; Addition instructions
1385 ;; -------------------------------------------------------------------------
1386
1387 (define_expand "adddi3"
1388 [(set (match_operand:DI 0 "arith_reg_operand" "")
1389 (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1390 (match_operand:DI 2 "arith_operand" "")))]
1391 ""
1392 {
1393 if (TARGET_SH1)
1394 {
1395 if (!can_create_pseudo_p () && ! arith_reg_operand (operands[2], DImode))
1396 FAIL;
1397 operands[2] = force_reg (DImode, operands[2]);
1398 emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1399 DONE;
1400 }
1401 })
1402
1403 (define_insn "*adddi3_media"
1404 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1405 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1406 (match_operand:DI 2 "arith_operand" "r,I10")))]
1407 "TARGET_SHMEDIA"
1408 "@
1409 add %1, %2, %0
1410 addi %1, %2, %0"
1411 [(set_attr "type" "arith_media")])
1412
1413 (define_insn "*adddisi3_media"
1414 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1415 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1416 (match_operand:DI 2 "arith_operand" "r,I10")))]
1417 "TARGET_SHMEDIA"
1418 "@
1419 add.l %1, %2, %0
1420 addi.l %1, %2, %0"
1421 [(set_attr "type" "arith_media")
1422 (set_attr "highpart" "ignore")])
1423
1424 (define_insn "adddi3z_media"
1425 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1426 (zero_extend:DI
1427 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1428 (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1429 "TARGET_SHMEDIA"
1430 "addz.l %1, %N2, %0"
1431 [(set_attr "type" "arith_media")
1432 (set_attr "highpart" "ignore")])
1433
1434 (define_insn "adddi3_compact"
1435 [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1436 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1437 (match_operand:DI 2 "arith_reg_operand" "r")))
1438 (clobber (reg:SI T_REG))]
1439 "TARGET_SH1"
1440 "#"
1441 [(set_attr "length" "6")])
1442
1443 (define_split
1444 [(set (match_operand:DI 0 "arith_reg_dest" "")
1445 (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1446 (match_operand:DI 2 "arith_reg_operand" "")))
1447 (clobber (reg:SI T_REG))]
1448 "TARGET_SH1 && reload_completed"
1449 [(const_int 0)]
1450 {
1451 rtx high0 = gen_highpart (SImode, operands[0]);
1452 rtx high2 = gen_highpart (SImode, operands[2]);
1453 rtx low0 = gen_lowpart (SImode, operands[0]);
1454
1455 emit_insn (gen_clrt ());
1456 emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
1457 emit_insn (gen_addc1 (high0, high0, high2));
1458 DONE;
1459 })
1460
1461 (define_insn "addc"
1462 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1463 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1464 (match_operand:SI 2 "arith_reg_operand" "r"))
1465 (reg:SI T_REG)))
1466 (set (reg:SI T_REG)
1467 (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1468 "TARGET_SH1"
1469 "addc %2,%0"
1470 [(set_attr "type" "arith")])
1471
1472 (define_insn "addc1"
1473 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1474 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1475 (match_operand:SI 2 "arith_reg_operand" "r"))
1476 (reg:SI T_REG)))
1477 (clobber (reg:SI T_REG))]
1478 "TARGET_SH1"
1479 "addc %2,%0"
1480 [(set_attr "type" "arith")])
1481
1482 (define_expand "addsi3"
1483 [(set (match_operand:SI 0 "arith_reg_operand" "")
1484 (plus:SI (match_operand:SI 1 "arith_operand" "")
1485 (match_operand:SI 2 "arith_operand" "")))]
1486 ""
1487 {
1488 if (TARGET_SHMEDIA)
1489 operands[1] = force_reg (SImode, operands[1]);
1490 })
1491
1492 (define_insn "addsi3_media"
1493 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1494 (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1495 (match_operand:SI 2 "arith_operand" "r,I10")))]
1496 "TARGET_SHMEDIA"
1497 "@
1498 add.l %1, %2, %0
1499 addi.l %1, %2, %0"
1500 [(set_attr "type" "arith_media")
1501 (set_attr "highpart" "ignore")])
1502
1503 (define_insn "addsidi3_media"
1504 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1505 (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
1506 "%r,r")
1507 (match_operand:SI 2 "arith_operand"
1508 "r,I10"))))]
1509 "TARGET_SHMEDIA"
1510 "@
1511 add.l %1, %2, %0
1512 addi.l %1, %2, %0"
1513 [(set_attr "type" "arith_media")
1514 (set_attr "highpart" "ignore")])
1515
1516 (define_insn "*addsi3_compact"
1517 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1518 (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1519 (match_operand:SI 2 "arith_operand" "rI08")))]
1520 "TARGET_SH1"
1521 "add %2,%0"
1522 [(set_attr "type" "arith")])
1523
1524 ;; -------------------------------------------------------------------------
1525 ;; Subtraction instructions
1526 ;; -------------------------------------------------------------------------
1527
1528 (define_expand "subdi3"
1529 [(set (match_operand:DI 0 "arith_reg_operand" "")
1530 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1531 (match_operand:DI 2 "arith_reg_operand" "")))]
1532 ""
1533 {
1534 if (TARGET_SH1)
1535 {
1536 operands[1] = force_reg (DImode, operands[1]);
1537 emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1538 DONE;
1539 }
1540 })
1541
1542 (define_insn "*subdi3_media"
1543 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1544 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1545 (match_operand:DI 2 "arith_reg_operand" "r")))]
1546 "TARGET_SHMEDIA"
1547 "sub %N1, %2, %0"
1548 [(set_attr "type" "arith_media")])
1549
1550 (define_insn "subdisi3_media"
1551 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
1552 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1553 (match_operand:DI 2 "arith_reg_operand" "r")))]
1554 "TARGET_SHMEDIA"
1555 "sub.l %N1, %2, %0"
1556 [(set_attr "type" "arith_media")
1557 (set_attr "highpart" "ignore")])
1558
1559 (define_insn "subdi3_compact"
1560 [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1561 (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1562 (match_operand:DI 2 "arith_reg_operand" "r")))
1563 (clobber (reg:SI T_REG))]
1564 "TARGET_SH1"
1565 "#"
1566 [(set_attr "length" "6")])
1567
1568 (define_split
1569 [(set (match_operand:DI 0 "arith_reg_dest" "")
1570 (minus:DI (match_operand:DI 1 "arith_reg_operand" "")
1571 (match_operand:DI 2 "arith_reg_operand" "")))
1572 (clobber (reg:SI T_REG))]
1573 "TARGET_SH1 && reload_completed"
1574 [(const_int 0)]
1575 {
1576 rtx high0 = gen_highpart (SImode, operands[0]);
1577 rtx high2 = gen_highpart (SImode, operands[2]);
1578 rtx low0 = gen_lowpart (SImode, operands[0]);
1579
1580 emit_insn (gen_clrt ());
1581 emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1582 emit_insn (gen_subc1 (high0, high0, high2));
1583 DONE;
1584 })
1585
1586 (define_insn "subc"
1587 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1588 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1589 (match_operand:SI 2 "arith_reg_operand" "r"))
1590 (reg:SI T_REG)))
1591 (set (reg:SI T_REG)
1592 (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1593 (reg:SI T_REG))
1594 (match_dup 1)))]
1595 "TARGET_SH1"
1596 "subc %2,%0"
1597 [(set_attr "type" "arith")])
1598
1599 (define_insn "subc1"
1600 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1601 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1602 (match_operand:SI 2 "arith_reg_operand" "r"))
1603 (reg:SI T_REG)))
1604 (clobber (reg:SI T_REG))]
1605 "TARGET_SH1"
1606 "subc %2,%0"
1607 [(set_attr "type" "arith")])
1608
1609 ;; life_analysis thinks rn is live before subc rn,rn, so make a special
1610 ;; pattern for this case. This helps multimedia applications that compute
1611 ;; the sum of absolute differences.
1612 (define_insn "mov_neg_si_t"
1613 [(set (match_operand:SI 0 "arith_reg_dest" "=r") (neg:SI (reg:SI T_REG)))]
1614 "TARGET_SH1"
1615 "subc %0,%0"
1616 [(set_attr "type" "arith")])
1617
1618 (define_insn "*subsi3_internal"
1619 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1620 (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1621 (match_operand:SI 2 "arith_reg_operand" "r")))]
1622 "TARGET_SH1"
1623 "sub %2,%0"
1624 [(set_attr "type" "arith")])
1625
1626 (define_insn_and_split "*subsi3_media"
1627 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1628 (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
1629 (match_operand:SI 2 "extend_reg_operand" "r")))]
1630 "TARGET_SHMEDIA
1631 && (operands[1] != constm1_rtx
1632 || (GET_CODE (operands[2]) != TRUNCATE
1633 && GET_CODE (operands[2]) != SUBREG))"
1634 "sub.l %N1, %2, %0"
1635 "operands[1] == constm1_rtx"
1636 [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
1637 ""
1638 [(set_attr "type" "arith_media")
1639 (set_attr "highpart" "ignore")])
1640
1641 (define_split
1642 [(set (match_operand:SI 0 "arith_reg_dest" "")
1643 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1644 "general_extend_operand"
1645 "") 0)) 0)))]
1646 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
1647 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1648 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1649 "")
1650
1651 (define_split
1652 [(set (match_operand:SI 0 "arith_reg_dest" "")
1653 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1654 "general_extend_operand"
1655 "") 0)) 3)))]
1656 "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
1657 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1658 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1659 "")
1660 ;; Convert `constant - reg' to `neg rX; add rX, #const' since this
1661 ;; will sometimes save one instruction. Otherwise we might get
1662 ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
1663 ;; are the same.
1664
1665 (define_expand "subsi3"
1666 [(set (match_operand:SI 0 "arith_reg_operand" "")
1667 (minus:SI (match_operand:SI 1 "arith_operand" "")
1668 (match_operand:SI 2 "arith_reg_operand" "")))]
1669 ""
1670 {
1671 if (TARGET_SH1 && CONST_INT_P (operands[1]))
1672 {
1673 emit_insn (gen_negsi2 (operands[0], operands[2]));
1674 emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
1675 DONE;
1676 }
1677 if (TARGET_SHMEDIA)
1678 {
1679 if (!can_create_pseudo_p ()
1680 && ! arith_reg_or_0_operand (operands[1], SImode))
1681 FAIL;
1682 if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
1683 operands[1] = force_reg (SImode, operands[1]);
1684 }
1685 })
1686 \f
1687 ;; -------------------------------------------------------------------------
1688 ;; Division instructions
1689 ;; -------------------------------------------------------------------------
1690
1691 ;; We take advantage of the library routines which don't clobber as many
1692 ;; registers as a normal function call would.
1693
1694 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
1695 ;; also has an effect on the register that holds the address of the sfunc.
1696 ;; To make this work, we have an extra dummy insn that shows the use
1697 ;; of this register for reorg.
1698
1699 (define_insn "use_sfunc_addr"
1700 [(set (reg:SI PR_REG)
1701 (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
1702 "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
1703 ""
1704 [(set_attr "length" "0")])
1705
1706 (define_insn "udivsi3_sh2a"
1707 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1708 (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
1709 (match_operand:SI 2 "arith_reg_operand" "z")))]
1710 "TARGET_SH2A"
1711 "divu %2,%1"
1712 [(set_attr "type" "arith")
1713 (set_attr "in_delay_slot" "no")])
1714
1715 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
1716 ;; hard register 0. If we used hard register 0, then the next instruction
1717 ;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg
1718 ;; gets allocated to a stack slot that needs its address reloaded, then
1719 ;; there is nothing to prevent reload from using r0 to reload the address.
1720 ;; This reload would clobber the value in r0 we are trying to store.
1721 ;; If we let reload allocate r0, then this problem can never happen.
1722
1723 (define_insn "udivsi3_i1"
1724 [(set (match_operand:SI 0 "register_operand" "=z")
1725 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1726 (clobber (reg:SI T_REG))
1727 (clobber (reg:SI PR_REG))
1728 (clobber (reg:SI R4_REG))
1729 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1730 "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
1731 "jsr @%1%#"
1732 [(set_attr "type" "sfunc")
1733 (set_attr "needs_delay_slot" "yes")])
1734
1735 ; Since shmedia-nofpu code could be linked against shcompact code, and
1736 ; the udivsi3 libcall has the same name, we must consider all registers
1737 ; clobbered that are in the union of the registers clobbered by the
1738 ; shmedia and the shcompact implementation. Note, if the shcompact
1739 ; implementation actually used shcompact code, we'd need to clobber
1740 ; also r23 and fr23.
1741 (define_insn "udivsi3_i1_media"
1742 [(set (match_operand:SI 0 "register_operand" "=z")
1743 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1744 (clobber (reg:SI T_MEDIA_REG))
1745 (clobber (reg:SI PR_MEDIA_REG))
1746 (clobber (reg:SI R20_REG))
1747 (clobber (reg:SI R21_REG))
1748 (clobber (reg:SI R22_REG))
1749 (clobber (reg:DI TR0_REG))
1750 (clobber (reg:DI TR1_REG))
1751 (clobber (reg:DI TR2_REG))
1752 (use (match_operand 1 "target_reg_operand" "b"))]
1753 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1754 "blink %1, r18"
1755 [(set_attr "type" "sfunc")
1756 (set_attr "needs_delay_slot" "yes")])
1757
1758 (define_expand "udivsi3_i4_media"
1759 [(set (match_dup 3)
1760 (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
1761 (set (match_dup 4)
1762 (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1763 (set (match_dup 5) (float:DF (match_dup 3)))
1764 (set (match_dup 6) (float:DF (match_dup 4)))
1765 (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
1766 (set (match_dup 8) (fix:DI (match_dup 7)))
1767 (set (match_operand:SI 0 "register_operand" "")
1768 (truncate:SI (match_dup 8)))]
1769 "TARGET_SHMEDIA_FPU"
1770 {
1771 operands[3] = gen_reg_rtx (DImode);
1772 operands[4] = gen_reg_rtx (DImode);
1773 operands[5] = gen_reg_rtx (DFmode);
1774 operands[6] = gen_reg_rtx (DFmode);
1775 operands[7] = gen_reg_rtx (DFmode);
1776 operands[8] = gen_reg_rtx (DImode);
1777 })
1778
1779 (define_insn "udivsi3_i4"
1780 [(set (match_operand:SI 0 "register_operand" "=y")
1781 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1782 (clobber (reg:SI T_REG))
1783 (clobber (reg:SI PR_REG))
1784 (clobber (reg:DF DR0_REG))
1785 (clobber (reg:DF DR2_REG))
1786 (clobber (reg:DF DR4_REG))
1787 (clobber (reg:SI R0_REG))
1788 (clobber (reg:SI R1_REG))
1789 (clobber (reg:SI R4_REG))
1790 (clobber (reg:SI R5_REG))
1791 (use (reg:PSI FPSCR_REG))
1792 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1793 "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1794 "jsr @%1%#"
1795 [(set_attr "type" "sfunc")
1796 (set_attr "fp_mode" "double")
1797 (set_attr "needs_delay_slot" "yes")])
1798
1799 (define_insn "udivsi3_i4_single"
1800 [(set (match_operand:SI 0 "register_operand" "=y")
1801 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1802 (clobber (reg:SI T_REG))
1803 (clobber (reg:SI PR_REG))
1804 (clobber (reg:DF DR0_REG))
1805 (clobber (reg:DF DR2_REG))
1806 (clobber (reg:DF DR4_REG))
1807 (clobber (reg:SI R0_REG))
1808 (clobber (reg:SI R1_REG))
1809 (clobber (reg:SI R4_REG))
1810 (clobber (reg:SI R5_REG))
1811 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1812 "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1813 "jsr @%1%#"
1814 [(set_attr "type" "sfunc")
1815 (set_attr "needs_delay_slot" "yes")])
1816
1817 (define_insn "udivsi3_i4_int"
1818 [(set (match_operand:SI 0 "register_operand" "=z")
1819 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1820 (clobber (reg:SI T_REG))
1821 (clobber (reg:SI R1_REG))
1822 (clobber (reg:SI PR_REG))
1823 (clobber (reg:SI MACH_REG))
1824 (clobber (reg:SI MACL_REG))
1825 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1826 "TARGET_SH1"
1827 "jsr @%1%#"
1828 [(set_attr "type" "sfunc")
1829 (set_attr "needs_delay_slot" "yes")])
1830
1831
1832 (define_expand "udivsi3"
1833 [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
1834 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1835 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1836 (parallel [(set (match_operand:SI 0 "register_operand" "")
1837 (udiv:SI (reg:SI R4_REG)
1838 (reg:SI R5_REG)))
1839 (clobber (reg:SI T_REG))
1840 (clobber (reg:SI PR_REG))
1841 (clobber (reg:SI R4_REG))
1842 (use (match_dup 3))])]
1843 ""
1844 {
1845 rtx last;
1846
1847 operands[3] = gen_reg_rtx (Pmode);
1848 /* Emit the move of the address to a pseudo outside of the libcall. */
1849 if (TARGET_DIVIDE_CALL_TABLE)
1850 {
1851 /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
1852 that causes problems when the divide code is supposed to come from a
1853 separate library. Division by zero is undefined, so dividing 1 can be
1854 implemented by comparing with the divisor. */
1855 if (operands[1] == const1_rtx && currently_expanding_to_rtl)
1856 {
1857 rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
1858 emit_insn (gen_cstoresi4 (operands[0], test,
1859 operands[1], operands[2]));
1860 DONE;
1861 }
1862 else if (operands[2] == const0_rtx)
1863 {
1864 emit_move_insn (operands[0], operands[2]);
1865 DONE;
1866 }
1867 function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT);
1868 last = gen_udivsi3_i4_int (operands[0], operands[3]);
1869 }
1870 else if (TARGET_DIVIDE_CALL_FP)
1871 {
1872 function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC);
1873 if (TARGET_FPU_SINGLE)
1874 last = gen_udivsi3_i4_single (operands[0], operands[3]);
1875 else
1876 last = gen_udivsi3_i4 (operands[0], operands[3]);
1877 }
1878 else if (TARGET_SHMEDIA_FPU)
1879 {
1880 operands[1] = force_reg (SImode, operands[1]);
1881 operands[2] = force_reg (SImode, operands[2]);
1882 emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
1883 DONE;
1884 }
1885 else if (TARGET_SH2A)
1886 {
1887 operands[1] = force_reg (SImode, operands[1]);
1888 operands[2] = force_reg (SImode, operands[2]);
1889 emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
1890 DONE;
1891 }
1892 else if (TARGET_SH5)
1893 {
1894 function_symbol (operands[3],
1895 TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3",
1896 SFUNC_STATIC);
1897
1898 if (TARGET_SHMEDIA)
1899 last = gen_udivsi3_i1_media (operands[0], operands[3]);
1900 else if (TARGET_FPU_ANY)
1901 last = gen_udivsi3_i4_single (operands[0], operands[3]);
1902 else
1903 last = gen_udivsi3_i1 (operands[0], operands[3]);
1904 }
1905 else
1906 {
1907 function_symbol (operands[3], "__udivsi3", SFUNC_STATIC);
1908 last = gen_udivsi3_i1 (operands[0], operands[3]);
1909 }
1910 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1911 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1912 emit_insn (last);
1913 DONE;
1914 })
1915
1916 (define_insn "divsi3_sh2a"
1917 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1918 (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
1919 (match_operand:SI 2 "arith_reg_operand" "z")))]
1920 "TARGET_SH2A"
1921 "divs %2,%1"
1922 [(set_attr "type" "arith")
1923 (set_attr "in_delay_slot" "no")])
1924
1925 (define_insn "divsi3_i1"
1926 [(set (match_operand:SI 0 "register_operand" "=z")
1927 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1928 (clobber (reg:SI T_REG))
1929 (clobber (reg:SI PR_REG))
1930 (clobber (reg:SI R1_REG))
1931 (clobber (reg:SI R2_REG))
1932 (clobber (reg:SI R3_REG))
1933 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1934 "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
1935 "jsr @%1%#"
1936 [(set_attr "type" "sfunc")
1937 (set_attr "needs_delay_slot" "yes")])
1938
1939 (define_insn "divsi3_i1_media"
1940 [(set (match_operand:SI 0 "register_operand" "=z")
1941 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1942 (clobber (reg:SI T_MEDIA_REG))
1943 (clobber (reg:SI PR_MEDIA_REG))
1944 (clobber (reg:SI R1_REG))
1945 (clobber (reg:SI R20_REG))
1946 (clobber (reg:SI R21_REG))
1947 (clobber (reg:SI TR0_REG))
1948 (use (match_operand 1 "target_reg_operand" "b"))]
1949 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1950 "blink %1, r18"
1951 [(set_attr "type" "sfunc")])
1952
1953 (define_insn "divsi3_media_2"
1954 [(set (match_operand:SI 0 "register_operand" "=z")
1955 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1956 (clobber (reg:SI T_MEDIA_REG))
1957 (clobber (reg:SI PR_MEDIA_REG))
1958 (clobber (reg:SI R1_REG))
1959 (clobber (reg:SI R21_REG))
1960 (clobber (reg:SI TR0_REG))
1961 (use (reg:SI R20_REG))
1962 (use (match_operand 1 "target_reg_operand" "b"))]
1963 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1964 "blink %1, r18"
1965 [(set_attr "type" "sfunc")])
1966
1967 ;; This pattern acts as a placeholder for -mdiv=inv:call to carry
1968 ;; hard reg clobbers and data dependencies that we need when we want
1969 ;; to rematerialize the division into a call.
1970 (define_insn_and_split "divsi_inv_call"
1971 [(set (match_operand:SI 0 "register_operand" "=r")
1972 (div:SI (match_operand:SI 1 "register_operand" "r")
1973 (match_operand:SI 2 "register_operand" "r")))
1974 (clobber (reg:SI R4_REG))
1975 (clobber (reg:SI R5_REG))
1976 (clobber (reg:SI T_MEDIA_REG))
1977 (clobber (reg:SI PR_MEDIA_REG))
1978 (clobber (reg:SI R1_REG))
1979 (clobber (reg:SI R21_REG))
1980 (clobber (reg:SI TR0_REG))
1981 (clobber (reg:SI R20_REG))
1982 (use (match_operand:SI 3 "register_operand" "r"))]
1983 "TARGET_SHMEDIA"
1984 "#"
1985 "&& (reload_in_progress || reload_completed)"
1986 [(set (match_dup 0) (match_dup 3))]
1987 ""
1988 [(set_attr "highpart" "must_split")])
1989
1990 ;; This is the combiner pattern for -mdiv=inv:call .
1991 (define_insn_and_split "*divsi_inv_call_combine"
1992 [(set (match_operand:SI 0 "register_operand" "=z")
1993 (div:SI (match_operand:SI 1 "register_operand" "r")
1994 (match_operand:SI 2 "register_operand" "r")))
1995 (clobber (reg:SI R4_REG))
1996 (clobber (reg:SI R5_REG))
1997 (clobber (reg:SI T_MEDIA_REG))
1998 (clobber (reg:SI PR_MEDIA_REG))
1999 (clobber (reg:SI R1_REG))
2000 (clobber (reg:SI R21_REG))
2001 (clobber (reg:SI TR0_REG))
2002 (clobber (reg:SI R20_REG))
2003 (use (unspec:SI [(match_dup 1)
2004 (match_operand:SI 3 "" "")
2005 (unspec:SI [(match_operand:SI 4 "" "")
2006 (match_dup 3)
2007 (match_operand:DI 5 "" "")]
2008 UNSPEC_DIV_INV_M2)
2009 (match_operand:DI 6 "" "")
2010 (const_int 0)
2011 (const_int 0)]
2012 UNSPEC_DIV_INV_M3))]
2013 "TARGET_SHMEDIA"
2014 "#"
2015 "&& (reload_in_progress || reload_completed)"
2016 [(pc)]
2017 {
2018 const char *name = sh_divsi3_libfunc;
2019 enum sh_function_kind kind = SFUNC_GOT;
2020 rtx sym;
2021
2022 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2023 emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2024 while (TARGET_DIVIDE_INV_CALL2)
2025 {
2026 rtx x = operands[3];
2027
2028 if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2029 break;
2030 x = XVECEXP (x, 0, 0);
2031 name = "__sdivsi3_2";
2032 kind = SFUNC_STATIC;
2033 emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2034 break;
2035 }
2036 sym = function_symbol (NULL, name, kind);
2037 emit_insn (gen_divsi3_media_2 (operands[0], sym));
2038 DONE;
2039 }
2040 [(set_attr "highpart" "must_split")])
2041
2042 (define_expand "divsi3_i4_media"
2043 [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2044 (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2045 (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2046 (set (match_operand:SI 0 "register_operand" "=r")
2047 (fix:SI (match_dup 5)))]
2048 "TARGET_SHMEDIA_FPU"
2049 {
2050 operands[3] = gen_reg_rtx (DFmode);
2051 operands[4] = gen_reg_rtx (DFmode);
2052 operands[5] = gen_reg_rtx (DFmode);
2053 })
2054
2055 (define_insn "divsi3_i4"
2056 [(set (match_operand:SI 0 "register_operand" "=y")
2057 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2058 (clobber (reg:SI PR_REG))
2059 (clobber (reg:DF DR0_REG))
2060 (clobber (reg:DF DR2_REG))
2061 (use (reg:PSI FPSCR_REG))
2062 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2063 "TARGET_SH4 && ! TARGET_FPU_SINGLE"
2064 "jsr @%1%#"
2065 [(set_attr "type" "sfunc")
2066 (set_attr "fp_mode" "double")
2067 (set_attr "needs_delay_slot" "yes")])
2068
2069 (define_insn "divsi3_i4_single"
2070 [(set (match_operand:SI 0 "register_operand" "=y")
2071 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2072 (clobber (reg:SI PR_REG))
2073 (clobber (reg:DF DR0_REG))
2074 (clobber (reg:DF DR2_REG))
2075 (clobber (reg:SI R2_REG))
2076 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2077 "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
2078 "jsr @%1%#"
2079 [(set_attr "type" "sfunc")
2080 (set_attr "needs_delay_slot" "yes")])
2081
2082 (define_insn "divsi3_i4_int"
2083 [(set (match_operand:SI 0 "register_operand" "=z")
2084 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2085 (clobber (reg:SI T_REG))
2086 (clobber (reg:SI PR_REG))
2087 (clobber (reg:SI R1_REG))
2088 (clobber (reg:SI MACH_REG))
2089 (clobber (reg:SI MACL_REG))
2090 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2091 "TARGET_SH1"
2092 "jsr @%1%#"
2093 [(set_attr "type" "sfunc")
2094 (set_attr "needs_delay_slot" "yes")])
2095
2096 (define_expand "divsi3"
2097 [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2098 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2099 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2100 (parallel [(set (match_operand:SI 0 "register_operand" "")
2101 (div:SI (reg:SI R4_REG)
2102 (reg:SI R5_REG)))
2103 (clobber (reg:SI T_REG))
2104 (clobber (reg:SI PR_REG))
2105 (clobber (reg:SI R1_REG))
2106 (clobber (reg:SI R2_REG))
2107 (clobber (reg:SI R3_REG))
2108 (use (match_dup 3))])]
2109 ""
2110 {
2111 rtx last;
2112
2113 operands[3] = gen_reg_rtx (Pmode);
2114 /* Emit the move of the address to a pseudo outside of the libcall. */
2115 if (TARGET_DIVIDE_CALL_TABLE)
2116 {
2117 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2118 last = gen_divsi3_i4_int (operands[0], operands[3]);
2119 }
2120 else if (TARGET_DIVIDE_CALL_FP)
2121 {
2122 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2123 if (TARGET_FPU_SINGLE)
2124 last = gen_divsi3_i4_single (operands[0], operands[3]);
2125 else
2126 last = gen_divsi3_i4 (operands[0], operands[3]);
2127 }
2128 else if (TARGET_SH2A)
2129 {
2130 operands[1] = force_reg (SImode, operands[1]);
2131 operands[2] = force_reg (SImode, operands[2]);
2132 emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2133 DONE;
2134 }
2135 else if (TARGET_DIVIDE_INV)
2136 {
2137 rtx dividend = operands[1];
2138 rtx divisor = operands[2];
2139 rtx tab_base;
2140 rtx nsb_res = gen_reg_rtx (DImode);
2141 rtx norm64 = gen_reg_rtx (DImode);
2142 rtx tab_ix = gen_reg_rtx (DImode);
2143 rtx norm32 = gen_reg_rtx (SImode);
2144 rtx i92 = force_reg (DImode, GEN_INT (92));
2145 rtx scratch0a = gen_reg_rtx (DImode);
2146 rtx scratch0b = gen_reg_rtx (DImode);
2147 rtx inv0 = gen_reg_rtx (SImode);
2148 rtx scratch1a = gen_reg_rtx (DImode);
2149 rtx scratch1b = gen_reg_rtx (DImode);
2150 rtx shift = gen_reg_rtx (DImode);
2151 rtx i2p27, i43;
2152 rtx inv1 = gen_reg_rtx (SImode);
2153 rtx scratch2a = gen_reg_rtx (DImode);
2154 rtx scratch2b = gen_reg_rtx (SImode);
2155 rtx inv2 = gen_reg_rtx (SImode);
2156 rtx scratch3a = gen_reg_rtx (DImode);
2157 rtx scratch3b = gen_reg_rtx (DImode);
2158 rtx scratch3c = gen_reg_rtx (DImode);
2159 rtx scratch3d = gen_reg_rtx (SImode);
2160 rtx scratch3e = gen_reg_rtx (DImode);
2161 rtx result = gen_reg_rtx (SImode);
2162
2163 if (! arith_reg_or_0_operand (dividend, SImode))
2164 dividend = force_reg (SImode, dividend);
2165 if (! arith_reg_operand (divisor, SImode))
2166 divisor = force_reg (SImode, divisor);
2167 if (flag_pic && Pmode != DImode)
2168 {
2169 tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2170 tab_base = gen_datalabel_ref (tab_base);
2171 tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2172 }
2173 else
2174 {
2175 tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table");
2176 tab_base = gen_datalabel_ref (tab_base);
2177 tab_base = force_reg (DImode, tab_base);
2178 }
2179 if (TARGET_DIVIDE_INV20U)
2180 i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2181 else
2182 i2p27 = GEN_INT (0);
2183 if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2184 i43 = force_reg (DImode, GEN_INT (43));
2185 else
2186 i43 = GEN_INT (0);
2187 emit_insn (gen_nsbdi (nsb_res,
2188 simplify_gen_subreg (DImode, divisor, SImode, 0)));
2189 emit_insn (gen_ashldi3_media (norm64,
2190 gen_rtx_SUBREG (DImode, divisor, 0),
2191 nsb_res));
2192 emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2193 emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2194 emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2195 inv0, scratch0a, scratch0b,
2196 scratch1a, scratch1b));
2197 emit_insn (gen_subdi3 (shift, i92, nsb_res));
2198 emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2199 scratch2a));
2200 emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2201 i2p27, i43,
2202 scratch3a, scratch3b, scratch3c,
2203 scratch2a, scratch2b, scratch3d, scratch3e));
2204 if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2205 emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2206 else if (TARGET_DIVIDE_INV_FP)
2207 emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2208 gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2209 gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2210 gen_reg_rtx (DFmode)));
2211 else
2212 emit_move_insn (operands[0], result);
2213 DONE;
2214 }
2215 else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2216 {
2217 operands[1] = force_reg (SImode, operands[1]);
2218 operands[2] = force_reg (SImode, operands[2]);
2219 emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2220 DONE;
2221 }
2222 else if (TARGET_SH5)
2223 {
2224 if (TARGET_DIVIDE_CALL2)
2225 {
2226 rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2227 tab_base = gen_datalabel_ref (tab_base);
2228 emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2229 }
2230 if (TARGET_FPU_ANY && TARGET_SH1)
2231 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2232 else if (TARGET_DIVIDE_CALL2)
2233 function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC);
2234 else
2235 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2236
2237 if (TARGET_SHMEDIA)
2238 last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2239 (operands[0], operands[3]));
2240 else if (TARGET_FPU_ANY)
2241 last = gen_divsi3_i4_single (operands[0], operands[3]);
2242 else
2243 last = gen_divsi3_i1 (operands[0], operands[3]);
2244 }
2245 else
2246 {
2247 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2248 last = gen_divsi3_i1 (operands[0], operands[3]);
2249 }
2250 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2251 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2252 emit_insn (last);
2253 DONE;
2254 })
2255
2256 ;; operands: scratch, tab_base, tab_ix
2257 ;; These are unspecs because we could generate an indexed addressing mode
2258 ;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2259 ;; confuse reload. See PR27117.
2260
2261 (define_insn "divsi_inv_qitable"
2262 [(set (match_operand:DI 0 "register_operand" "=r")
2263 (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2264 (match_operand:DI 2 "register_operand" "r")]
2265 UNSPEC_DIV_INV_TABLE)))]
2266 "TARGET_SHMEDIA"
2267 "@
2268 ldx.ub %1, %2, %0"
2269 [(set_attr "type" "load_media")
2270 (set_attr "highpart" "user")])
2271
2272 ;; operands: scratch, tab_base, tab_ix
2273 (define_insn "divsi_inv_hitable"
2274 [(set (match_operand:DI 0 "register_operand" "=r")
2275 (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2276 (match_operand:DI 2 "register_operand" "r")]
2277 UNSPEC_DIV_INV_TABLE)))]
2278 "TARGET_SHMEDIA"
2279 "@
2280 ldx.w %1, %2, %0"
2281 [(set_attr "type" "load_media")
2282 (set_attr "highpart" "user")])
2283
2284 ;; operands: inv0, tab_base, tab_ix, norm32
2285 ;; scratch equiv in sdivsi3_2: r19, r21
2286 (define_expand "divsi_inv_m0"
2287 [(set (match_operand:SI 0 "register_operand" "=r")
2288 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2289 (match_operand:DI 2 "register_operand" "r")
2290 (match_operand:SI 3 "register_operand" "r")]
2291 UNSPEC_DIV_INV_M0))
2292 (clobber (match_operand:DI 4 "register_operand" "=r"))
2293 (clobber (match_operand:DI 5 "register_operand" "=r"))]
2294 "TARGET_SHMEDIA"
2295 {
2296 /*
2297 tab_base: r20
2298 tab_ix: r21
2299 norm32: r25
2300 ldx.ub r20, r21, r19 // u0.8
2301 shlli r21, 1, r21
2302 muls.l r25, r19, r19 // s2.38
2303 ldx.w r20, r21, r21 // s2.14
2304 shari r19, 24, r19 // truncate to s2.14
2305 sub r21, r19, r19 // some 11 bit inverse in s1.14
2306 */
2307
2308 rtx inv0 = operands[0];
2309 rtx tab_base = operands[1];
2310 rtx tab_ix = operands[2];
2311 rtx norm32 = operands[3];
2312 rtx scratch0 = operands[4];
2313 rtx scratch0_si = gen_lowpart (SImode, scratch0);
2314 rtx scratch1 = operands[5];
2315
2316 emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2317 emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2318 emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2319 emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2320 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2321 emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2322 DONE;
2323 })
2324
2325 ;; operands: inv1, tab_base, tab_ix, norm32
2326 (define_insn_and_split "divsi_inv_m1"
2327 [(set (match_operand:SI 0 "register_operand" "=r")
2328 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2329 (match_operand:DI 2 "register_operand" "r")
2330 (match_operand:SI 3 "register_operand" "r")]
2331 UNSPEC_DIV_INV_M1))
2332 (clobber (match_operand:SI 4 "register_operand" "=r"))
2333 (clobber (match_operand:DI 5 "register_operand" "=r"))
2334 (clobber (match_operand:DI 6 "register_operand" "=r"))
2335 (clobber (match_operand:DI 7 "register_operand" "=r"))
2336 (clobber (match_operand:DI 8 "register_operand" "=r"))]
2337 "TARGET_SHMEDIA"
2338 "#"
2339 "&& !can_create_pseudo_p ()"
2340 [(pc)]
2341 {
2342 /* inv0: r19
2343 muls.l r19, r19, r18 // u0.28
2344 muls.l r25, r18, r18 // s2.58
2345 shlli r19, 45, r0 // multiply by two and convert to s2.58
2346 sub r0, r18, r18
2347 shari r18, 28, r18 // some 18 bit inverse in s1.30
2348 */
2349
2350 rtx inv1 = operands[0];
2351 rtx tab_base = operands[1];
2352 rtx tab_ix = operands[2];
2353 rtx norm32 = operands[3];
2354 rtx inv0 = operands[4];
2355 rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2356 rtx scratch0a = operands[5];
2357 rtx scratch0b = operands[6];
2358 rtx scratch0 = operands[7];
2359 rtx scratch1 = operands[8];
2360 rtx scratch1_si = gen_lowpart (SImode, scratch1);
2361
2362 emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2363 scratch0a, scratch0b));
2364 emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2365 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2366 emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2367 emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2368 emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2369 DONE;
2370 })
2371
2372 ;; operands: inv2, norm32, inv1, i92
2373 (define_insn_and_split "divsi_inv_m2"
2374 [(set (match_operand:SI 0 "register_operand" "=r")
2375 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2376 (match_operand:SI 2 "register_operand" "r")
2377 (match_operand:DI 3 "register_operand" "r")]
2378 UNSPEC_DIV_INV_M2))
2379 (clobber (match_operand:DI 4 "register_operand" "=r"))]
2380 "TARGET_SHMEDIA"
2381 "#"
2382 "&& !can_create_pseudo_p ()"
2383 [(pc)]
2384 {
2385 /*
2386 muls.l r18, r25, r0 // s2.60
2387 shari r0, 16, r0 // s-16.44
2388 sub
2389 muls.l r0, r18, r19 // s-16.74
2390 shari r19, 30, r19 // s-16.44
2391 */
2392 rtx inv2 = operands[0];
2393 rtx norm32 = operands[1];
2394 rtx inv1 = operands[2];
2395 rtx i92 = operands[3];
2396 rtx scratch0 = operands[4];
2397 rtx scratch0_si = gen_lowpart (SImode, scratch0);
2398
2399 emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2400 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2401 emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2402 emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2403 emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2404 DONE;
2405 })
2406
2407 (define_insn_and_split "divsi_inv_m3"
2408 [(set (match_operand:SI 0 "register_operand" "=r")
2409 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2410 (match_operand:SI 2 "register_operand" "r")
2411 (match_operand:SI 3 "register_operand" "r")
2412 (match_operand:DI 4 "register_operand" "r")
2413 (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
2414 (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
2415 UNSPEC_DIV_INV_M3))
2416 (clobber (match_operand:DI 7 "register_operand" "=r"))
2417 (clobber (match_operand:DI 8 "register_operand" "=r"))
2418 (clobber (match_operand:DI 9 "register_operand" "=r"))
2419 (clobber (match_operand:DI 10 "register_operand" "=r"))
2420 (clobber (match_operand:SI 11 "register_operand" "=r"))
2421 (clobber (match_operand:SI 12 "register_operand" "=r"))
2422 (clobber (match_operand:DI 13 "register_operand" "=r"))]
2423 "TARGET_SHMEDIA"
2424 "#"
2425 "&& !can_create_pseudo_p ()"
2426 [(pc)]
2427 {
2428 /*
2429 r0: result r1: shift r4: dividend r18: inv1 r19: inv2
2430 r0: scratch0 r19: scratch1 r21: scratch2
2431
2432 muls.l r18, r4, r25 // s32.30
2433 muls.l r19, r4, r19 // s15.30
2434 shari r25, 63, r21
2435 shari r19, 14, r19 // s18.-14
2436 sub r25, r19, r0
2437 shard r0, r1, r0
2438 sub r0, r21, r0
2439 */
2440
2441 rtx result = operands[0];
2442 rtx dividend = operands[1];
2443 rtx inv1 = operands[2];
2444 rtx inv2 = operands[3];
2445 rtx shift = operands[4];
2446 rtx scratch0 = operands[7];
2447 rtx scratch1 = operands[8];
2448 rtx scratch2 = operands[9];
2449
2450 if (satisfies_constraint_N (dividend))
2451 {
2452 emit_move_insn (result, dividend);
2453 DONE;
2454 }
2455
2456 emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
2457 emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
2458 emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
2459 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
2460 emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
2461 emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
2462 emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
2463 DONE;
2464 })
2465
2466 ;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
2467 ;; inv1: tab_base, tab_ix, norm32
2468 ;; inv2: norm32, inv1, i92
2469 (define_insn_and_split "divsi_inv_m1_3"
2470 [(set (match_operand:SI 0 "register_operand" "=r")
2471 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2472 (unspec:SI [(match_operand:DI 2 "register_operand" "r")
2473 (match_operand:DI 3 "register_operand" "r")
2474 (match_operand:SI 4 "register_operand" "r")]
2475 UNSPEC_DIV_INV_M1)
2476 (unspec:SI [(match_dup 4)
2477 (unspec:SI [(match_dup 2)
2478 (match_dup 3)
2479 (match_dup 4)] UNSPEC_DIV_INV_M1)
2480 (match_operand:SI 5 "" "")]
2481 UNSPEC_DIV_INV_M2)
2482 (match_operand:DI 6 "register_operand" "r")
2483 (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
2484 (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
2485 UNSPEC_DIV_INV_M3))
2486 (clobber (match_operand:DI 9 "register_operand" "=r"))
2487 (clobber (match_operand:DI 10 "register_operand" "=r"))
2488 (clobber (match_operand:DI 11 "register_operand" "=r"))
2489 (clobber (match_operand:DI 12 "register_operand" "=r"))
2490 (clobber (match_operand:SI 13 "register_operand" "=r"))
2491 (clobber (match_operand:SI 14 "register_operand" "=r"))
2492 (clobber (match_operand:DI 15 "register_operand" "=r"))]
2493 "TARGET_SHMEDIA
2494 && (TARGET_DIVIDE_INV_MINLAT
2495 || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2496 "#"
2497 "&& !can_create_pseudo_p ()"
2498 [(pc)]
2499 {
2500 rtx result = operands[0];
2501 rtx dividend = operands[1];
2502 rtx tab_base = operands[2];
2503 rtx tab_ix = operands[3];
2504 rtx norm32 = operands[4];
2505 /* rtx i92 = operands[5]; */
2506 rtx shift = operands[6];
2507 rtx i2p27 = operands[7];
2508 rtx i43 = operands[8];
2509 rtx scratch0 = operands[9];
2510 rtx scratch0_si = gen_lowpart (SImode, scratch0);
2511 rtx scratch1 = operands[10];
2512 rtx scratch1_si = gen_lowpart (SImode, scratch1);
2513 rtx scratch2 = operands[11];
2514 rtx scratch3 = operands[12];
2515 rtx scratch4 = operands[13];
2516 rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
2517 rtx scratch5 = operands[14];
2518 rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
2519 rtx scratch6 = operands[15];
2520
2521 emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
2522 scratch0, scratch1));
2523 /* inv0 == scratch4 */
2524 if (! TARGET_DIVIDE_INV20U)
2525 {
2526 emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
2527 i2p27 = scratch0;
2528 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
2529 }
2530 else
2531 {
2532 emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
2533 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2534 }
2535 emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
2536 emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
2537 emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
2538 /* inv1 == scratch4 */
2539
2540 if (TARGET_DIVIDE_INV_MINLAT)
2541 {
2542 emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
2543 emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
2544 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
2545 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
2546 emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
2547 emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
2548 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
2549 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
2550 emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
2551 emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
2552 emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
2553 }
2554 else
2555 {
2556 rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
2557 /* Use separate scratch regs for nsb and sign to allow scheduling. */
2558 emit_insn (gen_nsbdi (scratch6,
2559 simplify_gen_subreg (DImode, dividend, SImode, 0)));
2560 emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
2561 emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
2562 emit_insn (gen_divsi_inv20 (scratch2,
2563 norm32, scratch4, dividend,
2564 scratch6, scratch3, i43,
2565 /* scratch0 may be shared with i2p27. */
2566 scratch0, scratch1, scratch5,
2567 label, label, i2p27));
2568 }
2569 emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
2570 emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
2571 DONE;
2572 })
2573
2574 (define_insn "divsi_inv20"
2575 [(set (match_operand:DI 0 "register_operand" "=&r")
2576 (unspec:DI [(match_operand:SI 1 "register_operand" "r")
2577 (match_operand:SI 2 "register_operand" "r")
2578 (match_operand:SI 3 "register_operand" "r")
2579 (match_operand:DI 4 "register_operand" "r")
2580 (match_operand:DI 5 "register_operand" "r")
2581 (match_operand:DI 6 "register_operand" "r")
2582 (match_operand:DI 12 "register_operand" "r")
2583 (match_operand 10 "target_operand" "b")
2584 (match_operand 11 "immediate_operand" "i")]
2585 UNSPEC_DIV_INV20))
2586 (clobber (match_operand:DI 7 "register_operand" "=&r"))
2587 (clobber (match_operand:DI 8 "register_operand" "=&r"))
2588 (clobber (match_operand:SI 9 "register_operand" "=r"))]
2589 "TARGET_SHMEDIA
2590 && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2591 {
2592 /* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
2593 %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
2594 %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
2595 %10 label (tr), %11 label (imm)
2596
2597 muls.l inv1, norm32, scratch0 // s2.60
2598 muls.l inv1, dividend, result // s32.30
2599 xor i2p27, result_sign, round_scratch
2600 bge/u dividend_nsb, i43, tr.. (label)
2601 shari scratch0, 16, scratch0 // s-16.44
2602 muls.l sratch0_si, inv1, scratch0 // s-16.74
2603 sub result, round_scratch, result
2604 shari dividend, 14, scratch1 // s19.-14
2605 shari scratch0, 30, scratch0 // s-16.44
2606 muls.l scratch0, scratch1, round_scratch // s15.30
2607 label:
2608 sub result, round_scratch, result */
2609
2610 int likely = TARGET_DIVIDE_INV20L;
2611
2612 if (! likely) output_asm_insn ("muls.l\t%2, %1 , %8", operands);
2613 output_asm_insn ("muls.l\t%2, %3, %0\;xor\t%12, %5, %7", operands);
2614 output_asm_insn (likely
2615 ? "bge/l\t%4, %6, %10\;muls.l\t%2, %1 , %8"
2616 : "bge/u\t%4, %6, %10", operands);
2617 output_asm_insn ("shari\t%8, 16, %8\;muls.l\t%8, %2, %8", operands);
2618 if (! likely) output_asm_insn ("sub\t%0, %7, %0", operands);
2619 output_asm_insn ("shari\t%3, 14, %9\;shari\t%8, 30, %8", operands);
2620 return (likely
2621 ? "muls.l\t%8, %9, %8\;sub\t%0, %8, %0\n%11:\tadd\t%0, %7, %0"
2622 : "muls.l\t%8, %9, %7\n%11:\tsub\t%0, %7, %0");
2623 })
2624
2625 (define_insn_and_split "divsi_inv_fp"
2626 [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
2627 (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
2628 (match_operand:SI 2 "register_operand" "rf")))
2629 (use (match_operand:SI 3 "general_movsrc_operand" "r"))
2630 (clobber (match_operand:SI 4 "register_operand" "=r"))
2631 (clobber (match_operand:SI 5 "register_operand" "=r"))
2632 (clobber (match_operand:DF 6 "register_operand" "=r"))
2633 (clobber (match_operand:DF 7 "register_operand" "=r"))
2634 (clobber (match_operand:DF 8 "register_operand" "=r"))]
2635 "TARGET_SHMEDIA_FPU"
2636 "#"
2637 "&& (reload_in_progress || reload_completed)"
2638 [(set (match_dup 0) (match_dup 3))]
2639 ""
2640 [(set_attr "highpart" "must_split")])
2641
2642 ;; If a matching group of divide-by-inverse instructions is in the same
2643 ;; basic block after gcse & loop optimizations, we want to transform them
2644 ;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
2645 (define_insn_and_split "*divsi_inv_fp_combine"
2646 [(set (match_operand:SI 0 "register_operand" "=f")
2647 (div:SI (match_operand:SI 1 "register_operand" "f")
2648 (match_operand:SI 2 "register_operand" "f")))
2649 (use (unspec:SI [(match_dup 1)
2650 (match_operand:SI 3 "" "")
2651 (unspec:SI [(match_operand:SI 4 "" "")
2652 (match_dup 3)
2653 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
2654 (match_operand:DI 6 "" "")
2655 (const_int 0)
2656 (const_int 0)] UNSPEC_DIV_INV_M3))
2657 (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
2658 (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
2659 (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
2660 (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
2661 (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
2662 "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
2663 "#"
2664 "&& 1"
2665 [(set (match_dup 9) (float:DF (match_dup 1)))
2666 (set (match_dup 10) (float:DF (match_dup 2)))
2667 (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
2668 (set (match_dup 8)
2669 (fix:SI (match_dup 11)))
2670 (set (match_dup 0) (match_dup 8))]
2671 {
2672 if (! fp_arith_reg_operand (operands[1], SImode))
2673 {
2674 emit_move_insn (operands[7], operands[1]);
2675 operands[1] = operands[7];
2676 }
2677 if (! fp_arith_reg_operand (operands[2], SImode))
2678 {
2679 emit_move_insn (operands[8], operands[2]);
2680 operands[2] = operands[8];
2681 }
2682 }
2683 [(set_attr "highpart" "must_split")])
2684 \f
2685 ;; -------------------------------------------------------------------------
2686 ;; Multiplication instructions
2687 ;; -------------------------------------------------------------------------
2688
2689 (define_insn "umulhisi3_i"
2690 [(set (reg:SI MACL_REG)
2691 (mult:SI (zero_extend:SI
2692 (match_operand:HI 0 "arith_reg_operand" "r"))
2693 (zero_extend:SI
2694 (match_operand:HI 1 "arith_reg_operand" "r"))))]
2695 "TARGET_SH1"
2696 "mulu.w %1,%0"
2697 [(set_attr "type" "smpy")])
2698
2699 (define_insn "mulhisi3_i"
2700 [(set (reg:SI MACL_REG)
2701 (mult:SI (sign_extend:SI
2702 (match_operand:HI 0 "arith_reg_operand" "r"))
2703 (sign_extend:SI
2704 (match_operand:HI 1 "arith_reg_operand" "r"))))]
2705 "TARGET_SH1"
2706 "muls.w %1,%0"
2707 [(set_attr "type" "smpy")])
2708
2709 (define_expand "mulhisi3"
2710 [(set (reg:SI MACL_REG)
2711 (mult:SI (sign_extend:SI
2712 (match_operand:HI 1 "arith_reg_operand" ""))
2713 (sign_extend:SI
2714 (match_operand:HI 2 "arith_reg_operand" ""))))
2715 (set (match_operand:SI 0 "arith_reg_operand" "")
2716 (reg:SI MACL_REG))]
2717 "TARGET_SH1"
2718 {
2719 rtx insn, macl;
2720
2721 macl = gen_rtx_REG (SImode, MACL_REG);
2722 start_sequence ();
2723 emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
2724 insn = get_insns ();
2725 end_sequence ();
2726 /* expand_binop can't find a suitable code in umul_widen_optab to
2727 make a REG_EQUAL note from, so make one here.
2728 See also smulsi3_highpart.
2729 ??? Alternatively, we could put this at the calling site of expand_binop,
2730 i.e. expand_expr. */
2731 /* Use emit_libcall_block for loop invariant code motion and to make
2732 a REG_EQUAL note. */
2733 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
2734
2735 DONE;
2736 })
2737
2738 (define_expand "umulhisi3"
2739 [(set (reg:SI MACL_REG)
2740 (mult:SI (zero_extend:SI
2741 (match_operand:HI 1 "arith_reg_operand" ""))
2742 (zero_extend:SI
2743 (match_operand:HI 2 "arith_reg_operand" ""))))
2744 (set (match_operand:SI 0 "arith_reg_operand" "")
2745 (reg:SI MACL_REG))]
2746 "TARGET_SH1"
2747 {
2748 rtx insn, macl;
2749
2750 macl = gen_rtx_REG (SImode, MACL_REG);
2751 start_sequence ();
2752 emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
2753 insn = get_insns ();
2754 end_sequence ();
2755 /* expand_binop can't find a suitable code in umul_widen_optab to
2756 make a REG_EQUAL note from, so make one here.
2757 See also smulsi3_highpart.
2758 ??? Alternatively, we could put this at the calling site of expand_binop,
2759 i.e. expand_expr. */
2760 /* Use emit_libcall_block for loop invariant code motion and to make
2761 a REG_EQUAL note. */
2762 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
2763
2764 DONE;
2765 })
2766
2767 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
2768 ;; a call to a routine which clobbers known registers.
2769
2770 (define_insn ""
2771 [(set (match_operand:SI 1 "register_operand" "=z")
2772 (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2773 (clobber (reg:SI MACL_REG))
2774 (clobber (reg:SI T_REG))
2775 (clobber (reg:SI PR_REG))
2776 (clobber (reg:SI R3_REG))
2777 (clobber (reg:SI R2_REG))
2778 (clobber (reg:SI R1_REG))
2779 (use (match_operand:SI 0 "arith_reg_operand" "r"))]
2780 "TARGET_SH1"
2781 "jsr @%0%#"
2782 [(set_attr "type" "sfunc")
2783 (set_attr "needs_delay_slot" "yes")])
2784
2785 (define_expand "mulsi3_call"
2786 [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2787 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2788 (parallel[(set (match_operand:SI 0 "register_operand" "")
2789 (mult:SI (reg:SI R4_REG)
2790 (reg:SI R5_REG)))
2791 (clobber (reg:SI MACL_REG))
2792 (clobber (reg:SI T_REG))
2793 (clobber (reg:SI PR_REG))
2794 (clobber (reg:SI R3_REG))
2795 (clobber (reg:SI R2_REG))
2796 (clobber (reg:SI R1_REG))
2797 (use (match_operand:SI 3 "register_operand" ""))])]
2798 "TARGET_SH1"
2799 "")
2800
2801 (define_insn "mul_r"
2802 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2803 (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
2804 (match_operand:SI 2 "arith_reg_operand" "z")))]
2805 "TARGET_SH2A"
2806 "mulr %2,%0"
2807 [(set_attr "type" "dmpy")])
2808
2809 (define_insn "mul_l"
2810 [(set (reg:SI MACL_REG)
2811 (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
2812 (match_operand:SI 1 "arith_reg_operand" "r")))]
2813 "TARGET_SH2"
2814 "mul.l %1,%0"
2815 [(set_attr "type" "dmpy")])
2816
2817 (define_expand "mulsi3"
2818 [(set (reg:SI MACL_REG)
2819 (mult:SI (match_operand:SI 1 "arith_reg_operand" "")
2820 (match_operand:SI 2 "arith_reg_operand" "")))
2821 (set (match_operand:SI 0 "arith_reg_operand" "")
2822 (reg:SI MACL_REG))]
2823 "TARGET_SH1"
2824 {
2825 if (!TARGET_SH2)
2826 {
2827 /* The address must be set outside the libcall,
2828 since it goes into a pseudo. */
2829 rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC);
2830 rtx addr = force_reg (SImode, sym);
2831 rtx insns = gen_mulsi3_call (operands[0], operands[1],
2832 operands[2], addr);
2833 emit_insn (insns);
2834 }
2835 else
2836 {
2837 rtx macl = gen_rtx_REG (SImode, MACL_REG);
2838
2839 emit_insn (gen_mul_l (operands[1], operands[2]));
2840 /* consec_sets_giv can only recognize the first insn that sets a
2841 giv as the giv insn. So we must tag this also with a REG_EQUAL
2842 note. */
2843 emit_insn (gen_movsi_i ((operands[0]), macl));
2844 }
2845 DONE;
2846 })
2847
2848 (define_insn "mulsidi3_i"
2849 [(set (reg:SI MACH_REG)
2850 (truncate:SI
2851 (lshiftrt:DI
2852 (mult:DI
2853 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2854 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2855 (const_int 32))))
2856 (set (reg:SI MACL_REG)
2857 (mult:SI (match_dup 0)
2858 (match_dup 1)))]
2859 "TARGET_SH2"
2860 "dmuls.l %1,%0"
2861 [(set_attr "type" "dmpy")])
2862
2863 (define_expand "mulsidi3"
2864 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2865 (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2866 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2867 "TARGET_SH2 || TARGET_SHMEDIA"
2868 {
2869 if (TARGET_SH2)
2870 {
2871 emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2]));
2872 DONE;
2873 }
2874 })
2875
2876 (define_insn "mulsidi3_media"
2877 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2878 (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2879 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2880 "TARGET_SHMEDIA"
2881 "muls.l %1, %2, %0"
2882 [(set_attr "type" "dmpy_media")
2883 (set_attr "highpart" "ignore")])
2884
2885 (define_insn "mulsidi3_compact"
2886 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2887 (mult:DI
2888 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2889 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2890 (clobber (reg:SI MACH_REG))
2891 (clobber (reg:SI MACL_REG))]
2892 "TARGET_SH2"
2893 "#")
2894
2895 (define_split
2896 [(set (match_operand:DI 0 "arith_reg_dest" "")
2897 (mult:DI
2898 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2899 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2900 (clobber (reg:SI MACH_REG))
2901 (clobber (reg:SI MACL_REG))]
2902 "TARGET_SH2"
2903 [(const_int 0)]
2904 {
2905 rtx low_dst = gen_lowpart (SImode, operands[0]);
2906 rtx high_dst = gen_highpart (SImode, operands[0]);
2907
2908 emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
2909
2910 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
2911 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
2912 /* We need something to tag the possible REG_EQUAL notes on to. */
2913 emit_move_insn (operands[0], operands[0]);
2914 DONE;
2915 })
2916
2917 (define_insn "umulsidi3_i"
2918 [(set (reg:SI MACH_REG)
2919 (truncate:SI
2920 (lshiftrt:DI
2921 (mult:DI
2922 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2923 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2924 (const_int 32))))
2925 (set (reg:SI MACL_REG)
2926 (mult:SI (match_dup 0)
2927 (match_dup 1)))]
2928 "TARGET_SH2"
2929 "dmulu.l %1,%0"
2930 [(set_attr "type" "dmpy")])
2931
2932 (define_expand "umulsidi3"
2933 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2934 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2935 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2936 "TARGET_SH2 || TARGET_SHMEDIA"
2937 {
2938 if (TARGET_SH2)
2939 {
2940 emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2]));
2941 DONE;
2942 }
2943 })
2944
2945 (define_insn "umulsidi3_media"
2946 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2947 (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2948 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2949 "TARGET_SHMEDIA"
2950 "mulu.l %1, %2, %0"
2951 [(set_attr "type" "dmpy_media")
2952 (set_attr "highpart" "ignore")])
2953
2954 (define_insn "umulsidi3_compact"
2955 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2956 (mult:DI
2957 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2958 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2959 (clobber (reg:SI MACH_REG))
2960 (clobber (reg:SI MACL_REG))]
2961 "TARGET_SH2"
2962 "#")
2963
2964 (define_split
2965 [(set (match_operand:DI 0 "arith_reg_dest" "")
2966 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2967 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2968 (clobber (reg:SI MACH_REG))
2969 (clobber (reg:SI MACL_REG))]
2970 "TARGET_SH2"
2971 [(const_int 0)]
2972 {
2973 rtx low_dst = gen_lowpart (SImode, operands[0]);
2974 rtx high_dst = gen_highpart (SImode, operands[0]);
2975
2976 emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
2977
2978 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
2979 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
2980 /* We need something to tag the possible REG_EQUAL notes on to. */
2981 emit_move_insn (operands[0], operands[0]);
2982 DONE;
2983 })
2984
2985 (define_insn "smulsi3_highpart_i"
2986 [(set (reg:SI MACH_REG)
2987 (truncate:SI
2988 (lshiftrt:DI
2989 (mult:DI
2990 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2991 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2992 (const_int 32))))
2993 (clobber (reg:SI MACL_REG))]
2994 "TARGET_SH2"
2995 "dmuls.l %1,%0"
2996 [(set_attr "type" "dmpy")])
2997
2998 (define_expand "smulsi3_highpart"
2999 [(parallel
3000 [(set (reg:SI MACH_REG)
3001 (truncate:SI
3002 (lshiftrt:DI
3003 (mult:DI
3004 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3005 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3006 (const_int 32))))
3007 (clobber (reg:SI MACL_REG))])
3008 (set (match_operand:SI 0 "arith_reg_operand" "")
3009 (reg:SI MACH_REG))]
3010 "TARGET_SH2"
3011 {
3012 rtx insn, mach;
3013
3014 mach = gen_rtx_REG (SImode, MACH_REG);
3015 start_sequence ();
3016 emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3017 insn = get_insns ();
3018 end_sequence ();
3019 /* expand_binop can't find a suitable code in mul_highpart_optab to
3020 make a REG_EQUAL note from, so make one here.
3021 See also {,u}mulhisi.
3022 ??? Alternatively, we could put this at the calling site of expand_binop,
3023 i.e. expand_mult_highpart. */
3024 /* Use emit_libcall_block for loop invariant code motion and to make
3025 a REG_EQUAL note. */
3026 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3027
3028 DONE;
3029 })
3030
3031 (define_insn "umulsi3_highpart_i"
3032 [(set (reg:SI MACH_REG)
3033 (truncate:SI
3034 (lshiftrt:DI
3035 (mult:DI
3036 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3037 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3038 (const_int 32))))
3039 (clobber (reg:SI MACL_REG))]
3040 "TARGET_SH2"
3041 "dmulu.l %1,%0"
3042 [(set_attr "type" "dmpy")])
3043
3044 (define_expand "umulsi3_highpart"
3045 [(parallel
3046 [(set (reg:SI MACH_REG)
3047 (truncate:SI
3048 (lshiftrt:DI
3049 (mult:DI
3050 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3051 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3052 (const_int 32))))
3053 (clobber (reg:SI MACL_REG))])
3054 (set (match_operand:SI 0 "arith_reg_operand" "")
3055 (reg:SI MACH_REG))]
3056 "TARGET_SH2"
3057 {
3058 rtx insn, mach;
3059
3060 mach = gen_rtx_REG (SImode, MACH_REG);
3061 start_sequence ();
3062 emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3063 insn = get_insns ();
3064 end_sequence ();
3065 /* Use emit_libcall_block for loop invariant code motion and to make
3066 a REG_EQUAL note. */
3067 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3068
3069 DONE;
3070 })
3071
3072 (define_insn_and_split "muldi3"
3073 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3074 (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3075 (match_operand:DI 2 "arith_reg_operand" "r")))
3076 (clobber (match_scratch:DI 3 "=&r"))
3077 (clobber (match_scratch:DI 4 "=r"))]
3078 "TARGET_SHMEDIA"
3079 "#"
3080 "reload_completed"
3081 [(const_int 0)]
3082 {
3083 rtx op3_v2si, op2_v2si;
3084
3085 op3_v2si = operands[3];
3086 if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3087 {
3088 op3_v2si = XEXP (op3_v2si, 0);
3089 op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3090 }
3091 op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3092 op2_v2si = operands[2];
3093 if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3094 {
3095 op2_v2si = XEXP (op2_v2si, 0);
3096 op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3097 }
3098 op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3099 emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3100 emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3101 emit_insn (gen_umulsidi3_media (operands[4],
3102 sh_gen_truncate (SImode, operands[1], 0),
3103 sh_gen_truncate (SImode, operands[2], 0)));
3104 emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3105 emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3106 emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3107 emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3108 DONE;
3109 })
3110
3111 \f
3112 ;; -------------------------------------------------------------------------
3113 ;; Logical operations
3114 ;; -------------------------------------------------------------------------
3115
3116 (define_expand "andsi3"
3117 [(set (match_operand:SI 0 "arith_reg_operand" "")
3118 (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3119 (match_operand:SI 2 "logical_and_operand" "")))]
3120 ""
3121 {
3122 /* If it is possible to turn the and insn into a zero extension
3123 already, redundant zero extensions will be folded, which results
3124 in better code.
3125 Ideally the splitter of *andsi_compact would be enough, if reundant
3126 zero extensions were detected after the combine pass, which does not
3127 happen at the moment. */
3128 if (TARGET_SH1)
3129 {
3130 if (satisfies_constraint_Jmb (operands[2]))
3131 {
3132 emit_insn (gen_zero_extendqisi2 (operands[0],
3133 gen_lowpart (QImode, operands[1])));
3134 DONE;
3135 }
3136 else if (satisfies_constraint_Jmw (operands[2]))
3137 {
3138 emit_insn (gen_zero_extendhisi2 (operands[0],
3139 gen_lowpart (HImode, operands[1])));
3140 DONE;
3141 }
3142 }
3143 })
3144
3145 (define_insn_and_split "*andsi_compact"
3146 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r")
3147 (and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0")
3148 (match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))]
3149 "TARGET_SH1"
3150 "@
3151 extu.b %1,%0
3152 extu.w %1,%0
3153 and %2,%0
3154 and %2,%0"
3155 "&& 1"
3156 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
3157 {
3158 if (satisfies_constraint_Jmb (operands[2]))
3159 operands[1] = gen_lowpart (QImode, operands[1]);
3160 else if (satisfies_constraint_Jmw (operands[2]))
3161 operands[1] = gen_lowpart (HImode, operands[1]);
3162 else
3163 FAIL;
3164 }
3165 [(set_attr "type" "arith")])
3166
3167 (define_insn "*andsi3_media"
3168 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3169 (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3170 (match_operand:SI 2 "logical_operand" "r,I10")))]
3171 "TARGET_SHMEDIA"
3172 "@
3173 and %1, %2, %0
3174 andi %1, %2, %0"
3175 [(set_attr "type" "arith_media")])
3176
3177 (define_insn "*andsi3_bclr"
3178 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3179 (and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3180 (match_operand:SI 2 "const_int_operand" "Psz")))]
3181 "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
3182 "bclr\\t%W2,%0"
3183 [(set_attr "type" "arith")])
3184
3185 (define_insn_and_split "anddi3"
3186 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3187 (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3188 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
3189 "TARGET_SHMEDIA"
3190 "@
3191 and %1, %2, %0
3192 andi %1, %2, %0
3193 #"
3194 "reload_completed
3195 && ! logical_operand (operands[2], DImode)"
3196 [(const_int 0)]
3197 {
3198 if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3199 emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3200 else
3201 emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3202 DONE;
3203 }
3204 [(set_attr "type" "arith_media")])
3205
3206 (define_insn "andcsi3"
3207 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3208 (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3209 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3210 "TARGET_SHMEDIA"
3211 "andc %1,%2,%0"
3212 [(set_attr "type" "arith_media")])
3213
3214 (define_insn "andcdi3"
3215 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3216 (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3217 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3218 "TARGET_SHMEDIA"
3219 "andc %1,%2,%0"
3220 [(set_attr "type" "arith_media")])
3221
3222 (define_expand "iorsi3"
3223 [(set (match_operand:SI 0 "arith_reg_operand" "")
3224 (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3225 (match_operand:SI 2 "logical_operand" "")))]
3226 ""
3227 "")
3228
3229 (define_insn "*iorsi3_compact"
3230 [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3231 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3232 (match_operand:SI 2 "logical_operand" "r,K08")))]
3233 "TARGET_SH1
3234 && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
3235 "or %2,%0"
3236 [(set_attr "type" "arith")])
3237
3238 (define_insn "*iorsi3_media"
3239 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3240 (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3241 (match_operand:SI 2 "logical_operand" "r,I10")))]
3242 "TARGET_SHMEDIA"
3243 "@
3244 or %1, %2, %0
3245 ori %1, %2, %0"
3246 [(set_attr "type" "arith_media")])
3247
3248 (define_insn "*iorsi3_bset"
3249 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3250 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3251 (match_operand:SI 2 "const_int_operand" "Pso")))]
3252 "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
3253 "bset\\t%V2,%0"
3254 [(set_attr "type" "arith")])
3255
3256 (define_insn "iordi3"
3257 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3258 (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3259 (match_operand:DI 2 "logical_operand" "r,I10")))]
3260 "TARGET_SHMEDIA"
3261 "@
3262 or %1, %2, %0
3263 ori %1, %2, %0"
3264 [(set_attr "type" "arith_media")])
3265
3266 (define_insn_and_split "*logical_sidi3"
3267 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3268 (sign_extend:DI (match_operator:SI 3 "logical_operator"
3269 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3270 (match_operand:SI 2 "logical_operand" "r,I10")])))]
3271 "TARGET_SHMEDIA"
3272 "#"
3273 "&& reload_completed"
3274 [(set (match_dup 0) (match_dup 3))]
3275 {
3276 operands[3]
3277 = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3278 simplify_gen_subreg (DImode, operands[1], SImode, 0),
3279 simplify_gen_subreg (DImode, operands[2], SImode, 0));
3280 })
3281
3282 (define_insn_and_split "*logical_sidisi3"
3283 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3284 (truncate:SI (sign_extend:DI
3285 (match_operator:SI 3 "logical_operator"
3286 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3287 (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3288 "TARGET_SHMEDIA"
3289 "#"
3290 "&& 1"
3291 [(set (match_dup 0) (match_dup 3))])
3292
3293 (define_insn_and_split "*logical_sidi3_2"
3294 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3295 (sign_extend:DI (truncate:SI (sign_extend:DI
3296 (match_operator:SI 3 "logical_operator"
3297 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3298 (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3299 "TARGET_SHMEDIA"
3300 "#"
3301 "&& 1"
3302 [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3303
3304 (define_expand "xorsi3"
3305 [(set (match_operand:SI 0 "arith_reg_operand" "")
3306 (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3307 (match_operand:SI 2 "xor_operand" "")))]
3308 ""
3309 "")
3310
3311 (define_insn "*xorsi3_compact"
3312 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3313 (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3314 (match_operand:SI 2 "logical_operand" "K08,r")))]
3315 "TARGET_SH1"
3316 "xor %2,%0"
3317 [(set_attr "type" "arith")])
3318
3319 (define_insn "*xorsi3_media"
3320 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3321 (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3322 (match_operand:SI 2 "xor_operand" "r,I06")))]
3323 "TARGET_SHMEDIA"
3324 "@
3325 xor %1, %2, %0
3326 xori %1, %2, %0"
3327 [(set_attr "type" "arith_media")])
3328
3329 (define_insn "xordi3"
3330 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3331 (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3332 (match_operand:DI 2 "xor_operand" "r,I06")))]
3333 "TARGET_SHMEDIA"
3334 "@
3335 xor %1, %2, %0
3336 xori %1, %2, %0"
3337 [(set_attr "type" "arith_media")])
3338
3339 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3340 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
3341 (define_split
3342 [(set (match_operand:DI 0 "arith_reg_dest" "")
3343 (sign_extend:DI (match_operator 4 "binary_logical_operator"
3344 [(match_operand 1 "any_register_operand" "")
3345 (match_operand 2 "any_register_operand" "")])))]
3346 "TARGET_SHMEDIA"
3347 [(set (match_dup 5) (match_dup 4))
3348 (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3349 {
3350 enum machine_mode inmode = GET_MODE (operands[1]);
3351 int offset = 0;
3352
3353 if (GET_CODE (operands[0]) == SUBREG)
3354 {
3355 offset = SUBREG_BYTE (operands[0]);
3356 operands[0] = SUBREG_REG (operands[0]);
3357 }
3358 gcc_assert (REG_P (operands[0]));
3359 if (! TARGET_LITTLE_ENDIAN)
3360 offset += 8 - GET_MODE_SIZE (inmode);
3361 operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3362 })
3363 \f
3364 ;; -------------------------------------------------------------------------
3365 ;; Shifts and rotates
3366 ;; -------------------------------------------------------------------------
3367
3368 (define_expand "rotldi3"
3369 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3370 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3371 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3372 "TARGET_SHMEDIA"
3373 "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3374
3375 (define_insn "rotldi3_mextr"
3376 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3377 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3378 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3379 "TARGET_SHMEDIA"
3380 {
3381 static char templ[16];
3382
3383 sprintf (templ, "mextr%d\\t%%1,%%1,%%0",
3384 8 - (int) (INTVAL (operands[2]) >> 3));
3385 return templ;
3386 }
3387 [(set_attr "type" "arith_media")])
3388
3389 (define_expand "rotrdi3"
3390 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3391 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3392 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3393 "TARGET_SHMEDIA"
3394 {
3395 if (! mextr_bit_offset (operands[2], HImode))
3396 FAIL;
3397 })
3398
3399 (define_insn "rotrdi3_mextr"
3400 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3401 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3402 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3403 "TARGET_SHMEDIA"
3404 {
3405 static char templ[16];
3406
3407 sprintf (templ, "mextr%d\\t%%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3);
3408 return templ;
3409 }
3410 [(set_attr "type" "arith_media")])
3411
3412 (define_split
3413 [(set (match_operand:DI 0 "arith_reg_dest" "")
3414 (ior:DI (zero_extend:DI (mem:QI (match_operand 1
3415 "ua_address_operand" "")))
3416 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
3417 (const_int 8))))
3418 (clobber (match_operand:DI 3 "register_operand" ""))]
3419 "TARGET_SHMEDIA"
3420 [(match_dup 4) (match_dup 5)]
3421 {
3422 operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
3423 (operands[3], operands[1]));
3424 operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
3425 GEN_INT (56), GEN_INT (8));
3426 })
3427
3428 (define_insn "rotlsi3_1"
3429 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3430 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3431 (const_int 1)))
3432 (set (reg:SI T_REG)
3433 (lshiftrt:SI (match_dup 1) (const_int 31)))]
3434 "TARGET_SH1"
3435 "rotl %0"
3436 [(set_attr "type" "arith")])
3437
3438 (define_insn "rotlsi3_31"
3439 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3440 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3441 (const_int 31)))
3442 (clobber (reg:SI T_REG))]
3443 "TARGET_SH1"
3444 "rotr %0"
3445 [(set_attr "type" "arith")])
3446
3447 (define_insn "rotlsi3_16"
3448 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3449 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
3450 (const_int 16)))]
3451 "TARGET_SH1"
3452 "swap.w %1,%0"
3453 [(set_attr "type" "arith")])
3454
3455 (define_expand "rotlsi3"
3456 [(set (match_operand:SI 0 "arith_reg_dest" "")
3457 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
3458 (match_operand:SI 2 "immediate_operand" "")))]
3459 "TARGET_SH1"
3460 {
3461 static const char rot_tab[] = {
3462 000, 000, 000, 000, 000, 000, 010, 001,
3463 001, 001, 011, 013, 003, 003, 003, 003,
3464 003, 003, 003, 003, 003, 013, 012, 002,
3465 002, 002, 010, 000, 000, 000, 000, 000,
3466 };
3467
3468 int count, choice;
3469
3470 if (!CONST_INT_P (operands[2]))
3471 FAIL;
3472 count = INTVAL (operands[2]);
3473 choice = rot_tab[count];
3474 if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
3475 FAIL;
3476 choice &= 7;
3477 switch (choice)
3478 {
3479 case 0:
3480 emit_move_insn (operands[0], operands[1]);
3481 count -= (count & 16) * 2;
3482 break;
3483 case 3:
3484 emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
3485 count -= 16;
3486 break;
3487 case 1:
3488 case 2:
3489 {
3490 rtx parts[2];
3491 parts[0] = gen_reg_rtx (SImode);
3492 parts[1] = gen_reg_rtx (SImode);
3493 emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
3494 emit_move_insn (parts[choice-1], operands[1]);
3495 emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
3496 emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
3497 emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
3498 count = (count & ~16) - 8;
3499 }
3500 }
3501
3502 for (; count > 0; count--)
3503 emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
3504 for (; count < 0; count++)
3505 emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
3506
3507 DONE;
3508 })
3509
3510 (define_insn "*rotlhi3_8"
3511 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3512 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
3513 (const_int 8)))]
3514 "TARGET_SH1"
3515 "swap.b %1,%0"
3516 [(set_attr "type" "arith")])
3517
3518 (define_expand "rotlhi3"
3519 [(set (match_operand:HI 0 "arith_reg_operand" "")
3520 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "")
3521 (match_operand:HI 2 "immediate_operand" "")))]
3522 "TARGET_SH1"
3523 {
3524 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 8)
3525 FAIL;
3526 })
3527
3528 ;;
3529 ;; shift left
3530
3531 ;; This pattern is used by init_expmed for computing the costs of shift
3532 ;; insns.
3533
3534 (define_insn_and_split "ashlsi3_std"
3535 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,r,r")
3536 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
3537 (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
3538 (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
3539 "(TARGET_SH3 || TARGET_SH2A)
3540 || (TARGET_SH1 && satisfies_constraint_P27 (operands[2]))"
3541 "@
3542 shld %2,%0
3543 add %0,%0
3544 shll%O2 %0
3545 #"
3546 "(TARGET_SH3 || TARGET_SH2A)
3547 && reload_completed
3548 && CONST_INT_P (operands[2])
3549 && ! satisfies_constraint_P27 (operands[2])"
3550 [(set (match_dup 3) (match_dup 2))
3551 (parallel
3552 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
3553 (clobber (match_dup 4))])]
3554 {
3555 operands[4] = gen_rtx_SCRATCH (SImode);
3556 }
3557 [(set_attr "length" "*,*,*,4")
3558 (set_attr "type" "dyn_shift,arith,arith,arith")])
3559
3560 (define_insn "ashlhi3_k"
3561 [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
3562 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
3563 (match_operand:HI 2 "const_int_operand" "M,P27")))]
3564 "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
3565 "@
3566 add %0,%0
3567 shll%O2 %0"
3568 [(set_attr "type" "arith")])
3569
3570 (define_insn "ashlsi3_n"
3571 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3572 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3573 (match_operand:SI 2 "const_int_operand" "n")))
3574 (clobber (reg:SI T_REG))]
3575 "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3576 "#"
3577 [(set (attr "length")
3578 (cond [(match_test "shift_insns_rtx (insn)")
3579 (const_string "2")
3580 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3581 (const_string "4")
3582 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3583 (const_string "6")]
3584 (const_string "8")))
3585 (set_attr "type" "arith")])
3586
3587 (define_split
3588 [(set (match_operand:SI 0 "arith_reg_dest" "")
3589 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3590 (match_operand:SI 2 "const_int_operand" "")))
3591 (clobber (reg:SI T_REG))]
3592 "TARGET_SH1 && reload_completed"
3593 [(use (reg:SI R0_REG))]
3594 {
3595 gen_shifty_op (ASHIFT, operands);
3596 DONE;
3597 })
3598
3599 (define_insn "ashlsi3_media"
3600 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3601 (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3602 (match_operand:SI 2 "shift_count_operand" "r,n")))]
3603 "TARGET_SHMEDIA"
3604 "@
3605 shlld.l %1, %2, %0
3606 shlli.l %1, %2, %0"
3607 [(set_attr "type" "arith_media")
3608 (set_attr "highpart" "ignore")])
3609
3610 (define_expand "ashlsi3"
3611 [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3612 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3613 (match_operand:SI 2 "nonmemory_operand" "")))
3614 (clobber (reg:SI T_REG))])]
3615 ""
3616 {
3617 if (TARGET_SHMEDIA)
3618 {
3619 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
3620 DONE;
3621 }
3622 if (CONST_INT_P (operands[2])
3623 && sh_dynamicalize_shift_p (operands[2]))
3624 operands[2] = force_reg (SImode, operands[2]);
3625 if (TARGET_SH3 || TARGET_SH2A)
3626 {
3627 emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
3628 DONE;
3629 }
3630 if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3631 FAIL;
3632 })
3633
3634 (define_insn "*ashlhi3_n"
3635 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3636 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
3637 (match_operand:HI 2 "const_int_operand" "n")))
3638 (clobber (reg:SI T_REG))]
3639 "TARGET_SH1"
3640 "#"
3641 [(set (attr "length")
3642 (cond [(match_test "shift_insns_rtx (insn)")
3643 (const_string "2")
3644 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3645 (const_string "4")]
3646 (const_string "6")))
3647 (set_attr "type" "arith")])
3648
3649 (define_expand "ashlhi3"
3650 [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
3651 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3652 (match_operand:SI 2 "nonmemory_operand" "")))
3653 (clobber (reg:SI T_REG))])]
3654 "TARGET_SH1"
3655 {
3656 if (!CONST_INT_P (operands[2]))
3657 FAIL;
3658 /* It may be possible to call gen_ashlhi3 directly with more generic
3659 operands. Make sure operands[1] is a HImode register here. */
3660 if (!arith_reg_operand (operands[1], HImode))
3661 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3662 })
3663
3664 (define_split
3665 [(set (match_operand:HI 0 "arith_reg_dest" "")
3666 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3667 (match_operand:HI 2 "const_int_operand" "")))
3668 (clobber (reg:SI T_REG))]
3669 "TARGET_SH1 && reload_completed"
3670 [(use (reg:SI R0_REG))]
3671 {
3672 gen_shifty_hi_op (ASHIFT, operands);
3673 DONE;
3674 })
3675
3676 ;;
3677 ;; arithmetic shift right
3678 ;;
3679
3680 (define_insn "ashrsi3_k"
3681 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3682 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3683 (match_operand:SI 2 "const_int_operand" "M")))
3684 (clobber (reg:SI T_REG))]
3685 "TARGET_SH1 && INTVAL (operands[2]) == 1"
3686 "shar %0"
3687 [(set_attr "type" "arith")])
3688
3689 ;; We can't do HImode right shifts correctly unless we start out with an
3690 ;; explicit zero / sign extension; doing that would result in worse overall
3691 ;; code, so just let the machine independent code widen the mode.
3692 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
3693
3694
3695 ;; ??? This should be a define expand.
3696
3697 (define_insn "ashrsi2_16"
3698 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3699 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
3700 (const_int 16)))]
3701 "TARGET_SH1"
3702 "#"
3703 [(set_attr "length" "4")])
3704
3705 (define_split
3706 [(set (match_operand:SI 0 "arith_reg_dest" "")
3707 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3708 (const_int 16)))]
3709 "TARGET_SH1"
3710 [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
3711 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3712 {
3713 operands[2] = gen_lowpart (HImode, operands[0]);
3714 })
3715
3716 ;; ??? This should be a define expand.
3717
3718 (define_insn "ashrsi2_31"
3719 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3720 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3721 (const_int 31)))
3722 (clobber (reg:SI T_REG))]
3723 "TARGET_SH1"
3724 "#"
3725 [(set_attr "length" "4")])
3726
3727 (define_split
3728 [(set (match_operand:SI 0 "arith_reg_dest" "")
3729 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3730 (const_int 31)))
3731 (clobber (reg:SI T_REG))]
3732 "TARGET_SH1"
3733 [(const_int 0)]
3734 {
3735 emit_insn (gen_ashlsi_c (operands[0], operands[1]));
3736 emit_insn (gen_mov_neg_si_t (copy_rtx (operands[0])));
3737 DONE;
3738 })
3739
3740 (define_peephole2
3741 [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
3742 (set (reg:SI T_REG)
3743 (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
3744 "TARGET_SH1
3745 && peep2_reg_dead_p (2, operands[0])
3746 && peep2_reg_dead_p (2, operands[1])"
3747 [(const_int 0)]
3748 {
3749 emit_insn (gen_ashlsi_c (operands[1], operands[1]));
3750 DONE;
3751 })
3752
3753 (define_insn "ashlsi_c"
3754 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3755 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
3756 (set (reg:SI T_REG)
3757 (lt:SI (match_dup 1) (const_int 0)))]
3758 "TARGET_SH1"
3759 "shll %0"
3760 [(set_attr "type" "arith")])
3761
3762 (define_insn "*ashlsi_c_void"
3763 [(set (reg:SI T_REG)
3764 (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
3765 (clobber (match_scratch:SI 1 "=0"))]
3766 "TARGET_SH1 && cse_not_expected"
3767 "shll %0"
3768 [(set_attr "type" "arith")])
3769
3770 (define_insn "ashrsi3_d"
3771 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3772 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3773 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3774 "TARGET_SH3 || TARGET_SH2A"
3775 "shad %2,%0"
3776 [(set_attr "type" "dyn_shift")])
3777
3778 (define_insn "ashrsi3_n"
3779 [(set (reg:SI R4_REG)
3780 (ashiftrt:SI (reg:SI R4_REG)
3781 (match_operand:SI 0 "const_int_operand" "i")))
3782 (clobber (reg:SI T_REG))
3783 (clobber (reg:SI PR_REG))
3784 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
3785 "TARGET_SH1"
3786 "jsr @%1%#"
3787 [(set_attr "type" "sfunc")
3788 (set_attr "needs_delay_slot" "yes")])
3789
3790 (define_insn "ashrsi3_media"
3791 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3792 (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3793 (match_operand:SI 2 "shift_count_operand" "r,n")))]
3794 "TARGET_SHMEDIA"
3795 "@
3796 shard.l %1, %2, %0
3797 shari.l %1, %2, %0"
3798 [(set_attr "type" "arith_media")
3799 (set_attr "highpart" "ignore")])
3800
3801 (define_expand "ashrsi3"
3802 [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3803 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3804 (match_operand:SI 2 "nonmemory_operand" "")))
3805 (clobber (reg:SI T_REG))])]
3806 ""
3807 {
3808 if (TARGET_SHMEDIA)
3809 {
3810 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
3811 DONE;
3812 }
3813 if (expand_ashiftrt (operands))
3814 DONE;
3815 else
3816 FAIL;
3817 })
3818
3819 ;; logical shift right
3820
3821 (define_insn "lshrsi3_d"
3822 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3823 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3824 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3825 "TARGET_SH3 || TARGET_SH2A"
3826 "shld %2,%0"
3827 [(set_attr "type" "dyn_shift")])
3828
3829 ;; Only the single bit shift clobbers the T bit.
3830
3831 (define_insn "lshrsi3_m"
3832 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3833 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3834 (match_operand:SI 2 "const_int_operand" "M")))
3835 (clobber (reg:SI T_REG))]
3836 "TARGET_SH1 && satisfies_constraint_M (operands[2])"
3837 "shlr %0"
3838 [(set_attr "type" "arith")])
3839
3840 (define_insn "lshrsi3_k"
3841 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3842 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3843 (match_operand:SI 2 "const_int_operand" "P27")))]
3844 "TARGET_SH1 && satisfies_constraint_P27 (operands[2])
3845 && ! satisfies_constraint_M (operands[2])"
3846 "shlr%O2 %0"
3847 [(set_attr "type" "arith")])
3848
3849 (define_insn "lshrsi3_n"
3850 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3851 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3852 (match_operand:SI 2 "const_int_operand" "n")))
3853 (clobber (reg:SI T_REG))]
3854 "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3855 "#"
3856 [(set (attr "length")
3857 (cond [(match_test "shift_insns_rtx (insn)")
3858 (const_string "2")
3859 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3860 (const_string "4")
3861 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3862 (const_string "6")]
3863 (const_string "8")))
3864 (set_attr "type" "arith")])
3865
3866 (define_split
3867 [(set (match_operand:SI 0 "arith_reg_dest" "")
3868 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3869 (match_operand:SI 2 "const_int_operand" "")))
3870 (clobber (reg:SI T_REG))]
3871 "TARGET_SH1 && reload_completed"
3872 [(use (reg:SI R0_REG))]
3873 {
3874 gen_shifty_op (LSHIFTRT, operands);
3875 DONE;
3876 })
3877
3878 (define_insn "lshrsi3_media"
3879 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3880 (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3881 (match_operand:SI 2 "shift_count_operand" "r,n")))]
3882 "TARGET_SHMEDIA"
3883 "@
3884 shlrd.l %1, %2, %0
3885 shlri.l %1, %2, %0"
3886 [(set_attr "type" "arith_media")
3887 (set_attr "highpart" "ignore")])
3888
3889 (define_expand "lshrsi3"
3890 [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
3891 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3892 (match_operand:SI 2 "nonmemory_operand" "")))
3893 (clobber (reg:SI T_REG))])]
3894 ""
3895 {
3896 if (TARGET_SHMEDIA)
3897 {
3898 emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
3899 DONE;
3900 }
3901 if (CONST_INT_P (operands[2])
3902 && sh_dynamicalize_shift_p (operands[2]))
3903 operands[2] = force_reg (SImode, operands[2]);
3904 if ((TARGET_SH3 || TARGET_SH2A)
3905 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
3906 {
3907 rtx count = copy_to_mode_reg (SImode, operands[2]);
3908 emit_insn (gen_negsi2 (count, count));
3909 emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
3910 DONE;
3911 }
3912 if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3913 FAIL;
3914 })
3915
3916 ;; ??? This should be a define expand.
3917
3918 (define_insn "ashldi3_k"
3919 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3920 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
3921 (const_int 1)))
3922 (clobber (reg:SI T_REG))]
3923 "TARGET_SH1"
3924 "shll %R0\;rotcl %S0"
3925 [(set_attr "length" "4")
3926 (set_attr "type" "arith")])
3927
3928 ;; Expander for DImode shift left with SImode operations.
3929
3930 (define_expand "ashldi3_std"
3931 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3932 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
3933 (match_operand:DI 2 "const_int_operand" "n")))]
3934 "TARGET_SH1 && INTVAL (operands[2]) < 32"
3935 {
3936 rtx low_src = gen_lowpart (SImode, operands[1]);
3937 rtx high_src = gen_highpart (SImode, operands[1]);
3938 rtx dst = gen_reg_rtx (DImode);
3939 rtx low_dst = gen_lowpart (SImode, dst);
3940 rtx high_dst = gen_highpart (SImode, dst);
3941 rtx tmp0 = gen_reg_rtx (SImode);
3942 rtx tmp1 = gen_reg_rtx (SImode);
3943
3944 emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
3945 emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));
3946 emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));
3947 emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
3948 emit_move_insn (operands[0], dst);
3949 DONE;
3950 })
3951
3952 (define_insn "ashldi3_media"
3953 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3954 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3955 (match_operand:DI 2 "shift_count_operand" "r,n")))]
3956 "TARGET_SHMEDIA"
3957 "@
3958 shlld %1, %2, %0
3959 shlli %1, %2, %0"
3960 [(set_attr "type" "arith_media")])
3961
3962 (define_insn "*ashldisi3_media"
3963 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
3964 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
3965 (match_operand:DI 2 "const_int_operand" "n")))]
3966 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
3967 "shlli.l %1, %2, %0"
3968 [(set_attr "type" "arith_media")
3969 (set_attr "highpart" "ignore")])
3970
3971 (define_expand "ashldi3"
3972 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
3973 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
3974 (match_operand:DI 2 "immediate_operand" "")))
3975 (clobber (reg:SI T_REG))])]
3976 ""
3977 {
3978 if (TARGET_SHMEDIA)
3979 {
3980 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
3981 DONE;
3982 }
3983 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
3984 {
3985 emit_insn (gen_ashldi3_k (operands[0], operands[1]));
3986 DONE;
3987 }
3988 else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32)
3989 {
3990 emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
3991 DONE;
3992 }
3993 else
3994 FAIL;
3995 })
3996
3997 ;; ??? This should be a define expand.
3998
3999 (define_insn "lshrdi3_k"
4000 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4001 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4002 (const_int 1)))
4003 (clobber (reg:SI T_REG))]
4004 "TARGET_SH1"
4005 "shlr %S0\;rotcr %R0"
4006 [(set_attr "length" "4")
4007 (set_attr "type" "arith")])
4008
4009 (define_insn "lshrdi3_media"
4010 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4011 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4012 (match_operand:DI 2 "shift_count_operand" "r,n")))]
4013 "TARGET_SHMEDIA
4014 && (arith_reg_dest (operands[0], DImode)
4015 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
4016 "@
4017 shlrd %1, %2, %0
4018 shlri %1, %2, %0"
4019 [(set_attr "type" "arith_media")])
4020
4021 (define_insn "*lshrdisi3_media"
4022 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4023 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4024 (match_operand:DI 2 "const_int_operand" "n")))]
4025 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4026 "shlri.l %1, %2, %0"
4027 [(set_attr "type" "arith_media")
4028 (set_attr "highpart" "ignore")])
4029
4030 (define_expand "lshrdi3"
4031 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4032 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4033 (match_operand:DI 2 "immediate_operand" "")))
4034 (clobber (reg:SI T_REG))])]
4035 ""
4036 {
4037 if (TARGET_SHMEDIA)
4038 {
4039 emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
4040 DONE;
4041 }
4042 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
4043 FAIL;
4044 })
4045
4046 ;; ??? This should be a define expand.
4047
4048 (define_insn "ashrdi3_k"
4049 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4050 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4051 (const_int 1)))
4052 (clobber (reg:SI T_REG))]
4053 "TARGET_SH1"
4054 "shar %S0\;rotcr %R0"
4055 [(set_attr "length" "4")
4056 (set_attr "type" "arith")])
4057
4058 (define_insn "ashrdi3_media"
4059 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4060 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4061 (match_operand:DI 2 "shift_count_operand" "r,n")))]
4062 "TARGET_SHMEDIA
4063 && (arith_reg_dest (operands[0], DImode)
4064 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
4065 "@
4066 shard %1, %2, %0
4067 shari %1, %2, %0"
4068 [(set_attr "type" "arith_media")])
4069
4070 (define_insn "*ashrdisi3_media"
4071 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4072 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4073 (match_operand:DI 2 "const_int_operand" "n")))]
4074 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4075 "shari.l %1, %2, %0"
4076 [(set_attr "type" "arith_media")
4077 (set_attr "highpart" "ignore")])
4078
4079 (define_insn "ashrdisi3_media_high"
4080 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4081 (truncate:SI
4082 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4083 (match_operand:DI 2 "const_int_operand" "n"))))]
4084 "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
4085 "shari %1, %2, %0"
4086 [(set_attr "type" "arith_media")])
4087
4088 (define_insn "ashrdisi3_media_opaque"
4089 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4090 (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
4091 (match_operand:DI 2 "const_int_operand" "n")]
4092 UNSPEC_ASHIFTRT))]
4093 "TARGET_SHMEDIA"
4094 "shari %1, %2, %0"
4095 [(set_attr "type" "arith_media")])
4096
4097 (define_expand "ashrdi3"
4098 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4099 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4100 (match_operand:DI 2 "immediate_operand" "")))
4101 (clobber (reg:SI T_REG))])]
4102 ""
4103 {
4104 if (TARGET_SHMEDIA)
4105 {
4106 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4107 DONE;
4108 }
4109 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
4110 FAIL;
4111 })
4112
4113 ;; combined left/right shift
4114
4115 (define_split
4116 [(set (match_operand:SI 0 "register_operand" "")
4117 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4118 (match_operand:SI 2 "const_int_operand" ""))
4119 (match_operand:SI 3 "const_int_operand" "")))]
4120 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4121 [(use (reg:SI R0_REG))]
4122 {
4123 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
4124 FAIL;
4125 DONE;
4126 })
4127
4128 (define_split
4129 [(set (match_operand:SI 0 "register_operand" "")
4130 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4131 (match_operand:SI 2 "const_int_operand" ""))
4132 (match_operand:SI 3 "const_int_operand" "")))
4133 (clobber (reg:SI T_REG))]
4134 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4135 [(use (reg:SI R0_REG))]
4136 {
4137 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
4138 FAIL;
4139 DONE;
4140 })
4141
4142 (define_insn ""
4143 [(set (match_operand:SI 0 "register_operand" "=r")
4144 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4145 (match_operand:SI 2 "const_int_operand" "n"))
4146 (match_operand:SI 3 "const_int_operand" "n")))
4147 (clobber (reg:SI T_REG))]
4148 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
4149 "#"
4150 [(set (attr "length")
4151 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4152 (const_string "4")
4153 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4154 (const_string "6")
4155 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4156 (const_string "8")
4157 (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
4158 (const_string "10")
4159 (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
4160 (const_string "12")
4161 (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
4162 (const_string "14")
4163 (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
4164 (const_string "16")]
4165 (const_string "18")))
4166 (set_attr "type" "arith")])
4167
4168 (define_insn ""
4169 [(set (match_operand:SI 0 "register_operand" "=z")
4170 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4171 (match_operand:SI 2 "const_int_operand" "n"))
4172 (match_operand:SI 3 "const_int_operand" "n")))
4173 (clobber (reg:SI T_REG))]
4174 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
4175 "#"
4176 [(set (attr "length")
4177 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4178 (const_string "4")
4179 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4180 (const_string "6")
4181 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4182 (const_string "8")]
4183 (const_string "10")))
4184 (set_attr "type" "arith")])
4185
4186 ;; shift left / and combination with a scratch register: The combine pass
4187 ;; does not accept the individual instructions, even though they are
4188 ;; cheap. But it needs a precise description so that it is usable after
4189 ;; reload.
4190 (define_insn "and_shl_scratch"
4191 [(set (match_operand:SI 0 "register_operand" "=r,&r")
4192 (lshiftrt:SI
4193 (ashift:SI
4194 (and:SI
4195 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
4196 (match_operand:SI 2 "const_int_operand" "N,n"))
4197 (match_operand:SI 3 "" "0,r"))
4198 (match_operand:SI 4 "const_int_operand" "n,n"))
4199 (match_operand:SI 5 "const_int_operand" "n,n")))
4200 (clobber (reg:SI T_REG))]
4201 "TARGET_SH1"
4202 "#"
4203 [(set (attr "length")
4204 (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
4205 (const_string "4")
4206 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
4207 (const_string "6")
4208 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
4209 (const_string "8")
4210 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
4211 (const_string "10")]
4212 (const_string "12")))
4213 (set_attr "type" "arith")])
4214
4215 (define_split
4216 [(set (match_operand:SI 0 "register_operand" "")
4217 (lshiftrt:SI
4218 (ashift:SI
4219 (and:SI
4220 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
4221 (match_operand:SI 2 "const_int_operand" ""))
4222 (match_operand:SI 3 "register_operand" ""))
4223 (match_operand:SI 4 "const_int_operand" ""))
4224 (match_operand:SI 5 "const_int_operand" "")))
4225 (clobber (reg:SI T_REG))]
4226 "TARGET_SH1"
4227 [(use (reg:SI R0_REG))]
4228 {
4229 rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
4230
4231 if (INTVAL (operands[2]))
4232 {
4233 gen_shifty_op (LSHIFTRT, operands);
4234 }
4235 emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
4236 operands[2] = operands[4];
4237 gen_shifty_op (ASHIFT, operands);
4238 if (INTVAL (operands[5]))
4239 {
4240 operands[2] = operands[5];
4241 gen_shifty_op (LSHIFTRT, operands);
4242 }
4243 DONE;
4244 })
4245
4246 ;; signed left/right shift combination.
4247 (define_split
4248 [(set (match_operand:SI 0 "register_operand" "")
4249 (sign_extract:SI
4250 (ashift:SI (match_operand:SI 1 "register_operand" "")
4251 (match_operand:SI 2 "const_int_operand" ""))
4252 (match_operand:SI 3 "const_int_operand" "")
4253 (const_int 0)))
4254 (clobber (reg:SI T_REG))]
4255 "TARGET_SH1"
4256 [(use (reg:SI R0_REG))]
4257 {
4258 if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1]))
4259 FAIL;
4260 DONE;
4261 })
4262
4263 (define_insn "shl_sext_ext"
4264 [(set (match_operand:SI 0 "register_operand" "=r")
4265 (sign_extract:SI
4266 (ashift:SI (match_operand:SI 1 "register_operand" "0")
4267 (match_operand:SI 2 "const_int_operand" "n"))
4268 (match_operand:SI 3 "const_int_operand" "n")
4269 (const_int 0)))
4270 (clobber (reg:SI T_REG))]
4271 "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
4272 "#"
4273 [(set (attr "length")
4274 (cond [(match_test "shl_sext_length (insn)")
4275 (const_string "2")
4276 (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
4277 (const_string "4")
4278 (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4279 (const_string "6")
4280 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4281 (const_string "8")
4282 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4283 (const_string "10")
4284 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4285 (const_string "12")
4286 (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
4287 (const_string "14")
4288 (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
4289 (const_string "16")]
4290 (const_string "18")))
4291 (set_attr "type" "arith")])
4292
4293 (define_insn "shl_sext_sub"
4294 [(set (match_operand:SI 0 "register_operand" "=z")
4295 (sign_extract:SI
4296 (ashift:SI (match_operand:SI 1 "register_operand" "0")
4297 (match_operand:SI 2 "const_int_operand" "n"))
4298 (match_operand:SI 3 "const_int_operand" "n")
4299 (const_int 0)))
4300 (clobber (reg:SI T_REG))]
4301 "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
4302 "#"
4303 [(set (attr "length")
4304 (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4305 (const_string "6")
4306 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4307 (const_string "8")
4308 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4309 (const_string "10")
4310 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4311 (const_string "12")]
4312 (const_string "14")))
4313 (set_attr "type" "arith")])
4314
4315 ;; These patterns are found in expansions of DImode shifts by 16, and
4316 ;; allow the xtrct instruction to be generated from C source.
4317
4318 (define_insn "xtrct_left"
4319 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4320 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
4321 (const_int 16))
4322 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
4323 (const_int 16))))]
4324 "TARGET_SH1"
4325 "xtrct %1,%0"
4326 [(set_attr "type" "arith")])
4327
4328 (define_insn "xtrct_right"
4329 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4330 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4331 (const_int 16))
4332 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
4333 (const_int 16))))]
4334 "TARGET_SH1"
4335 "xtrct %2,%0"
4336 [(set_attr "type" "arith")])
4337
4338 ;; -------------------------------------------------------------------------
4339 ;; Unary arithmetic
4340 ;; -------------------------------------------------------------------------
4341
4342 (define_expand "negc"
4343 [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
4344 (neg:SI (plus:SI (reg:SI T_REG)
4345 (match_operand:SI 1 "arith_reg_operand" ""))))
4346 (set (reg:SI T_REG)
4347 (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
4348 (const_int 0)))])]
4349 ""
4350 "")
4351
4352 (define_insn "*negc"
4353 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4354 (neg:SI (plus:SI (reg:SI T_REG)
4355 (match_operand:SI 1 "arith_reg_operand" "r"))))
4356 (set (reg:SI T_REG)
4357 (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
4358 (const_int 0)))]
4359 "TARGET_SH1"
4360 "negc %1,%0"
4361 [(set_attr "type" "arith")])
4362
4363 (define_insn "*negdi_media"
4364 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4365 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
4366 "TARGET_SHMEDIA"
4367 "sub r63, %1, %0"
4368 [(set_attr "type" "arith_media")])
4369
4370 ;; Don't expand immediately because otherwise neg:DI (abs:DI) will not be
4371 ;; combined.
4372 (define_expand "negdi2"
4373 [(set (match_operand:DI 0 "arith_reg_dest" "")
4374 (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))
4375 (clobber (reg:SI T_REG))]
4376 "TARGET_SH1"
4377 "")
4378
4379 (define_insn_and_split "*negdi2"
4380 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4381 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
4382 "TARGET_SH1"
4383 "#"
4384 "TARGET_SH1"
4385 [(const_int 0)]
4386 {
4387 rtx low_src = gen_lowpart (SImode, operands[1]);
4388 rtx high_src = gen_highpart (SImode, operands[1]);
4389 rtx low_dst = gen_lowpart (SImode, operands[0]);
4390 rtx high_dst = gen_highpart (SImode, operands[0]);
4391
4392 emit_insn (gen_clrt ());
4393 emit_insn (gen_negc (low_dst, low_src));
4394 emit_insn (gen_negc (high_dst, high_src));
4395 DONE;
4396 })
4397
4398 (define_insn "negsi2"
4399 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4400 (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4401 "TARGET_SH1"
4402 "neg %1,%0"
4403 [(set_attr "type" "arith")])
4404
4405 (define_insn "one_cmplsi2"
4406 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4407 (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4408 "TARGET_SH1"
4409 "not %1,%0"
4410 [(set_attr "type" "arith")])
4411
4412 (define_expand "one_cmpldi2"
4413 [(set (match_operand:DI 0 "arith_reg_dest" "")
4414 (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
4415 (const_int -1)))]
4416 "TARGET_SHMEDIA" "")
4417
4418 (define_expand "abssi2"
4419 [(set (match_operand:SI 0 "arith_reg_dest" "")
4420 (abs:SI (match_operand:SI 1 "arith_reg_operand" "")))
4421 (clobber (reg:SI T_REG))]
4422 "TARGET_SH1"
4423 "")
4424
4425 (define_insn_and_split "*abssi2"
4426 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4427 (abs:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4428 "TARGET_SH1"
4429 "#"
4430 "TARGET_SH1"
4431 [(const_int 0)]
4432 {
4433 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
4434 emit_insn (gen_negsi_cond (operands[0], operands[1], operands[1],
4435 const1_rtx));
4436 DONE;
4437 })
4438
4439 (define_insn_and_split "*negabssi2"
4440 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4441 (neg:SI (abs:SI (match_operand:SI 1 "arith_reg_operand" "r"))))]
4442 "TARGET_SH1"
4443 "#"
4444 "TARGET_SH1"
4445 [(const_int 0)]
4446 {
4447 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
4448 emit_insn (gen_negsi_cond (operands[0], operands[1], operands[1],
4449 const0_rtx));
4450 DONE;
4451 })
4452
4453 ;; The SH4 202 can do zero-offset branches without pipeline stalls.
4454 ;; This can be used as some kind of conditional execution, which is useful
4455 ;; for abs.
4456 ;; Actually the instruction scheduling should decide whether to use a
4457 ;; zero-offset branch or not for any generic case involving a single
4458 ;; instruction on SH4 202.
4459
4460 (define_insn_and_split "negsi_cond"
4461 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4462 (if_then_else:SI (eq:SI (reg:SI T_REG)
4463 (match_operand:SI 3 "const_int_operand" "M,N"))
4464 (match_operand:SI 1 "arith_reg_operand" "0,0")
4465 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
4466 "TARGET_HARD_SH4"
4467 "@
4468 bt\\t0f\;neg\\t%2,%0\\n0:
4469 bf\\t0f\;neg\\t%2,%0\\n0:"
4470 "!TARGET_HARD_SH4"
4471 [(const_int 0)]
4472 {
4473 rtx skip_neg_label = gen_label_rtx ();
4474
4475 emit_insn (gen_movsi (operands[0], operands[1]));
4476
4477 emit_jump_insn (INTVAL (operands[3])
4478 ? gen_branch_true (skip_neg_label, get_t_reg_rtx ())
4479 : gen_branch_false (skip_neg_label, get_t_reg_rtx ()));
4480
4481 emit_label_after (skip_neg_label,
4482 emit_insn (gen_negsi2 (operands[0], operands[1])));
4483 DONE;
4484 }
4485 [(set_attr "type" "arith") ;; poor approximation
4486 (set_attr "length" "4")])
4487
4488 (define_expand "absdi2"
4489 [(set (match_operand:DI 0 "arith_reg_dest" "")
4490 (abs:DI (match_operand:DI 1 "arith_reg_operand" "")))
4491 (clobber (reg:SI T_REG))]
4492 "TARGET_SH1"
4493 "")
4494
4495 (define_insn_and_split "*absdi2"
4496 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4497 (abs:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
4498 "TARGET_SH1"
4499 "#"
4500 "&& reload_completed"
4501 [(const_int 0)]
4502 {
4503 rtx high_src = gen_highpart (SImode, operands[1]);
4504 emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
4505 emit_insn (gen_negdi_cond (operands[0], operands[1], operands[1],
4506 const1_rtx));
4507 DONE;
4508 })
4509
4510 (define_insn_and_split "*negabsdi2"
4511 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4512 (neg:DI (abs:DI (match_operand:DI 1 "arith_reg_operand" "r"))))]
4513 "TARGET_SH1"
4514 "#"
4515 "&& reload_completed"
4516 [(const_int 0)]
4517 {
4518 rtx high_src = gen_highpart (SImode, operands[1]);
4519 emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
4520 emit_insn (gen_negdi_cond (operands[0], operands[1], operands[1],
4521 const0_rtx));
4522 DONE;
4523 })
4524
4525 (define_insn_and_split "negdi_cond"
4526 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4527 (if_then_else:DI (eq:SI (reg:SI T_REG)
4528 (match_operand:SI 3 "const_int_operand" "M,N"))
4529 (match_operand:DI 1 "arith_reg_operand" "r,r")
4530 (neg:DI (match_operand:DI 2 "arith_reg_operand" "1,1"))))]
4531 "TARGET_SH1"
4532 "#"
4533 "TARGET_SH1"
4534 [(const_int 0)]
4535 {
4536 rtx low_src = gen_lowpart (SImode, operands[1]);
4537 rtx high_src = gen_highpart (SImode, operands[1]);
4538 rtx low_dst = gen_lowpart (SImode, operands[0]);
4539 rtx high_dst = gen_highpart (SImode, operands[0]);
4540
4541 rtx skip_neg_label = gen_label_rtx ();
4542
4543 emit_insn (gen_movsi (low_dst, low_src));
4544 emit_insn (gen_movsi (high_dst, high_src));
4545
4546 emit_jump_insn (INTVAL (operands[3])
4547 ? gen_branch_true (skip_neg_label, get_t_reg_rtx ())
4548 : gen_branch_false (skip_neg_label, get_t_reg_rtx ()));
4549
4550 if (!INTVAL (operands[3]))
4551 emit_insn (gen_clrt ());
4552
4553 emit_insn (gen_negc (low_dst, low_src));
4554 emit_label_after (skip_neg_label, emit_insn (gen_negc (high_dst, high_src)));
4555 DONE;
4556 })
4557
4558 (define_expand "bswapsi2"
4559 [(set (match_operand:SI 0 "arith_reg_dest" "")
4560 (bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))]
4561 "TARGET_SH1"
4562 {
4563 if (! can_create_pseudo_p ())
4564 FAIL;
4565 else
4566 {
4567 rtx tmp0 = gen_reg_rtx (SImode);
4568 rtx tmp1 = gen_reg_rtx (SImode);
4569
4570 emit_insn (gen_swapbsi2 (tmp0, operands[1]));
4571 emit_insn (gen_rotlsi3_16 (tmp1, tmp0));
4572 emit_insn (gen_swapbsi2 (operands[0], tmp1));
4573 DONE;
4574 }
4575 })
4576
4577 (define_insn "swapbsi2"
4578 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4579 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
4580 (const_int 4294901760))
4581 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
4582 (const_int 65280))
4583 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
4584 (const_int 255)))))]
4585 "TARGET_SH1"
4586 "swap.b %1,%0"
4587 [(set_attr "type" "arith")])
4588
4589 ;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying
4590 ;; partial byte swap expressions such as...
4591 ;; ((x & 0xFF) << 8) | ((x >> 8) & 0xFF).
4592 ;; ...which are currently not handled by the tree optimizers.
4593 ;; The combine pass will not initially try to combine the full expression,
4594 ;; but only some sub-expressions. In such a case the *swapbisi2_and_shl8
4595 ;; pattern acts as an intermediate pattern that will eventually lead combine
4596 ;; to the swapbsi2 pattern above.
4597 ;; As a side effect this also improves code that does (x & 0xFF) << 8
4598 ;; or (x << 8) & 0xFF00.
4599 (define_insn_and_split "*swapbisi2_and_shl8"
4600 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4601 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
4602 (const_int 8))
4603 (const_int 65280))
4604 (match_operand:SI 2 "arith_reg_operand" "r")))]
4605 "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
4606 "#"
4607 "&& can_create_pseudo_p ()"
4608 [(const_int 0)]
4609 {
4610 rtx tmp0 = gen_reg_rtx (SImode);
4611 rtx tmp1 = gen_reg_rtx (SImode);
4612
4613 emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1])));
4614 emit_insn (gen_swapbsi2 (tmp1, tmp0));
4615 emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2]));
4616 DONE;
4617 })
4618
4619 ;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another
4620 ;; intermediate pattern that will help the combine pass arriving at swapbsi2.
4621 (define_insn_and_split "*swapbhisi2"
4622 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4623 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
4624 (const_int 8))
4625 (const_int 65280))
4626 (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))]
4627 "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
4628 "#"
4629 "&& can_create_pseudo_p ()"
4630 [(const_int 0)]
4631 {
4632 rtx tmp = gen_reg_rtx (SImode);
4633
4634 emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1])));
4635 emit_insn (gen_swapbsi2 (operands[0], tmp));
4636 DONE;
4637 })
4638
4639 ;; In some cases the swapbsi2 pattern might leave a sequence such as...
4640 ;; swap.b r4,r4
4641 ;; mov r4,r0
4642 ;;
4643 ;; which can be simplified to...
4644 ;; swap.b r4,r0
4645 (define_peephole2
4646 [(set (match_operand:SI 0 "arith_reg_dest" "")
4647 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
4648 (const_int 4294901760))
4649 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
4650 (const_int 65280))
4651 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
4652 (const_int 255)))))
4653 (set (match_operand:SI 2 "arith_reg_dest" "")
4654 (match_dup 0))]
4655 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
4656 [(set (match_dup 2)
4657 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
4658 (const_int 4294901760))
4659 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
4660 (const_int 65280))
4661 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
4662 (const_int 255)))))])
4663
4664 \f
4665 ;; -------------------------------------------------------------------------
4666 ;; Zero extension instructions
4667 ;; -------------------------------------------------------------------------
4668
4669 (define_insn "zero_extendsidi2"
4670 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4671 (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
4672 "TARGET_SHMEDIA"
4673 "addz.l %1, r63, %0"
4674 [(set_attr "type" "arith_media")
4675 (set_attr "highpart" "extend")])
4676
4677 (define_insn "zero_extendhidi2"
4678 [(set (match_operand:DI 0 "register_operand" "=r,r")
4679 (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4680 "TARGET_SHMEDIA"
4681 "@
4682 #
4683 ld%M1.uw %m1, %0"
4684 [(set_attr "type" "*,load_media")
4685 (set (attr "highpart")
4686 (cond [(match_test "sh_contains_memref_p (insn)")
4687 (const_string "user")]
4688 (const_string "ignore")))])
4689
4690 (define_split
4691 [(set (match_operand:DI 0 "register_operand" "")
4692 (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4693 "TARGET_SHMEDIA && reload_completed"
4694 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4695 (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
4696 {
4697 if (GET_CODE (operands[1]) == TRUNCATE)
4698 operands[1] = XEXP (operands[1], 0);
4699 })
4700
4701 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
4702 ;; reload the entire truncate expression.
4703 (define_insn_and_split "*loaddi_trunc"
4704 [(set (match_operand 0 "any_register_operand" "=r")
4705 (truncate (match_operand:DI 1 "memory_operand" "m")))]
4706 "TARGET_SHMEDIA && reload_completed"
4707 "#"
4708 "TARGET_SHMEDIA && reload_completed"
4709 [(set (match_dup 0) (match_dup 1))]
4710 {
4711 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
4712 })
4713
4714 (define_insn "zero_extendqidi2"
4715 [(set (match_operand:DI 0 "register_operand" "=r,r")
4716 (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4717 "TARGET_SHMEDIA"
4718 "@
4719 andi %1, 255, %0
4720 ld%M1.ub %m1, %0"
4721 [(set_attr "type" "arith_media,load_media")
4722 (set (attr "highpart")
4723 (cond [(match_test "sh_contains_memref_p (insn)")
4724 (const_string "user")]
4725 (const_string "ignore")))])
4726
4727 (define_expand "zero_extendhisi2"
4728 [(set (match_operand:SI 0 "arith_reg_dest" "")
4729 (zero_extend:SI (match_operand:HI 1 "zero_extend_operand" "")))])
4730
4731 (define_insn "*zero_extendhisi2_compact"
4732 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4733 (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))]
4734 "TARGET_SH1"
4735 "extu.w %1,%0"
4736 [(set_attr "type" "arith")])
4737
4738 (define_insn "*zero_extendhisi2_media"
4739 [(set (match_operand:SI 0 "register_operand" "=r,r")
4740 (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4741 "TARGET_SHMEDIA"
4742 "@
4743 #
4744 ld%M1.uw %m1, %0"
4745 [(set_attr "type" "arith_media,load_media")
4746 (set (attr "highpart")
4747 (cond [(match_test "sh_contains_memref_p (insn)")
4748 (const_string "user")]
4749 (const_string "ignore")))])
4750
4751 (define_split
4752 [(set (match_operand:SI 0 "register_operand" "")
4753 (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4754 "TARGET_SHMEDIA && reload_completed"
4755 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4756 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4757 {
4758 rtx op1 = operands[1];
4759
4760 if (GET_CODE (op1) == TRUNCATE)
4761 op1 = XEXP (op1, 0);
4762 operands[2]
4763 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4764 subreg_lowpart_offset (SImode, GET_MODE (op1)));
4765 })
4766
4767 (define_expand "zero_extendqisi2"
4768 [(set (match_operand:SI 0 "arith_reg_dest" "")
4769 (zero_extend:SI (match_operand:QI 1 "zero_extend_operand" "")))])
4770
4771 (define_insn "*zero_extendqisi2_compact"
4772 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4773 (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))]
4774 "TARGET_SH1"
4775 "extu.b %1,%0"
4776 [(set_attr "type" "arith")])
4777
4778 (define_insn "*zero_extendqisi2_media"
4779 [(set (match_operand:SI 0 "register_operand" "=r,r")
4780 (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4781 "TARGET_SHMEDIA"
4782 "@
4783 andi %1, 255, %0
4784 ld%M1.ub %m1, %0"
4785 [(set_attr "type" "arith_media,load_media")
4786 (set (attr "highpart")
4787 (cond [(match_test "sh_contains_memref_p (insn)")
4788 (const_string "user")]
4789 (const_string "ignore")))])
4790
4791 (define_insn "zero_extendqihi2"
4792 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4793 (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
4794 "TARGET_SH1"
4795 "extu.b %1,%0"
4796 [(set_attr "type" "arith")])
4797
4798 ;; -------------------------------------------------------------------------
4799 ;; Sign extension instructions
4800 ;; -------------------------------------------------------------------------
4801
4802 ;; ??? This should be a define expand.
4803 ;; ??? Or perhaps it should be dropped?
4804
4805 ;; convert_move generates good code for SH[1-4].
4806 (define_insn "extendsidi2"
4807 [(set (match_operand:DI 0 "register_operand" "=r,r,r")
4808 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
4809 "TARGET_SHMEDIA"
4810 "@
4811 add.l %1, r63, %0
4812 ld%M1.l %m1, %0
4813 fmov.sl %1, %0"
4814 [(set_attr "type" "arith_media,load_media,fpconv_media")
4815 (set (attr "highpart")
4816 (cond [(match_test "sh_contains_memref_p (insn)")
4817 (const_string "user")]
4818 (const_string "extend")))])
4819
4820 (define_insn "extendhidi2"
4821 [(set (match_operand:DI 0 "register_operand" "=r,r")
4822 (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4823 "TARGET_SHMEDIA"
4824 "@
4825 #
4826 ld%M1.w %m1, %0"
4827 [(set_attr "type" "*,load_media")
4828 (set (attr "highpart")
4829 (cond [(match_test "sh_contains_memref_p (insn)")
4830 (const_string "user")]
4831 (const_string "ignore")))])
4832
4833 (define_split
4834 [(set (match_operand:DI 0 "register_operand" "")
4835 (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4836 "TARGET_SHMEDIA && reload_completed"
4837 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4838 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
4839 {
4840 if (GET_CODE (operands[1]) == TRUNCATE)
4841 operands[1] = XEXP (operands[1], 0);
4842 })
4843
4844 (define_insn "extendqidi2"
4845 [(set (match_operand:DI 0 "register_operand" "=r,r")
4846 (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4847 "TARGET_SHMEDIA"
4848 "@
4849 #
4850 ld%M1.b %m1, %0"
4851 [(set_attr "type" "*,load_media")
4852 (set (attr "highpart")
4853 (cond [(match_test "sh_contains_memref_p (insn)")
4854 (const_string "user")]
4855 (const_string "ignore")))])
4856
4857 (define_split
4858 [(set (match_operand:DI 0 "register_operand" "")
4859 (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
4860 "TARGET_SHMEDIA && reload_completed"
4861 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
4862 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
4863 {
4864 if (GET_CODE (operands[1]) == TRUNCATE)
4865 operands[1] = XEXP (operands[1], 0);
4866 })
4867
4868 ;; FIXME: Maybe fold HImode and QImode stuff with mode iterator?
4869 (define_expand "extendhisi2"
4870 [(set (match_operand:SI 0 "arith_reg_dest" "")
4871 (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "")))]
4872 ""
4873 "")
4874
4875 (define_expand "extendqisi2"
4876 [(set (match_operand:SI 0 "arith_reg_dest" "")
4877 (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
4878 ""
4879 "")
4880
4881 (define_insn "*extendhisi2_media"
4882 [(set (match_operand:SI 0 "register_operand" "=r,r")
4883 (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4884 "TARGET_SHMEDIA"
4885 "@
4886 #
4887 ld%M1.w %m1, %0"
4888 [(set_attr "type" "arith_media,load_media")
4889 (set (attr "highpart")
4890 (cond [(match_test "sh_contains_memref_p (insn)")
4891 (const_string "user")]
4892 (const_string "ignore")))])
4893
4894 (define_split
4895 [(set (match_operand:SI 0 "register_operand" "")
4896 (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4897 "TARGET_SHMEDIA && reload_completed"
4898 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4899 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4900 {
4901 rtx op1 = operands[1];
4902 if (GET_CODE (op1) == TRUNCATE)
4903 op1 = XEXP (op1, 0);
4904 operands[2]
4905 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4906 subreg_lowpart_offset (SImode, GET_MODE (op1)));
4907 })
4908
4909 (define_insn "*extendqisi2_compact_reg"
4910 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4911 (sign_extend:SI (match_operand:QI 1 "register_operand" "r,t")))]
4912 "TARGET_SH1"
4913 "@
4914 exts.b %1,%0
4915 movt %0"
4916 [(set_attr "type" "arith,arith")])
4917
4918 (define_insn "*extendhisi2_compact_reg"
4919 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4920 (sign_extend:SI (match_operand:HI 1 "register_operand" "r,t")))]
4921 "TARGET_SH1"
4922 "@
4923 exts.w %1,%0
4924 movt %0"
4925 [(set_attr "type" "arith,arith")])
4926
4927 ;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute.
4928 ;; See movqi insns.
4929 (define_insn "*extendqisi2_compact_mem_disp"
4930 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
4931 (sign_extend:SI
4932 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
4933 (match_operand:SI 2 "const_int_operand" "K04,N")))))]
4934 "TARGET_SH1 && ! TARGET_SH2A
4935 && sh_legitimate_index_p (QImode, operands[2], false, true)"
4936 "@
4937 mov.b @(%O2,%1),%0
4938 mov.b @%1,%0"
4939 [(set_attr "type" "load")])
4940
4941 (define_insn "*extendhisi2_compact_mem_disp"
4942 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
4943 (sign_extend:SI
4944 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
4945 (match_operand:SI 2 "const_int_operand" "K05,N")))))]
4946 "TARGET_SH1 && ! TARGET_SH2A
4947 && sh_legitimate_index_p (HImode, operands[2], false, true)"
4948 "@
4949 mov.w @(%O2,%1),%0
4950 mov.w @%1,%0"
4951 [(set_attr "type" "load")])
4952
4953 (define_insn "*extendqisi2_compact_mem_disp"
4954 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
4955 (sign_extend:SI
4956 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
4957 (match_operand:SI 2 "const_int_operand" "K04,N,K12")))))]
4958 "TARGET_SH2A && sh_legitimate_index_p (QImode, operands[2], true, true)"
4959 "@
4960 mov.b @(%O2,%1),%0
4961 mov.b @%1,%0
4962 mov.b @(%O2,%1),%0"
4963 [(set_attr "type" "load")
4964 (set_attr "length" "2,2,4")])
4965
4966 (define_insn "*extendhisi2_compact_mem_disp"
4967 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
4968 (sign_extend:SI
4969 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
4970 (match_operand:SI 2 "const_int_operand" "K05,N,K13")))))]
4971 "TARGET_SH2A && sh_legitimate_index_p (HImode, operands[2], true, true)"
4972 "@
4973 mov.w @(%O2,%1),%0
4974 mov.w @%1,%0
4975 mov.w @(%O2,%1),%0"
4976 [(set_attr "type" "load")
4977 (set_attr "length" "2,2,4")])
4978
4979 ;; The *_snd patterns will take care of other QImode/HImode addressing
4980 ;; modes than displacement addressing. They must be defined _after_ the
4981 ;; displacement addressing patterns. Otherwise the displacement addressing
4982 ;; patterns will not be picked.
4983 (define_insn "*extendqisi2_compact_snd"
4984 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4985 (sign_extend:SI (match_operand:QI 1 "movsrc_no_disp_mem_operand" "Snd")))]
4986 "TARGET_SH1"
4987 "mov.b %1,%0"
4988 [(set_attr "type" "load")])
4989
4990 (define_insn "*extendhisi2_compact_snd"
4991 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4992 (sign_extend:SI (match_operand:HI 1 "movsrc_no_disp_mem_operand" "Snd")))]
4993 "TARGET_SH1"
4994 "mov.w %1,%0"
4995 [(set_attr "type" "load")])
4996
4997 (define_insn "*extendqisi2_media"
4998 [(set (match_operand:SI 0 "register_operand" "=r,r")
4999 (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5000 "TARGET_SHMEDIA"
5001 "@
5002 #
5003 ld%M1.b %m1, %0"
5004 [(set_attr "type" "arith_media,load_media")
5005 (set (attr "highpart")
5006 (cond [(match_test "sh_contains_memref_p (insn)")
5007 (const_string "user")]
5008 (const_string "ignore")))])
5009
5010 (define_split
5011 [(set (match_operand:SI 0 "register_operand" "")
5012 (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
5013 "TARGET_SHMEDIA && reload_completed"
5014 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5015 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5016 {
5017 rtx op1 = operands[1];
5018 if (GET_CODE (op1) == TRUNCATE)
5019 op1 = XEXP (op1, 0);
5020 operands[2]
5021 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
5022 subreg_lowpart_offset (SImode, GET_MODE (op1)));
5023 })
5024
5025 (define_expand "extendqihi2"
5026 [(set (match_operand:HI 0 "arith_reg_dest" "")
5027 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "")))]
5028 ""
5029 "")
5030
5031 (define_insn "*extendqihi2_compact_reg"
5032 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
5033 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
5034 "TARGET_SH1"
5035 "exts.b %1,%0"
5036 [(set_attr "type" "arith")])
5037
5038 ;; It would seem useful to combine the truncXi patterns into the movXi
5039 ;; patterns, but unary operators are ignored when matching constraints,
5040 ;; so we need separate patterns.
5041 (define_insn "truncdisi2"
5042 [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
5043 (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
5044 "TARGET_SHMEDIA"
5045 "@
5046 add.l %1, r63, %0
5047 st%M0.l %m0, %1
5048 fst%M0.s %m0, %T1
5049 fmov.ls %1, %0
5050 fmov.sl %T1, %0
5051 fmov.s %T1, %0"
5052 [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")
5053 (set (attr "highpart")
5054 (cond [(match_test "sh_contains_memref_p (insn)")
5055 (const_string "user")]
5056 (const_string "extend")))])
5057
5058 (define_insn "truncdihi2"
5059 [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
5060 (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
5061 "TARGET_SHMEDIA"
5062 "@
5063 shlli\\t%1,48,%0\;shlri\\t%0,48,%0
5064 st%M0.w %m0, %1"
5065 [(set_attr "type" "arith_media,store_media")
5066 (set_attr "length" "8,4")
5067 (set (attr "highpart")
5068 (cond [(match_test "sh_contains_memref_p (insn)")
5069 (const_string "user")]
5070 (const_string "extend")))])
5071
5072 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
5073 ; Because we use zero extension, we can't provide signed QImode compares
5074 ; using a simple compare or conditional branch insn.
5075 (define_insn "truncdiqi2"
5076 [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
5077 (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
5078 "TARGET_SHMEDIA"
5079 "@
5080 andi %1, 255, %0
5081 st%M0.b %m0, %1"
5082 [(set_attr "type" "arith_media,store")
5083 (set (attr "highpart")
5084 (cond [(match_test "sh_contains_memref_p (insn)")
5085 (const_string "user")]
5086 (const_string "extend")))])
5087 ;; -------------------------------------------------------------------------
5088 ;; Move instructions
5089 ;; -------------------------------------------------------------------------
5090
5091 ;; define push and pop so it is easy for sh.c
5092 ;; We can't use push and pop on SHcompact because the stack must always
5093 ;; be 8-byte aligned.
5094
5095 (define_expand "push"
5096 [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
5097 (match_operand:SI 0 "register_operand" "r,l,x"))]
5098 "TARGET_SH1 && ! TARGET_SH5"
5099 "")
5100
5101 (define_expand "pop"
5102 [(set (match_operand:SI 0 "register_operand" "=r,l,x")
5103 (mem:SI (post_inc:SI (reg:SI SP_REG))))]
5104 "TARGET_SH1 && ! TARGET_SH5"
5105 "")
5106
5107 (define_expand "push_e"
5108 [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
5109 (match_operand:SF 0 "" ""))
5110 (use (reg:PSI FPSCR_REG))
5111 (clobber (scratch:SI))])]
5112 "TARGET_SH1 && ! TARGET_SH5"
5113 "")
5114
5115 (define_insn "push_fpul"
5116 [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
5117 "TARGET_SH2E && ! TARGET_SH5"
5118 "sts.l fpul,@-r15"
5119 [(set_attr "type" "fstore")
5120 (set_attr "late_fp_use" "yes")
5121 (set_attr "hit_stack" "yes")])
5122
5123 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
5124 ;; so use that.
5125 (define_expand "push_4"
5126 [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
5127 (match_operand:DF 0 "" ""))
5128 (use (reg:PSI FPSCR_REG))
5129 (clobber (scratch:SI))])]
5130 "TARGET_SH1 && ! TARGET_SH5"
5131 "")
5132
5133 (define_expand "pop_e"
5134 [(parallel [(set (match_operand:SF 0 "" "")
5135 (mem:SF (post_inc:SI (reg:SI SP_REG))))
5136 (use (reg:PSI FPSCR_REG))
5137 (clobber (scratch:SI))])]
5138 "TARGET_SH1 && ! TARGET_SH5"
5139 "")
5140
5141 (define_insn "pop_fpul"
5142 [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
5143 "TARGET_SH2E && ! TARGET_SH5"
5144 "lds.l @r15+,fpul"
5145 [(set_attr "type" "load")
5146 (set_attr "hit_stack" "yes")])
5147
5148 (define_expand "pop_4"
5149 [(parallel [(set (match_operand:DF 0 "" "")
5150 (mem:DF (post_inc:SI (reg:SI SP_REG))))
5151 (use (reg:PSI FPSCR_REG))
5152 (clobber (scratch:SI))])]
5153 "TARGET_SH1 && ! TARGET_SH5"
5154 "")
5155
5156 (define_expand "push_fpscr"
5157 [(const_int 0)]
5158 "TARGET_SH2E"
5159 {
5160 rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
5161 gen_rtx_PRE_DEC (Pmode,
5162 stack_pointer_rtx)),
5163 get_fpscr_rtx ()));
5164 add_reg_note (insn, REG_INC, stack_pointer_rtx);
5165 DONE;
5166 })
5167
5168 (define_expand "pop_fpscr"
5169 [(const_int 0)]
5170 "TARGET_SH2E"
5171 {
5172 rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
5173 gen_frame_mem (PSImode,
5174 gen_rtx_POST_INC (Pmode,
5175 stack_pointer_rtx))));
5176 add_reg_note (insn, REG_INC, stack_pointer_rtx);
5177 DONE;
5178 })
5179
5180 ;; These two patterns can happen as the result of optimization, when
5181 ;; comparisons get simplified to a move of zero or 1 into the T reg.
5182 ;; They don't disappear completely, because the T reg is a fixed hard reg.
5183
5184 (define_insn "clrt"
5185 [(set (reg:SI T_REG) (const_int 0))]
5186 "TARGET_SH1"
5187 "clrt")
5188
5189 (define_insn "sett"
5190 [(set (reg:SI T_REG) (const_int 1))]
5191 "TARGET_SH1"
5192 "sett")
5193
5194 ;; Define additional pop for SH1 and SH2 so it does not get
5195 ;; placed in the delay slot.
5196 (define_insn "*movsi_pop"
5197 [(set (match_operand:SI 0 "register_operand" "=r,x,l")
5198 (match_operand:SI 1 "sh_no_delay_pop_operand" ">,>,>"))]
5199 "(TARGET_SH1 || TARGET_SH2E || TARGET_SH2A)
5200 && ! TARGET_SH3"
5201 "@
5202 mov.l %1,%0
5203 lds.l %1,%0
5204 lds.l %1,%0"
5205 [(set_attr "type" "load_si,mem_mac,pload")
5206 (set_attr "length" "2,2,2")
5207 (set_attr "in_delay_slot" "no,no,no")])
5208
5209 ;; t/r must come after r/r, lest reload will try to reload stuff like
5210 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
5211 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
5212 (define_insn "movsi_i"
5213 [(set (match_operand:SI 0 "general_movdst_operand"
5214 "=r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
5215 (match_operand:SI 1 "general_movsrc_operand"
5216 "Q,r,I08,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
5217 "TARGET_SH1
5218 && ! TARGET_SH2E
5219 && ! TARGET_SH2A
5220 && (register_operand (operands[0], SImode)
5221 || register_operand (operands[1], SImode))"
5222 "@
5223 mov.l %1,%0
5224 mov %1,%0
5225 mov %1,%0
5226 cmp/pl %1
5227 mov.l %1,%0
5228 sts %1,%0
5229 sts %1,%0
5230 movt %0
5231 mov.l %1,%0
5232 sts.l %1,%0
5233 sts.l %1,%0
5234 lds %1,%0
5235 lds %1,%0
5236 lds.l %1,%0
5237 lds.l %1,%0
5238 fake %1,%0"
5239 [(set_attr "type" "pcload_si,move,movi8,mt_group,load_si,mac_gp,prget,arith,store,mac_mem,pstore,gp_mac,prset,mem_mac,pload,pcload_si")
5240 (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
5241
5242 ;; t/r must come after r/r, lest reload will try to reload stuff like
5243 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
5244 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
5245 ;; will require a reload.
5246 ;; ??? We can't include f/f because we need the proper FPSCR setting when
5247 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
5248 (define_insn "movsi_ie"
5249 [(set (match_operand:SI 0 "general_movdst_operand"
5250 "=r,r,r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
5251 (match_operand:SI 1 "general_movsrc_operand"
5252 "Q,r,I08,I20,I28,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
5253 "(TARGET_SH2E || TARGET_SH2A)
5254 && (register_operand (operands[0], SImode)
5255 || register_operand (operands[1], SImode))"
5256 "@
5257 mov.l %1,%0
5258 mov %1,%0
5259 mov %1,%0
5260 movi20 %1,%0
5261 movi20s %1,%0
5262 cmp/pl %1
5263 mov.l %1,%0
5264 sts %1,%0
5265 sts %1,%0
5266 movt %0
5267 mov.l %1,%0
5268 sts.l %1,%0
5269 sts.l %1,%0
5270 lds %1,%0
5271 lds %1,%0
5272 lds.l %1,%0
5273 lds.l %1,%0
5274 lds.l %1,%0
5275 sts.l %1,%0
5276 fake %1,%0
5277 lds %1,%0
5278 sts %1,%0
5279 fsts fpul,%0
5280 flds %1,fpul
5281 fmov %1,%0
5282 ! move optimized away"
5283 [(set_attr "type" "pcload_si,move,movi8,move,move,*,load_si,mac_gp,prget,arith,store,mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore,pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
5284 (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
5285 (set_attr_alternative "length"
5286 [(const_int 2)
5287 (const_int 2)
5288 (const_int 2)
5289 (const_int 4)
5290 (const_int 4)
5291 (const_int 2)
5292 (if_then_else
5293 (match_test "TARGET_SH2A")
5294 (const_int 4) (const_int 2))
5295 (const_int 2)
5296 (const_int 2)
5297 (const_int 2)
5298 (if_then_else
5299 (match_test "TARGET_SH2A")
5300 (const_int 4) (const_int 2))
5301 (const_int 2)
5302 (const_int 2)
5303 (const_int 2)
5304 (const_int 2)
5305 (const_int 2)
5306 (const_int 2)
5307 (const_int 2)
5308 (const_int 2)
5309 (const_int 2)
5310 (const_int 2)
5311 (const_int 2)
5312 (const_int 2)
5313 (const_int 2)
5314 (const_int 2)
5315 (const_int 0)])])
5316
5317 (define_insn "movsi_i_lowpart"
5318 [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,r,m,r"))
5319 (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,t,r,i"))]
5320 "TARGET_SH1
5321 && (register_operand (operands[0], SImode)
5322 || register_operand (operands[1], SImode))"
5323 "@
5324 mov.l %1,%0
5325 mov %1,%0
5326 mov %1,%0
5327 mov.l %1,%0
5328 sts %1,%0
5329 sts %1,%0
5330 movt %0
5331 mov.l %1,%0
5332 fake %1,%0"
5333 [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,arith,store,pcload")])
5334
5335 (define_insn_and_split "load_ra"
5336 [(set (match_operand:SI 0 "general_movdst_operand" "")
5337 (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
5338 "TARGET_SH1"
5339 "#"
5340 "&& ! currently_expanding_to_rtl"
5341 [(set (match_dup 0) (match_dup 1))]
5342 {
5343 if (TARGET_SHCOMPACT && crtl->saves_all_registers)
5344 operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
5345 })
5346
5347 ;; The '?'s in the following constraints may not reflect the time taken
5348 ;; to perform the move. They are there to discourage the use of floating-
5349 ;; point registers for storing integer values.
5350 (define_insn "*movsi_media"
5351 [(set (match_operand:SI 0 "general_movdst_operand"
5352 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
5353 (match_operand:SI 1 "general_movsrc_operand"
5354 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5355 "TARGET_SHMEDIA_FPU
5356 && (register_operand (operands[0], SImode)
5357 || sh_register_operand (operands[1], SImode)
5358 || GET_CODE (operands[1]) == TRUNCATE)"
5359 "@
5360 add.l %1, r63, %0
5361 movi %1, %0
5362 #
5363 ld%M1.l %m1, %0
5364 st%M0.l %m0, %N1
5365 fld%M1.s %m1, %0
5366 fst%M0.s %m0, %1
5367 fmov.ls %N1, %0
5368 fmov.sl %1, %0
5369 fmov.s %1, %0
5370 ptabs %1, %0
5371 gettr %1, %0
5372 pt %1, %0"
5373 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,fload_media,fstore_media,fload_media,fpconv_media,fmove_media,ptabs_media,gettr_media,pt_media")
5374 (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
5375 (set (attr "highpart")
5376 (cond [(match_test "sh_contains_memref_p (insn)")
5377 (const_string "user")]
5378 (const_string "ignore")))])
5379
5380 (define_insn "*movsi_media_nofpu"
5381 [(set (match_operand:SI 0 "general_movdst_operand"
5382 "=r,r,r,r,m,*b,r,*b")
5383 (match_operand:SI 1 "general_movsrc_operand"
5384 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
5385 "TARGET_SHMEDIA
5386 && (register_operand (operands[0], SImode)
5387 || sh_register_operand (operands[1], SImode)
5388 || GET_CODE (operands[1]) == TRUNCATE)"
5389 "@
5390 add.l %1, r63, %0
5391 movi %1, %0
5392 #
5393 ld%M1.l %m1, %0
5394 st%M0.l %m0, %N1
5395 ptabs %1, %0
5396 gettr %1, %0
5397 pt %1, %0"
5398 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5399 (set_attr "length" "4,4,8,4,4,4,4,12")
5400 (set (attr "highpart")
5401 (cond [(match_test "sh_contains_memref_p (insn)")
5402 (const_string "user")]
5403 (const_string "ignore")))])
5404
5405 (define_expand "movsi_const"
5406 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5407 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
5408 (const_int 16)] UNSPEC_EXTRACT_S16)))
5409 (set (match_dup 0)
5410 (ior:SI (ashift:SI (match_dup 0) (const_int 16))
5411 (const:SI (unspec:SI [(match_dup 1)
5412 (const_int 0)] UNSPEC_EXTRACT_U16))))]
5413 "TARGET_SHMEDIA && reload_completed
5414 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5415 {
5416 if (GET_CODE (operands[1]) == LABEL_REF
5417 && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
5418 LABEL_NUSES (XEXP (operands[1], 0)) += 2;
5419 else if (GOTOFF_P (operands[1]))
5420 {
5421 rtx unspec = XEXP (operands[1], 0);
5422
5423 if (! UNSPEC_GOTOFF_P (unspec))
5424 {
5425 unspec = XEXP (unspec, 0);
5426 if (! UNSPEC_GOTOFF_P (unspec))
5427 abort ();
5428 }
5429 if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
5430 && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
5431 LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
5432 }
5433 })
5434
5435 (define_expand "movsi_const_16bit"
5436 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5437 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
5438 (const_int 0)] UNSPEC_EXTRACT_S16)))]
5439 "TARGET_SHMEDIA && flag_pic && reload_completed
5440 && GET_CODE (operands[1]) == SYMBOL_REF"
5441 "")
5442
5443 (define_split
5444 [(set (match_operand:SI 0 "arith_reg_dest" "")
5445 (match_operand:SI 1 "immediate_operand" ""))]
5446 "TARGET_SHMEDIA && reload_completed
5447 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5448 [(const_int 0)]
5449 {
5450 rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
5451
5452 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
5453
5454 DONE;
5455 })
5456
5457 (define_split
5458 [(set (match_operand:SI 0 "register_operand" "")
5459 (match_operand:SI 1 "immediate_operand" ""))]
5460 "TARGET_SHMEDIA && reload_completed
5461 && ((CONST_INT_P (operands[1])
5462 && ! satisfies_constraint_I16 (operands[1]))
5463 || GET_CODE (operands[1]) == CONST_DOUBLE)"
5464 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5465
5466 (define_expand "movsi"
5467 [(set (match_operand:SI 0 "general_movdst_operand" "")
5468 (match_operand:SI 1 "general_movsrc_operand" ""))]
5469 ""
5470 {
5471 prepare_move_operands (operands, SImode);
5472 })
5473
5474 (define_expand "ic_invalidate_line"
5475 [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
5476 (match_dup 1)] UNSPEC_ICACHE)
5477 (clobber (scratch:SI))])]
5478 "TARGET_HARD_SH4 || TARGET_SH5"
5479 {
5480 if (TARGET_SHMEDIA)
5481 {
5482 emit_insn (gen_ic_invalidate_line_media (operands[0]));
5483 DONE;
5484 }
5485 else if (TARGET_SHCOMPACT)
5486 {
5487 operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC);
5488 operands[1] = force_reg (Pmode, operands[1]);
5489 emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
5490 DONE;
5491 }
5492 else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
5493 {
5494 emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
5495 DONE;
5496 }
5497 operands[0] = force_reg (Pmode, operands[0]);
5498 operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
5499 Pmode)));
5500 })
5501
5502 ;; The address %0 is assumed to be 4-aligned at least. Thus, by ORing
5503 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
5504 ;; the requirement *1*00 for associative address writes. The alignment of
5505 ;; %0 implies that its least significant bit is cleared,
5506 ;; thus we clear the V bit of a matching entry if there is one.
5507 (define_insn "ic_invalidate_line_i"
5508 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
5509 (match_operand:SI 1 "register_operand" "r")]
5510 UNSPEC_ICACHE)
5511 (clobber (match_scratch:SI 2 "=&r"))]
5512 "TARGET_HARD_SH4"
5513 "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
5514 [(set_attr "length" "8")
5515 (set_attr "type" "cwb")])
5516
5517 (define_insn "ic_invalidate_line_sh4a"
5518 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
5519 UNSPEC_ICACHE)]
5520 "TARGET_SH4A_ARCH || TARGET_SH4_300"
5521 "ocbwb\\t@%0\;synco\;icbi\\t@%0"
5522 [(set_attr "length" "16")
5523 (set_attr "type" "cwb")])
5524
5525 ;; ??? could make arg 0 an offsettable memory operand to allow to save
5526 ;; an add in the code that calculates the address.
5527 (define_insn "ic_invalidate_line_media"
5528 [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
5529 UNSPEC_ICACHE)]
5530 "TARGET_SHMEDIA"
5531 "ocbwb %0,0\;synco\;icbi %0, 0\;synci"
5532 [(set_attr "length" "16")
5533 (set_attr "type" "invalidate_line_media")])
5534
5535 (define_insn "ic_invalidate_line_compact"
5536 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5537 (match_operand:SI 1 "register_operand" "r")]
5538 UNSPEC_ICACHE)
5539 (clobber (reg:SI PR_REG))]
5540 "TARGET_SHCOMPACT"
5541 "jsr @%1%#"
5542 [(set_attr "type" "sfunc")
5543 (set_attr "needs_delay_slot" "yes")])
5544
5545 (define_expand "initialize_trampoline"
5546 [(match_operand:SI 0 "" "")
5547 (match_operand:SI 1 "" "")
5548 (match_operand:SI 2 "" "")]
5549 "TARGET_SHCOMPACT"
5550 {
5551 rtx sfun, tramp;
5552
5553 tramp = force_reg (Pmode, operands[0]);
5554 sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline",
5555 SFUNC_STATIC));
5556 emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
5557 emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
5558
5559 emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
5560 DONE;
5561 })
5562
5563 (define_insn "initialize_trampoline_compact"
5564 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5565 (match_operand:SI 1 "register_operand" "r")
5566 (reg:SI R2_REG) (reg:SI R3_REG)]
5567 UNSPEC_INIT_TRAMP)
5568
5569 (clobber (reg:SI PR_REG))]
5570 "TARGET_SHCOMPACT"
5571 "jsr @%1%#"
5572 [(set_attr "type" "sfunc")
5573 (set_attr "needs_delay_slot" "yes")])
5574
5575 (define_expand "movhi"
5576 [(set (match_operand:HI 0 "general_movdst_operand" "")
5577 (match_operand:HI 1 "general_movsrc_operand" ""))]
5578 ""
5579 {
5580 prepare_move_operands (operands, HImode);
5581 })
5582
5583 (define_expand "movqi"
5584 [(set (match_operand:QI 0 "general_operand" "")
5585 (match_operand:QI 1 "general_operand" ""))]
5586 ""
5587 {
5588 prepare_move_operands (operands, QImode);
5589 })
5590
5591 ;; If movqi_reg_reg is specified as an alternative of movqi, movqi will be
5592 ;; selected to copy QImode regs. If one of them happens to be allocated
5593 ;; on the stack, reload will stick to movqi insn and generate wrong
5594 ;; displacement addressing because of the generic m alternatives.
5595 ;; With the movqi_reg_reg being specified before movqi it will be initially
5596 ;; picked to load/store regs. If the regs regs are on the stack reload will
5597 ;; try other insns and not stick to movqi_reg_reg.
5598 ;; The same applies to the movhi variants.
5599 (define_insn "*movqi_reg_reg"
5600 [(set (match_operand:QI 0 "arith_reg_dest" "=r,r")
5601 (match_operand:QI 1 "register_operand" "r,t"))]
5602 "TARGET_SH1"
5603 "@
5604 mov %1,%0
5605 movt %0"
5606 [(set_attr "type" "move,arith")])
5607
5608 (define_insn "*movhi_reg_reg"
5609 [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
5610 (match_operand:HI 1 "register_operand" "r,t"))]
5611 "TARGET_SH1"
5612 "@
5613 mov %1,%0
5614 movt %0"
5615 [(set_attr "type" "move,arith")])
5616
5617 ;; FIXME: The non-SH2A and SH2A variants should be combined by adding
5618 ;; "enabled" attribute as it is done in other targets.
5619 (define_insn "*movqi_store_mem_disp04"
5620 [(set (mem:QI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
5621 (match_operand:SI 1 "const_int_operand" "K04,N")))
5622 (match_operand:QI 2 "arith_reg_operand" "z,r"))]
5623 "TARGET_SH1 && sh_legitimate_index_p (QImode, operands[1], false, true)"
5624 "@
5625 mov.b %2,@(%O1,%0)
5626 mov.b %2,@%0"
5627 [(set_attr "type" "store")])
5628
5629 (define_insn "*movhi_store_mem_disp05"
5630 [(set (mem:HI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
5631 (match_operand:SI 1 "const_int_operand" "K05,N")))
5632 (match_operand:HI 2 "arith_reg_operand" "z,r"))]
5633 "TARGET_SH1 && sh_legitimate_index_p (HImode, operands[1], false, true)"
5634 "@
5635 mov.w %2,@(%O1,%0)
5636 mov.w %2,@%0"
5637 [(set_attr "type" "store")])
5638
5639 (define_insn "*movqi_store_mem_disp12"
5640 [(set (mem:QI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
5641 (match_operand:SI 1 "const_int_operand" "K12")))
5642 (match_operand:QI 2 "arith_reg_operand" "r"))]
5643 "TARGET_SH2A && sh_legitimate_index_p (QImode, operands[1], true, true)"
5644 "mov.b %2,@(%O1,%0)"
5645 [(set_attr "type" "store")
5646 (set_attr "length" "4")])
5647
5648 (define_insn "*movhi_store_mem_disp13"
5649 [(set (mem:HI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
5650 (match_operand:SI 1 "const_int_operand" "K13")))
5651 (match_operand:HI 2 "arith_reg_operand" "r"))]
5652 "TARGET_SH2A && sh_legitimate_index_p (HImode, operands[1], true, true)"
5653 "mov.w %2,@(%O1,%0)"
5654 [(set_attr "type" "store")
5655 (set_attr "length" "4")])
5656
5657 (define_insn "*movqi_load_mem_disp"
5658 [(set (match_operand:QI 0 "arith_reg_dest" "=z,r")
5659 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
5660 (match_operand:SI 2 "const_int_operand" "K04,N"))))]
5661 "TARGET_SH1 && ! TARGET_SH2A
5662 && sh_legitimate_index_p (QImode, operands[2], false, true)"
5663 "@
5664 mov.b @(%O2,%1),%0
5665 mov.b @%1,%0"
5666 [(set_attr "type" "load")])
5667
5668 (define_insn "*movhi_load_mem_disp"
5669 [(set (match_operand:HI 0 "arith_reg_dest" "=z,r")
5670 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
5671 (match_operand:SI 2 "const_int_operand" "K05,N"))))]
5672 "TARGET_SH1 && ! TARGET_SH2A
5673 && sh_legitimate_index_p (HImode, operands[2], false, true)"
5674 "@
5675 mov.w @(%O2,%1),%0
5676 mov.w @%1,%0"
5677 [(set_attr "type" "load")])
5678
5679 (define_insn "*movqi_load_mem_disp"
5680 [(set (match_operand:QI 0 "arith_reg_dest" "=z,r,r")
5681 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
5682 (match_operand:SI 2 "const_int_operand" "K04,N,K12"))))]
5683 "TARGET_SH2A && sh_legitimate_index_p (QImode, operands[2], true, true)"
5684 "@
5685 mov.b @(%O2,%1),%0
5686 mov.b @%1,%0
5687 mov.b @(%O2,%1),%0"
5688 [(set_attr "type" "load")
5689 (set_attr "length" "2,2,4")])
5690
5691 (define_insn "*movhi_load_mem_disp"
5692 [(set (match_operand:HI 0 "arith_reg_dest" "=z,r,r")
5693 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
5694 (match_operand:SI 2 "const_int_operand" "K05,N,K13"))))]
5695 "TARGET_SH2A && sh_legitimate_index_p (HImode, operands[2], true, true)"
5696 "@
5697 mov.w @(%O2,%1),%0
5698 mov.w @%1,%0
5699 mov.w @(%O2,%1),%0"
5700 [(set_attr "type" "load")
5701 (set_attr "length" "2,2,4")])
5702
5703 ;; The m constraints basically allow any kind of addresses to be used with any
5704 ;; source/target register as the other operand. This is not true for
5705 ;; displacement addressing modes on anything but SH2A. That's why the
5706 ;; specialized load/store insns are specified above.
5707 (define_insn "*movqi"
5708 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,l")
5709 (match_operand:QI 1 "general_movsrc_operand" "i,m,r,l,r"))]
5710 "TARGET_SH1
5711 && (arith_reg_operand (operands[0], QImode)
5712 || arith_reg_operand (operands[1], QImode))"
5713 "@
5714 mov %1,%0
5715 mov.b %1,%0
5716 mov.b %1,%0
5717 sts %1,%0
5718 lds %1,%0"
5719 [(set_attr "type" "movi8,load,store,prget,prset")])
5720
5721 (define_insn "*movhi"
5722 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,m,r,l")
5723 (match_operand:HI 1 "general_movsrc_operand" "Q,i,m,r,l,r"))]
5724 "TARGET_SH1
5725 && (arith_reg_operand (operands[0], HImode)
5726 || arith_reg_operand (operands[1], HImode))"
5727 "@
5728 mov.w %1,%0
5729 mov %1,%0
5730 mov.w %1,%0
5731 mov.w %1,%0
5732 sts %1,%0
5733 lds %1,%0"
5734 [(set_attr "type" "pcload,movi8,load,store,prget,prset")])
5735
5736 (define_insn "*movqi_media"
5737 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
5738 (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
5739 "TARGET_SHMEDIA
5740 && (arith_reg_operand (operands[0], QImode)
5741 || extend_reg_or_0_operand (operands[1], QImode))"
5742 "@
5743 add.l %1, r63, %0
5744 movi %1, %0
5745 ld%M1.ub %m1, %0
5746 st%M0.b %m0, %N1"
5747 [(set_attr "type" "arith_media,arith_media,load_media,store_media")
5748 (set (attr "highpart")
5749 (cond [(match_test "sh_contains_memref_p (insn)")
5750 (const_string "user")]
5751 (const_string "ignore")))])
5752
5753 (define_expand "reload_inqi"
5754 [(set (match_operand:SI 2 "" "=&r")
5755 (match_operand:QI 1 "inqhi_operand" ""))
5756 (set (match_operand:QI 0 "arith_reg_operand" "=r")
5757 (truncate:QI (match_dup 3)))]
5758 "TARGET_SHMEDIA"
5759 {
5760 rtx inner = XEXP (operands[1], 0);
5761 int regno = REGNO (inner);
5762
5763 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5764 operands[1] = gen_rtx_REG (SImode, regno);
5765 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5766 })
5767
5768 (define_insn "*movhi_media"
5769 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m")
5770 (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
5771 "TARGET_SHMEDIA
5772 && (arith_reg_operand (operands[0], HImode)
5773 || arith_reg_or_0_operand (operands[1], HImode))"
5774 "@
5775 add.l %1, r63, %0
5776 movi %1, %0
5777 #
5778 ld%M1.w %m1, %0
5779 st%M0.w %m0, %N1"
5780 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
5781 (set (attr "highpart")
5782 (cond [(match_test "sh_contains_memref_p (insn)")
5783 (const_string "user")]
5784 (const_string "ignore")))])
5785
5786 (define_split
5787 [(set (match_operand:HI 0 "register_operand" "")
5788 (match_operand:HI 1 "immediate_operand" ""))]
5789 "TARGET_SHMEDIA && reload_completed
5790 && ! satisfies_constraint_I16 (operands[1])"
5791 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5792
5793 (define_expand "reload_inhi"
5794 [(set (match_operand:SI 2 "" "=&r")
5795 (match_operand:HI 1 "inqhi_operand" ""))
5796 (set (match_operand:HI 0 "arith_reg_operand" "=r")
5797 (truncate:HI (match_dup 3)))]
5798 "TARGET_SHMEDIA"
5799 {
5800 rtx inner = XEXP (operands[1], 0);
5801 int regno = REGNO (inner);
5802
5803 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5804 operands[1] = gen_rtx_REG (SImode, regno);
5805 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5806 })
5807
5808 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
5809 ;; compiled with -m2 -ml -O3 -funroll-loops
5810 (define_insn "*movdi_i"
5811 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
5812 (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
5813 "TARGET_SH1
5814 && (arith_reg_operand (operands[0], DImode)
5815 || arith_reg_operand (operands[1], DImode))"
5816 {
5817 return output_movedouble (insn, operands, DImode);
5818 }
5819 [(set_attr "length" "4")
5820 (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
5821
5822 ;; If the output is a register and the input is memory or a register, we have
5823 ;; to be careful and see which word needs to be loaded first.
5824
5825 (define_split
5826 [(set (match_operand:DI 0 "general_movdst_operand" "")
5827 (match_operand:DI 1 "general_movsrc_operand" ""))]
5828 "TARGET_SH1 && reload_completed"
5829 [(set (match_dup 2) (match_dup 3))
5830 (set (match_dup 4) (match_dup 5))]
5831 {
5832 int regno;
5833
5834 if ((MEM_P (operands[0])
5835 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
5836 || (MEM_P (operands[1])
5837 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
5838 FAIL;
5839
5840 switch (GET_CODE (operands[0]))
5841 {
5842 case REG:
5843 regno = REGNO (operands[0]);
5844 break;
5845 case SUBREG:
5846 regno = subreg_regno (operands[0]);
5847 break;
5848 case MEM:
5849 regno = -1;
5850 break;
5851 default:
5852 gcc_unreachable ();
5853 }
5854
5855 if (regno == -1
5856 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
5857 {
5858 operands[2] = operand_subword (operands[0], 0, 0, DImode);
5859 operands[3] = operand_subword (operands[1], 0, 0, DImode);
5860 operands[4] = operand_subword (operands[0], 1, 0, DImode);
5861 operands[5] = operand_subword (operands[1], 1, 0, DImode);
5862 }
5863 else
5864 {
5865 operands[2] = operand_subword (operands[0], 1, 0, DImode);
5866 operands[3] = operand_subword (operands[1], 1, 0, DImode);
5867 operands[4] = operand_subword (operands[0], 0, 0, DImode);
5868 operands[5] = operand_subword (operands[1], 0, 0, DImode);
5869 }
5870
5871 if (operands[2] == 0 || operands[3] == 0
5872 || operands[4] == 0 || operands[5] == 0)
5873 FAIL;
5874 })
5875
5876 ;; The '?'s in the following constraints may not reflect the time taken
5877 ;; to perform the move. They are there to discourage the use of floating-
5878 ;; point registers for storing integer values.
5879 (define_insn "*movdi_media"
5880 [(set (match_operand:DI 0 "general_movdst_operand"
5881 "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
5882 (match_operand:DI 1 "general_movsrc_operand"
5883 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5884 "TARGET_SHMEDIA_FPU
5885 && (register_operand (operands[0], DImode)
5886 || sh_register_operand (operands[1], DImode))"
5887 "@
5888 add %1, r63, %0
5889 movi %1, %0
5890 #
5891 ld%M1.q %m1, %0
5892 st%M0.q %m0, %N1
5893 fld%M1.d %m1, %0
5894 fst%M0.d %m0, %1
5895 fmov.qd %N1, %0
5896 fmov.dq %1, %0
5897 fmov.d %1, %0
5898 ptabs %1, %0
5899 gettr %1, %0
5900 pt %1, %0"
5901 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,fload_media,fstore_media,fload_media,dfpconv_media,fmove_media,ptabs_media,gettr_media,pt_media")
5902 (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
5903
5904 (define_insn "*movdi_media_nofpu"
5905 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
5906 (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
5907 "TARGET_SHMEDIA
5908 && (register_operand (operands[0], DImode)
5909 || sh_register_operand (operands[1], DImode))"
5910 "@
5911 add %1, r63, %0
5912 movi %1, %0
5913 #
5914 ld%M1.q %m1, %0
5915 st%M0.q %m0, %N1
5916 ptabs %1, %0
5917 gettr %1, %0
5918 pt %1, %0"
5919 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5920 (set_attr "length" "4,4,16,4,4,4,4,*")])
5921
5922 (define_insn "*movdi_media_I16"
5923 [(set (match_operand:DI 0 "ext_dest_operand" "=r")
5924 (match_operand:DI 1 "const_int_operand" "I16"))]
5925 "TARGET_SHMEDIA && reload_completed"
5926 "movi %1, %0"
5927 [(set_attr "type" "arith_media")
5928 (set_attr "length" "4")])
5929
5930 (define_split
5931 [(set (match_operand:DI 0 "arith_reg_dest" "")
5932 (match_operand:DI 1 "immediate_operand" ""))]
5933 "TARGET_SHMEDIA && reload_completed
5934 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5935 [(set (match_dup 0) (match_dup 1))]
5936 {
5937 rtx insn;
5938
5939 if (TARGET_SHMEDIA64)
5940 insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
5941 else
5942 insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
5943
5944 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
5945
5946 DONE;
5947 })
5948
5949 (define_expand "movdi_const"
5950 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5951 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5952 (const_int 48)] UNSPEC_EXTRACT_S16)))
5953 (set (match_dup 0)
5954 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5955 (const:DI (unspec:DI [(match_dup 1)
5956 (const_int 32)] UNSPEC_EXTRACT_U16))))
5957 (set (match_dup 0)
5958 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5959 (const:DI (unspec:DI [(match_dup 1)
5960 (const_int 16)] UNSPEC_EXTRACT_U16))))
5961 (set (match_dup 0)
5962 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5963 (const:DI (unspec:DI [(match_dup 1)
5964 (const_int 0)] UNSPEC_EXTRACT_U16))))]
5965 "TARGET_SHMEDIA64 && reload_completed
5966 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5967 {
5968 sh_mark_label (operands[1], 4);
5969 })
5970
5971 (define_expand "movdi_const_32bit"
5972 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5973 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5974 (const_int 16)] UNSPEC_EXTRACT_S16)))
5975 (set (match_dup 0)
5976 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5977 (const:DI (unspec:DI [(match_dup 1)
5978 (const_int 0)] UNSPEC_EXTRACT_U16))))]
5979 "TARGET_SHMEDIA32 && reload_completed
5980 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5981 {
5982 sh_mark_label (operands[1], 2);
5983 })
5984
5985 (define_expand "movdi_const_16bit"
5986 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5987 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5988 (const_int 0)] UNSPEC_EXTRACT_S16)))]
5989 "TARGET_SHMEDIA && flag_pic && reload_completed
5990 && GET_CODE (operands[1]) == SYMBOL_REF"
5991 "")
5992
5993 (define_split
5994 [(set (match_operand:DI 0 "ext_dest_operand" "")
5995 (match_operand:DI 1 "immediate_operand" ""))]
5996 "TARGET_SHMEDIA && reload_completed
5997 && CONST_INT_P (operands[1])
5998 && ! satisfies_constraint_I16 (operands[1])"
5999 [(set (match_dup 0) (match_dup 2))
6000 (match_dup 1)]
6001 {
6002 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
6003 unsigned HOST_WIDE_INT low = val;
6004 unsigned HOST_WIDE_INT high = val;
6005 unsigned HOST_WIDE_INT sign;
6006 unsigned HOST_WIDE_INT val2 = val ^ (val-1);
6007
6008 /* Zero-extend the 16 least-significant bits. */
6009 low &= 0xffff;
6010
6011 /* Arithmetic shift right the word by 16 bits. */
6012 high >>= 16;
6013 if (GET_CODE (operands[0]) == SUBREG
6014 && GET_MODE (SUBREG_REG (operands[0])) == SImode)
6015 {
6016 high &= 0xffff;
6017 high ^= 0x8000;
6018 high -= 0x8000;
6019 }
6020 else
6021 {
6022 sign = 1;
6023 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
6024 high ^= sign;
6025 high -= sign;
6026 }
6027 do
6028 {
6029 /* If we can't generate the constant with a two-insn movi / shori
6030 sequence, try some other strategies. */
6031 if (! CONST_OK_FOR_I16 (high))
6032 {
6033 /* Try constant load / left shift. We know VAL != 0. */
6034 val2 = val ^ (val-1);
6035 if (val2 > 0x1ffff)
6036 {
6037 int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
6038
6039 if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
6040 || (! CONST_OK_FOR_I16 (high >> 16)
6041 && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
6042 {
6043 val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
6044 operands[1] = gen_ashldi3_media (operands[0], operands[0],
6045 GEN_INT (trailing_zeroes));
6046 break;
6047 }
6048 }
6049 /* Try constant load / right shift. */
6050 val2 = (val >> 15) + 1;
6051 if (val2 == (val2 & -val2))
6052 {
6053 int shift = 49 - exact_log2 (val2);
6054
6055 val2 = trunc_int_for_mode (val << shift, DImode);
6056 if (CONST_OK_FOR_I16 (val2))
6057 {
6058 operands[1] = gen_lshrdi3_media (operands[0], operands[0],
6059 GEN_INT (shift));
6060 break;
6061 }
6062 }
6063 /* Try mperm.w . */
6064 val2 = val & 0xffff;
6065 if ((val >> 16 & 0xffff) == val2
6066 && (val >> 32 & 0xffff) == val2
6067 && (val >> 48 & 0xffff) == val2)
6068 {
6069 val2 = (HOST_WIDE_INT) val >> 48;
6070 operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
6071 operands[1] = gen_mperm_w0 (operands[1], operands[1]);
6072 break;
6073 }
6074 /* Try movi / mshflo.l */
6075 val2 = (HOST_WIDE_INT) val >> 32;
6076 if (val2 == ((unsigned HOST_WIDE_INT)
6077 trunc_int_for_mode (val, SImode)))
6078 {
6079 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
6080 operands[0]);
6081 break;
6082 }
6083 /* Try movi / mshflo.l w/ r63. */
6084 val2 = val + ((HOST_WIDE_INT) -1 << 32);
6085 if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
6086 {
6087 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
6088 const0_rtx);
6089 break;
6090 }
6091 }
6092 val2 = high;
6093 operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
6094 }
6095 while (0);
6096 operands[2] = GEN_INT (val2);
6097 })
6098
6099 (define_split
6100 [(set (match_operand:DI 0 "ext_dest_operand" "")
6101 (match_operand:DI 1 "immediate_operand" ""))]
6102 "TARGET_SHMEDIA && reload_completed
6103 && GET_CODE (operands[1]) == CONST_DOUBLE"
6104 [(set (match_dup 0) (match_dup 2))
6105 (set (match_dup 0)
6106 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
6107 {
6108 unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
6109 unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
6110 unsigned HOST_WIDE_INT val = low;
6111 unsigned HOST_WIDE_INT sign;
6112
6113 /* Zero-extend the 16 least-significant bits. */
6114 val &= 0xffff;
6115 operands[1] = GEN_INT (val);
6116
6117 /* Arithmetic shift right the double-word by 16 bits. */
6118 low >>= 16;
6119 low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
6120 high >>= 16;
6121 sign = 1;
6122 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
6123 high ^= sign;
6124 high -= sign;
6125
6126 /* This will only be true if high is a sign-extension of low, i.e.,
6127 it must be either 0 or (unsigned)-1, and be zero iff the
6128 most-significant bit of low is set. */
6129 if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
6130 operands[2] = GEN_INT (low);
6131 else
6132 operands[2] = immed_double_const (low, high, DImode);
6133 })
6134
6135 (define_insn "shori_media"
6136 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
6137 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
6138 (const_int 16))
6139 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
6140 "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
6141 "@
6142 shori %u2, %0
6143 #"
6144 [(set_attr "type" "arith_media,*")])
6145
6146 (define_insn "*shori_media_si"
6147 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6148 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
6149 (const_int 16))
6150 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
6151 "TARGET_SHMEDIA"
6152 "shori %u2, %0")
6153
6154 (define_expand "movdi"
6155 [(set (match_operand:DI 0 "general_movdst_operand" "")
6156 (match_operand:DI 1 "general_movsrc_operand" ""))]
6157 ""
6158 {
6159 prepare_move_operands (operands, DImode);
6160 })
6161
6162 (define_insn "movdf_media"
6163 [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
6164 (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
6165 "TARGET_SHMEDIA_FPU
6166 && (register_operand (operands[0], DFmode)
6167 || sh_register_operand (operands[1], DFmode))"
6168 "@
6169 fmov.d %1, %0
6170 fmov.qd %N1, %0
6171 fmov.dq %1, %0
6172 add %1, r63, %0
6173 #
6174 fld%M1.d %m1, %0
6175 fst%M0.d %m0, %1
6176 ld%M1.q %m1, %0
6177 st%M0.q %m0, %N1"
6178 [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
6179
6180 (define_insn "movdf_media_nofpu"
6181 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
6182 (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
6183 "TARGET_SHMEDIA
6184 && (register_operand (operands[0], DFmode)
6185 || sh_register_operand (operands[1], DFmode))"
6186 "@
6187 add %1, r63, %0
6188 #
6189 ld%M1.q %m1, %0
6190 st%M0.q %m0, %N1"
6191 [(set_attr "type" "arith_media,*,load_media,store_media")])
6192
6193 (define_split
6194 [(set (match_operand:DF 0 "arith_reg_dest" "")
6195 (match_operand:DF 1 "immediate_operand" ""))]
6196 "TARGET_SHMEDIA && reload_completed"
6197 [(set (match_dup 3) (match_dup 2))]
6198 {
6199 int endian = WORDS_BIG_ENDIAN ? 1 : 0;
6200 long values[2];
6201 REAL_VALUE_TYPE value;
6202
6203 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
6204 REAL_VALUE_TO_TARGET_DOUBLE (value, values);
6205
6206 if (HOST_BITS_PER_WIDE_INT >= 64)
6207 operands[2] = immed_double_const ((unsigned long) values[endian]
6208 | ((HOST_WIDE_INT) values[1 - endian]
6209 << 32), 0, DImode);
6210 else
6211 {
6212 gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
6213 operands[2] = immed_double_const (values[endian], values[1 - endian],
6214 DImode);
6215 }
6216
6217 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6218 })
6219
6220 ;; ??? This should be a define expand.
6221
6222 (define_insn "movdf_k"
6223 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
6224 (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
6225 "TARGET_SH1
6226 && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
6227 /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
6228 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
6229 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
6230 && (arith_reg_operand (operands[0], DFmode)
6231 || arith_reg_operand (operands[1], DFmode))"
6232 {
6233 return output_movedouble (insn, operands, DFmode);
6234 }
6235 [(set_attr "length" "4")
6236 (set_attr "type" "move,pcload,load,store")])
6237
6238 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
6239 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
6240 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
6241 ;; the d/m/c/X alternative, which is split later into single-precision
6242 ;; instructions. And when not optimizing, no splits are done before fixing
6243 ;; up pcloads, so we need usable length information for that.
6244 (define_insn "movdf_i4"
6245 [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
6246 (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
6247 (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
6248 (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
6249 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
6250 && (arith_reg_operand (operands[0], DFmode)
6251 || arith_reg_operand (operands[1], DFmode))"
6252 {
6253 switch (which_alternative)
6254 {
6255 case 0:
6256 if (TARGET_FMOVD)
6257 return "fmov %1,%0";
6258 else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
6259 return "fmov %R1,%R0\n\tfmov %S1,%S0";
6260 else
6261 return "fmov %S1,%S0\n\tfmov %R1,%R0";
6262 case 3:
6263 case 4:
6264 return "fmov.d %1,%0";
6265 default:
6266 return "#";
6267 }
6268 }
6269 [(set_attr_alternative "length"
6270 [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
6271 (const_int 4)
6272 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
6273 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
6274 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
6275 (const_int 4)
6276 (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
6277 ;; We can't use 4-byte push/pop on SHcompact, so we have to
6278 ;; increment or decrement r15 explicitly.
6279 (if_then_else
6280 (match_test "TARGET_SHCOMPACT")
6281 (const_int 10) (const_int 8))
6282 (if_then_else
6283 (match_test "TARGET_SHCOMPACT")
6284 (const_int 10) (const_int 8))])
6285 (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
6286 (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
6287 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
6288 (const_string "double")
6289 (const_string "none")))])
6290
6291 ;; Moving DFmode between fp/general registers through memory
6292 ;; (the top of the stack) is faster than moving through fpul even for
6293 ;; little endian. Because the type of an instruction is important for its
6294 ;; scheduling, it is beneficial to split these operations, rather than
6295 ;; emitting them in one single chunk, even if this will expose a stack
6296 ;; use that will prevent scheduling of other stack accesses beyond this
6297 ;; instruction.
6298 (define_split
6299 [(set (match_operand:DF 0 "register_operand" "")
6300 (match_operand:DF 1 "register_operand" ""))
6301 (use (match_operand:PSI 2 "fpscr_operand" ""))
6302 (clobber (match_scratch:SI 3 "=X"))]
6303 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
6304 && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
6305 [(const_int 0)]
6306 {
6307 rtx insn, tos;
6308
6309 if (TARGET_SH5 && true_regnum (operands[1]) < 16)
6310 {
6311 emit_move_insn (stack_pointer_rtx,
6312 plus_constant (Pmode, stack_pointer_rtx, -8));
6313 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
6314 }
6315 else
6316 tos = gen_tmp_stack_mem (DFmode,
6317 gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
6318 insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
6319 if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
6320 add_reg_note (insn, REG_INC, stack_pointer_rtx);
6321 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
6322 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
6323 else
6324 tos = gen_tmp_stack_mem (DFmode,
6325 gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
6326 insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
6327 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
6328 emit_move_insn (stack_pointer_rtx,
6329 plus_constant (Pmode, stack_pointer_rtx, 8));
6330 else
6331 add_reg_note (insn, REG_INC, stack_pointer_rtx);
6332 DONE;
6333 })
6334
6335 ;; local-alloc sometimes allocates scratch registers even when not required,
6336 ;; so we must be prepared to handle these.
6337
6338 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
6339 (define_split
6340 [(set (match_operand:DF 0 "general_movdst_operand" "")
6341 (match_operand:DF 1 "general_movsrc_operand" ""))
6342 (use (match_operand:PSI 2 "fpscr_operand" ""))
6343 (clobber (match_scratch:SI 3 ""))]
6344 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
6345 && reload_completed
6346 && true_regnum (operands[0]) < 16
6347 && true_regnum (operands[1]) < 16"
6348 [(set (match_dup 0) (match_dup 1))]
6349 {
6350 /* If this was a reg <-> mem operation with base + index reg addressing,
6351 we have to handle this in a special way. */
6352 rtx mem = operands[0];
6353 int store_p = 1;
6354 if (! memory_operand (mem, DFmode))
6355 {
6356 mem = operands[1];
6357 store_p = 0;
6358 }
6359 if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
6360 mem = SUBREG_REG (mem);
6361 if (MEM_P (mem))
6362 {
6363 rtx addr = XEXP (mem, 0);
6364 if (GET_CODE (addr) == PLUS
6365 && REG_P (XEXP (addr, 0))
6366 && REG_P (XEXP (addr, 1)))
6367 {
6368 int offset;
6369 rtx reg0 = gen_rtx_REG (Pmode, 0);
6370 rtx regop = operands[store_p], word0 ,word1;
6371
6372 if (GET_CODE (regop) == SUBREG)
6373 alter_subreg (&regop);
6374 if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
6375 offset = 2;
6376 else
6377 offset = 4;
6378 mem = copy_rtx (mem);
6379 PUT_MODE (mem, SImode);
6380 word0 = gen_rtx_SUBREG (SImode, regop, 0);
6381 alter_subreg (&word0);
6382 word1 = gen_rtx_SUBREG (SImode, regop, 4);
6383 alter_subreg (&word1);
6384 if (store_p || ! refers_to_regno_p (REGNO (word0),
6385 REGNO (word0) + 1, addr, 0))
6386 {
6387 emit_insn (store_p
6388 ? gen_movsi_ie (mem, word0)
6389 : gen_movsi_ie (word0, mem));
6390 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
6391 mem = copy_rtx (mem);
6392 emit_insn (store_p
6393 ? gen_movsi_ie (mem, word1)
6394 : gen_movsi_ie (word1, mem));
6395 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
6396 }
6397 else
6398 {
6399 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
6400 emit_insn (gen_movsi_ie (word1, mem));
6401 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
6402 mem = copy_rtx (mem);
6403 emit_insn (gen_movsi_ie (word0, mem));
6404 }
6405 DONE;
6406 }
6407 }
6408 })
6409
6410 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
6411 (define_split
6412 [(set (match_operand:DF 0 "register_operand" "")
6413 (match_operand:DF 1 "memory_operand" ""))
6414 (use (match_operand:PSI 2 "fpscr_operand" ""))
6415 (clobber (reg:SI R0_REG))]
6416 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
6417 [(parallel [(set (match_dup 0) (match_dup 1))
6418 (use (match_dup 2))
6419 (clobber (scratch:SI))])]
6420 "")
6421
6422 (define_expand "reload_indf__frn"
6423 [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
6424 (match_operand:DF 1 "immediate_operand" "FQ"))
6425 (use (reg:PSI FPSCR_REG))
6426 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6427 "TARGET_SH1"
6428 "")
6429
6430 (define_expand "reload_outdf__RnFRm"
6431 [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
6432 (match_operand:DF 1 "register_operand" "af,r"))
6433 (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
6434 "TARGET_SH1"
6435 "")
6436
6437 ;; Simplify no-op moves.
6438 (define_split
6439 [(set (match_operand:SF 0 "register_operand" "")
6440 (match_operand:SF 1 "register_operand" ""))
6441 (use (match_operand:PSI 2 "fpscr_operand" ""))
6442 (clobber (match_scratch:SI 3 ""))]
6443 "TARGET_SH2E && reload_completed
6444 && true_regnum (operands[0]) == true_regnum (operands[1])"
6445 [(set (match_dup 0) (match_dup 0))]
6446 "")
6447
6448 ;; fmovd substitute post-reload splits
6449 (define_split
6450 [(set (match_operand:DF 0 "register_operand" "")
6451 (match_operand:DF 1 "register_operand" ""))
6452 (use (match_operand:PSI 2 "fpscr_operand" ""))
6453 (clobber (match_scratch:SI 3 ""))]
6454 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
6455 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
6456 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6457 [(const_int 0)]
6458 {
6459 int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
6460 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
6461 gen_rtx_REG (SFmode, src), operands[2]));
6462 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
6463 gen_rtx_REG (SFmode, src + 1), operands[2]));
6464 DONE;
6465 })
6466
6467 (define_split
6468 [(set (match_operand:DF 0 "register_operand" "")
6469 (mem:DF (match_operand:SI 1 "register_operand" "")))
6470 (use (match_operand:PSI 2 "fpscr_operand" ""))
6471 (clobber (match_scratch:SI 3 ""))]
6472 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6473 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
6474 && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
6475 [(const_int 0)]
6476 {
6477 int regno = true_regnum (operands[0]);
6478 rtx insn;
6479 rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
6480 rtx mem2
6481 = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
6482 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6483 regno + !! TARGET_LITTLE_ENDIAN),
6484 mem2, operands[2]));
6485 add_reg_note (insn, REG_INC, operands[1]);
6486 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6487 regno + ! TARGET_LITTLE_ENDIAN),
6488 change_address (mem, SFmode, NULL_RTX),
6489 operands[2]));
6490 DONE;
6491 })
6492
6493 (define_split
6494 [(set (match_operand:DF 0 "register_operand" "")
6495 (match_operand:DF 1 "memory_operand" ""))
6496 (use (match_operand:PSI 2 "fpscr_operand" ""))
6497 (clobber (match_scratch:SI 3 ""))]
6498 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6499 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
6500 [(const_int 0)]
6501 {
6502 int regno = true_regnum (operands[0]);
6503 rtx addr, insn;
6504 rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
6505 rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
6506 rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
6507
6508 operands[1] = copy_rtx (mem2);
6509 addr = XEXP (mem2, 0);
6510
6511 switch (GET_CODE (addr))
6512 {
6513 case REG:
6514 /* This is complicated. If the register is an arithmetic register
6515 we can just fall through to the REG+DISP case below. Otherwise
6516 we have to use a combination of POST_INC and REG addressing... */
6517 if (! arith_reg_operand (operands[1], SFmode))
6518 {
6519 XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
6520 insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
6521 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6522
6523 emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6524
6525 /* If we have modified the stack pointer, the value that we have
6526 read with post-increment might be modified by an interrupt,
6527 so write it back. */
6528 if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
6529 emit_insn (gen_push_e (reg0));
6530 else
6531 emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0), GEN_INT (-4)));
6532 break;
6533 }
6534 /* Fall through. */
6535
6536 case PLUS:
6537 emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
6538 operands[1] = copy_rtx (operands[1]);
6539 XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4);
6540 emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6541 break;
6542
6543 case POST_INC:
6544 insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
6545 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6546
6547 insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6548 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6549 break;
6550
6551 default:
6552 debug_rtx (addr);
6553 gcc_unreachable ();
6554 }
6555
6556 DONE;
6557 })
6558
6559 (define_split
6560 [(set (match_operand:DF 0 "memory_operand" "")
6561 (match_operand:DF 1 "register_operand" ""))
6562 (use (match_operand:PSI 2 "fpscr_operand" ""))
6563 (clobber (match_scratch:SI 3 ""))]
6564 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6565 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6566 [(const_int 0)]
6567 {
6568 int regno = true_regnum (operands[1]);
6569 rtx insn, addr;
6570 rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
6571 rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
6572
6573 operands[0] = copy_rtx (operands[0]);
6574 PUT_MODE (operands[0], SFmode);
6575 addr = XEXP (operands[0], 0);
6576
6577 switch (GET_CODE (addr))
6578 {
6579 case REG:
6580 /* This is complicated. If the register is an arithmetic register
6581 we can just fall through to the REG+DISP case below. Otherwise
6582 we have to use a combination of REG and PRE_DEC addressing... */
6583 if (! arith_reg_operand (operands[0], SFmode))
6584 {
6585 emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
6586 emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
6587
6588 operands[0] = copy_rtx (operands[0]);
6589 XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
6590
6591 insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6592 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6593 break;
6594 }
6595 /* Fall through. */
6596
6597 case PLUS:
6598 /* Since REG+DISP addressing has already been decided upon by gcc
6599 we can rely upon it having chosen an arithmetic register as the
6600 register component of the address. Just emit the lower numbered
6601 register first, to the lower address, then the higher numbered
6602 register to the higher address. */
6603 emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6604
6605 operands[0] = copy_rtx (operands[0]);
6606 XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4);
6607
6608 emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
6609 break;
6610
6611 case PRE_DEC:
6612 /* This is easy. Output the word to go to the higher address
6613 first (ie the word in the higher numbered register) then the
6614 word to go to the lower address. */
6615
6616 insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
6617 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6618
6619 insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6620 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6621 break;
6622
6623 default:
6624 /* FAIL; */
6625 debug_rtx (addr);
6626 gcc_unreachable ();
6627 }
6628
6629 DONE;
6630 })
6631
6632 ;; If the output is a register and the input is memory or a register, we have
6633 ;; to be careful and see which word needs to be loaded first.
6634
6635 (define_split
6636 [(set (match_operand:DF 0 "general_movdst_operand" "")
6637 (match_operand:DF 1 "general_movsrc_operand" ""))]
6638 "TARGET_SH1 && reload_completed"
6639 [(set (match_dup 2) (match_dup 3))
6640 (set (match_dup 4) (match_dup 5))]
6641 {
6642 int regno;
6643
6644 if ((MEM_P (operands[0])
6645 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
6646 || (MEM_P (operands[1])
6647 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
6648 FAIL;
6649
6650 switch (GET_CODE (operands[0]))
6651 {
6652 case REG:
6653 regno = REGNO (operands[0]);
6654 break;
6655 case SUBREG:
6656 regno = subreg_regno (operands[0]);
6657 break;
6658 case MEM:
6659 regno = -1;
6660 break;
6661 default:
6662 gcc_unreachable ();
6663 }
6664
6665 if (regno == -1
6666 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
6667 {
6668 operands[2] = operand_subword (operands[0], 0, 0, DFmode);
6669 operands[3] = operand_subword (operands[1], 0, 0, DFmode);
6670 operands[4] = operand_subword (operands[0], 1, 0, DFmode);
6671 operands[5] = operand_subword (operands[1], 1, 0, DFmode);
6672 }
6673 else
6674 {
6675 operands[2] = operand_subword (operands[0], 1, 0, DFmode);
6676 operands[3] = operand_subword (operands[1], 1, 0, DFmode);
6677 operands[4] = operand_subword (operands[0], 0, 0, DFmode);
6678 operands[5] = operand_subword (operands[1], 0, 0, DFmode);
6679 }
6680
6681 if (operands[2] == 0 || operands[3] == 0
6682 || operands[4] == 0 || operands[5] == 0)
6683 FAIL;
6684 })
6685
6686 (define_expand "movdf"
6687 [(set (match_operand:DF 0 "general_movdst_operand" "")
6688 (match_operand:DF 1 "general_movsrc_operand" ""))]
6689 ""
6690 {
6691 prepare_move_operands (operands, DFmode);
6692 if (TARGET_SHMEDIA)
6693 {
6694 if (TARGET_SHMEDIA_FPU)
6695 emit_insn (gen_movdf_media (operands[0], operands[1]));
6696 else
6697 emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
6698 DONE;
6699 }
6700 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
6701 {
6702 emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
6703 DONE;
6704 }
6705 })
6706
6707 ;;This is incompatible with the way gcc uses subregs.
6708 ;;(define_insn "movv2sf_i"
6709 ;; [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
6710 ;; (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
6711 ;; "TARGET_SHMEDIA_FPU
6712 ;; && (fp_arith_reg_operand (operands[0], V2SFmode)
6713 ;; || fp_arith_reg_operand (operands[1], V2SFmode))"
6714 ;; "@
6715 ;; #
6716 ;; fld%M1.p %m1, %0
6717 ;; fst%M0.p %m0, %1"
6718 ;; [(set_attr "type" "*,fload_media,fstore_media")])
6719
6720 (define_insn_and_split "movv2sf_i"
6721 [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6722 (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6723 "TARGET_SHMEDIA_FPU"
6724 "#"
6725 "TARGET_SHMEDIA_FPU && reload_completed"
6726 [(set (match_dup 0) (match_dup 1))]
6727 {
6728 operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
6729 operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
6730 })
6731
6732 (define_expand "movv2sf"
6733 [(set (match_operand:V2SF 0 "general_movdst_operand" "")
6734 (match_operand:V2SF 1 "nonimmediate_operand" ""))]
6735 "TARGET_SHMEDIA_FPU"
6736 {
6737 prepare_move_operands (operands, V2SFmode);
6738 })
6739
6740 (define_expand "addv2sf3"
6741 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6742 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6743 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6744 "TARGET_SHMEDIA_FPU"
6745 {
6746 sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
6747 DONE;
6748 })
6749
6750 (define_expand "subv2sf3"
6751 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6752 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6753 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6754 "TARGET_SHMEDIA_FPU"
6755 {
6756 sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
6757 DONE;
6758 })
6759
6760 (define_expand "mulv2sf3"
6761 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6762 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6763 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6764 "TARGET_SHMEDIA_FPU"
6765 {
6766 sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
6767 DONE;
6768 })
6769
6770 (define_expand "divv2sf3"
6771 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6772 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6773 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6774 "TARGET_SHMEDIA_FPU"
6775 {
6776 sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
6777 DONE;
6778 })
6779
6780 (define_insn_and_split "*movv4sf_i"
6781 [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6782 (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6783 "TARGET_SHMEDIA_FPU"
6784 "#"
6785 "&& reload_completed"
6786 [(const_int 0)]
6787 {
6788 int i;
6789
6790 for (i = 0; i < 4/2; i++)
6791 {
6792 rtx x, y;
6793
6794 if (MEM_P (operands[0]))
6795 x = adjust_address (operands[0], V2SFmode,
6796 i * GET_MODE_SIZE (V2SFmode));
6797 else
6798 x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
6799
6800 if (MEM_P (operands[1]))
6801 y = adjust_address (operands[1], V2SFmode,
6802 i * GET_MODE_SIZE (V2SFmode));
6803 else
6804 y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
6805
6806 emit_insn (gen_movv2sf_i (x, y));
6807 }
6808
6809 DONE;
6810 }
6811 [(set_attr "length" "8")])
6812
6813 (define_expand "movv4sf"
6814 [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
6815 (match_operand:V4SF 1 "general_operand" ""))]
6816 "TARGET_SHMEDIA_FPU"
6817 {
6818 prepare_move_operands (operands, V4SFmode);
6819 })
6820
6821 (define_insn_and_split "*movv16sf_i"
6822 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6823 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6824 "TARGET_SHMEDIA_FPU"
6825 "#"
6826 "&& reload_completed"
6827 [(const_int 0)]
6828 {
6829 int i;
6830
6831 for (i = 0; i < 16/2; i++)
6832 {
6833 rtx x,y;
6834
6835 if (MEM_P (operands[0]))
6836 x = adjust_address (operands[0], V2SFmode,
6837 i * GET_MODE_SIZE (V2SFmode));
6838 else
6839 {
6840 x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
6841 alter_subreg (&x);
6842 }
6843
6844 if (MEM_P (operands[1]))
6845 y = adjust_address (operands[1], V2SFmode,
6846 i * GET_MODE_SIZE (V2SFmode));
6847 else
6848 {
6849 y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
6850 alter_subreg (&y);
6851 }
6852
6853 emit_insn (gen_movv2sf_i (x, y));
6854 }
6855
6856 DONE;
6857 }
6858 [(set_attr "length" "32")])
6859
6860 (define_expand "movv16sf"
6861 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6862 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6863 "TARGET_SHMEDIA_FPU"
6864 {
6865 prepare_move_operands (operands, V16SFmode);
6866 })
6867
6868 (define_insn "movsf_media"
6869 [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
6870 (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
6871 "TARGET_SHMEDIA_FPU
6872 && (register_operand (operands[0], SFmode)
6873 || sh_register_operand (operands[1], SFmode))"
6874 "@
6875 fmov.s %1, %0
6876 fmov.ls %N1, %0
6877 fmov.sl %1, %0
6878 add.l %1, r63, %0
6879 #
6880 fld%M1.s %m1, %0
6881 fst%M0.s %m0, %1
6882 ld%M1.l %m1, %0
6883 st%M0.l %m0, %N1"
6884 [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
6885 (set (attr "highpart")
6886 (cond [(match_test "sh_contains_memref_p (insn)")
6887 (const_string "user")]
6888 (const_string "ignore")))])
6889
6890 (define_insn "movsf_media_nofpu"
6891 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
6892 (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
6893 "TARGET_SHMEDIA
6894 && (register_operand (operands[0], SFmode)
6895 || sh_register_operand (operands[1], SFmode))"
6896 "@
6897 add.l %1, r63, %0
6898 #
6899 ld%M1.l %m1, %0
6900 st%M0.l %m0, %N1"
6901 [(set_attr "type" "arith_media,*,load_media,store_media")
6902 (set (attr "highpart")
6903 (cond [(match_test "sh_contains_memref_p (insn)")
6904 (const_string "user")]
6905 (const_string "ignore")))])
6906
6907 (define_split
6908 [(set (match_operand:SF 0 "arith_reg_dest" "")
6909 (match_operand:SF 1 "immediate_operand" ""))]
6910 "TARGET_SHMEDIA && reload_completed
6911 && ! FP_REGISTER_P (true_regnum (operands[0]))"
6912 [(set (match_dup 3) (match_dup 2))]
6913 {
6914 long values;
6915 REAL_VALUE_TYPE value;
6916
6917 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
6918 REAL_VALUE_TO_TARGET_SINGLE (value, values);
6919 operands[2] = GEN_INT (values);
6920
6921 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6922 })
6923
6924 (define_insn "movsf_i"
6925 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
6926 (match_operand:SF 1 "general_movsrc_operand" "r,G,FQ,mr,r,r,l"))]
6927 "TARGET_SH1
6928 && (! TARGET_SH2E
6929 /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
6930 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
6931 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
6932 && (arith_reg_operand (operands[0], SFmode)
6933 || arith_reg_operand (operands[1], SFmode))"
6934 "@
6935 mov %1,%0
6936 mov #0,%0
6937 mov.l %1,%0
6938 mov.l %1,%0
6939 mov.l %1,%0
6940 lds %1,%0
6941 sts %1,%0"
6942 [(set_attr "type" "move,move,pcload,load,store,move,move")])
6943
6944 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
6945 ;; update_flow_info would not know where to put REG_EQUAL notes
6946 ;; when the destination changes mode.
6947 (define_insn "movsf_ie"
6948 [(set (match_operand:SF 0 "general_movdst_operand"
6949 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
6950 (match_operand:SF 1 "general_movsrc_operand"
6951 "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
6952 (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"))
6953 (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
6954 "TARGET_SH2E
6955 && (arith_reg_operand (operands[0], SFmode)
6956 || arith_reg_operand (operands[1], SFmode)
6957 || arith_reg_operand (operands[3], SImode)
6958 || (fpul_operand (operands[0], SFmode)
6959 && memory_operand (operands[1], SFmode)
6960 && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
6961 || (fpul_operand (operands[1], SFmode)
6962 && memory_operand (operands[0], SFmode)
6963 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
6964 "@
6965 fmov %1,%0
6966 mov %1,%0
6967 fldi0 %0
6968 fldi1 %0
6969 #
6970 fmov.s %1,%0
6971 fmov.s %1,%0
6972 mov.l %1,%0
6973 mov.l %1,%0
6974 mov.l %1,%0
6975 fsts fpul,%0
6976 flds %1,fpul
6977 lds.l %1,%0
6978 #
6979 sts %1,%0
6980 lds %1,%0
6981 sts.l %1,%0
6982 lds.l %1,%0
6983 ! move optimized away"
6984 [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
6985 (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
6986 (set_attr_alternative "length"
6987 [(const_int 2)
6988 (const_int 2)
6989 (const_int 2)
6990 (const_int 2)
6991 (const_int 4)
6992 (if_then_else
6993 (match_test "TARGET_SH2A")
6994 (const_int 4) (const_int 2))
6995 (if_then_else
6996 (match_test "TARGET_SH2A")
6997 (const_int 4) (const_int 2))
6998 (const_int 2)
6999 (if_then_else
7000 (match_test "TARGET_SH2A")
7001 (const_int 4) (const_int 2))
7002 (if_then_else
7003 (match_test "TARGET_SH2A")
7004 (const_int 4) (const_int 2))
7005 (const_int 2)
7006 (const_int 2)
7007 (const_int 2)
7008 (const_int 4)
7009 (const_int 2)
7010 (const_int 2)
7011 (const_int 2)
7012 (const_int 2)
7013 (const_int 0)])
7014 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
7015 (const_string "single")
7016 (const_string "single")))])
7017
7018 (define_split
7019 [(set (match_operand:SF 0 "register_operand" "")
7020 (match_operand:SF 1 "register_operand" ""))
7021 (use (match_operand:PSI 2 "fpscr_operand" ""))
7022 (clobber (reg:SI FPUL_REG))]
7023 "TARGET_SH1"
7024 [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
7025 (use (match_dup 2))
7026 (clobber (scratch:SI))])
7027 (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
7028 (use (match_dup 2))
7029 (clobber (scratch:SI))])]
7030 "")
7031
7032 (define_expand "movsf"
7033 [(set (match_operand:SF 0 "general_movdst_operand" "")
7034 (match_operand:SF 1 "general_movsrc_operand" ""))]
7035 ""
7036 {
7037 prepare_move_operands (operands, SFmode);
7038 if (TARGET_SHMEDIA)
7039 {
7040 if (TARGET_SHMEDIA_FPU)
7041 emit_insn (gen_movsf_media (operands[0], operands[1]));
7042 else
7043 emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
7044 DONE;
7045 }
7046 if (TARGET_SH2E)
7047 {
7048 emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
7049 DONE;
7050 }
7051 })
7052
7053 (define_insn "mov_nop"
7054 [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
7055 "TARGET_SH2E"
7056 ""
7057 [(set_attr "length" "0")
7058 (set_attr "type" "nil")])
7059
7060 (define_expand "reload_insf__frn"
7061 [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
7062 (match_operand:SF 1 "immediate_operand" "FQ"))
7063 (use (reg:PSI FPSCR_REG))
7064 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
7065 "TARGET_SH1"
7066 "")
7067
7068 (define_expand "reload_insi__i_fpul"
7069 [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
7070 (match_operand:SI 1 "immediate_operand" "i"))
7071 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
7072 "TARGET_SH1"
7073 "")
7074
7075 (define_expand "ptabs"
7076 [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
7077 "TARGET_SHMEDIA"
7078 {
7079 if (!TARGET_PT_FIXED)
7080 {
7081 rtx eq = operands[1];
7082
7083 /* ??? For canonical RTL we really should remove any CONST from EQ
7084 before wrapping it in the AND, and finally wrap the EQ into a
7085 const if is constant. However, for reload we must expose the
7086 input register or symbolic constant, and we can't have
7087 different insn structures outside of the operands for different
7088 alternatives of the same pattern. */
7089 eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
7090 GEN_INT (3));
7091 operands[1]
7092 = (gen_rtx_IF_THEN_ELSE
7093 (PDImode,
7094 eq,
7095 gen_rtx_MEM (PDImode, operands[1]),
7096 gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
7097 PDImode, operands[1])));
7098 }
7099 })
7100
7101 ;; expanded by ptabs expander.
7102 (define_insn "*extendsipdi_media"
7103 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
7104 (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
7105 "r,Csy")
7106 (const_int 3))
7107 (const_int 3))
7108 (mem:PDI (match_dup 1))
7109 (sign_extend:PDI (match_dup 1))))]
7110 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
7111 "@
7112 ptabs %1, %0
7113 pt %1, %0"
7114 [(set_attr "type" "ptabs_media,pt_media")
7115 (set_attr "length" "4,*")])
7116
7117 (define_insn "*truncdipdi_media"
7118 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
7119 (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
7120 "r,Csy")
7121 (const_int 3))
7122 (const_int 3))
7123 (mem:PDI (match_dup 1))
7124 (truncate:PDI (match_dup 1))))]
7125 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
7126 "@
7127 ptabs %1, %0
7128 pt %1, %0"
7129 [(set_attr "type" "ptabs_media,pt_media")
7130 (set_attr "length" "4,*")])
7131
7132 (define_insn "*movsi_y"
7133 [(set (match_operand:SI 0 "register_operand" "=y,y")
7134 (match_operand:SI 1 "immediate_operand" "Qi,I08"))
7135 (clobber (match_scratch:SI 2 "=&z,r"))]
7136 "TARGET_SH2E
7137 && (reload_in_progress || reload_completed)"
7138 "#"
7139 [(set_attr "length" "4")
7140 (set_attr "type" "pcload,move")])
7141
7142 (define_split
7143 [(set (match_operand:SI 0 "register_operand" "")
7144 (match_operand:SI 1 "immediate_operand" ""))
7145 (clobber (match_operand:SI 2 "register_operand" ""))]
7146 "TARGET_SH1"
7147 [(set (match_dup 2) (match_dup 1))
7148 (set (match_dup 0) (match_dup 2))]
7149 "")
7150 \f
7151 ;; ------------------------------------------------------------------------
7152 ;; Define the real conditional branch instructions.
7153 ;; ------------------------------------------------------------------------
7154
7155 (define_insn "branch_true"
7156 [(set (pc) (if_then_else (ne (match_operand 1 "t_reg_operand" "")
7157 (const_int 0))
7158 (label_ref (match_operand 0 "" ""))
7159 (pc)))]
7160 "TARGET_SH1"
7161 {
7162 return output_branch (1, insn, operands);
7163 }
7164 [(set_attr "type" "cbranch")])
7165
7166 (define_insn "*branch_true_eq"
7167 [(set (pc) (if_then_else (eq (match_operand 1 "t_reg_operand" "")
7168 (const_int 1))
7169 (label_ref (match_operand 0 "" ""))
7170 (pc)))]
7171 "TARGET_SH1"
7172 {
7173 return output_branch (1, insn, operands);
7174 }
7175 [(set_attr "type" "cbranch")])
7176
7177 (define_insn "branch_false"
7178 [(set (pc) (if_then_else (eq (match_operand 1 "t_reg_operand" "")
7179 (const_int 0))
7180 (label_ref (match_operand 0 "" ""))
7181 (pc)))]
7182 "TARGET_SH1"
7183 {
7184 return output_branch (0, insn, operands);
7185 }
7186 [(set_attr "type" "cbranch")])
7187
7188 (define_insn "*branch_false_ne"
7189 [(set (pc) (if_then_else (ne (match_operand 1 "t_reg_operand" "")
7190 (const_int 1))
7191 (label_ref (match_operand 0 "" ""))
7192 (pc)))]
7193 "TARGET_SH1"
7194 {
7195 return output_branch (0, insn, operands);
7196 }
7197 [(set_attr "type" "cbranch")])
7198
7199 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
7200 ;; which destination is too far away.
7201 ;; The const_int_operand is distinct for each branch target; it avoids
7202 ;; unwanted matches with redundant_insn.
7203 (define_insn "block_branch_redirect"
7204 [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
7205 "TARGET_SH1"
7206 ""
7207 [(set_attr "length" "0")])
7208
7209 ;; This one has the additional purpose to record a possible scratch register
7210 ;; for the following branch.
7211 ;; ??? Unfortunately, just setting the scratch register is not good enough,
7212 ;; because the insn then might be deemed dead and deleted. And we can't
7213 ;; make the use in the jump insn explicit because that would disable
7214 ;; delay slot scheduling from the target.
7215 (define_insn "indirect_jump_scratch"
7216 [(set (match_operand:SI 0 "register_operand" "=r")
7217 (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
7218 (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
7219 "TARGET_SH1"
7220 ""
7221 [(set_attr "length" "0")])
7222
7223 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
7224 ;; being pulled into the delay slot of a condbranch that has been made to
7225 ;; jump around the unconditional jump because it was out of range.
7226 (define_insn "stuff_delay_slot"
7227 [(set (pc)
7228 (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
7229 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
7230 "TARGET_SH1"
7231 ""
7232 [(set_attr "length" "0")
7233 (set_attr "cond_delay_slot" "yes")])
7234 \f
7235 ;; Conditional branch insns
7236
7237 (define_expand "cbranchint4_media"
7238 [(set (pc)
7239 (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
7240 [(match_operand 1 "" "")
7241 (match_operand 2 "" "")])
7242 (match_operand 3 "" "")
7243 (pc)))]
7244 "TARGET_SHMEDIA"
7245 {
7246 enum machine_mode mode = GET_MODE (operands[1]);
7247 if (mode == VOIDmode)
7248 mode = GET_MODE (operands[2]);
7249 if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
7250 {
7251 operands[1] = force_reg (mode, operands[1]);
7252 if (CONSTANT_P (operands[2])
7253 && (! satisfies_constraint_I06 (operands[2])))
7254 operands[2] = force_reg (mode, operands[2]);
7255 }
7256 else
7257 {
7258 if (operands[1] != const0_rtx)
7259 operands[1] = force_reg (mode, operands[1]);
7260 if (operands[2] != const0_rtx)
7261 operands[2] = force_reg (mode, operands[2]);
7262 }
7263 switch (GET_CODE (operands[0]))
7264 {
7265 case LEU:
7266 case LE:
7267 case LTU:
7268 case LT:
7269 operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
7270 VOIDmode, operands[2], operands[1]);
7271 operands[1] = XEXP (operands[0], 0);
7272 operands[2] = XEXP (operands[0], 1);
7273 break;
7274 default:
7275 operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
7276 VOIDmode, operands[1], operands[2]);
7277 break;
7278 }
7279 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
7280 })
7281
7282 (define_expand "cbranchfp4_media"
7283 [(set (pc)
7284 (if_then_else (match_operator 0 "sh_float_comparison_operator"
7285 [(match_operand 1 "" "")
7286 (match_operand 2 "" "")])
7287 (match_operand 3 "" "")
7288 (pc)))]
7289 "TARGET_SHMEDIA"
7290 {
7291 rtx tmp = gen_reg_rtx (SImode);
7292 rtx cmp;
7293 if (GET_CODE (operands[0]) == NE)
7294 cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
7295 else
7296 cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
7297 operands[1], operands[2]);
7298
7299 emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
7300
7301 if (GET_CODE (cmp) == GET_CODE (operands[0]))
7302 operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
7303 else
7304 operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
7305 operands[1] = tmp;
7306 operands[2] = const0_rtx;
7307 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
7308 })
7309
7310 (define_insn "*beq_media_i"
7311 [(set (pc)
7312 (if_then_else (match_operator 3 "equality_comparison_operator"
7313 [(match_operand:DI 1 "arith_reg_operand" "r,r")
7314 (match_operand:DI 2 "arith_operand" "r,I06")])
7315 (match_operand 0 "target_operand" "b,b")
7316 (pc)))]
7317 "TARGET_SHMEDIA"
7318 "@
7319 b%o3%' %1, %2, %0%>
7320 b%o3i%' %1, %2, %0%>"
7321 [(set_attr "type" "cbranch_media")])
7322
7323 (define_insn "*beq_media_i32"
7324 [(set (pc)
7325 (if_then_else (match_operator 3 "equality_comparison_operator"
7326 [(match_operand:SI 1 "arith_reg_operand" "r,r")
7327 (match_operand:SI 2 "arith_operand" "r,I06")])
7328 (match_operand 0 "target_operand" "b,b")
7329 (pc)))]
7330 "TARGET_SHMEDIA"
7331 "@
7332 b%o3%' %1, %2, %0%>
7333 b%o3i%' %1, %2, %0%>"
7334 [(set_attr "type" "cbranch_media")])
7335
7336 (define_insn "*bgt_media_i"
7337 [(set (pc)
7338 (if_then_else (match_operator 3 "greater_comparison_operator"
7339 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
7340 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
7341 (match_operand 0 "target_operand" "b")
7342 (pc)))]
7343 "TARGET_SHMEDIA"
7344 "b%o3%' %N1, %N2, %0%>"
7345 [(set_attr "type" "cbranch_media")])
7346
7347 (define_insn "*bgt_media_i32"
7348 [(set (pc)
7349 (if_then_else (match_operator 3 "greater_comparison_operator"
7350 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
7351 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
7352 (match_operand 0 "target_operand" "b")
7353 (pc)))]
7354 "TARGET_SHMEDIA"
7355 "b%o3%' %N1, %N2, %0%>"
7356 [(set_attr "type" "cbranch_media")])
7357
7358 ;; These are only needed to make invert_jump() happy - otherwise, jump
7359 ;; optimization will be silently disabled.
7360 (define_insn "*blt_media_i"
7361 [(set (pc)
7362 (if_then_else (match_operator 3 "less_comparison_operator"
7363 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
7364 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
7365 (match_operand 0 "target_operand" "b")
7366 (pc)))]
7367 "TARGET_SHMEDIA"
7368 "b%o3%' %N2, %N1, %0%>"
7369 [(set_attr "type" "cbranch_media")])
7370
7371 (define_insn "*blt_media_i32"
7372 [(set (pc)
7373 (if_then_else (match_operator 3 "less_comparison_operator"
7374 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
7375 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
7376 (match_operand 0 "target_operand" "b")
7377 (pc)))]
7378 "TARGET_SHMEDIA"
7379 "b%o3%' %N2, %N1, %0%>"
7380 [(set_attr "type" "cbranch_media")])
7381
7382 ;; combiner splitter for test-and-branch on single bit in register. This
7383 ;; is endian dependent because the non-paradoxical subreg looks different
7384 ;; on big endian.
7385 (define_split
7386 [(set (pc)
7387 (if_then_else
7388 (match_operator 3 "equality_comparison_operator"
7389 [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1
7390 "extend_reg_operand" "")
7391 0)
7392 (const_int 1)
7393 (match_operand 2
7394 "const_int_operand" "")) 0)
7395 (const_int 0)])
7396 (match_operand 0 "target_operand" "")
7397 (pc)))
7398 (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
7399 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
7400 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
7401 (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
7402 {
7403 operands[5] = GEN_INT (31 - INTVAL (operands[2]));
7404 operands[6] = (GET_CODE (operands[3]) == EQ
7405 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
7406 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
7407 })
7408
7409 ; operand 0 is the loop count pseudo register
7410 ; operand 1 is the number of loop iterations or 0 if it is unknown
7411 ; operand 2 is the maximum number of loop iterations
7412 ; operand 3 is the number of levels of enclosed loops
7413 ; operand 4 is the label to jump to at the top of the loop
7414
7415 (define_expand "doloop_end"
7416 [(parallel [(set (pc) (if_then_else
7417 (ne:SI (match_operand:SI 0 "" "")
7418 (const_int 1))
7419 (label_ref (match_operand 4 "" ""))
7420 (pc)))
7421 (set (match_dup 0)
7422 (plus:SI (match_dup 0) (const_int -1)))
7423 (clobber (reg:SI T_REG))])]
7424 "TARGET_SH2"
7425 {
7426 if (GET_MODE (operands[0]) != SImode)
7427 FAIL;
7428 })
7429
7430 (define_insn_and_split "doloop_end_split"
7431 [(set (pc)
7432 (if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0")
7433 (const_int 1))
7434 (label_ref (match_operand 1 "" ""))
7435 (pc)))
7436 (set (match_operand:SI 0 "arith_reg_dest" "=r")
7437 (plus (match_dup 2) (const_int -1)))
7438 (clobber (reg:SI T_REG))]
7439 "TARGET_SH2"
7440 "#"
7441 ""
7442 [(parallel [(set (reg:SI T_REG)
7443 (eq:SI (match_dup 2) (const_int 1)))
7444 (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
7445 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
7446 (label_ref (match_dup 1))
7447 (pc)))]
7448 ""
7449 [(set_attr "type" "cbranch")])
7450
7451 \f
7452 ;; ------------------------------------------------------------------------
7453 ;; Jump and linkage insns
7454 ;; ------------------------------------------------------------------------
7455
7456 (define_insn "jump_compact"
7457 [(set (pc)
7458 (label_ref (match_operand 0 "" "")))]
7459 "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
7460 {
7461 /* The length is 16 if the delay slot is unfilled. */
7462 if (get_attr_length(insn) > 4)
7463 return output_far_jump(insn, operands[0]);
7464 else
7465 return "bra %l0%#";
7466 }
7467 [(set_attr "type" "jump")
7468 (set_attr "needs_delay_slot" "yes")])
7469
7470 ;; ??? It would be much saner to explicitly use the scratch register
7471 ;; in the jump insn, and have indirect_jump_scratch only set it,
7472 ;; but fill_simple_delay_slots would refuse to do delay slot filling
7473 ;; from the target then, as it uses simplejump_p.
7474 ;;(define_insn "jump_compact_far"
7475 ;; [(set (pc)
7476 ;; (label_ref (match_operand 0 "" "")))
7477 ;; (use (match_operand 1 "register_operand" "r")]
7478 ;; "TARGET_SH1"
7479 ;; "* return output_far_jump(insn, operands[0], operands[1]);"
7480 ;; [(set_attr "type" "jump")
7481 ;; (set_attr "needs_delay_slot" "yes")])
7482
7483 (define_insn "jump_media"
7484 [(set (pc)
7485 (match_operand 0 "target_operand" "b"))]
7486 "TARGET_SHMEDIA"
7487 "blink %0, r63%>"
7488 [(set_attr "type" "jump_media")])
7489
7490 (define_expand "jump"
7491 [(set (pc)
7492 (label_ref (match_operand 0 "" "")))]
7493 ""
7494 {
7495 if (TARGET_SH1)
7496 emit_jump_insn (gen_jump_compact (operands[0]));
7497 else if (TARGET_SHMEDIA)
7498 {
7499 if (reload_in_progress || reload_completed)
7500 FAIL;
7501 emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode,
7502 operands[0])));
7503 }
7504 DONE;
7505 })
7506
7507 (define_insn "force_mode_for_call"
7508 [(use (reg:PSI FPSCR_REG))]
7509 "TARGET_SHCOMPACT"
7510 ""
7511 [(set_attr "length" "0")
7512 (set (attr "fp_mode")
7513 (if_then_else (eq_attr "fpu_single" "yes")
7514 (const_string "single") (const_string "double")))])
7515
7516 (define_insn "calli"
7517 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7518 (match_operand 1 "" ""))
7519 (use (reg:PSI FPSCR_REG))
7520 (clobber (reg:SI PR_REG))]
7521 "TARGET_SH1"
7522 {
7523 if (TARGET_SH2A && (dbr_sequence_length () == 0))
7524 return "jsr/n\\t@%0";
7525 else
7526 return "jsr\\t@%0%#";
7527 }
7528 [(set_attr "type" "call")
7529 (set (attr "fp_mode")
7530 (if_then_else (eq_attr "fpu_single" "yes")
7531 (const_string "single") (const_string "double")))
7532 (set_attr "needs_delay_slot" "yes")
7533 (set_attr "fp_set" "unknown")])
7534
7535 ;; This is TBR relative jump instruction for SH2A architecture.
7536 ;; Its use is enabled assigning an attribute "function_vector"
7537 ;; and the vector number to a function during its declaration.
7538
7539 (define_insn "calli_tbr_rel"
7540 [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
7541 (match_operand 1 "" ""))
7542 (use (reg:PSI FPSCR_REG))
7543 (clobber (reg:SI PR_REG))]
7544 "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
7545 {
7546 unsigned HOST_WIDE_INT vect_num;
7547 vect_num = sh2a_get_function_vector_number (operands[0]);
7548 operands[2] = GEN_INT (vect_num * 4);
7549
7550 return "jsr/n\\t@@(%O2,tbr)";
7551 }
7552 [(set_attr "type" "call")
7553 (set (attr "fp_mode")
7554 (if_then_else (eq_attr "fpu_single" "yes")
7555 (const_string "single") (const_string "double")))
7556 (set_attr "needs_delay_slot" "no")
7557 (set_attr "fp_set" "unknown")])
7558
7559 ;; This is a pc-rel call, using bsrf, for use with PIC.
7560
7561 (define_insn "calli_pcrel"
7562 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7563 (match_operand 1 "" ""))
7564 (use (reg:PSI FPSCR_REG))
7565 (use (reg:SI PIC_REG))
7566 (use (match_operand 2 "" ""))
7567 (clobber (reg:SI PR_REG))]
7568 "TARGET_SH2"
7569 "bsrf %0\\n%O2:%#"
7570 [(set_attr "type" "call")
7571 (set (attr "fp_mode")
7572 (if_then_else (eq_attr "fpu_single" "yes")
7573 (const_string "single") (const_string "double")))
7574 (set_attr "needs_delay_slot" "yes")
7575 (set_attr "fp_set" "unknown")])
7576
7577 (define_insn_and_split "call_pcrel"
7578 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7579 (match_operand 1 "" ""))
7580 (use (reg:PSI FPSCR_REG))
7581 (use (reg:SI PIC_REG))
7582 (clobber (reg:SI PR_REG))
7583 (clobber (match_scratch:SI 2 "=r"))]
7584 "TARGET_SH2"
7585 "#"
7586 "reload_completed"
7587 [(const_int 0)]
7588 {
7589 rtx lab = PATTERN (gen_call_site ());
7590
7591 if (SYMBOL_REF_LOCAL_P (operands[0]))
7592 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7593 else
7594 emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
7595 emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
7596 DONE;
7597 }
7598 [(set_attr "type" "call")
7599 (set (attr "fp_mode")
7600 (if_then_else (eq_attr "fpu_single" "yes")
7601 (const_string "single") (const_string "double")))
7602 (set_attr "needs_delay_slot" "yes")
7603 (set_attr "fp_set" "unknown")])
7604
7605 (define_insn "call_compact"
7606 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7607 (match_operand 1 "" ""))
7608 (match_operand 2 "immediate_operand" "n")
7609 (use (reg:SI R0_REG))
7610 (use (reg:SI R1_REG))
7611 (use (reg:PSI FPSCR_REG))
7612 (clobber (reg:SI PR_REG))]
7613 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7614 "jsr @%0%#"
7615 [(set_attr "type" "call")
7616 (set (attr "fp_mode")
7617 (if_then_else (eq_attr "fpu_single" "yes")
7618 (const_string "single") (const_string "double")))
7619 (set_attr "needs_delay_slot" "yes")])
7620
7621 (define_insn "call_compact_rettramp"
7622 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7623 (match_operand 1 "" ""))
7624 (match_operand 2 "immediate_operand" "n")
7625 (use (reg:SI R0_REG))
7626 (use (reg:SI R1_REG))
7627 (use (reg:PSI FPSCR_REG))
7628 (clobber (reg:SI R10_REG))
7629 (clobber (reg:SI PR_REG))]
7630 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7631 "jsr @%0%#"
7632 [(set_attr "type" "call")
7633 (set (attr "fp_mode")
7634 (if_then_else (eq_attr "fpu_single" "yes")
7635 (const_string "single") (const_string "double")))
7636 (set_attr "needs_delay_slot" "yes")])
7637
7638 (define_insn "call_media"
7639 [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
7640 (match_operand 1 "" ""))
7641 (clobber (reg:DI PR_MEDIA_REG))]
7642 "TARGET_SHMEDIA"
7643 "blink %0, r18"
7644 [(set_attr "type" "jump_media")])
7645
7646 (define_insn "call_valuei"
7647 [(set (match_operand 0 "" "=rf")
7648 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7649 (match_operand 2 "" "")))
7650 (use (reg:PSI FPSCR_REG))
7651 (clobber (reg:SI PR_REG))]
7652 "TARGET_SH1"
7653 {
7654 if (TARGET_SH2A && (dbr_sequence_length () == 0))
7655 return "jsr/n\\t@%1";
7656 else
7657 return "jsr\\t@%1%#";
7658 }
7659 [(set_attr "type" "call")
7660 (set (attr "fp_mode")
7661 (if_then_else (eq_attr "fpu_single" "yes")
7662 (const_string "single") (const_string "double")))
7663 (set_attr "needs_delay_slot" "yes")
7664 (set_attr "fp_set" "unknown")])
7665
7666 ;; This is TBR relative jump instruction for SH2A architecture.
7667 ;; Its use is enabled by assigning an attribute "function_vector"
7668 ;; and the vector number to a function during its declaration.
7669
7670 (define_insn "call_valuei_tbr_rel"
7671 [(set (match_operand 0 "" "=rf")
7672 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7673 (match_operand 2 "" "")))
7674 (use (reg:PSI FPSCR_REG))
7675 (clobber (reg:SI PR_REG))]
7676 "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
7677 {
7678 unsigned HOST_WIDE_INT vect_num;
7679 vect_num = sh2a_get_function_vector_number (operands[1]);
7680 operands[3] = GEN_INT (vect_num * 4);
7681
7682 return "jsr/n\\t@@(%O3,tbr)";
7683 }
7684 [(set_attr "type" "call")
7685 (set (attr "fp_mode")
7686 (if_then_else (eq_attr "fpu_single" "yes")
7687 (const_string "single") (const_string "double")))
7688 (set_attr "needs_delay_slot" "no")
7689 (set_attr "fp_set" "unknown")])
7690
7691 (define_insn "call_valuei_pcrel"
7692 [(set (match_operand 0 "" "=rf")
7693 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7694 (match_operand 2 "" "")))
7695 (use (reg:PSI FPSCR_REG))
7696 (use (reg:SI PIC_REG))
7697 (use (match_operand 3 "" ""))
7698 (clobber (reg:SI PR_REG))]
7699 "TARGET_SH2"
7700 "bsrf %1\\n%O3:%#"
7701 [(set_attr "type" "call")
7702 (set (attr "fp_mode")
7703 (if_then_else (eq_attr "fpu_single" "yes")
7704 (const_string "single") (const_string "double")))
7705 (set_attr "needs_delay_slot" "yes")
7706 (set_attr "fp_set" "unknown")])
7707
7708 (define_insn_and_split "call_value_pcrel"
7709 [(set (match_operand 0 "" "=rf")
7710 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7711 (match_operand 2 "" "")))
7712 (use (reg:PSI FPSCR_REG))
7713 (use (reg:SI PIC_REG))
7714 (clobber (reg:SI PR_REG))
7715 (clobber (match_scratch:SI 3 "=r"))]
7716 "TARGET_SH2"
7717 "#"
7718 "reload_completed"
7719 [(const_int 0)]
7720 {
7721 rtx lab = PATTERN (gen_call_site ());
7722
7723 if (SYMBOL_REF_LOCAL_P (operands[1]))
7724 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
7725 else
7726 emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
7727 emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
7728 operands[2], copy_rtx (lab)));
7729 DONE;
7730 }
7731 [(set_attr "type" "call")
7732 (set (attr "fp_mode")
7733 (if_then_else (eq_attr "fpu_single" "yes")
7734 (const_string "single") (const_string "double")))
7735 (set_attr "needs_delay_slot" "yes")
7736 (set_attr "fp_set" "unknown")])
7737
7738 (define_insn "call_value_compact"
7739 [(set (match_operand 0 "" "=rf")
7740 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7741 (match_operand 2 "" "")))
7742 (match_operand 3 "immediate_operand" "n")
7743 (use (reg:SI R0_REG))
7744 (use (reg:SI R1_REG))
7745 (use (reg:PSI FPSCR_REG))
7746 (clobber (reg:SI PR_REG))]
7747 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7748 "jsr @%1%#"
7749 [(set_attr "type" "call")
7750 (set (attr "fp_mode")
7751 (if_then_else (eq_attr "fpu_single" "yes")
7752 (const_string "single") (const_string "double")))
7753 (set_attr "needs_delay_slot" "yes")])
7754
7755 (define_insn "call_value_compact_rettramp"
7756 [(set (match_operand 0 "" "=rf")
7757 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7758 (match_operand 2 "" "")))
7759 (match_operand 3 "immediate_operand" "n")
7760 (use (reg:SI R0_REG))
7761 (use (reg:SI R1_REG))
7762 (use (reg:PSI FPSCR_REG))
7763 (clobber (reg:SI R10_REG))
7764 (clobber (reg:SI PR_REG))]
7765 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7766 "jsr @%1%#"
7767 [(set_attr "type" "call")
7768 (set (attr "fp_mode")
7769 (if_then_else (eq_attr "fpu_single" "yes")
7770 (const_string "single") (const_string "double")))
7771 (set_attr "needs_delay_slot" "yes")])
7772
7773 (define_insn "call_value_media"
7774 [(set (match_operand 0 "" "=rf")
7775 (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
7776 (match_operand 2 "" "")))
7777 (clobber (reg:DI PR_MEDIA_REG))]
7778 "TARGET_SHMEDIA"
7779 "blink %1, r18"
7780 [(set_attr "type" "jump_media")])
7781
7782 (define_expand "call"
7783 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7784 (match_operand 1 "" ""))
7785 (match_operand 2 "" "")
7786 (use (reg:PSI FPSCR_REG))
7787 (clobber (reg:SI PR_REG))])]
7788 ""
7789 {
7790 if (TARGET_SHMEDIA)
7791 {
7792 operands[0] = shmedia_prepare_call_address (operands[0], 0);
7793 emit_call_insn (gen_call_media (operands[0], operands[1]));
7794 DONE;
7795 }
7796 else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
7797 {
7798 rtx cookie_rtx = operands[2];
7799 long cookie = INTVAL (cookie_rtx);
7800 rtx func = XEXP (operands[0], 0);
7801 rtx r0, r1;
7802
7803 if (flag_pic)
7804 {
7805 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7806 {
7807 rtx reg = gen_reg_rtx (Pmode);
7808
7809 emit_insn (gen_symGOTPLT2reg (reg, func));
7810 func = reg;
7811 }
7812 else
7813 func = legitimize_pic_address (func, Pmode, 0);
7814 }
7815
7816 r0 = gen_rtx_REG (SImode, R0_REG);
7817 r1 = gen_rtx_REG (SImode, R1_REG);
7818
7819 /* Since such a call function may use all call-clobbered
7820 registers, we force a mode switch earlier, so that we don't
7821 run out of registers when adjusting fpscr for the call. */
7822 emit_insn (gen_force_mode_for_call ());
7823
7824 operands[0]
7825 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
7826 operands[0] = force_reg (SImode, operands[0]);
7827
7828 emit_move_insn (r0, func);
7829 emit_move_insn (r1, cookie_rtx);
7830
7831 if (cookie & CALL_COOKIE_RET_TRAMP (1))
7832 emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
7833 operands[2]));
7834 else
7835 emit_call_insn (gen_call_compact (operands[0], operands[1],
7836 operands[2]));
7837
7838 DONE;
7839 }
7840 else if (TARGET_SHCOMPACT && flag_pic
7841 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7842 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7843 {
7844 rtx reg = gen_reg_rtx (Pmode);
7845
7846 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
7847 XEXP (operands[0], 0) = reg;
7848 }
7849 if (!flag_pic && TARGET_SH2A
7850 && MEM_P (operands[0])
7851 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
7852 {
7853 if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
7854 {
7855 emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
7856 operands[1]));
7857 DONE;
7858 }
7859 }
7860 if (flag_pic && TARGET_SH2
7861 && MEM_P (operands[0])
7862 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
7863 {
7864 emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
7865 DONE;
7866 }
7867 else
7868 {
7869 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
7870 operands[1] = operands[2];
7871 }
7872
7873 emit_call_insn (gen_calli (operands[0], operands[1]));
7874 DONE;
7875 })
7876
7877 (define_insn "call_pop_compact"
7878 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7879 (match_operand 1 "" ""))
7880 (match_operand 2 "immediate_operand" "n")
7881 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7882 (match_operand 3 "immediate_operand" "n")))
7883 (use (reg:SI R0_REG))
7884 (use (reg:SI R1_REG))
7885 (use (reg:PSI FPSCR_REG))
7886 (clobber (reg:SI PR_REG))]
7887 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7888 "jsr @%0%#"
7889 [(set_attr "type" "call")
7890 (set (attr "fp_mode")
7891 (if_then_else (eq_attr "fpu_single" "yes")
7892 (const_string "single") (const_string "double")))
7893 (set_attr "needs_delay_slot" "yes")])
7894
7895 (define_insn "call_pop_compact_rettramp"
7896 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7897 (match_operand 1 "" ""))
7898 (match_operand 2 "immediate_operand" "n")
7899 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7900 (match_operand 3 "immediate_operand" "n")))
7901 (use (reg:SI R0_REG))
7902 (use (reg:SI R1_REG))
7903 (use (reg:PSI FPSCR_REG))
7904 (clobber (reg:SI R10_REG))
7905 (clobber (reg:SI PR_REG))]
7906 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7907 "jsr @%0%#"
7908 [(set_attr "type" "call")
7909 (set (attr "fp_mode")
7910 (if_then_else (eq_attr "fpu_single" "yes")
7911 (const_string "single") (const_string "double")))
7912 (set_attr "needs_delay_slot" "yes")])
7913
7914 (define_expand "call_pop"
7915 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7916 (match_operand 1 "" ""))
7917 (match_operand 2 "" "")
7918 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7919 (match_operand 3 "" "")))])]
7920 "TARGET_SHCOMPACT"
7921 {
7922 rtx cookie_rtx;
7923 long cookie;
7924 rtx func;
7925 rtx r0, r1;
7926
7927 gcc_assert (operands[2] && INTVAL (operands[2]));
7928 cookie_rtx = operands[2];
7929 cookie = INTVAL (cookie_rtx);
7930 func = XEXP (operands[0], 0);
7931
7932 if (flag_pic)
7933 {
7934 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7935 {
7936 rtx reg = gen_reg_rtx (Pmode);
7937 emit_insn (gen_symGOTPLT2reg (reg, func));
7938 func = reg;
7939 }
7940 else
7941 func = legitimize_pic_address (func, Pmode, 0);
7942 }
7943
7944 r0 = gen_rtx_REG (SImode, R0_REG);
7945 r1 = gen_rtx_REG (SImode, R1_REG);
7946
7947 /* Since such a call function may use all call-clobbered
7948 registers, we force a mode switch earlier, so that we don't
7949 run out of registers when adjusting fpscr for the call. */
7950 emit_insn (gen_force_mode_for_call ());
7951
7952 operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
7953 SFUNC_GOT);
7954 operands[0] = force_reg (SImode, operands[0]);
7955
7956 emit_move_insn (r0, func);
7957 emit_move_insn (r1, cookie_rtx);
7958
7959 if (cookie & CALL_COOKIE_RET_TRAMP (1))
7960 emit_call_insn (gen_call_pop_compact_rettramp
7961 (operands[0], operands[1], operands[2], operands[3]));
7962 else
7963 emit_call_insn (gen_call_pop_compact
7964 (operands[0], operands[1], operands[2], operands[3]));
7965
7966 DONE;
7967 })
7968
7969 (define_expand "call_value"
7970 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
7971 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
7972 (match_operand 2 "" "")))
7973 (match_operand 3 "" "")
7974 (use (reg:PSI FPSCR_REG))
7975 (clobber (reg:SI PR_REG))])]
7976 ""
7977 {
7978 if (TARGET_SHMEDIA)
7979 {
7980 operands[1] = shmedia_prepare_call_address (operands[1], 0);
7981 emit_call_insn (gen_call_value_media (operands[0], operands[1],
7982 operands[2]));
7983 DONE;
7984 }
7985 else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
7986 {
7987 rtx cookie_rtx = operands[3];
7988 long cookie = INTVAL (cookie_rtx);
7989 rtx func = XEXP (operands[1], 0);
7990 rtx r0, r1;
7991
7992 if (flag_pic)
7993 {
7994 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7995 {
7996 rtx reg = gen_reg_rtx (Pmode);
7997
7998 emit_insn (gen_symGOTPLT2reg (reg, func));
7999 func = reg;
8000 }
8001 else
8002 func = legitimize_pic_address (func, Pmode, 0);
8003 }
8004
8005 r0 = gen_rtx_REG (SImode, R0_REG);
8006 r1 = gen_rtx_REG (SImode, R1_REG);
8007
8008 /* Since such a call function may use all call-clobbered
8009 registers, we force a mode switch earlier, so that we don't
8010 run out of registers when adjusting fpscr for the call. */
8011 emit_insn (gen_force_mode_for_call ());
8012
8013 operands[1]
8014 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
8015 operands[1] = force_reg (SImode, operands[1]);
8016
8017 emit_move_insn (r0, func);
8018 emit_move_insn (r1, cookie_rtx);
8019
8020 if (cookie & CALL_COOKIE_RET_TRAMP (1))
8021 emit_call_insn (gen_call_value_compact_rettramp (operands[0],
8022 operands[1],
8023 operands[2],
8024 operands[3]));
8025 else
8026 emit_call_insn (gen_call_value_compact (operands[0], operands[1],
8027 operands[2], operands[3]));
8028
8029 DONE;
8030 }
8031 else if (TARGET_SHCOMPACT && flag_pic
8032 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8033 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
8034 {
8035 rtx reg = gen_reg_rtx (Pmode);
8036
8037 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
8038 XEXP (operands[1], 0) = reg;
8039 }
8040 if (!flag_pic && TARGET_SH2A
8041 && MEM_P (operands[1])
8042 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
8043 {
8044 if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
8045 {
8046 emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
8047 XEXP (operands[1], 0), operands[2]));
8048 DONE;
8049 }
8050 }
8051 if (flag_pic && TARGET_SH2
8052 && MEM_P (operands[1])
8053 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
8054 {
8055 emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
8056 operands[2]));
8057 DONE;
8058 }
8059 else
8060 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
8061
8062 emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
8063 DONE;
8064 })
8065
8066 (define_insn "sibcalli"
8067 [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
8068 (match_operand 1 "" ""))
8069 (use (reg:PSI FPSCR_REG))
8070 (return)]
8071 "TARGET_SH1"
8072 "jmp @%0%#"
8073 [(set_attr "needs_delay_slot" "yes")
8074 (set (attr "fp_mode")
8075 (if_then_else (eq_attr "fpu_single" "yes")
8076 (const_string "single") (const_string "double")))
8077 (set_attr "type" "jump_ind")])
8078
8079 (define_insn "sibcalli_pcrel"
8080 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
8081 (match_operand 1 "" ""))
8082 (use (match_operand 2 "" ""))
8083 (use (reg:PSI FPSCR_REG))
8084 (return)]
8085 "TARGET_SH2"
8086 "braf %0\\n%O2:%#"
8087 [(set_attr "needs_delay_slot" "yes")
8088 (set (attr "fp_mode")
8089 (if_then_else (eq_attr "fpu_single" "yes")
8090 (const_string "single") (const_string "double")))
8091 (set_attr "type" "jump_ind")])
8092
8093 ;; This uses an unspec to describe that the symbol_ref is very close.
8094 (define_insn "sibcalli_thunk"
8095 [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
8096 UNSPEC_THUNK))
8097 (match_operand 1 "" ""))
8098 (use (reg:PSI FPSCR_REG))
8099 (return)]
8100 "TARGET_SH1"
8101 "bra %O0"
8102 [(set_attr "needs_delay_slot" "yes")
8103 (set (attr "fp_mode")
8104 (if_then_else (eq_attr "fpu_single" "yes")
8105 (const_string "single") (const_string "double")))
8106 (set_attr "type" "jump")
8107 (set_attr "length" "2")])
8108
8109 (define_insn_and_split "sibcall_pcrel"
8110 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
8111 (match_operand 1 "" ""))
8112 (use (reg:PSI FPSCR_REG))
8113 (clobber (match_scratch:SI 2 "=k"))
8114 (return)]
8115 "TARGET_SH2"
8116 "#"
8117 "reload_completed"
8118 [(const_int 0)]
8119 {
8120 rtx lab = PATTERN (gen_call_site ());
8121 rtx call_insn;
8122
8123 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
8124 call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
8125 copy_rtx (lab)));
8126 SIBLING_CALL_P (call_insn) = 1;
8127 DONE;
8128 }
8129 [(set_attr "needs_delay_slot" "yes")
8130 (set (attr "fp_mode")
8131 (if_then_else (eq_attr "fpu_single" "yes")
8132 (const_string "single") (const_string "double")))
8133 (set_attr "type" "jump_ind")])
8134
8135 (define_insn "sibcall_compact"
8136 [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
8137 (match_operand 1 "" ""))
8138 (return)
8139 (use (match_operand:SI 2 "register_operand" "z,x"))
8140 (use (reg:SI R1_REG))
8141 (use (reg:PSI FPSCR_REG))
8142 ;; We want to make sure the `x' above will only match MACH_REG
8143 ;; because sibcall_epilogue may clobber MACL_REG.
8144 (clobber (reg:SI MACL_REG))]
8145 "TARGET_SHCOMPACT"
8146 "@
8147 jmp @%0%#
8148 jmp @%0\\n sts %2, r0"
8149 [(set_attr "needs_delay_slot" "yes,no")
8150 (set_attr "length" "2,4")
8151 (set (attr "fp_mode") (const_string "single"))
8152 (set_attr "type" "jump_ind")])
8153
8154 (define_insn "sibcall_media"
8155 [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
8156 (match_operand 1 "" ""))
8157 (use (reg:SI PR_MEDIA_REG))
8158 (return)]
8159 "TARGET_SHMEDIA"
8160 "blink %0, r63"
8161 [(set_attr "type" "jump_media")])
8162
8163 (define_expand "sibcall"
8164 [(parallel
8165 [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
8166 (match_operand 1 "" ""))
8167 (match_operand 2 "" "")
8168 (use (reg:PSI FPSCR_REG))
8169 (return)])]
8170 ""
8171 {
8172 if (TARGET_SHMEDIA)
8173 {
8174 operands[0] = shmedia_prepare_call_address (operands[0], 1);
8175 emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
8176 DONE;
8177 }
8178 else if (TARGET_SHCOMPACT && operands[2]
8179 && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
8180 {
8181 rtx cookie_rtx = operands[2];
8182 long cookie = INTVAL (cookie_rtx);
8183 rtx func = XEXP (operands[0], 0);
8184 rtx mach, r1;
8185
8186 if (flag_pic)
8187 {
8188 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8189 {
8190 rtx reg = gen_reg_rtx (Pmode);
8191
8192 emit_insn (gen_symGOT2reg (reg, func));
8193 func = reg;
8194 }
8195 else
8196 func = legitimize_pic_address (func, Pmode, 0);
8197 }
8198
8199 /* FIXME: if we could tell whether all argument registers are
8200 already taken, we could decide whether to force the use of
8201 MACH_REG or to stick to R0_REG. Unfortunately, there's no
8202 simple way to tell. We could use the CALL_COOKIE, but we
8203 can't currently tell a register used for regular argument
8204 passing from one that is unused. If we leave it up to reload
8205 to decide which register to use, it seems to always choose
8206 R0_REG, which leaves no available registers in SIBCALL_REGS
8207 to hold the address of the trampoline. */
8208 mach = gen_rtx_REG (SImode, MACH_REG);
8209 r1 = gen_rtx_REG (SImode, R1_REG);
8210
8211 /* Since such a call function may use all call-clobbered
8212 registers, we force a mode switch earlier, so that we don't
8213 run out of registers when adjusting fpscr for the call. */
8214 emit_insn (gen_force_mode_for_call ());
8215
8216 operands[0]
8217 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
8218 operands[0] = force_reg (SImode, operands[0]);
8219
8220 /* We don't need a return trampoline, since the callee will
8221 return directly to the upper caller. */
8222 if (cookie & CALL_COOKIE_RET_TRAMP (1))
8223 {
8224 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
8225 cookie_rtx = GEN_INT (cookie);
8226 }
8227
8228 emit_move_insn (mach, func);
8229 emit_move_insn (r1, cookie_rtx);
8230
8231 emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
8232 DONE;
8233 }
8234 else if (TARGET_SHCOMPACT && flag_pic
8235 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8236 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
8237 {
8238 rtx reg = gen_reg_rtx (Pmode);
8239
8240 emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
8241 XEXP (operands[0], 0) = reg;
8242 }
8243 if (flag_pic && TARGET_SH2
8244 && MEM_P (operands[0])
8245 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8246 /* The PLT needs the PIC register, but the epilogue would have
8247 to restore it, so we can only use PC-relative PIC calls for
8248 static functions. */
8249 && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
8250 {
8251 emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
8252 DONE;
8253 }
8254 else
8255 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
8256
8257 emit_call_insn (gen_sibcalli (operands[0], operands[1]));
8258 DONE;
8259 })
8260
8261 (define_insn "sibcall_valuei"
8262 [(set (match_operand 0 "" "=rf")
8263 (call (mem:SI (match_operand:SI 1 "register_operand" "k"))
8264 (match_operand 2 "" "")))
8265 (use (reg:PSI FPSCR_REG))
8266 (return)]
8267 "TARGET_SH1"
8268 "jmp @%1%#"
8269 [(set_attr "needs_delay_slot" "yes")
8270 (set (attr "fp_mode")
8271 (if_then_else (eq_attr "fpu_single" "yes")
8272 (const_string "single") (const_string "double")))
8273 (set_attr "type" "jump_ind")])
8274
8275 (define_insn "sibcall_valuei_pcrel"
8276 [(set (match_operand 0 "" "=rf")
8277 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
8278 (match_operand 2 "" "")))
8279 (use (match_operand 3 "" ""))
8280 (use (reg:PSI FPSCR_REG))
8281 (return)]
8282 "TARGET_SH2"
8283 "braf %1\\n%O3:%#"
8284 [(set_attr "needs_delay_slot" "yes")
8285 (set (attr "fp_mode")
8286 (if_then_else (eq_attr "fpu_single" "yes")
8287 (const_string "single") (const_string "double")))
8288 (set_attr "type" "jump_ind")])
8289
8290 (define_insn_and_split "sibcall_value_pcrel"
8291 [(set (match_operand 0 "" "=rf")
8292 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
8293 (match_operand 2 "" "")))
8294 (use (reg:PSI FPSCR_REG))
8295 (clobber (match_scratch:SI 3 "=k"))
8296 (return)]
8297 "TARGET_SH2"
8298 "#"
8299 "reload_completed"
8300 [(const_int 0)]
8301 {
8302 rtx lab = PATTERN (gen_call_site ());
8303 rtx call_insn;
8304
8305 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
8306 call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
8307 operands[3],
8308 operands[2],
8309 copy_rtx (lab)));
8310 SIBLING_CALL_P (call_insn) = 1;
8311 DONE;
8312 }
8313 [(set_attr "needs_delay_slot" "yes")
8314 (set (attr "fp_mode")
8315 (if_then_else (eq_attr "fpu_single" "yes")
8316 (const_string "single") (const_string "double")))
8317 (set_attr "type" "jump_ind")])
8318
8319 (define_insn "sibcall_value_compact"
8320 [(set (match_operand 0 "" "=rf,rf")
8321 (call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
8322 (match_operand 2 "" "")))
8323 (return)
8324 (use (match_operand:SI 3 "register_operand" "z,x"))
8325 (use (reg:SI R1_REG))
8326 (use (reg:PSI FPSCR_REG))
8327 ;; We want to make sure the `x' above will only match MACH_REG
8328 ;; because sibcall_epilogue may clobber MACL_REG.
8329 (clobber (reg:SI MACL_REG))]
8330 "TARGET_SHCOMPACT"
8331 "@
8332 jmp @%1%#
8333 jmp @%1\\n sts %3, r0"
8334 [(set_attr "needs_delay_slot" "yes,no")
8335 (set_attr "length" "2,4")
8336 (set (attr "fp_mode") (const_string "single"))
8337 (set_attr "type" "jump_ind")])
8338
8339 (define_insn "sibcall_value_media"
8340 [(set (match_operand 0 "" "=rf")
8341 (call (mem:DI (match_operand 1 "target_reg_operand" "k"))
8342 (match_operand 2 "" "")))
8343 (use (reg:SI PR_MEDIA_REG))
8344 (return)]
8345 "TARGET_SHMEDIA"
8346 "blink %1, r63"
8347 [(set_attr "type" "jump_media")])
8348
8349 (define_expand "sibcall_value"
8350 [(parallel
8351 [(set (match_operand 0 "arith_reg_operand" "")
8352 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
8353 (match_operand 2 "" "")))
8354 (match_operand 3 "" "")
8355 (use (reg:PSI FPSCR_REG))
8356 (return)])]
8357 ""
8358 {
8359 if (TARGET_SHMEDIA)
8360 {
8361 operands[1] = shmedia_prepare_call_address (operands[1], 1);
8362 emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
8363 operands[2]));
8364 DONE;
8365 }
8366 else if (TARGET_SHCOMPACT && operands[3]
8367 && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
8368 {
8369 rtx cookie_rtx = operands[3];
8370 long cookie = INTVAL (cookie_rtx);
8371 rtx func = XEXP (operands[1], 0);
8372 rtx mach, r1;
8373
8374 if (flag_pic)
8375 {
8376 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8377 {
8378 rtx reg = gen_reg_rtx (Pmode);
8379
8380 emit_insn (gen_symGOT2reg (reg, func));
8381 func = reg;
8382 }
8383 else
8384 func = legitimize_pic_address (func, Pmode, 0);
8385 }
8386
8387 /* FIXME: if we could tell whether all argument registers are
8388 already taken, we could decide whether to force the use of
8389 MACH_REG or to stick to R0_REG. Unfortunately, there's no
8390 simple way to tell. We could use the CALL_COOKIE, but we
8391 can't currently tell a register used for regular argument
8392 passing from one that is unused. If we leave it up to reload
8393 to decide which register to use, it seems to always choose
8394 R0_REG, which leaves no available registers in SIBCALL_REGS
8395 to hold the address of the trampoline. */
8396 mach = gen_rtx_REG (SImode, MACH_REG);
8397 r1 = gen_rtx_REG (SImode, R1_REG);
8398
8399 /* Since such a call function may use all call-clobbered
8400 registers, we force a mode switch earlier, so that we don't
8401 run out of registers when adjusting fpscr for the call. */
8402 emit_insn (gen_force_mode_for_call ());
8403
8404 operands[1]
8405 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
8406 operands[1] = force_reg (SImode, operands[1]);
8407
8408 /* We don't need a return trampoline, since the callee will
8409 return directly to the upper caller. */
8410 if (cookie & CALL_COOKIE_RET_TRAMP (1))
8411 {
8412 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
8413 cookie_rtx = GEN_INT (cookie);
8414 }
8415
8416 emit_move_insn (mach, func);
8417 emit_move_insn (r1, cookie_rtx);
8418
8419 emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
8420 operands[2], mach));
8421 DONE;
8422 }
8423 else if (TARGET_SHCOMPACT && flag_pic
8424 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8425 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
8426 {
8427 rtx reg = gen_reg_rtx (Pmode);
8428
8429 emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
8430 XEXP (operands[1], 0) = reg;
8431 }
8432 if (flag_pic && TARGET_SH2
8433 && MEM_P (operands[1])
8434 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8435 /* The PLT needs the PIC register, but the epilogue would have
8436 to restore it, so we can only use PC-relative PIC calls for
8437 static functions. */
8438 && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
8439 {
8440 emit_call_insn (gen_sibcall_value_pcrel (operands[0],
8441 XEXP (operands[1], 0),
8442 operands[2]));
8443 DONE;
8444 }
8445 else
8446 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
8447
8448 emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
8449 DONE;
8450 })
8451
8452 (define_insn "call_value_pop_compact"
8453 [(set (match_operand 0 "" "=rf")
8454 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8455 (match_operand 2 "" "")))
8456 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8457 (match_operand 4 "immediate_operand" "n")))
8458 (match_operand 3 "immediate_operand" "n")
8459 (use (reg:SI R0_REG))
8460 (use (reg:SI R1_REG))
8461 (use (reg:PSI FPSCR_REG))
8462 (clobber (reg:SI PR_REG))]
8463 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8464 "jsr @%1%#"
8465 [(set_attr "type" "call")
8466 (set (attr "fp_mode")
8467 (if_then_else (eq_attr "fpu_single" "yes")
8468 (const_string "single") (const_string "double")))
8469 (set_attr "needs_delay_slot" "yes")])
8470
8471 (define_insn "call_value_pop_compact_rettramp"
8472 [(set (match_operand 0 "" "=rf")
8473 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8474 (match_operand 2 "" "")))
8475 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8476 (match_operand 4 "immediate_operand" "n")))
8477 (match_operand 3 "immediate_operand" "n")
8478 (use (reg:SI R0_REG))
8479 (use (reg:SI R1_REG))
8480 (use (reg:PSI FPSCR_REG))
8481 (clobber (reg:SI R10_REG))
8482 (clobber (reg:SI PR_REG))]
8483 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8484 "jsr @%1%#"
8485 [(set_attr "type" "call")
8486 (set (attr "fp_mode")
8487 (if_then_else (eq_attr "fpu_single" "yes")
8488 (const_string "single") (const_string "double")))
8489 (set_attr "needs_delay_slot" "yes")])
8490
8491 (define_expand "call_value_pop"
8492 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
8493 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
8494 (match_operand 2 "" "")))
8495 (match_operand 3 "" "")
8496 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8497 (match_operand 4 "" "")))])]
8498 "TARGET_SHCOMPACT"
8499 {
8500 rtx cookie_rtx;
8501 long cookie;
8502 rtx func;
8503 rtx r0, r1;
8504
8505 gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
8506 cookie_rtx = operands[3];
8507 cookie = INTVAL (cookie_rtx);
8508 func = XEXP (operands[1], 0);
8509
8510 if (flag_pic)
8511 {
8512 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8513 {
8514 rtx reg = gen_reg_rtx (Pmode);
8515
8516 emit_insn (gen_symGOTPLT2reg (reg, func));
8517 func = reg;
8518 }
8519 else
8520 func = legitimize_pic_address (func, Pmode, 0);
8521 }
8522
8523 r0 = gen_rtx_REG (SImode, R0_REG);
8524 r1 = gen_rtx_REG (SImode, R1_REG);
8525
8526 /* Since such a call function may use all call-clobbered
8527 registers, we force a mode switch earlier, so that we don't
8528 run out of registers when adjusting fpscr for the call. */
8529 emit_insn (gen_force_mode_for_call ());
8530
8531 operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
8532 SFUNC_GOT);
8533 operands[1] = force_reg (SImode, operands[1]);
8534
8535 emit_move_insn (r0, func);
8536 emit_move_insn (r1, cookie_rtx);
8537
8538 if (cookie & CALL_COOKIE_RET_TRAMP (1))
8539 emit_call_insn (gen_call_value_pop_compact_rettramp
8540 (operands[0], operands[1], operands[2],
8541 operands[3], operands[4]));
8542 else
8543 emit_call_insn (gen_call_value_pop_compact
8544 (operands[0], operands[1], operands[2],
8545 operands[3], operands[4]));
8546
8547 DONE;
8548 })
8549
8550 (define_expand "sibcall_epilogue"
8551 [(return)]
8552 ""
8553 {
8554 sh_expand_epilogue (1);
8555 if (TARGET_SHCOMPACT)
8556 {
8557 rtx insn, set;
8558
8559 /* If epilogue clobbers r0, preserve it in macl. */
8560 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
8561 if ((set = single_set (insn))
8562 && REG_P (SET_DEST (set))
8563 && REGNO (SET_DEST (set)) == R0_REG)
8564 {
8565 rtx r0 = gen_rtx_REG (SImode, R0_REG);
8566 rtx tmp = gen_rtx_REG (SImode, MACL_REG);
8567
8568 /* We can't tell at this point whether the sibcall is a
8569 sibcall_compact and, if it is, whether it uses r0 or
8570 mach as operand 2, so let the instructions that
8571 preserve r0 be optimized away if r0 turns out to be
8572 dead. */
8573 emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
8574 emit_move_insn (r0, tmp);
8575 break;
8576 }
8577 }
8578 DONE;
8579 })
8580
8581 (define_insn "indirect_jump_compact"
8582 [(set (pc)
8583 (match_operand:SI 0 "arith_reg_operand" "r"))]
8584 "TARGET_SH1"
8585 "jmp @%0%#"
8586 [(set_attr "needs_delay_slot" "yes")
8587 (set_attr "type" "jump_ind")])
8588
8589 (define_expand "indirect_jump"
8590 [(set (pc)
8591 (match_operand 0 "register_operand" ""))]
8592 ""
8593 {
8594 if (GET_MODE (operands[0]) != Pmode)
8595 operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
8596 })
8597
8598 ;; The use of operand 1 / 2 helps us distinguish case table jumps
8599 ;; which can be present in structured code from indirect jumps which can not
8600 ;; be present in structured code. This allows -fprofile-arcs to work.
8601
8602 ;; For SH1 processors.
8603 (define_insn "casesi_jump_1"
8604 [(set (pc)
8605 (match_operand:SI 0 "register_operand" "r"))
8606 (use (label_ref (match_operand 1 "" "")))]
8607 "TARGET_SH1"
8608 "jmp @%0%#"
8609 [(set_attr "needs_delay_slot" "yes")
8610 (set_attr "type" "jump_ind")])
8611
8612 ;; For all later processors.
8613 (define_insn "casesi_jump_2"
8614 [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
8615 (label_ref (match_operand 1 "" ""))))
8616 (use (label_ref (match_operand 2 "" "")))]
8617 "TARGET_SH2
8618 && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
8619 "braf %0%#"
8620 [(set_attr "needs_delay_slot" "yes")
8621 (set_attr "type" "jump_ind")])
8622
8623 (define_insn "casesi_jump_media"
8624 [(set (pc) (match_operand 0 "target_reg_operand" "b"))
8625 (use (label_ref (match_operand 1 "" "")))]
8626 "TARGET_SHMEDIA"
8627 "blink %0, r63"
8628 [(set_attr "type" "jump_media")])
8629
8630 ;; Call subroutine returning any type.
8631 ;; ??? This probably doesn't work.
8632
8633 (define_expand "untyped_call"
8634 [(parallel [(call (match_operand 0 "" "")
8635 (const_int 0))
8636 (match_operand 1 "" "")
8637 (match_operand 2 "" "")])]
8638 "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
8639 {
8640 int i;
8641
8642 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
8643
8644 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8645 {
8646 rtx set = XVECEXP (operands[2], 0, i);
8647 emit_move_insn (SET_DEST (set), SET_SRC (set));
8648 }
8649
8650 /* The optimizer does not know that the call sets the function value
8651 registers we stored in the result block. We avoid problems by
8652 claiming that all hard registers are used and clobbered at this
8653 point. */
8654 emit_insn (gen_blockage ());
8655
8656 DONE;
8657 })
8658 \f
8659 ;; ------------------------------------------------------------------------
8660 ;; Misc insns
8661 ;; ------------------------------------------------------------------------
8662
8663 (define_insn "dect"
8664 [(set (reg:SI T_REG)
8665 (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
8666 (set (match_operand:SI 0 "arith_reg_dest" "=r")
8667 (plus:SI (match_dup 1) (const_int -1)))]
8668 "TARGET_SH2"
8669 "dt %0"
8670 [(set_attr "type" "arith")])
8671
8672 (define_insn "nop"
8673 [(const_int 0)]
8674 ""
8675 "nop")
8676
8677 ;; Load address of a label. This is only generated by the casesi expand,
8678 ;; and by machine_dependent_reorg (fixing up fp moves).
8679 ;; This must use unspec, because this only works for labels that are
8680 ;; within range,
8681
8682 (define_insn "mova"
8683 [(set (reg:SI R0_REG)
8684 (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
8685 "TARGET_SH1"
8686 "mova %O0,r0"
8687 [(set_attr "in_delay_slot" "no")
8688 (set_attr "type" "arith")])
8689
8690 ;; machine_dependent_reorg will make this a `mova'.
8691 (define_insn "mova_const"
8692 [(set (reg:SI R0_REG)
8693 (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
8694 "TARGET_SH1"
8695 "#"
8696 [(set_attr "in_delay_slot" "no")
8697 (set_attr "type" "arith")])
8698
8699 (define_expand "GOTaddr2picreg"
8700 [(set (reg:SI R0_REG)
8701 (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
8702 UNSPEC_MOVA))
8703 (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
8704 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
8705 ""
8706 {
8707 if (TARGET_VXWORKS_RTP)
8708 {
8709 rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
8710 rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
8711 emit_insn (gen_vxworks_picreg (gott_base, gott_index));
8712 DONE;
8713 }
8714
8715 operands[0] = gen_rtx_REG (Pmode, PIC_REG);
8716 operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
8717
8718 if (TARGET_SHMEDIA)
8719 {
8720 rtx tr = gen_rtx_REG (Pmode, TR0_REG);
8721 rtx pic = operands[0];
8722 rtx lab = PATTERN (gen_call_site ());
8723 rtx insn, equiv;
8724
8725 equiv = operands[1];
8726 operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
8727 UNSPEC_PCREL_SYMOFF);
8728 operands[1] = gen_rtx_CONST (Pmode, operands[1]);
8729
8730 if (Pmode == SImode)
8731 {
8732 emit_insn (gen_movsi_const (pic, operands[1]));
8733 emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
8734 }
8735 else
8736 {
8737 emit_insn (gen_movdi_const (pic, operands[1]));
8738 emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
8739 }
8740
8741 insn = emit_move_insn (operands[0], tr);
8742
8743 set_unique_reg_note (insn, REG_EQUAL, equiv);
8744
8745 DONE;
8746 }
8747 })
8748
8749 ;; A helper for GOTaddr2picreg to finish up the initialization of the
8750 ;; PIC register.
8751
8752 (define_expand "vxworks_picreg"
8753 [(set (reg:SI PIC_REG)
8754 (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
8755 (set (reg:SI R0_REG)
8756 (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
8757 (set (reg:SI PIC_REG)
8758 (mem:SI (reg:SI PIC_REG)))
8759 (set (reg:SI PIC_REG)
8760 (mem:SI (plus:SI (reg:SI PIC_REG)
8761 (reg:SI R0_REG))))]
8762 "TARGET_VXWORKS_RTP")
8763
8764 (define_insn "*ptb"
8765 [(set (match_operand 0 "target_reg_operand" "=b")
8766 (const (unspec [(match_operand 1 "" "Csy")]
8767 UNSPEC_DATALABEL)))]
8768 "TARGET_SHMEDIA && flag_pic
8769 && satisfies_constraint_Csy (operands[1])"
8770 "ptb/u datalabel %1, %0"
8771 [(set_attr "type" "ptabs_media")
8772 (set_attr "length" "*")])
8773
8774 (define_insn "ptrel_si"
8775 [(set (match_operand:SI 0 "target_reg_operand" "=b")
8776 (plus:SI (match_operand:SI 1 "register_operand" "r")
8777 (pc)))
8778 (match_operand:SI 2 "" "")]
8779 "TARGET_SHMEDIA"
8780 "%O2: ptrel/u %1, %0"
8781 [(set_attr "type" "ptabs_media")])
8782
8783 (define_insn "ptrel_di"
8784 [(set (match_operand:DI 0 "target_reg_operand" "=b")
8785 (plus:DI (match_operand:DI 1 "register_operand" "r")
8786 (pc)))
8787 (match_operand:DI 2 "" "")]
8788 "TARGET_SHMEDIA"
8789 "%O2: ptrel/u %1, %0"
8790 [(set_attr "type" "ptabs_media")])
8791
8792 (define_expand "builtin_setjmp_receiver"
8793 [(match_operand 0 "" "")]
8794 "flag_pic"
8795 {
8796 emit_insn (gen_GOTaddr2picreg ());
8797 DONE;
8798 })
8799
8800 (define_expand "call_site"
8801 [(unspec [(match_dup 0)] UNSPEC_CALLER)]
8802 "TARGET_SH1"
8803 {
8804 static HOST_WIDE_INT i = 0;
8805 operands[0] = GEN_INT (i);
8806 i++;
8807 })
8808
8809 ;; op0 = op1 + r12 but hide it before reload completed. See the comment
8810 ;; in symGOT_load expand.
8811
8812 (define_insn_and_split "chk_guard_add"
8813 [(set (match_operand:SI 0 "register_operand" "=&r")
8814 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
8815 (reg:SI PIC_REG)]
8816 UNSPEC_CHKADD))]
8817 "TARGET_SH1"
8818 "#"
8819 "TARGET_SH1 && reload_completed"
8820 [(set (match_dup 0) (reg:SI PIC_REG))
8821 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8822 ""
8823 [(set_attr "type" "arith")])
8824
8825 (define_expand "sym_label2reg"
8826 [(set (match_operand:SI 0 "" "")
8827 (const:SI (unspec:SI [(match_operand:SI 1 "" "")
8828 (const (plus:SI (match_operand:SI 2 "" "")
8829 (const_int 2)))]
8830 UNSPEC_SYMOFF)))]
8831 "TARGET_SH1" "")
8832
8833 (define_expand "symGOT_load"
8834 [(set (match_dup 2) (match_operand 1 "" ""))
8835 (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
8836 (set (match_operand 0 "" "") (mem (match_dup 3)))]
8837 ""
8838 {
8839 rtx mem;
8840
8841 operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
8842 operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
8843
8844 if (TARGET_SHMEDIA)
8845 {
8846 rtx reg = operands[2];
8847
8848 if (Pmode == DImode)
8849 {
8850 if (flag_pic > 1)
8851 emit_insn (gen_movdi_const_32bit (reg, operands[1]));
8852 else
8853 emit_insn (gen_movdi_const_16bit (reg, operands[1]));
8854 }
8855 else
8856 {
8857 if (flag_pic > 1)
8858 emit_insn (gen_movsi_const (reg, operands[1]));
8859 else
8860 emit_insn (gen_movsi_const_16bit (reg, operands[1]));
8861 }
8862 }
8863 else
8864 emit_move_insn (operands[2], operands[1]);
8865
8866 /* When stack protector inserts codes after the result is set to
8867 R0, @(rX, r12) will cause a spill failure for R0. Use a unspec
8868 insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
8869 when rX is a GOT address for the guard symbol. Ugly but doesn't
8870 matter because this is a rare situation. */
8871 if (!TARGET_SHMEDIA
8872 && flag_stack_protect
8873 && GET_CODE (operands[1]) == CONST
8874 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
8875 && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
8876 && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
8877 "__stack_chk_guard") == 0)
8878 emit_insn (gen_chk_guard_add (operands[3], operands[2]));
8879 else
8880 emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
8881 gen_rtx_REG (Pmode, PIC_REG)));
8882
8883 /* N.B. This is not constant for a GOTPLT relocation. */
8884 mem = gen_rtx_MEM (Pmode, operands[3]);
8885 MEM_NOTRAP_P (mem) = 1;
8886 /* ??? Should we have a special alias set for the GOT? */
8887 emit_move_insn (operands[0], mem);
8888
8889 DONE;
8890 })
8891
8892 (define_expand "sym2GOT"
8893 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
8894 ""
8895 "")
8896
8897 (define_expand "symGOT2reg"
8898 [(match_operand 0 "" "") (match_operand 1 "" "")]
8899 ""
8900 {
8901 rtx gotsym, insn;
8902
8903 gotsym = gen_sym2GOT (operands[1]);
8904 PUT_MODE (gotsym, Pmode);
8905 insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
8906
8907 MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
8908
8909 DONE;
8910 })
8911
8912 (define_expand "symGOTPLT2reg"
8913 [(match_operand 0 "" "") (match_operand 1 "" "")]
8914 ""
8915 {
8916 rtx pltsym = gen_rtx_CONST (Pmode,
8917 gen_rtx_UNSPEC (Pmode,
8918 gen_rtvec (1, operands[1]),
8919 UNSPEC_GOTPLT));
8920 emit_insn (gen_symGOT_load (operands[0], pltsym));
8921 DONE;
8922 })
8923
8924 (define_expand "sym2GOTOFF"
8925 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
8926 ""
8927 "")
8928
8929 (define_expand "symGOTOFF2reg"
8930 [(match_operand 0 "" "") (match_operand 1 "" "")]
8931 ""
8932 {
8933 rtx gotoffsym, insn;
8934 rtx t = (!can_create_pseudo_p ()
8935 ? operands[0]
8936 : gen_reg_rtx (GET_MODE (operands[0])));
8937
8938 gotoffsym = gen_sym2GOTOFF (operands[1]);
8939 PUT_MODE (gotoffsym, Pmode);
8940 emit_move_insn (t, gotoffsym);
8941 insn = emit_move_insn (operands[0],
8942 gen_rtx_PLUS (Pmode, t,
8943 gen_rtx_REG (Pmode, PIC_REG)));
8944
8945 set_unique_reg_note (insn, REG_EQUAL, operands[1]);
8946
8947 DONE;
8948 })
8949
8950 (define_expand "symPLT_label2reg"
8951 [(set (match_operand:SI 0 "" "")
8952 (const:SI
8953 (unspec:SI
8954 [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
8955 (const:SI (plus:SI (match_operand:SI 2 "" "")
8956 (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
8957 ;; Even though the PIC register is not really used by the call
8958 ;; sequence in which this is expanded, the PLT code assumes the PIC
8959 ;; register is set, so we must not skip its initialization. Since
8960 ;; we only use this expand as part of calling sequences, and never
8961 ;; to take the address of a function, this is the best point to
8962 ;; insert the (use). Using the PLT to take the address of a
8963 ;; function would be wrong, not only because the PLT entry could
8964 ;; then be called from a function that doesn't initialize the PIC
8965 ;; register to the proper GOT, but also because pointers to the
8966 ;; same function might not compare equal, should they be set by
8967 ;; different shared libraries.
8968 (use (reg:SI PIC_REG))]
8969 "TARGET_SH1"
8970 "")
8971
8972 (define_expand "sym2PIC"
8973 [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
8974 ""
8975 "")
8976
8977 ;; TLS code generation.
8978 ;; ??? this should be a define_insn_and_split
8979 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
8980 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
8981 ;; for details.
8982
8983 (define_insn "tls_global_dynamic"
8984 [(set (match_operand:SI 0 "register_operand" "=&z")
8985 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8986 UNSPEC_TLSGD))
8987 (const_int 0)))
8988 (use (reg:PSI FPSCR_REG))
8989 (use (reg:SI PIC_REG))
8990 (clobber (reg:SI PR_REG))
8991 (clobber (scratch:SI))]
8992 "TARGET_SH1"
8993 {
8994 return "mov.l 1f,r4" "\n"
8995 " mova 2f,r0" "\n"
8996 " mov.l 2f,r1" "\n"
8997 " add r0,r1" "\n"
8998 " jsr @r1" "\n"
8999 " add r12,r4" "\n"
9000 " bra 3f" "\n"
9001 " nop" "\n"
9002 " .align 2" "\n"
9003 "1: .long %a1@TLSGD" "\n"
9004 "2: .long __tls_get_addr@PLT" "\n"
9005 "3:";
9006 }
9007 [(set_attr "type" "tls_load")
9008 (set_attr "length" "26")])
9009
9010 (define_insn "tls_local_dynamic"
9011 [(set (match_operand:SI 0 "register_operand" "=&z")
9012 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
9013 UNSPEC_TLSLDM))
9014 (const_int 0)))
9015 (use (reg:PSI FPSCR_REG))
9016 (use (reg:SI PIC_REG))
9017 (clobber (reg:SI PR_REG))
9018 (clobber (scratch:SI))]
9019 "TARGET_SH1"
9020 {
9021 return "mov.l 1f,r4" "\n"
9022 " mova 2f,r0" "\n"
9023 " mov.l 2f,r1" "\n"
9024 " add r0,r1" "\n"
9025 " jsr @r1" "\n"
9026 " add r12,r4" "\n"
9027 " bra 3f" "\n"
9028 " nop" "\n"
9029 " .align 2" "\n"
9030 "1: .long %a1@TLSLDM" "\n"
9031 "2: .long __tls_get_addr@PLT" "\n"
9032 "3:";
9033 }
9034 [(set_attr "type" "tls_load")
9035 (set_attr "length" "26")])
9036
9037 (define_expand "sym2DTPOFF"
9038 [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
9039 ""
9040 "")
9041
9042 (define_expand "symDTPOFF2reg"
9043 [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
9044 ""
9045 {
9046 rtx dtpoffsym;
9047 rtx t = (!can_create_pseudo_p ()
9048 ? operands[0]
9049 : gen_reg_rtx (GET_MODE (operands[0])));
9050
9051 dtpoffsym = gen_sym2DTPOFF (operands[1]);
9052 PUT_MODE (dtpoffsym, Pmode);
9053 emit_move_insn (t, dtpoffsym);
9054 emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
9055 DONE;
9056 })
9057
9058 (define_expand "sym2GOTTPOFF"
9059 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
9060 ""
9061 "")
9062
9063 (define_insn "tls_initial_exec"
9064 [(set (match_operand:SI 0 "register_operand" "=&r")
9065 (unspec:SI [(match_operand:SI 1 "" "")]
9066 UNSPEC_TLSIE))
9067 (use (reg:SI GBR_REG))
9068 (use (reg:SI PIC_REG))
9069 (clobber (reg:SI R0_REG))]
9070 ""
9071 {
9072 return "mov.l 1f,r0" "\n"
9073 " stc gbr,%0" "\n"
9074 " mov.l @(r0,r12),r0" "\n"
9075 " bra 2f" "\n"
9076 " add r0,%0" "\n"
9077 " .align 2" "\n"
9078 "1: .long %a1" "\n"
9079 "2:";
9080 }
9081 [(set_attr "type" "tls_load")
9082 (set_attr "length" "16")])
9083
9084 (define_expand "sym2TPOFF"
9085 [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
9086 ""
9087 "")
9088
9089 (define_expand "symTPOFF2reg"
9090 [(match_operand 0 "" "") (match_operand 1 "" "")]
9091 ""
9092 {
9093 rtx tpoffsym;
9094
9095 tpoffsym = gen_sym2TPOFF (operands[1]);
9096 PUT_MODE (tpoffsym, Pmode);
9097 emit_move_insn (operands[0], tpoffsym);
9098 DONE;
9099 })
9100
9101 (define_insn "load_gbr"
9102 [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))
9103 (use (reg:SI GBR_REG))]
9104 ""
9105 "stc gbr,%0"
9106 [(set_attr "type" "tls_load")])
9107
9108 ;; case instruction for switch statements.
9109
9110 ;; Operand 0 is index
9111 ;; operand 1 is the minimum bound
9112 ;; operand 2 is the maximum bound - minimum bound + 1
9113 ;; operand 3 is CODE_LABEL for the table;
9114 ;; operand 4 is the CODE_LABEL to go to if index out of range.
9115
9116 (define_expand "casesi"
9117 [(match_operand:SI 0 "arith_reg_operand" "")
9118 (match_operand:SI 1 "arith_reg_operand" "")
9119 (match_operand:SI 2 "arith_reg_operand" "")
9120 (match_operand 3 "" "") (match_operand 4 "" "")]
9121 ""
9122 {
9123 rtx reg = gen_reg_rtx (SImode);
9124 rtx reg2 = gen_reg_rtx (SImode);
9125 if (TARGET_SHMEDIA)
9126 {
9127 rtx reg = gen_reg_rtx (DImode);
9128 rtx reg2 = gen_reg_rtx (DImode);
9129 rtx reg3 = gen_reg_rtx (Pmode);
9130 rtx reg4 = gen_reg_rtx (Pmode);
9131 rtx reg5 = gen_reg_rtx (Pmode);
9132 rtx load, test;
9133
9134 operands[0] = convert_modes (DImode, SImode, operands[0], 0);
9135 operands[1] = convert_modes (DImode, SImode, operands[1], 0);
9136 operands[2] = convert_modes (DImode, SImode, operands[2], 1);
9137
9138 test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
9139 emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0], operands[4]));
9140 emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
9141 test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
9142 emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
9143 emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
9144 emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
9145 (Pmode, operands[3])));
9146 /* Messy: can we subreg to clean this up? */
9147 if (Pmode == DImode)
9148 load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
9149 else
9150 load = gen_casesi_load_media (reg4,
9151 gen_rtx_SUBREG (DImode, reg3, 0),
9152 reg2, operands[3]);
9153 PUT_MODE (SET_SRC (load), Pmode);
9154 emit_insn (load);
9155 /* ??? The following add could be eliminated if we used ptrel. */
9156 emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
9157 emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
9158 emit_barrier ();
9159 DONE;
9160 }
9161 operands[1] = copy_to_mode_reg (SImode, operands[1]);
9162 operands[2] = copy_to_mode_reg (SImode, operands[2]);
9163 /* If optimizing, casesi_worker depends on the mode of the instruction
9164 before label it 'uses' - operands[3]. */
9165 emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
9166 reg));
9167 emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
9168 if (TARGET_SH2)
9169 emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
9170 else
9171 emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
9172 /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
9173 operands[3], but to lab. We will fix this up in
9174 machine_dependent_reorg. */
9175 emit_barrier ();
9176 DONE;
9177 })
9178
9179 (define_expand "casesi_0"
9180 [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
9181 (set (match_dup 4) (minus:SI (match_dup 4)
9182 (match_operand:SI 1 "arith_operand" "")))
9183 (set (reg:SI T_REG)
9184 (gtu:SI (match_dup 4)
9185 (match_operand:SI 2 "arith_reg_operand" "")))
9186 (set (pc)
9187 (if_then_else (ne (reg:SI T_REG)
9188 (const_int 0))
9189 (label_ref (match_operand 3 "" ""))
9190 (pc)))]
9191 "TARGET_SH1"
9192 "")
9193
9194 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
9195 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
9196 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
9197
9198 (define_insn "casesi_worker_0"
9199 [(set (match_operand:SI 0 "register_operand" "=r,r")
9200 (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
9201 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9202 (clobber (match_scratch:SI 3 "=X,1"))
9203 (clobber (match_scratch:SI 4 "=&z,z"))]
9204 "TARGET_SH1"
9205 "#")
9206
9207 (define_split
9208 [(set (match_operand:SI 0 "register_operand" "")
9209 (unspec:SI [(match_operand:SI 1 "register_operand" "")
9210 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9211 (clobber (match_scratch:SI 3 ""))
9212 (clobber (match_scratch:SI 4 ""))]
9213 "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
9214 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
9215 (parallel [(set (match_dup 0)
9216 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
9217 (label_ref (match_dup 2))] UNSPEC_CASESI))
9218 (clobber (match_dup 3))])
9219 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
9220 {
9221 if (GET_CODE (operands[2]) == CODE_LABEL)
9222 LABEL_NUSES (operands[2])++;
9223 })
9224
9225 (define_split
9226 [(set (match_operand:SI 0 "register_operand" "")
9227 (unspec:SI [(match_operand:SI 1 "register_operand" "")
9228 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9229 (clobber (match_scratch:SI 3 ""))
9230 (clobber (match_scratch:SI 4 ""))]
9231 "TARGET_SH2 && reload_completed"
9232 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
9233 (parallel [(set (match_dup 0)
9234 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
9235 (label_ref (match_dup 2))] UNSPEC_CASESI))
9236 (clobber (match_dup 3))])]
9237 {
9238 if (GET_CODE (operands[2]) == CODE_LABEL)
9239 LABEL_NUSES (operands[2])++;
9240 })
9241
9242 (define_insn "casesi_worker_1"
9243 [(set (match_operand:SI 0 "register_operand" "=r,r")
9244 (unspec:SI [(reg:SI R0_REG)
9245 (match_operand:SI 1 "register_operand" "0,r")
9246 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9247 (clobber (match_scratch:SI 3 "=X,1"))]
9248 "TARGET_SH1"
9249 {
9250 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
9251
9252 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9253
9254 switch (GET_MODE (diff_vec))
9255 {
9256 case SImode:
9257 return "shll2 %1\;mov.l @(r0,%1),%0";
9258 case HImode:
9259 return "add %1,%1\;mov.w @(r0,%1),%0";
9260 case QImode:
9261 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9262 return "mov.b @(r0,%1),%0\;extu.b %0,%0";
9263 return "mov.b @(r0,%1),%0";
9264 default:
9265 gcc_unreachable ();
9266 }
9267 }
9268 [(set_attr "length" "4")])
9269
9270 (define_insn "casesi_worker_2"
9271 [(set (match_operand:SI 0 "register_operand" "=r,r")
9272 (unspec:SI [(reg:SI R0_REG)
9273 (match_operand:SI 1 "register_operand" "0,r")
9274 (label_ref (match_operand 2 "" ""))
9275 (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
9276 (clobber (match_operand:SI 4 "" "=X,1"))]
9277 "TARGET_SH2 && reload_completed && flag_pic"
9278 {
9279 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
9280 const char *load;
9281
9282 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9283
9284 switch (GET_MODE (diff_vec))
9285 {
9286 case SImode:
9287 output_asm_insn ("shll2 %1", operands);
9288 load = "mov.l @(r0,%1),%0"; break;
9289 case HImode:
9290 output_asm_insn ("add %1,%1", operands);
9291 load = "mov.w @(r0,%1),%0"; break;
9292 case QImode:
9293 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9294 load = "mov.b @(r0,%1),%0\;extu.b %0,%0";
9295 else
9296 load = "mov.b @(r0,%1),%0";
9297 break;
9298 default:
9299 gcc_unreachable ();
9300 }
9301 output_asm_insn ("add\tr0,%1\;mova\t%O3,r0\\n", operands);
9302 return load;
9303 }
9304 [(set_attr "length" "8")])
9305
9306 (define_insn "casesi_shift_media"
9307 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9308 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
9309 (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
9310 UNSPEC_CASESI)))]
9311 "TARGET_SHMEDIA"
9312 {
9313 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
9314
9315 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9316
9317 switch (GET_MODE (diff_vec))
9318 {
9319 case SImode:
9320 return "shlli %1, 2, %0";
9321 case HImode:
9322 return "shlli %1, 1, %0";
9323 case QImode:
9324 if (rtx_equal_p (operands[0], operands[1]))
9325 return "";
9326 return "add %1, r63, %0";
9327 default:
9328 gcc_unreachable ();
9329 }
9330 }
9331 [(set_attr "type" "arith_media")])
9332
9333 (define_insn "casesi_load_media"
9334 [(set (match_operand 0 "any_arith_reg_dest" "=r")
9335 (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
9336 (match_operand:DI 2 "arith_reg_operand" "r")
9337 (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
9338 "TARGET_SHMEDIA"
9339 {
9340 rtx diff_vec = PATTERN (next_real_insn (operands[3]));
9341
9342 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9343
9344 switch (GET_MODE (diff_vec))
9345 {
9346 case SImode:
9347 return "ldx.l %1, %2, %0";
9348 case HImode:
9349 #if 0
9350 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9351 return "ldx.uw %1, %2, %0";
9352 #endif
9353 return "ldx.w %1, %2, %0";
9354 case QImode:
9355 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9356 return "ldx.ub %1, %2, %0";
9357 return "ldx.b %1, %2, %0";
9358 default:
9359 gcc_unreachable ();
9360 }
9361 }
9362 [(set_attr "type" "load_media")])
9363
9364 (define_expand "return"
9365 [(return)]
9366 "reload_completed && ! sh_need_epilogue ()"
9367 {
9368 if (TARGET_SHMEDIA)
9369 {
9370 emit_jump_insn (gen_return_media ());
9371 DONE;
9372 }
9373
9374 if (TARGET_SHCOMPACT
9375 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
9376 {
9377 emit_jump_insn (gen_shcompact_return_tramp ());
9378 DONE;
9379 }
9380 })
9381
9382 (define_insn "*return_i"
9383 [(return)]
9384 "TARGET_SH1 && ! (TARGET_SHCOMPACT
9385 && (crtl->args.info.call_cookie
9386 & CALL_COOKIE_RET_TRAMP (1)))
9387 && reload_completed
9388 && ! sh_cfun_trap_exit_p ()"
9389 {
9390 if (TARGET_SH2A && (dbr_sequence_length () == 0)
9391 && !current_function_interrupt)
9392 return "rts/n";
9393 else
9394 return "%@ %#";
9395 }
9396 [(set_attr "type" "return")
9397 (set_attr "needs_delay_slot" "yes")])
9398
9399 ;; trapa has no delay slot.
9400 (define_insn "*return_trapa"
9401 [(return)]
9402 "TARGET_SH1 && !TARGET_SHCOMPACT
9403 && reload_completed"
9404 "%@"
9405 [(set_attr "type" "return")])
9406
9407 (define_expand "shcompact_return_tramp"
9408 [(return)]
9409 "TARGET_SHCOMPACT
9410 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
9411 {
9412 rtx reg = gen_rtx_REG (Pmode, R0_REG);
9413
9414 function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC);
9415 emit_jump_insn (gen_shcompact_return_tramp_i ());
9416 DONE;
9417 })
9418
9419 (define_insn "shcompact_return_tramp_i"
9420 [(parallel [(return) (use (reg:SI R0_REG))])]
9421 "TARGET_SHCOMPACT
9422 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
9423 "jmp @r0%#"
9424 [(set_attr "type" "jump_ind")
9425 (set_attr "needs_delay_slot" "yes")])
9426
9427 (define_insn "return_media_i"
9428 [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
9429 "TARGET_SHMEDIA && reload_completed"
9430 "blink %0, r63"
9431 [(set_attr "type" "jump_media")])
9432
9433 (define_insn "return_media_rte"
9434 [(return)]
9435 "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
9436 "rte"
9437 [(set_attr "type" "jump_media")])
9438
9439 (define_expand "return_media"
9440 [(return)]
9441 "TARGET_SHMEDIA && reload_completed"
9442 {
9443 int tr_regno = sh_media_register_for_return ();
9444 rtx tr;
9445
9446 if (current_function_interrupt)
9447 {
9448 emit_jump_insn (gen_return_media_rte ());
9449 DONE;
9450 }
9451 if (tr_regno < 0)
9452 {
9453 rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
9454
9455 gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
9456 tr_regno = TR0_REG;
9457 tr = gen_rtx_REG (Pmode, tr_regno);
9458 emit_move_insn (tr, r18);
9459 }
9460 else
9461 tr = gen_rtx_REG (Pmode, tr_regno);
9462
9463 emit_jump_insn (gen_return_media_i (tr));
9464 DONE;
9465 })
9466
9467 (define_insn "shcompact_preserve_incoming_args"
9468 [(set (match_operand:SI 0 "register_operand" "+r")
9469 (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
9470 "TARGET_SHCOMPACT"
9471 ""
9472 [(set_attr "length" "0")])
9473
9474 (define_insn "shcompact_incoming_args"
9475 [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
9476 (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
9477 (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
9478 (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
9479 (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
9480 (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
9481 (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
9482 (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
9483 (set (mem:BLK (reg:SI MACL_REG))
9484 (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
9485 (use (reg:SI R0_REG))
9486 (clobber (reg:SI R0_REG))
9487 (clobber (reg:SI MACL_REG))
9488 (clobber (reg:SI MACH_REG))
9489 (clobber (reg:SI PR_REG))]
9490 "TARGET_SHCOMPACT"
9491 "jsr @r0%#"
9492 [(set_attr "needs_delay_slot" "yes")])
9493
9494 (define_insn "shmedia_save_restore_regs_compact"
9495 [(set (reg:SI SP_REG)
9496 (plus:SI (reg:SI SP_REG)
9497 (match_operand:SI 0 "immediate_operand" "i")))
9498 (use (reg:SI R0_REG))
9499 (clobber (reg:SI PR_REG))]
9500 "TARGET_SHCOMPACT
9501 && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
9502 || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
9503 "jsr @r0%#"
9504 [(set_attr "needs_delay_slot" "yes")])
9505
9506 (define_expand "prologue"
9507 [(const_int 0)]
9508 ""
9509 {
9510 sh_expand_prologue ();
9511 DONE;
9512 })
9513
9514 (define_expand "epilogue"
9515 [(return)]
9516 ""
9517 {
9518 sh_expand_epilogue (0);
9519 emit_jump_insn (gen_return ());
9520 DONE;
9521 })
9522
9523 (define_expand "eh_return"
9524 [(use (match_operand 0 "register_operand" ""))]
9525 ""
9526 {
9527 rtx ra = operands[0];
9528
9529 if (TARGET_SHMEDIA64)
9530 emit_insn (gen_eh_set_ra_di (ra));
9531 else
9532 emit_insn (gen_eh_set_ra_si (ra));
9533
9534 DONE;
9535 })
9536
9537 ;; Clobber the return address on the stack. We can't expand this
9538 ;; until we know where it will be put in the stack frame.
9539
9540 (define_insn "eh_set_ra_si"
9541 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
9542 UNSPECV_EH_RETURN)
9543 (clobber (match_scratch:SI 1 "=&r"))]
9544 "! TARGET_SHMEDIA64"
9545 "#")
9546
9547 (define_insn "eh_set_ra_di"
9548 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
9549 UNSPECV_EH_RETURN)
9550 (clobber (match_scratch:DI 1 "=&r"))]
9551 "TARGET_SHMEDIA64"
9552 "#")
9553
9554 (define_split
9555 [(unspec_volatile [(match_operand 0 "register_operand" "")]
9556 UNSPECV_EH_RETURN)
9557 (clobber (match_scratch 1 ""))]
9558 "reload_completed"
9559 [(const_int 0)]
9560 {
9561 sh_set_return_address (operands[0], operands[1]);
9562 DONE;
9563 })
9564
9565 (define_insn "blockage"
9566 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
9567 ""
9568 ""
9569 [(set_attr "length" "0")])
9570 \f
9571 ;; Define movml instructions for SH2A target. Currently they are
9572 ;; used to push and pop all banked registers only.
9573
9574 (define_insn "movml_push_banked"
9575 [(set (match_operand:SI 0 "register_operand" "=r")
9576 (plus (match_dup 0) (const_int -32)))
9577 (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
9578 (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
9579 (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
9580 (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
9581 (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
9582 (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
9583 (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
9584 (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
9585 "TARGET_SH2A && REGNO (operands[0]) == 15"
9586 "movml.l\tr7,@-r15"
9587 [(set_attr "in_delay_slot" "no")])
9588
9589 (define_insn "movml_pop_banked"
9590 [(set (match_operand:SI 0 "register_operand" "=r")
9591 (plus (match_dup 0) (const_int 32)))
9592 (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
9593 (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
9594 (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
9595 (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
9596 (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
9597 (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
9598 (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
9599 (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
9600 "TARGET_SH2A && REGNO (operands[0]) == 15"
9601 "movml.l\t@r15+,r7"
9602 [(set_attr "in_delay_slot" "no")])
9603 \f
9604 ;; ------------------------------------------------------------------------
9605 ;; Scc instructions
9606 ;; ------------------------------------------------------------------------
9607
9608 (define_insn "movt"
9609 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9610 (match_operand:SI 1 "t_reg_operand"))]
9611 "TARGET_SH1"
9612 "movt %0"
9613 [(set_attr "type" "arith")])
9614
9615 (define_insn "movrt"
9616 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9617 (xor:SI (reg:SI T_REG) (const_int 1)))]
9618 "TARGET_SH2A"
9619 "movrt %0"
9620 [(set_attr "type" "arith")])
9621
9622 (define_expand "cstore4_media"
9623 [(set (match_operand:SI 0 "register_operand" "=r")
9624 (match_operator:SI 1 "sh_float_comparison_operator"
9625 [(match_operand 2 "logical_operand" "")
9626 (match_operand 3 "cmp_operand" "")]))]
9627 "TARGET_SHMEDIA"
9628 {
9629 enum machine_mode mode = GET_MODE (operands[2]);
9630 enum rtx_code code = GET_CODE (operands[1]);
9631 bool invert, swap;
9632 if (mode == VOIDmode)
9633 mode = GET_MODE (operands[3]);
9634 if (operands[2] == const0_rtx)
9635 {
9636 if (code == EQ || code == NE)
9637 operands[2] = operands[3], operands[3] = const0_rtx;
9638 }
9639 else
9640 operands[2] = force_reg (mode, operands[2]);
9641 if (operands[3] != const0_rtx)
9642 operands[3] = force_reg (mode, operands[3]);
9643
9644 switch (code)
9645 {
9646 case GEU:
9647 case GE:
9648 swap = invert = !FLOAT_MODE_P (mode);
9649 break;
9650
9651 case LEU:
9652 case LE:
9653 swap = FLOAT_MODE_P (mode), invert = !swap;
9654 break;
9655
9656 case LTU:
9657 case LT:
9658 swap = true, invert = false;
9659 break;
9660
9661 case GTU:
9662 case GT:
9663 case EQ:
9664 case UNORDERED:
9665 swap = invert = false;
9666 break;
9667
9668 case NE:
9669 swap = invert = true;
9670 break;
9671
9672 default:
9673 gcc_unreachable ();
9674 }
9675
9676 if (swap)
9677 {
9678 rtx tem = operands[2];
9679 operands[2] = operands[3];
9680 operands[3] = tem;
9681 code = swap_condition (code);
9682 }
9683
9684 if (invert)
9685 {
9686 rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
9687 code = reverse_condition (code);
9688 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
9689 emit_insn (gen_cstore4_media (tem, operands[1],
9690 operands[2], operands[3]));
9691 code = EQ;
9692 operands[2] = tem;
9693 operands[3] = const0_rtx;
9694 }
9695
9696 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
9697 })
9698
9699 (define_expand "cstoresi4"
9700 [(set (match_operand:SI 0 "register_operand" "=r")
9701 (match_operator:SI 1 "comparison_operator"
9702 [(match_operand:SI 2 "cmpsi_operand" "")
9703 (match_operand:SI 3 "arith_operand" "")]))]
9704 "TARGET_SH1 || TARGET_SHMEDIA"
9705 {
9706 if (TARGET_SHMEDIA)
9707 {
9708 emit_insn (gen_cstore4_media (operands[0], operands[1],
9709 operands[2], operands[3]));
9710 DONE;
9711 }
9712
9713 if (sh_expand_t_scc (operands))
9714 DONE;
9715
9716 if (! currently_expanding_to_rtl)
9717 FAIL;
9718
9719 sh_emit_compare_and_set (operands, SImode);
9720 DONE;
9721 })
9722
9723 (define_expand "cstoredi4"
9724 [(set (match_operand:SI 0 "register_operand" "=r")
9725 (match_operator:SI 1 "comparison_operator"
9726 [(match_operand:DI 2 "arith_operand" "")
9727 (match_operand:DI 3 "arith_operand" "")]))]
9728 "TARGET_SH2 || TARGET_SHMEDIA"
9729 {
9730 if (TARGET_SHMEDIA)
9731 {
9732 emit_insn (gen_cstore4_media (operands[0], operands[1],
9733 operands[2], operands[3]));
9734 DONE;
9735 }
9736
9737 if (sh_expand_t_scc (operands))
9738 DONE;
9739
9740 if (! currently_expanding_to_rtl)
9741 FAIL;
9742
9743 sh_emit_compare_and_set (operands, DImode);
9744 DONE;
9745 })
9746
9747 ;; Move the complement of the T reg to a reg.
9748 ;; On SH2A the movrt insn can be used.
9749 ;; On anything else than SH2A this has to be done with multiple instructions.
9750 ;; One obvious way would be:
9751 ;; cmp/eq ...
9752 ;; movt r0
9753 ;; xor #1,r0
9754 ;;
9755 ;; However, this puts pressure on r0 in most cases and thus the following is
9756 ;; more appealing:
9757 ;; cmp/eq ...
9758 ;; mov #-1,temp
9759 ;; negc temp,dest
9760 ;;
9761 ;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
9762 ;; becomes a one instruction operation. Moreover, care must be taken that
9763 ;; the insn can still be combined with inverted compare and branch code
9764 ;; around it. On the other hand, if a function returns the complement of
9765 ;; a previous comparison result in the T bit, the xor #1,r0 approach might
9766 ;; lead to better code.
9767
9768 (define_expand "movnegt"
9769 [(set (match_operand:SI 0 "arith_reg_dest" "")
9770 (xor:SI (reg:SI T_REG) (const_int 1)))]
9771 ""
9772 {
9773 if (TARGET_SH2A)
9774 emit_insn (gen_movrt (operands[0]));
9775 else
9776 {
9777 rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
9778 emit_insn (gen_movrt_negc (operands[0], val));
9779 }
9780 DONE;
9781 })
9782
9783 (define_insn "movrt_negc"
9784 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9785 (xor:SI (reg:SI T_REG) (const_int 1)))
9786 (set (reg:SI T_REG) (const_int 1))
9787 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
9788 "TARGET_SH1"
9789 "negc %1,%0"
9790 [(set_attr "type" "arith")])
9791
9792 ;; The *negnegt pattern helps the combine pass to figure out how to fold
9793 ;; an explicit double T bit negation.
9794 (define_insn_and_split "*negnegt"
9795 [(set (reg:SI T_REG)
9796 (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
9797 "TARGET_SH1"
9798 "#"
9799 ""
9800 [(const_int 0)])
9801
9802 ;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
9803 (define_insn_and_split "*movtt"
9804 [(set (reg:SI T_REG)
9805 (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
9806 "TARGET_SH1"
9807 "#"
9808 ""
9809 [(const_int 0)])
9810
9811 (define_insn_and_split "nott"
9812 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))]
9813 "TARGET_SH1"
9814 {
9815 gcc_assert (TARGET_SH2A);
9816 return "nott";
9817 }
9818 "! TARGET_SH2A && can_create_pseudo_p ()"
9819 [(set (match_dup 0) (reg:SI T_REG))
9820 (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
9821 {
9822 operands[0] = gen_reg_rtx (SImode);
9823 })
9824
9825 (define_expand "cstoresf4"
9826 [(set (match_operand:SI 0 "register_operand" "=r")
9827 (match_operator:SI 1 "sh_float_comparison_operator"
9828 [(match_operand:SF 2 "arith_operand" "")
9829 (match_operand:SF 3 "arith_operand" "")]))]
9830 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
9831 {
9832 if (TARGET_SHMEDIA)
9833 {
9834 emit_insn (gen_cstore4_media (operands[0], operands[1],
9835 operands[2], operands[3]));
9836 DONE;
9837 }
9838
9839 if (! currently_expanding_to_rtl)
9840 FAIL;
9841
9842 sh_emit_compare_and_set (operands, SFmode);
9843 DONE;
9844 })
9845
9846 (define_expand "cstoredf4"
9847 [(set (match_operand:SI 0 "register_operand" "=r")
9848 (match_operator:SI 1 "sh_float_comparison_operator"
9849 [(match_operand:DF 2 "arith_operand" "")
9850 (match_operand:DF 3 "arith_operand" "")]))]
9851 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9852 {
9853 if (TARGET_SHMEDIA)
9854 {
9855 emit_insn (gen_cstore4_media (operands[0], operands[1],
9856 operands[2], operands[3]));
9857 DONE;
9858 }
9859
9860 if (! currently_expanding_to_rtl)
9861 FAIL;
9862
9863 sh_emit_compare_and_set (operands, DFmode);
9864 DONE;
9865 })
9866
9867 ;; -------------------------------------------------------------------------
9868 ;; Instructions to cope with inline literal tables
9869 ;; -------------------------------------------------------------------------
9870
9871 ; 2 byte integer in line
9872
9873 (define_insn "consttable_2"
9874 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9875 (match_operand 1 "" "")]
9876 UNSPECV_CONST2)]
9877 ""
9878 {
9879 if (operands[1] != const0_rtx)
9880 assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
9881 return "";
9882 }
9883 [(set_attr "length" "2")
9884 (set_attr "in_delay_slot" "no")])
9885
9886 ; 4 byte integer in line
9887
9888 (define_insn "consttable_4"
9889 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9890 (match_operand 1 "" "")]
9891 UNSPECV_CONST4)]
9892 ""
9893 {
9894 if (operands[1] != const0_rtx)
9895 {
9896 assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
9897 mark_symbol_refs_as_used (operands[0]);
9898 }
9899 return "";
9900 }
9901 [(set_attr "length" "4")
9902 (set_attr "in_delay_slot" "no")])
9903
9904 ; 8 byte integer in line
9905
9906 (define_insn "consttable_8"
9907 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9908 (match_operand 1 "" "")]
9909 UNSPECV_CONST8)]
9910 ""
9911 {
9912 if (operands[1] != const0_rtx)
9913 assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
9914 return "";
9915 }
9916 [(set_attr "length" "8")
9917 (set_attr "in_delay_slot" "no")])
9918
9919 ; 4 byte floating point
9920
9921 (define_insn "consttable_sf"
9922 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
9923 (match_operand 1 "" "")]
9924 UNSPECV_CONST4)]
9925 ""
9926 {
9927 if (operands[1] != const0_rtx)
9928 {
9929 REAL_VALUE_TYPE d;
9930 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9931 assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
9932 }
9933 return "";
9934 }
9935 [(set_attr "length" "4")
9936 (set_attr "in_delay_slot" "no")])
9937
9938 ; 8 byte floating point
9939
9940 (define_insn "consttable_df"
9941 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
9942 (match_operand 1 "" "")]
9943 UNSPECV_CONST8)]
9944 ""
9945 {
9946 if (operands[1] != const0_rtx)
9947 {
9948 REAL_VALUE_TYPE d;
9949 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9950 assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
9951 }
9952 return "";
9953 }
9954 [(set_attr "length" "8")
9955 (set_attr "in_delay_slot" "no")])
9956
9957 ;; Alignment is needed for some constant tables; it may also be added for
9958 ;; Instructions at the start of loops, or after unconditional branches.
9959 ;; ??? We would get more accurate lengths if we did instruction
9960 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
9961 ;; here is too conservative.
9962
9963 ; align to a two byte boundary
9964
9965 (define_expand "align_2"
9966 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
9967 ""
9968 "")
9969
9970 ; align to a four byte boundary
9971 ;; align_4 and align_log are instructions for the starts of loops, or
9972 ;; after unconditional branches, which may take up extra room.
9973
9974 (define_expand "align_4"
9975 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
9976 ""
9977 "")
9978
9979 ; align to a cache line boundary
9980
9981 (define_insn "align_log"
9982 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
9983 ""
9984 ""
9985 [(set_attr "length" "0")
9986 (set_attr "in_delay_slot" "no")])
9987
9988 ; emitted at the end of the literal table, used to emit the
9989 ; 32bit branch labels if needed.
9990
9991 (define_insn "consttable_end"
9992 [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
9993 ""
9994 {
9995 return output_jump_label_table ();
9996 }
9997 [(set_attr "in_delay_slot" "no")])
9998
9999 ; emitted at the end of the window in the literal table.
10000
10001 (define_insn "consttable_window_end"
10002 [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
10003 ""
10004 ""
10005 [(set_attr "length" "0")
10006 (set_attr "in_delay_slot" "no")])
10007
10008 ;; -------------------------------------------------------------------------
10009 ;; Misc
10010 ;; -------------------------------------------------------------------------
10011
10012 ;; String/block move insn.
10013
10014 (define_expand "movmemsi"
10015 [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
10016 (mem:BLK (match_operand:BLK 1 "" "")))
10017 (use (match_operand:SI 2 "nonmemory_operand" ""))
10018 (use (match_operand:SI 3 "immediate_operand" ""))
10019 (clobber (reg:SI PR_REG))
10020 (clobber (reg:SI R4_REG))
10021 (clobber (reg:SI R5_REG))
10022 (clobber (reg:SI R0_REG))])]
10023 "TARGET_SH1 && ! TARGET_SH5"
10024 {
10025 if(expand_block_move (operands))
10026 DONE;
10027 else FAIL;
10028 })
10029
10030 (define_insn "block_move_real"
10031 [(parallel [(set (mem:BLK (reg:SI R4_REG))
10032 (mem:BLK (reg:SI R5_REG)))
10033 (use (match_operand:SI 0 "arith_reg_operand" "r"))
10034 (clobber (reg:SI PR_REG))
10035 (clobber (reg:SI R0_REG))])]
10036 "TARGET_SH1 && ! TARGET_HARD_SH4"
10037 "jsr @%0%#"
10038 [(set_attr "type" "sfunc")
10039 (set_attr "needs_delay_slot" "yes")])
10040
10041 (define_insn "block_lump_real"
10042 [(parallel [(set (mem:BLK (reg:SI R4_REG))
10043 (mem:BLK (reg:SI R5_REG)))
10044 (use (match_operand:SI 0 "arith_reg_operand" "r"))
10045 (use (reg:SI R6_REG))
10046 (clobber (reg:SI PR_REG))
10047 (clobber (reg:SI T_REG))
10048 (clobber (reg:SI R4_REG))
10049 (clobber (reg:SI R5_REG))
10050 (clobber (reg:SI R6_REG))
10051 (clobber (reg:SI R0_REG))])]
10052 "TARGET_SH1 && ! TARGET_HARD_SH4"
10053 "jsr @%0%#"
10054 [(set_attr "type" "sfunc")
10055 (set_attr "needs_delay_slot" "yes")])
10056
10057 (define_insn "block_move_real_i4"
10058 [(parallel [(set (mem:BLK (reg:SI R4_REG))
10059 (mem:BLK (reg:SI R5_REG)))
10060 (use (match_operand:SI 0 "arith_reg_operand" "r"))
10061 (clobber (reg:SI PR_REG))
10062 (clobber (reg:SI R0_REG))
10063 (clobber (reg:SI R1_REG))
10064 (clobber (reg:SI R2_REG))])]
10065 "TARGET_HARD_SH4"
10066 "jsr @%0%#"
10067 [(set_attr "type" "sfunc")
10068 (set_attr "needs_delay_slot" "yes")])
10069
10070 (define_insn "block_lump_real_i4"
10071 [(parallel [(set (mem:BLK (reg:SI R4_REG))
10072 (mem:BLK (reg:SI R5_REG)))
10073 (use (match_operand:SI 0 "arith_reg_operand" "r"))
10074 (use (reg:SI R6_REG))
10075 (clobber (reg:SI PR_REG))
10076 (clobber (reg:SI T_REG))
10077 (clobber (reg:SI R4_REG))
10078 (clobber (reg:SI R5_REG))
10079 (clobber (reg:SI R6_REG))
10080 (clobber (reg:SI R0_REG))
10081 (clobber (reg:SI R1_REG))
10082 (clobber (reg:SI R2_REG))
10083 (clobber (reg:SI R3_REG))])]
10084 "TARGET_HARD_SH4"
10085 "jsr @%0%#"
10086 [(set_attr "type" "sfunc")
10087 (set_attr "needs_delay_slot" "yes")])
10088 \f
10089 ;; -------------------------------------------------------------------------
10090 ;; Floating point instructions.
10091 ;; -------------------------------------------------------------------------
10092
10093 ;; ??? All patterns should have a type attribute.
10094
10095 (define_expand "movpsi"
10096 [(set (match_operand:PSI 0 "register_operand" "")
10097 (match_operand:PSI 1 "general_movsrc_operand" ""))]
10098 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10099 "")
10100
10101 ;; The c / m alternative is a fake to guide reload to load directly into
10102 ;; fpscr, since reload doesn't know how to use post-increment.
10103 ;; TARGET_LEGITIMATE_ADDRESS_P guards about bogus addresses before reload,
10104 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
10105 ;; predicate after reload.
10106 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
10107 ;; like a mac -> gpr move.
10108 (define_insn "fpu_switch"
10109 [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
10110 (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
10111 "TARGET_SH2E
10112 && (! reload_completed
10113 || true_regnum (operands[0]) != FPSCR_REG
10114 || !MEM_P (operands[1])
10115 || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
10116 "@
10117 ! precision stays the same
10118 lds.l %1,fpscr
10119 mov.l %1,%0
10120 #
10121 lds %1,fpscr
10122 mov %1,%0
10123 mov.l %1,%0
10124 sts fpscr,%0
10125 sts.l fpscr,%0"
10126 [(set_attr "length" "0,2,2,4,2,2,2,2,2")
10127 (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,fstore")])
10128
10129 (define_peephole2
10130 [(set (reg:PSI FPSCR_REG)
10131 (mem:PSI (match_operand:SI 0 "register_operand" "")))]
10132 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
10133 [(const_int 0)]
10134 {
10135 rtx fpscr, mem, new_insn;
10136
10137 fpscr = SET_DEST (PATTERN (curr_insn));
10138 mem = SET_SRC (PATTERN (curr_insn));
10139 mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
10140
10141 new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
10142 add_reg_note (new_insn, REG_INC, operands[0]);
10143 DONE;
10144 })
10145
10146 (define_split
10147 [(set (reg:PSI FPSCR_REG)
10148 (mem:PSI (match_operand:SI 0 "register_operand" "")))]
10149 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
10150 && (flag_peephole2 ? epilogue_completed : reload_completed)"
10151 [(const_int 0)]
10152 {
10153 rtx fpscr, mem, new_insn;
10154
10155 fpscr = SET_DEST (PATTERN (curr_insn));
10156 mem = SET_SRC (PATTERN (curr_insn));
10157 mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
10158
10159 new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
10160 add_reg_note (new_insn, REG_INC, operands[0]);
10161
10162 if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
10163 emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
10164 DONE;
10165 })
10166
10167 ;; ??? This uses the fp unit, but has no type indicating that.
10168 ;; If we did that, this would either give a bogus latency or introduce
10169 ;; a bogus FIFO constraint.
10170 ;; Since this insn is currently only used for prologues/epilogues,
10171 ;; it is probably best to claim no function unit, which matches the
10172 ;; current setting.
10173 (define_insn "toggle_sz"
10174 [(set (reg:PSI FPSCR_REG)
10175 (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
10176 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10177 "fschg"
10178 [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
10179
10180 ;; There's no way we can use it today, since optimize mode switching
10181 ;; doesn't enable us to know from which mode we're switching to the
10182 ;; mode it requests, to tell whether we can use a relative mode switch
10183 ;; (like toggle_pr) or an absolute switch (like loading fpscr from
10184 ;; memory).
10185 (define_insn "toggle_pr"
10186 [(set (reg:PSI FPSCR_REG)
10187 (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
10188 "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
10189 "fpchg"
10190 [(set_attr "type" "fpscr_toggle")])
10191
10192 (define_expand "addsf3"
10193 [(set (match_operand:SF 0 "arith_reg_operand" "")
10194 (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
10195 (match_operand:SF 2 "arith_reg_operand" "")))]
10196 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10197 {
10198 if (TARGET_SH2E)
10199 {
10200 expand_sf_binop (&gen_addsf3_i, operands);
10201 DONE;
10202 }
10203 })
10204
10205 (define_insn "*addsf3_media"
10206 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10207 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10208 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10209 "TARGET_SHMEDIA_FPU"
10210 "fadd.s %1, %2, %0"
10211 [(set_attr "type" "fparith_media")])
10212
10213 (define_insn_and_split "unary_sf_op"
10214 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10215 (vec_select:V2SF
10216 (vec_concat:V2SF
10217 (vec_select:SF
10218 (match_dup 0)
10219 (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
10220 (match_operator:SF 2 "unary_float_operator"
10221 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10222 (parallel [(match_operand 4
10223 "const_int_operand" "n")]))]))
10224 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
10225 "TARGET_SHMEDIA_FPU"
10226 "#"
10227 "TARGET_SHMEDIA_FPU && reload_completed"
10228 [(set (match_dup 5) (match_dup 6))]
10229 {
10230 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10231 rtx op1 = gen_rtx_REG (SFmode,
10232 (true_regnum (operands[1])
10233 + (INTVAL (operands[4]) ^ endian)));
10234
10235 operands[7] = gen_rtx_REG (SFmode,
10236 (true_regnum (operands[0])
10237 + (INTVAL (operands[3]) ^ endian)));
10238 operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
10239 }
10240 [(set_attr "type" "fparith_media")])
10241
10242 (define_insn_and_split "binary_sf_op0"
10243 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10244 (vec_concat:V2SF
10245 (match_operator:SF 3 "binary_float_operator"
10246 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10247 (parallel [(const_int 0)]))
10248 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
10249 (parallel [(const_int 0)]))])
10250 (vec_select:SF
10251 (match_dup 0)
10252 (parallel [(const_int 1)]))))]
10253 "TARGET_SHMEDIA_FPU"
10254 "#"
10255 "&& reload_completed"
10256 [(set (match_dup 4) (match_dup 5))]
10257 {
10258 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10259 rtx op1 = gen_rtx_REG (SFmode,
10260 true_regnum (operands[1]) + endian);
10261 rtx op2 = gen_rtx_REG (SFmode,
10262 true_regnum (operands[2]) + endian);
10263
10264 operands[4] = gen_rtx_REG (SFmode,
10265 true_regnum (operands[0]) + endian);
10266 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
10267 }
10268 [(set_attr "type" "fparith_media")])
10269
10270 (define_insn_and_split "binary_sf_op1"
10271 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10272 (vec_concat:V2SF
10273 (vec_select:SF
10274 (match_dup 0)
10275 (parallel [(const_int 0)]))
10276 (match_operator:SF 3 "binary_float_operator"
10277 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10278 (parallel [(const_int 1)]))
10279 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
10280 (parallel [(const_int 1)]))])))]
10281 "TARGET_SHMEDIA_FPU"
10282 "#"
10283 "&& reload_completed"
10284 [(set (match_dup 4) (match_dup 5))]
10285 {
10286 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10287 rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian));
10288 rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian));
10289
10290 operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian));
10291 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
10292 }
10293 [(set_attr "type" "fparith_media")])
10294
10295 (define_insn "addsf3_i"
10296 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10297 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10298 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10299 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10300 "TARGET_SH2E"
10301 "fadd %2,%0"
10302 [(set_attr "type" "fp")
10303 (set_attr "fp_mode" "single")])
10304
10305 (define_expand "subsf3"
10306 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10307 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10308 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
10309 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10310 {
10311 if (TARGET_SH2E)
10312 {
10313 expand_sf_binop (&gen_subsf3_i, operands);
10314 DONE;
10315 }
10316 })
10317
10318 (define_insn "*subsf3_media"
10319 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10320 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10321 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10322 "TARGET_SHMEDIA_FPU"
10323 "fsub.s %1, %2, %0"
10324 [(set_attr "type" "fparith_media")])
10325
10326 (define_insn "subsf3_i"
10327 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10328 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
10329 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10330 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10331 "TARGET_SH2E"
10332 "fsub %2,%0"
10333 [(set_attr "type" "fp")
10334 (set_attr "fp_mode" "single")])
10335
10336 (define_expand "mulsf3"
10337 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10338 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10339 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
10340 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10341 "")
10342
10343 (define_insn "*mulsf3_media"
10344 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10345 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10346 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10347 "TARGET_SHMEDIA_FPU"
10348 "fmul.s %1, %2, %0"
10349 [(set_attr "type" "fparith_media")])
10350
10351 ;; FIXME: These fmac combine pass assisting specifics are obsolete since
10352 ;; we now use the FMA patterns, which do not depend on the combine
10353 ;; pass anymore.
10354 ;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
10355 ;; register in feeding fp instructions. Thus, in order to generate fmac,
10356 ;; we start out with a mulsf pattern that does not depend on fpscr.
10357 ;; This is split after combine to introduce the dependency, in order to
10358 ;; get mode switching and scheduling right.
10359 (define_insn_and_split "mulsf3_ie"
10360 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10361 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10362 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10363 "TARGET_SH2E"
10364 "fmul %2,%0"
10365 "TARGET_SH4 || TARGET_SH2A_SINGLE"
10366 [(const_int 0)]
10367 {
10368 emit_insn (gen_mulsf3_i4 (operands[0], operands[1], operands[2],
10369 get_fpscr_rtx ()));
10370 DONE;
10371 }
10372 [(set_attr "type" "fp")])
10373
10374 (define_insn "mulsf3_i4"
10375 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10376 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10377 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10378 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10379 "TARGET_SH2E"
10380 "fmul %2,%0"
10381 [(set_attr "type" "fp")
10382 (set_attr "fp_mode" "single")])
10383
10384 ;; FMA (fused multiply-add) patterns
10385 (define_expand "fmasf4"
10386 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10387 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10388 (match_operand:SF 2 "fp_arith_reg_operand" "")
10389 (match_operand:SF 3 "fp_arith_reg_operand" "")))]
10390 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10391 {
10392 if (TARGET_SH2E)
10393 {
10394 emit_sf_insn (gen_fmasf4_i (operands[0], operands[1], operands[2],
10395 operands[3], get_fpscr_rtx ()));
10396 DONE;
10397 }
10398 })
10399
10400 (define_insn "fmasf4_i"
10401 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10402 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w")
10403 (match_operand:SF 2 "fp_arith_reg_operand" "f")
10404 (match_operand:SF 3 "fp_arith_reg_operand" "0")))
10405 (use (match_operand:PSI 4 "fpscr_operand" "c"))]
10406 "TARGET_SH2E"
10407 "fmac %1,%2,%0"
10408 [(set_attr "type" "fp")
10409 (set_attr "fp_mode" "single")])
10410
10411 (define_insn "fmasf4_media"
10412 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10413 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10414 (match_operand:SF 2 "fp_arith_reg_operand" "f")
10415 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
10416 "TARGET_SHMEDIA_FPU"
10417 "fmac.s %1, %2, %0"
10418 [(set_attr "type" "fparith_media")])
10419
10420 (define_expand "divsf3"
10421 [(set (match_operand:SF 0 "arith_reg_operand" "")
10422 (div:SF (match_operand:SF 1 "arith_reg_operand" "")
10423 (match_operand:SF 2 "arith_reg_operand" "")))]
10424 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10425 {
10426 if (TARGET_SH2E)
10427 {
10428 expand_sf_binop (&gen_divsf3_i, operands);
10429 DONE;
10430 }
10431 })
10432
10433 (define_insn "*divsf3_media"
10434 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10435 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10436 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10437 "TARGET_SHMEDIA_FPU"
10438 "fdiv.s %1, %2, %0"
10439 [(set_attr "type" "fdiv_media")])
10440
10441 (define_insn "divsf3_i"
10442 [(set (match_operand:SF 0 "arith_reg_dest" "=f")
10443 (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
10444 (match_operand:SF 2 "arith_reg_operand" "f")))
10445 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10446 "TARGET_SH2E"
10447 "fdiv %2,%0"
10448 [(set_attr "type" "fdiv")
10449 (set_attr "fp_mode" "single")])
10450
10451 (define_insn "floatdisf2"
10452 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10453 (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10454 "TARGET_SHMEDIA_FPU"
10455 "float.qs %1, %0"
10456 [(set_attr "type" "fpconv_media")])
10457
10458 (define_expand "floatsisf2"
10459 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10460 (float:SF (match_operand:SI 1 "fpul_operand" "")))]
10461 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10462 {
10463 if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10464 {
10465 emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10466 DONE;
10467 }
10468 })
10469
10470 (define_insn "*floatsisf2_media"
10471 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10472 (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10473 "TARGET_SHMEDIA_FPU"
10474 "float.ls %1, %0"
10475 [(set_attr "type" "fpconv_media")])
10476
10477 (define_insn "floatsisf2_i4"
10478 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10479 (float:SF (match_operand:SI 1 "fpul_operand" "y")))
10480 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10481 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10482 "float %1,%0"
10483 [(set_attr "type" "fp")
10484 (set_attr "fp_mode" "single")])
10485
10486 (define_insn "*floatsisf2_ie"
10487 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10488 (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
10489 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10490 "float %1,%0"
10491 [(set_attr "type" "fp")])
10492
10493 (define_insn "fix_truncsfdi2"
10494 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10495 (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10496 "TARGET_SHMEDIA_FPU"
10497 "ftrc.sq %1, %0"
10498 [(set_attr "type" "fpconv_media")])
10499
10500 (define_expand "fix_truncsfsi2"
10501 [(set (match_operand:SI 0 "fpul_operand" "=y")
10502 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10503 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10504 {
10505 if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10506 {
10507 emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10508 DONE;
10509 }
10510 })
10511
10512 (define_insn "*fix_truncsfsi2_media"
10513 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10514 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10515 "TARGET_SHMEDIA_FPU"
10516 "ftrc.sl %1, %0"
10517 [(set_attr "type" "fpconv_media")])
10518
10519 (define_insn "fix_truncsfsi2_i4"
10520 [(set (match_operand:SI 0 "fpul_operand" "=y")
10521 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10522 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10523 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10524 "ftrc %1,%0"
10525 [(set_attr "type" "ftrc_s")
10526 (set_attr "fp_mode" "single")])
10527
10528 ;; ??? This pattern is used nowhere. fix_truncsfsi2 always expands to
10529 ;; fix_truncsfsi2_i4.
10530 ;; (define_insn "fix_truncsfsi2_i4_2"
10531 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10532 ;; (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10533 ;; (use (reg:PSI FPSCR_REG))
10534 ;; (clobber (reg:SI FPUL_REG))]
10535 ;; "TARGET_SH4"
10536 ;; "#"
10537 ;; [(set_attr "length" "4")
10538 ;; (set_attr "fp_mode" "single")])
10539
10540 ;;(define_split
10541 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10542 ;; (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10543 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
10544 ;; (clobber (reg:SI FPUL_REG))]
10545 ;; "TARGET_SH4"
10546 ;; [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10547 ;; (use (match_dup 2))])
10548 ;; (set (match_dup 0) (reg:SI FPUL_REG))])
10549
10550 (define_insn "*fixsfsi"
10551 [(set (match_operand:SI 0 "fpul_operand" "=y")
10552 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10553 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10554 "ftrc %1,%0"
10555 [(set_attr "type" "fp")])
10556
10557 (define_insn "cmpgtsf_t"
10558 [(set (reg:SI T_REG)
10559 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10560 (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10561 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10562 "fcmp/gt %1,%0"
10563 [(set_attr "type" "fp_cmp")
10564 (set_attr "fp_mode" "single")])
10565
10566 (define_insn "cmpeqsf_t"
10567 [(set (reg:SI T_REG)
10568 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10569 (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10570 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10571 "fcmp/eq %1,%0"
10572 [(set_attr "type" "fp_cmp")
10573 (set_attr "fp_mode" "single")])
10574
10575 (define_insn "ieee_ccmpeqsf_t"
10576 [(set (reg:SI T_REG)
10577 (ior:SI (reg:SI T_REG)
10578 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10579 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
10580 "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10581 {
10582 return output_ieee_ccmpeq (insn, operands);
10583 }
10584 [(set_attr "length" "4")])
10585
10586
10587 (define_insn "cmpgtsf_t_i4"
10588 [(set (reg:SI T_REG)
10589 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10590 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10591 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10592 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10593 "fcmp/gt %1,%0"
10594 [(set_attr "type" "fp_cmp")
10595 (set_attr "fp_mode" "single")])
10596
10597 (define_insn "cmpeqsf_t_i4"
10598 [(set (reg:SI T_REG)
10599 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10600 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10601 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10602 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10603 "fcmp/eq %1,%0"
10604 [(set_attr "type" "fp_cmp")
10605 (set_attr "fp_mode" "single")])
10606
10607 (define_insn "*ieee_ccmpeqsf_t_4"
10608 [(set (reg:SI T_REG)
10609 (ior:SI (reg:SI T_REG)
10610 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10611 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
10612 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10613 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10614 {
10615 return output_ieee_ccmpeq (insn, operands);
10616 }
10617 [(set_attr "length" "4")
10618 (set_attr "fp_mode" "single")])
10619
10620 (define_insn "cmpeqsf_media"
10621 [(set (match_operand:SI 0 "register_operand" "=r")
10622 (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10623 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10624 "TARGET_SHMEDIA_FPU"
10625 "fcmpeq.s %1, %2, %0"
10626 [(set_attr "type" "fcmp_media")])
10627
10628 (define_insn "cmpgtsf_media"
10629 [(set (match_operand:SI 0 "register_operand" "=r")
10630 (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10631 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10632 "TARGET_SHMEDIA_FPU"
10633 "fcmpgt.s %1, %2, %0"
10634 [(set_attr "type" "fcmp_media")])
10635
10636 (define_insn "cmpgesf_media"
10637 [(set (match_operand:SI 0 "register_operand" "=r")
10638 (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10639 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10640 "TARGET_SHMEDIA_FPU"
10641 "fcmpge.s %1, %2, %0"
10642 [(set_attr "type" "fcmp_media")])
10643
10644 (define_insn "cmpunsf_media"
10645 [(set (match_operand:SI 0 "register_operand" "=r")
10646 (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10647 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10648 "TARGET_SHMEDIA_FPU"
10649 "fcmpun.s %1, %2, %0"
10650 [(set_attr "type" "fcmp_media")])
10651
10652 (define_expand "cbranchsf4"
10653 [(set (pc)
10654 (if_then_else (match_operator 0 "sh_float_comparison_operator"
10655 [(match_operand:SF 1 "arith_operand" "")
10656 (match_operand:SF 2 "arith_operand" "")])
10657 (match_operand 3 "" "")
10658 (pc)))]
10659 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10660 {
10661 if (TARGET_SHMEDIA)
10662 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
10663 operands[3]));
10664 else
10665 sh_emit_compare_and_branch (operands, SFmode);
10666 DONE;
10667 })
10668
10669 (define_expand "negsf2"
10670 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10671 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10672 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10673 {
10674 if (TARGET_SH2E)
10675 {
10676 expand_sf_unop (&gen_negsf2_i, operands);
10677 DONE;
10678 }
10679 })
10680
10681 (define_insn "*negsf2_media"
10682 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10683 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10684 "TARGET_SHMEDIA_FPU"
10685 "fneg.s %1, %0"
10686 [(set_attr "type" "fmove_media")])
10687
10688 (define_insn "negsf2_i"
10689 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10690 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10691 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10692 "TARGET_SH2E"
10693 "fneg %0"
10694 [(set_attr "type" "fmove")
10695 (set_attr "fp_mode" "single")])
10696
10697 (define_expand "sqrtsf2"
10698 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10699 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10700 "TARGET_SH3E || TARGET_SHMEDIA_FPU"
10701 {
10702 if (TARGET_SH3E)
10703 {
10704 expand_sf_unop (&gen_sqrtsf2_i, operands);
10705 DONE;
10706 }
10707 })
10708
10709 (define_insn "*sqrtsf2_media"
10710 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10711 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10712 "TARGET_SHMEDIA_FPU"
10713 "fsqrt.s %1, %0"
10714 [(set_attr "type" "fdiv_media")])
10715
10716 (define_insn "sqrtsf2_i"
10717 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10718 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10719 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10720 "TARGET_SH3E"
10721 "fsqrt %0"
10722 [(set_attr "type" "fdiv")
10723 (set_attr "fp_mode" "single")])
10724
10725 (define_insn "rsqrtsf2"
10726 [(set (match_operand:SF 0 "register_operand" "=f")
10727 (div:SF (match_operand:SF 1 "immediate_operand" "i")
10728 (sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
10729 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10730 "TARGET_FPU_ANY && TARGET_FSRRA
10731 && operands[1] == CONST1_RTX (SFmode)"
10732 "fsrra %0"
10733 [(set_attr "type" "fsrra")
10734 (set_attr "fp_mode" "single")])
10735
10736 (define_insn "fsca"
10737 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10738 (vec_concat:V2SF
10739 (unspec:SF [(mult:SF
10740 (float:SF (match_operand:SI 1 "fpul_operand" "y"))
10741 (match_operand:SF 2 "immediate_operand" "i"))
10742 ] UNSPEC_FSINA)
10743 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
10744 ] UNSPEC_FCOSA)))
10745 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10746 "TARGET_FPU_ANY && TARGET_FSCA
10747 && operands[2] == sh_fsca_int2sf ()"
10748 "fsca fpul,%d0"
10749 [(set_attr "type" "fsca")
10750 (set_attr "fp_mode" "single")])
10751
10752 ;; When the sincos pattern is defined, the builtin functions sin and cos
10753 ;; will be expanded to the sincos pattern and one of the output values will
10754 ;; remain unused.
10755 (define_expand "sincossf3"
10756 [(set (match_operand:SF 0 "nonimmediate_operand" "")
10757 (unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand" "")]
10758 UNSPEC_FSINA))
10759 (set (match_operand:SF 1 "nonimmediate_operand" "")
10760 (unspec:SF [(match_dup 2)] UNSPEC_FCOSA))]
10761 "TARGET_FPU_ANY && TARGET_FSCA"
10762 {
10763 rtx scaled = gen_reg_rtx (SFmode);
10764 rtx truncated = gen_reg_rtx (SImode);
10765 rtx fsca = gen_reg_rtx (V2SFmode);
10766 rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10767
10768 emit_sf_insn (gen_mulsf3 (scaled, operands[2], scale_reg));
10769 emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10770 emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10771 get_fpscr_rtx ()));
10772
10773 emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 0));
10774 emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 4));
10775 DONE;
10776 })
10777
10778 (define_expand "abssf2"
10779 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10780 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10781 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10782 {
10783 if (TARGET_SH2E)
10784 {
10785 expand_sf_unop (&gen_abssf2_i, operands);
10786 DONE;
10787 }
10788 })
10789
10790 (define_insn "*abssf2_media"
10791 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10792 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10793 "TARGET_SHMEDIA_FPU"
10794 "fabs.s %1, %0"
10795 [(set_attr "type" "fmove_media")])
10796
10797 (define_insn "abssf2_i"
10798 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10799 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10800 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10801 "TARGET_SH2E"
10802 "fabs %0"
10803 [(set_attr "type" "fmove")
10804 (set_attr "fp_mode" "single")])
10805
10806 (define_expand "adddf3"
10807 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10808 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10809 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10810 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10811 {
10812 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10813 {
10814 expand_df_binop (&gen_adddf3_i, operands);
10815 DONE;
10816 }
10817 })
10818
10819 (define_insn "*adddf3_media"
10820 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10821 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10822 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10823 "TARGET_SHMEDIA_FPU"
10824 "fadd.d %1, %2, %0"
10825 [(set_attr "type" "dfparith_media")])
10826
10827 (define_insn "adddf3_i"
10828 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10829 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10830 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10831 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10832 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10833 "fadd %2,%0"
10834 [(set_attr "type" "dfp_arith")
10835 (set_attr "fp_mode" "double")])
10836
10837 (define_expand "subdf3"
10838 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10839 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10840 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10841 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10842 {
10843 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10844 {
10845 expand_df_binop (&gen_subdf3_i, operands);
10846 DONE;
10847 }
10848 })
10849
10850 (define_insn "*subdf3_media"
10851 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10852 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10853 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10854 "TARGET_SHMEDIA_FPU"
10855 "fsub.d %1, %2, %0"
10856 [(set_attr "type" "dfparith_media")])
10857
10858 (define_insn "subdf3_i"
10859 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10860 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10861 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10862 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10863 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10864 "fsub %2,%0"
10865 [(set_attr "type" "dfp_arith")
10866 (set_attr "fp_mode" "double")])
10867
10868 (define_expand "muldf3"
10869 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10870 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10871 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10872 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10873 {
10874 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10875 {
10876 expand_df_binop (&gen_muldf3_i, operands);
10877 DONE;
10878 }
10879 })
10880
10881 (define_insn "*muldf3_media"
10882 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10883 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10884 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10885 "TARGET_SHMEDIA_FPU"
10886 "fmul.d %1, %2, %0"
10887 [(set_attr "type" "dfmul_media")])
10888
10889 (define_insn "muldf3_i"
10890 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10891 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10892 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10893 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10894 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10895 "fmul %2,%0"
10896 [(set_attr "type" "dfp_mul")
10897 (set_attr "fp_mode" "double")])
10898
10899 (define_expand "divdf3"
10900 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10901 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10902 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10903 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10904 {
10905 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10906 {
10907 expand_df_binop (&gen_divdf3_i, operands);
10908 DONE;
10909 }
10910 })
10911
10912 (define_insn "*divdf3_media"
10913 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10914 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10915 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10916 "TARGET_SHMEDIA_FPU"
10917 "fdiv.d %1, %2, %0"
10918 [(set_attr "type" "dfdiv_media")])
10919
10920 (define_insn "divdf3_i"
10921 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10922 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10923 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10924 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10925 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10926 "fdiv %2,%0"
10927 [(set_attr "type" "dfdiv")
10928 (set_attr "fp_mode" "double")])
10929
10930 (define_insn "floatdidf2"
10931 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10932 (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10933 "TARGET_SHMEDIA_FPU"
10934 "float.qd %1, %0"
10935 [(set_attr "type" "dfpconv_media")])
10936
10937 (define_expand "floatsidf2"
10938 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10939 (float:DF (match_operand:SI 1 "fpul_operand" "")))]
10940 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10941 {
10942 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10943 {
10944 emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
10945 get_fpscr_rtx ()));
10946 DONE;
10947 }
10948 })
10949
10950 (define_insn "*floatsidf2_media"
10951 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10952 (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10953 "TARGET_SHMEDIA_FPU"
10954 "float.ld %1, %0"
10955 [(set_attr "type" "dfpconv_media")])
10956
10957 (define_insn "floatsidf2_i"
10958 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10959 (float:DF (match_operand:SI 1 "fpul_operand" "y")))
10960 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10961 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10962 "float %1,%0"
10963 [(set_attr "type" "dfp_conv")
10964 (set_attr "fp_mode" "double")])
10965
10966 (define_insn "fix_truncdfdi2"
10967 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10968 (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10969 "TARGET_SHMEDIA_FPU"
10970 "ftrc.dq %1, %0"
10971 [(set_attr "type" "dfpconv_media")])
10972
10973 (define_expand "fix_truncdfsi2"
10974 [(set (match_operand:SI 0 "fpul_operand" "")
10975 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
10976 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10977 {
10978 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10979 {
10980 emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
10981 get_fpscr_rtx ()));
10982 DONE;
10983 }
10984 })
10985
10986 (define_insn "*fix_truncdfsi2_media"
10987 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10988 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10989 "TARGET_SHMEDIA_FPU"
10990 "ftrc.dl %1, %0"
10991 [(set_attr "type" "dfpconv_media")])
10992
10993 (define_insn "fix_truncdfsi2_i"
10994 [(set (match_operand:SI 0 "fpul_operand" "=y")
10995 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
10996 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10997 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10998 "ftrc %1,%0"
10999 [(set_attr "type" "dfp_conv")
11000 (set_attr "dfp_comp" "no")
11001 (set_attr "fp_mode" "double")])
11002
11003 ;; ??? This pattern is used nowhere. fix_truncdfsi2 always expands to
11004 ;; fix_truncdfsi2_i.
11005 ;; (define_insn "fix_truncdfsi2_i4"
11006 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11007 ;; (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
11008 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
11009 ;; (clobber (reg:SI FPUL_REG))]
11010 ;; "TARGET_SH4"
11011 ;; "#"
11012 ;; [(set_attr "length" "4")
11013 ;; (set_attr "fp_mode" "double")])
11014 ;;
11015 ;; (define_split
11016 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11017 ;; (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
11018 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
11019 ;; (clobber (reg:SI FPUL_REG))]
11020 ;; "TARGET_SH4"
11021 ;; [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
11022 ;; (use (match_dup 2))])
11023 ;; (set (match_dup 0) (reg:SI FPUL_REG))])
11024
11025 (define_insn "cmpgtdf_t"
11026 [(set (reg:SI T_REG)
11027 (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
11028 (match_operand:DF 1 "arith_reg_operand" "f")))
11029 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11030 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11031 "fcmp/gt %1,%0"
11032 [(set_attr "type" "dfp_cmp")
11033 (set_attr "fp_mode" "double")])
11034
11035 (define_insn "cmpeqdf_t"
11036 [(set (reg:SI T_REG)
11037 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
11038 (match_operand:DF 1 "arith_reg_operand" "f")))
11039 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11040 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11041 "fcmp/eq %1,%0"
11042 [(set_attr "type" "dfp_cmp")
11043 (set_attr "fp_mode" "double")])
11044
11045 (define_insn "*ieee_ccmpeqdf_t"
11046 [(set (reg:SI T_REG)
11047 (ior:SI (reg:SI T_REG)
11048 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
11049 (match_operand:DF 1 "arith_reg_operand" "f"))))
11050 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11051 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11052 {
11053 return output_ieee_ccmpeq (insn, operands);
11054 }
11055 [(set_attr "length" "4")
11056 (set_attr "fp_mode" "double")])
11057
11058 (define_insn "cmpeqdf_media"
11059 [(set (match_operand:SI 0 "register_operand" "=r")
11060 (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
11061 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11062 "TARGET_SHMEDIA_FPU"
11063 "fcmpeq.d %1,%2,%0"
11064 [(set_attr "type" "fcmp_media")])
11065
11066 (define_insn "cmpgtdf_media"
11067 [(set (match_operand:SI 0 "register_operand" "=r")
11068 (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
11069 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11070 "TARGET_SHMEDIA_FPU"
11071 "fcmpgt.d %1,%2,%0"
11072 [(set_attr "type" "fcmp_media")])
11073
11074 (define_insn "cmpgedf_media"
11075 [(set (match_operand:SI 0 "register_operand" "=r")
11076 (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
11077 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11078 "TARGET_SHMEDIA_FPU"
11079 "fcmpge.d %1,%2,%0"
11080 [(set_attr "type" "fcmp_media")])
11081
11082 (define_insn "cmpundf_media"
11083 [(set (match_operand:SI 0 "register_operand" "=r")
11084 (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
11085 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11086 "TARGET_SHMEDIA_FPU"
11087 "fcmpun.d %1,%2,%0"
11088 [(set_attr "type" "fcmp_media")])
11089
11090 (define_expand "cbranchdf4"
11091 [(set (pc)
11092 (if_then_else (match_operator 0 "sh_float_comparison_operator"
11093 [(match_operand:DF 1 "arith_operand" "")
11094 (match_operand:DF 2 "arith_operand" "")])
11095 (match_operand 3 "" "")
11096 (pc)))]
11097 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11098 {
11099 if (TARGET_SHMEDIA)
11100 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
11101 operands[3]));
11102 else
11103 sh_emit_compare_and_branch (operands, DFmode);
11104 DONE;
11105 })
11106
11107
11108 (define_expand "negdf2"
11109 [(set (match_operand:DF 0 "arith_reg_operand" "")
11110 (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
11111 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11112 {
11113 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11114 {
11115 expand_df_unop (&gen_negdf2_i, operands);
11116 DONE;
11117 }
11118 })
11119
11120 (define_insn "*negdf2_media"
11121 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11122 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11123 "TARGET_SHMEDIA_FPU"
11124 "fneg.d %1, %0"
11125 [(set_attr "type" "fmove_media")])
11126
11127 (define_insn "negdf2_i"
11128 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11129 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11130 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11131 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11132 "fneg %0"
11133 [(set_attr "type" "fmove")
11134 (set_attr "fp_mode" "double")])
11135
11136 (define_expand "sqrtdf2"
11137 [(set (match_operand:DF 0 "arith_reg_operand" "")
11138 (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
11139 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11140 {
11141 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11142 {
11143 expand_df_unop (&gen_sqrtdf2_i, operands);
11144 DONE;
11145 }
11146 })
11147
11148 (define_insn "*sqrtdf2_media"
11149 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11150 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11151 "TARGET_SHMEDIA_FPU"
11152 "fsqrt.d %1, %0"
11153 [(set_attr "type" "dfdiv_media")])
11154
11155 (define_insn "sqrtdf2_i"
11156 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11157 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11158 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11159 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11160 "fsqrt %0"
11161 [(set_attr "type" "dfdiv")
11162 (set_attr "fp_mode" "double")])
11163
11164 (define_expand "absdf2"
11165 [(set (match_operand:DF 0 "arith_reg_operand" "")
11166 (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
11167 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11168 {
11169 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11170 {
11171 expand_df_unop (&gen_absdf2_i, operands);
11172 DONE;
11173 }
11174 })
11175
11176 (define_insn "*absdf2_media"
11177 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11178 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11179 "TARGET_SHMEDIA_FPU"
11180 "fabs.d %1, %0"
11181 [(set_attr "type" "fmove_media")])
11182
11183 (define_insn "absdf2_i"
11184 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11185 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11186 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11187 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11188 "fabs %0"
11189 [(set_attr "type" "fmove")
11190 (set_attr "fp_mode" "double")])
11191
11192 (define_expand "extendsfdf2"
11193 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
11194 (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
11195 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11196 {
11197 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11198 {
11199 emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
11200 get_fpscr_rtx ()));
11201 DONE;
11202 }
11203 })
11204
11205 (define_insn "*extendsfdf2_media"
11206 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11207 (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
11208 "TARGET_SHMEDIA_FPU"
11209 "fcnv.sd %1, %0"
11210 [(set_attr "type" "dfpconv_media")])
11211
11212 (define_insn "extendsfdf2_i4"
11213 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11214 (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
11215 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11216 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11217 "fcnvsd %1,%0"
11218 [(set_attr "type" "fp")
11219 (set_attr "fp_mode" "double")])
11220
11221 (define_expand "truncdfsf2"
11222 [(set (match_operand:SF 0 "fpul_operand" "")
11223 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
11224 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11225 {
11226 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11227 {
11228 emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
11229 get_fpscr_rtx ()));
11230 DONE;
11231 }
11232 })
11233
11234 (define_insn "*truncdfsf2_media"
11235 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11236 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11237 "TARGET_SHMEDIA_FPU"
11238 "fcnv.ds %1, %0"
11239 [(set_attr "type" "dfpconv_media")])
11240
11241 (define_insn "truncdfsf2_i4"
11242 [(set (match_operand:SF 0 "fpul_operand" "=y")
11243 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
11244 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11245 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11246 "fcnvds %1,%0"
11247 [(set_attr "type" "fp")
11248 (set_attr "fp_mode" "double")])
11249 \f
11250 ;; Bit field extract patterns. These give better code for packed bitfields,
11251 ;; because they allow auto-increment addresses to be generated.
11252
11253 (define_expand "insv"
11254 [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
11255 (match_operand:SI 1 "immediate_operand" "")
11256 (match_operand:SI 2 "immediate_operand" ""))
11257 (match_operand:SI 3 "general_operand" ""))]
11258 "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
11259 {
11260 rtx addr_target, orig_address, shift_reg, qi_val;
11261 HOST_WIDE_INT bitsize, size, v = 0;
11262 rtx x = operands[3];
11263
11264 if (TARGET_SH2A && TARGET_BITOPS
11265 && (satisfies_constraint_Sbw (operands[0])
11266 || satisfies_constraint_Sbv (operands[0]))
11267 && satisfies_constraint_M (operands[1])
11268 && satisfies_constraint_K03 (operands[2]))
11269 {
11270 if (satisfies_constraint_N (operands[3]))
11271 {
11272 emit_insn (gen_bclr_m2a (operands[0], operands[2]));
11273 DONE;
11274 }
11275 else if (satisfies_constraint_M (operands[3]))
11276 {
11277 emit_insn (gen_bset_m2a (operands[0], operands[2]));
11278 DONE;
11279 }
11280 else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
11281 && satisfies_constraint_M (operands[1]))
11282 {
11283 emit_insn (gen_bst_m2a (operands[0], operands[2]));
11284 DONE;
11285 }
11286 else if (REG_P (operands[3])
11287 && satisfies_constraint_M (operands[1]))
11288 {
11289 emit_insn (gen_bld_reg (operands[3], const0_rtx));
11290 emit_insn (gen_bst_m2a (operands[0], operands[2]));
11291 DONE;
11292 }
11293 }
11294 /* ??? expmed doesn't care for non-register predicates. */
11295 if (! memory_operand (operands[0], VOIDmode)
11296 || ! immediate_operand (operands[1], VOIDmode)
11297 || ! immediate_operand (operands[2], VOIDmode)
11298 || ! general_operand (x, VOIDmode))
11299 FAIL;
11300 /* If this isn't a 16 / 24 / 32 bit field, or if
11301 it doesn't start on a byte boundary, then fail. */
11302 bitsize = INTVAL (operands[1]);
11303 if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
11304 || (INTVAL (operands[2]) % 8) != 0)
11305 FAIL;
11306
11307 size = bitsize / 8;
11308 orig_address = XEXP (operands[0], 0);
11309 shift_reg = gen_reg_rtx (SImode);
11310 if (CONST_INT_P (x))
11311 {
11312 v = INTVAL (x);
11313 qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
11314 }
11315 else
11316 {
11317 emit_insn (gen_movsi (shift_reg, operands[3]));
11318 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11319 }
11320 addr_target = copy_addr_to_reg (plus_constant (Pmode,
11321 orig_address, size - 1));
11322
11323 operands[0] = replace_equiv_address (operands[0], addr_target);
11324 emit_insn (gen_movqi (operands[0], qi_val));
11325
11326 while (size -= 1)
11327 {
11328 if (CONST_INT_P (x))
11329 qi_val
11330 = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
11331 else
11332 {
11333 emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
11334 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11335 }
11336 emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
11337 emit_insn (gen_movqi (operands[0], qi_val));
11338 }
11339
11340 DONE;
11341 })
11342
11343 (define_insn "movua"
11344 [(set (match_operand:SI 0 "register_operand" "=z")
11345 (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
11346 UNSPEC_MOVUA))]
11347 "TARGET_SH4A_ARCH"
11348 "movua.l %1,%0"
11349 [(set_attr "type" "movua")])
11350
11351 ;; We shouldn't need this, but cse replaces increments with references
11352 ;; to other regs before flow has a chance to create post_inc
11353 ;; addressing modes, and only postreload's cse_move2add brings the
11354 ;; increments back to a usable form.
11355 (define_peephole2
11356 [(set (match_operand:SI 0 "register_operand" "")
11357 (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
11358 (const_int 32) (const_int 0)))
11359 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11360 "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
11361 [(set (match_operand:SI 0 "register_operand" "")
11362 (sign_extract:SI (mem:SI (post_inc:SI
11363 (match_operand:SI 1 "register_operand" "")))
11364 (const_int 32) (const_int 0)))]
11365 "")
11366
11367 (define_expand "extv"
11368 [(set (match_operand:SI 0 "register_operand" "")
11369 (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11370 (match_operand 2 "const_int_operand" "")
11371 (match_operand 3 "const_int_operand" "")))]
11372 "TARGET_SH4A_ARCH || TARGET_SH2A"
11373 {
11374 if (TARGET_SH2A && TARGET_BITOPS
11375 && (satisfies_constraint_Sbw (operands[1])
11376 || satisfies_constraint_Sbv (operands[1]))
11377 && satisfies_constraint_M (operands[2])
11378 && satisfies_constraint_K03 (operands[3]))
11379 {
11380 emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
11381 if (REGNO (operands[0]) != T_REG)
11382 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
11383 DONE;
11384 }
11385 if (TARGET_SH4A_ARCH
11386 && INTVAL (operands[2]) == 32
11387 && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11388 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
11389 {
11390 rtx src = adjust_address (operands[1], BLKmode, 0);
11391 set_mem_size (src, 4);
11392 emit_insn (gen_movua (operands[0], src));
11393 DONE;
11394 }
11395
11396 FAIL;
11397 })
11398
11399 (define_expand "extzv"
11400 [(set (match_operand:SI 0 "register_operand" "")
11401 (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11402 (match_operand 2 "const_int_operand" "")
11403 (match_operand 3 "const_int_operand" "")))]
11404 "TARGET_SH4A_ARCH || TARGET_SH2A"
11405 {
11406 if (TARGET_SH2A && TARGET_BITOPS
11407 && (satisfies_constraint_Sbw (operands[1])
11408 || satisfies_constraint_Sbv (operands[1]))
11409 && satisfies_constraint_M (operands[2])
11410 && satisfies_constraint_K03 (operands[3]))
11411 {
11412 emit_insn (gen_bld_m2a (operands[1], operands[3]));
11413 if (REGNO (operands[0]) != T_REG)
11414 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
11415 DONE;
11416 }
11417 if (TARGET_SH4A_ARCH
11418 && INTVAL (operands[2]) == 32
11419 && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11420 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
11421 {
11422 rtx src = adjust_address (operands[1], BLKmode, 0);
11423 set_mem_size (src, 4);
11424 emit_insn (gen_movua (operands[0], src));
11425 DONE;
11426 }
11427
11428 FAIL;
11429 })
11430
11431 ;; SH2A instructions for bitwise operations.
11432
11433 ;; Clear a bit in a memory location.
11434 (define_insn "bclr_m2a"
11435 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11436 (and:QI
11437 (not:QI (ashift:QI (const_int 1)
11438 (match_operand:QI 1 "const_int_operand" "K03,K03")))
11439 (match_dup 0)))]
11440 "TARGET_SH2A && TARGET_BITOPS"
11441 "@
11442 bclr.b\\t%1,%0
11443 bclr.b\\t%1,@(0,%t0)"
11444 [(set_attr "length" "4,4")])
11445
11446 (define_insn "bclrmem_m2a"
11447 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11448 (and:QI (match_dup 0)
11449 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
11450 "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
11451 "@
11452 bclr.b\\t%W1,%0
11453 bclr.b\\t%W1,@(0,%t0)"
11454 [(set_attr "length" "4,4")])
11455
11456 ;; Set a bit in a memory location.
11457 (define_insn "bset_m2a"
11458 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11459 (ior:QI
11460 (ashift:QI (const_int 1)
11461 (match_operand:QI 1 "const_int_operand" "K03,K03"))
11462 (match_dup 0)))]
11463 "TARGET_SH2A && TARGET_BITOPS"
11464 "@
11465 bset.b\\t%1,%0
11466 bset.b\\t%1,@(0,%t0)"
11467 [(set_attr "length" "4,4")])
11468
11469 (define_insn "bsetmem_m2a"
11470 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11471 (ior:QI (match_dup 0)
11472 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
11473 "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
11474 "@
11475 bset.b\\t%V1,%0
11476 bset.b\\t%V1,@(0,%t0)"
11477 [(set_attr "length" "4,4")])
11478
11479 ;;; Transfer the contents of the T bit to a specified bit of memory.
11480 (define_insn "bst_m2a"
11481 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
11482 (if_then_else (eq (reg:SI T_REG) (const_int 0))
11483 (and:QI
11484 (not:QI (ashift:QI (const_int 1)
11485 (match_operand:QI 1 "const_int_operand" "K03,K03")))
11486 (match_dup 0))
11487 (ior:QI
11488 (ashift:QI (const_int 1) (match_dup 1))
11489 (match_dup 0))))]
11490 "TARGET_SH2A && TARGET_BITOPS"
11491 "@
11492 bst.b\\t%1,%0
11493 bst.b\\t%1,@(0,%t0)"
11494 [(set_attr "length" "4")])
11495
11496 ;; Store a specified bit of memory in the T bit.
11497 (define_insn "bld_m2a"
11498 [(set (reg:SI T_REG)
11499 (zero_extract:SI
11500 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
11501 (const_int 1)
11502 (match_operand 1 "const_int_operand" "K03,K03")))]
11503 "TARGET_SH2A && TARGET_BITOPS"
11504 "@
11505 bld.b\\t%1,%0
11506 bld.b\\t%1,@(0,%t0)"
11507 [(set_attr "length" "4,4")])
11508
11509 ;; Store a specified bit of memory in the T bit.
11510 (define_insn "bldsign_m2a"
11511 [(set (reg:SI T_REG)
11512 (sign_extract:SI
11513 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11514 (const_int 1)
11515 (match_operand 1 "const_int_operand" "K03,K03")))]
11516 "TARGET_SH2A && TARGET_BITOPS"
11517 "@
11518 bld.b\\t%1,%0
11519 bld.b\\t%1,@(0,%t0)"
11520 [(set_attr "length" "4,4")])
11521
11522 ;; Store a specified bit of the LSB 8 bits of a register in the T bit.
11523 (define_insn "bld_reg"
11524 [(set (reg:SI T_REG)
11525 (zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
11526 (const_int 1)
11527 (match_operand 1 "const_int_operand" "K03")))]
11528 "TARGET_SH2A"
11529 "bld\\t%1,%0")
11530
11531 (define_insn "*bld_regqi"
11532 [(set (reg:SI T_REG)
11533 (zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
11534 (const_int 1)
11535 (match_operand 1 "const_int_operand" "K03")))]
11536 "TARGET_SH2A"
11537 "bld\\t%1,%0")
11538
11539 ;; Take logical and of a specified bit of memory with the T bit and
11540 ;; store its result in the T bit.
11541 (define_insn "band_m2a"
11542 [(set (reg:SI T_REG)
11543 (and:SI (reg:SI T_REG)
11544 (zero_extract:SI
11545 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11546 (const_int 1)
11547 (match_operand 1 "const_int_operand" "K03,K03"))))]
11548 "TARGET_SH2A && TARGET_BITOPS"
11549 "@
11550 band.b\\t%1,%0
11551 band.b\\t%1,@(0,%t0)"
11552 [(set_attr "length" "4,4")])
11553
11554 (define_insn "bandreg_m2a"
11555 [(set (match_operand:SI 0 "register_operand" "=r,r")
11556 (and:SI (zero_extract:SI
11557 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11558 (const_int 1)
11559 (match_operand 2 "const_int_operand" "K03,K03"))
11560 (match_operand:SI 3 "register_operand" "r,r")))]
11561 "TARGET_SH2A && TARGET_BITOPS"
11562 "@
11563 band.b\\t%2,%1\;movt\\t%0
11564 band.b\\t%2,@(0,%t1)\;movt\\t%0"
11565 [(set_attr "length" "6,6")])
11566
11567 ;; Take logical or of a specified bit of memory with the T bit and
11568 ;; store its result in the T bit.
11569 (define_insn "bor_m2a"
11570 [(set (reg:SI T_REG)
11571 (ior:SI (reg:SI T_REG)
11572 (zero_extract:SI
11573 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11574 (const_int 1)
11575 (match_operand 1 "const_int_operand" "K03,K03"))))]
11576 "TARGET_SH2A && TARGET_BITOPS"
11577 "@
11578 bor.b\\t%1,%0
11579 bor.b\\t%1,@(0,%t0)"
11580 [(set_attr "length" "4,4")])
11581
11582 (define_insn "borreg_m2a"
11583 [(set (match_operand:SI 0 "register_operand" "=r,r")
11584 (ior:SI (zero_extract:SI
11585 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11586 (const_int 1)
11587 (match_operand 2 "const_int_operand" "K03,K03"))
11588 (match_operand:SI 3 "register_operand" "=r,r")))]
11589 "TARGET_SH2A && TARGET_BITOPS"
11590 "@
11591 bor.b\\t%2,%1\;movt\\t%0
11592 bor.b\\t%2,@(0,%t1)\;movt\\t%0"
11593 [(set_attr "length" "6,6")])
11594
11595 ;; Take exclusive or of a specified bit of memory with the T bit and
11596 ;; store its result in the T bit.
11597 (define_insn "bxor_m2a"
11598 [(set (reg:SI T_REG)
11599 (xor:SI (reg:SI T_REG)
11600 (zero_extract:SI
11601 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11602 (const_int 1)
11603 (match_operand 1 "const_int_operand" "K03,K03"))))]
11604 "TARGET_SH2A && TARGET_BITOPS"
11605 "@
11606 bxor.b\\t%1,%0
11607 bxor.b\\t%1,@(0,%t0)"
11608 [(set_attr "length" "4,4")])
11609
11610 (define_insn "bxorreg_m2a"
11611 [(set (match_operand:SI 0 "register_operand" "=r,r")
11612 (xor:SI (zero_extract:SI
11613 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11614 (const_int 1)
11615 (match_operand 2 "const_int_operand" "K03,K03"))
11616 (match_operand:SI 3 "register_operand" "=r,r")))]
11617 "TARGET_SH2A && TARGET_BITOPS"
11618 "@
11619 bxor.b\\t%2,%1\;movt\\t%0
11620 bxor.b\\t%2,@(0,%t1)\;movt\\t%0"
11621 [(set_attr "length" "6,6")])
11622
11623 \f
11624 ;; -------------------------------------------------------------------------
11625 ;; Peepholes
11626 ;; -------------------------------------------------------------------------
11627 ;; This matches cases where the bit in a memory location is set.
11628 (define_peephole2
11629 [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
11630 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
11631 (set (match_dup 0)
11632 (ior:SI (match_dup 0)
11633 (match_operand:SI 2 "const_int_operand" "Pso,Pso")))
11634 (set (match_dup 1)
11635 (match_operand 3 "arith_reg_operand" "r,r"))]
11636 "TARGET_SH2A && TARGET_BITOPS
11637 && satisfies_constraint_Pso (operands[2])
11638 && REGNO (operands[0]) == REGNO (operands[3])"
11639 [(set (match_dup 1)
11640 (ior:QI (match_dup 1)
11641 (match_dup 2)))]
11642 "")
11643
11644 ;; This matches cases where the bit in a memory location is cleared.
11645 (define_peephole2
11646 [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
11647 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
11648 (set (match_dup 0)
11649 (and:SI (match_dup 0)
11650 (match_operand:SI 2 "const_int_operand" "Psz,Psz")))
11651 (set (match_dup 1)
11652 (match_operand 3 "arith_reg_operand" "r,r"))]
11653 "TARGET_SH2A && TARGET_BITOPS
11654 && satisfies_constraint_Psz (operands[2])
11655 && REGNO (operands[0]) == REGNO (operands[3])"
11656 [(set (match_dup 1)
11657 (and:QI (match_dup 1)
11658 (match_dup 2)))]
11659 "")
11660
11661 ;; This matches cases where a stack pointer increment at the start of the
11662 ;; epilogue combines with a stack slot read loading the return value.
11663
11664 (define_peephole
11665 [(set (match_operand:SI 0 "arith_reg_operand" "")
11666 (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
11667 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11668 "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
11669 "mov.l @%1+,%0")
11670
11671 ;; See the comment on the dt combiner pattern above.
11672
11673 (define_peephole
11674 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11675 (plus:SI (match_dup 0)
11676 (const_int -1)))
11677 (set (reg:SI T_REG)
11678 (eq:SI (match_dup 0)
11679 (const_int 0)))]
11680 "TARGET_SH2"
11681 "dt %0")
11682
11683 ;; The following peepholes fold load sequences for which reload was not
11684 ;; able to generate a displacement addressing move insn.
11685 ;; This can happen when reload has to transform a move insn
11686 ;; without displacement into one with displacement. Or when reload can't
11687 ;; fit a displacement into the insn's constraints. In the latter case, the
11688 ;; load destination reg remains at r0, which reload compensates by inserting
11689 ;; another mov insn.
11690
11691 ;; Fold sequence:
11692 ;; mov #54,r0
11693 ;; mov.{b,w} @(r0,r15),r0
11694 ;; mov r0,r3
11695 ;; into:
11696 ;; mov.{b,w} @(54,r15),r3
11697 ;;
11698 (define_peephole2
11699 [(set (match_operand:SI 0 "arith_reg_dest" "")
11700 (match_operand:SI 1 "const_int_operand" ""))
11701 (set (match_operand:SI 2 "arith_reg_dest" "")
11702 (sign_extend:SI
11703 (mem:QI (plus:SI (match_dup 0)
11704 (match_operand:SI 3 "arith_reg_operand" "")))))
11705 (set (match_operand:QI 4 "arith_reg_dest" "")
11706 (match_operand:QI 5 "arith_reg_operand" ""))]
11707 "TARGET_SH2A
11708 && sh_legitimate_index_p (QImode, operands[1], true, true)
11709 && REGNO (operands[2]) == REGNO (operands[5])
11710 && peep2_reg_dead_p (3, operands[5])"
11711 [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))]
11712 "")
11713
11714 (define_peephole2
11715 [(set (match_operand:SI 0 "arith_reg_dest" "")
11716 (match_operand:SI 1 "const_int_operand" ""))
11717 (set (match_operand:SI 2 "arith_reg_dest" "")
11718 (sign_extend:SI
11719 (mem:HI (plus:SI (match_dup 0)
11720 (match_operand:SI 3 "arith_reg_operand" "")))))
11721 (set (match_operand:HI 4 "arith_reg_dest" "")
11722 (match_operand:HI 5 "arith_reg_operand" ""))]
11723 "TARGET_SH2A
11724 && sh_legitimate_index_p (HImode, operands[1], true, true)
11725 && REGNO (operands[2]) == REGNO (operands[5])
11726 && peep2_reg_dead_p (3, operands[5])"
11727 [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))]
11728 "")
11729
11730 ;; Fold sequence:
11731 ;; mov #54,r0
11732 ;; mov.{b,w} @(r0,r15),r1
11733 ;; into:
11734 ;; mov.{b,w} @(54,r15),r1
11735 ;;
11736 (define_peephole2
11737 [(set (match_operand:SI 0 "arith_reg_dest" "")
11738 (match_operand:SI 1 "const_int_operand" ""))
11739 (set (match_operand:SI 2 "arith_reg_dest" "")
11740 (sign_extend:SI
11741 (mem:QI (plus:SI (match_dup 0)
11742 (match_operand:SI 3 "arith_reg_operand" "")))))]
11743 "TARGET_SH2A
11744 && sh_legitimate_index_p (QImode, operands[1], true, true)
11745 && (peep2_reg_dead_p (2, operands[0])
11746 || REGNO (operands[0]) == REGNO (operands[2]))"
11747 [(set (match_dup 2)
11748 (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))]
11749 "")
11750
11751 (define_peephole2
11752 [(set (match_operand:SI 0 "arith_reg_dest" "")
11753 (match_operand:SI 1 "const_int_operand" ""))
11754 (set (match_operand:SI 2 "arith_reg_dest" "")
11755 (sign_extend:SI
11756 (mem:HI (plus:SI (match_dup 0)
11757 (match_operand:SI 3 "arith_reg_operand" "")))))]
11758 "TARGET_SH2A
11759 && sh_legitimate_index_p (HImode, operands[1], true, true)
11760 && (peep2_reg_dead_p (2, operands[0])
11761 || REGNO (operands[0]) == REGNO (operands[2]))"
11762 [(set (match_dup 2)
11763 (sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))]
11764 "")
11765
11766 ;; Fold sequence:
11767 ;; mov.{b,w} @(r0,r15),r0
11768 ;; mov r0,r3
11769 ;; into:
11770 ;; mov.{b,w} @(r0,r15),r3
11771 ;;
11772 ;; This can happen when initially a displacement address is picked, where
11773 ;; the destination reg is fixed to r0, and then the address is transformed
11774 ;; into 'r0 + reg'.
11775 (define_peephole2
11776 [(set (match_operand:SI 0 "arith_reg_dest" "")
11777 (sign_extend:SI
11778 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
11779 (match_operand:SI 2 "arith_reg_operand" "")))))
11780 (set (match_operand:QI 3 "arith_reg_dest" "")
11781 (match_operand:QI 4 "arith_reg_operand" ""))]
11782 "TARGET_SH1
11783 && REGNO (operands[0]) == REGNO (operands[4])
11784 && peep2_reg_dead_p (2, operands[0])"
11785 [(set (match_dup 3)
11786 (mem:QI (plus:SI (match_dup 1) (match_dup 2))))]
11787 "")
11788
11789 (define_peephole2
11790 [(set (match_operand:SI 0 "arith_reg_dest" "")
11791 (sign_extend:SI
11792 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
11793 (match_operand:SI 2 "arith_reg_operand" "")))))
11794 (set (match_operand:HI 3 "arith_reg_dest" "")
11795 (match_operand:HI 4 "arith_reg_operand" ""))]
11796 "TARGET_SH1
11797 && REGNO (operands[0]) == REGNO (operands[4])
11798 && peep2_reg_dead_p (2, operands[0])"
11799 [(set (match_dup 3)
11800 (mem:HI (plus:SI (match_dup 1) (match_dup 2))))]
11801 "")
11802
11803 ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
11804 ;; to `mov #k,r0; mov.l @(r0,r15),rn'. These sequences are generated by
11805 ;; reload when the constant is too large for a reg+offset address.
11806
11807 ;; ??? We would get much better code if this was done in reload. This would
11808 ;; require modifying find_reloads_address to recognize that if the constant
11809 ;; is out-of-range for an immediate add, then we get better code by reloading
11810 ;; the constant into a register than by reloading the sum into a register,
11811 ;; since the former is one instruction shorter if the address does not need
11812 ;; to be offsettable. Unfortunately this does not work, because there is
11813 ;; only one register, r0, that can be used as an index register. This register
11814 ;; is also the function return value register. So, if we try to force reload
11815 ;; to use double-reg addresses, then we end up with some instructions that
11816 ;; need to use r0 twice. The only way to fix this is to change the calling
11817 ;; convention so that r0 is not used to return values.
11818
11819 (define_peephole
11820 [(set (match_operand:SI 0 "register_operand" "=r")
11821 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11822 (set (mem:SI (match_dup 0))
11823 (match_operand:SI 2 "general_movsrc_operand" ""))]
11824 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11825 "mov.l %2,@(%0,%1)")
11826
11827 (define_peephole
11828 [(set (match_operand:SI 0 "register_operand" "=r")
11829 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11830 (set (match_operand:SI 2 "general_movdst_operand" "")
11831 (mem:SI (match_dup 0)))]
11832 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11833 "mov.l @(%0,%1),%2")
11834
11835 (define_peephole
11836 [(set (match_operand:SI 0 "register_operand" "=r")
11837 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11838 (set (mem:HI (match_dup 0))
11839 (match_operand:HI 2 "general_movsrc_operand" ""))]
11840 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11841 "mov.w %2,@(%0,%1)")
11842
11843 (define_peephole
11844 [(set (match_operand:SI 0 "register_operand" "=r")
11845 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11846 (set (match_operand:HI 2 "general_movdst_operand" "")
11847 (mem:HI (match_dup 0)))]
11848 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11849 "mov.w @(%0,%1),%2")
11850
11851 (define_peephole
11852 [(set (match_operand:SI 0 "register_operand" "=r")
11853 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11854 (set (mem:QI (match_dup 0))
11855 (match_operand:QI 2 "general_movsrc_operand" ""))]
11856 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11857 "mov.b %2,@(%0,%1)")
11858
11859 (define_peephole
11860 [(set (match_operand:SI 0 "register_operand" "=r")
11861 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11862 (set (match_operand:QI 2 "general_movdst_operand" "")
11863 (mem:QI (match_dup 0)))]
11864 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11865 "mov.b @(%0,%1),%2")
11866
11867 (define_peephole
11868 [(set (match_operand:SI 0 "register_operand" "=r")
11869 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11870 (set (mem:SF (match_dup 0))
11871 (match_operand:SF 2 "general_movsrc_operand" ""))]
11872 "TARGET_SH1 && REGNO (operands[0]) == 0
11873 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
11874 || (GET_CODE (operands[2]) == SUBREG
11875 && REGNO (SUBREG_REG (operands[2])) < 16))
11876 && reg_unused_after (operands[0], insn)"
11877 "mov.l %2,@(%0,%1)")
11878
11879 (define_peephole
11880 [(set (match_operand:SI 0 "register_operand" "=r")
11881 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11882 (set (match_operand:SF 2 "general_movdst_operand" "")
11883
11884 (mem:SF (match_dup 0)))]
11885 "TARGET_SH1 && REGNO (operands[0]) == 0
11886 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
11887 || (GET_CODE (operands[2]) == SUBREG
11888 && REGNO (SUBREG_REG (operands[2])) < 16))
11889 && reg_unused_after (operands[0], insn)"
11890 "mov.l @(%0,%1),%2")
11891
11892 (define_peephole
11893 [(set (match_operand:SI 0 "register_operand" "=r")
11894 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11895 (set (mem:SF (match_dup 0))
11896 (match_operand:SF 2 "general_movsrc_operand" ""))]
11897 "TARGET_SH2E && REGNO (operands[0]) == 0
11898 && ((REG_P (operands[2])
11899 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11900 || (GET_CODE (operands[2]) == SUBREG
11901 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11902 && reg_unused_after (operands[0], insn)"
11903 "fmov{.s|} %2,@(%0,%1)")
11904
11905 (define_peephole
11906 [(set (match_operand:SI 0 "register_operand" "=r")
11907 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11908 (set (match_operand:SF 2 "general_movdst_operand" "")
11909
11910 (mem:SF (match_dup 0)))]
11911 "TARGET_SH2E && REGNO (operands[0]) == 0
11912 && ((REG_P (operands[2])
11913 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11914 || (GET_CODE (operands[2]) == SUBREG
11915 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11916 && reg_unused_after (operands[0], insn)"
11917 "fmov{.s|} @(%0,%1),%2")
11918
11919 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF). */
11920 (define_insn "sp_switch_1"
11921 [(const_int 1) (match_operand:SI 0 "symbol_ref_operand" "s")]
11922 "TARGET_SH1"
11923 {
11924 output_asm_insn ("mov.l r0,@-r15\;mov.l %0,r0", operands);
11925 output_asm_insn ("mov.l @r0,r0\;mov.l r15,@-r0", operands);
11926 return "mov r0,r15";
11927 }
11928 [(set_attr "length" "10")])
11929
11930 ;; Switch back to the original stack for interrupt functions with the
11931 ;; sp_switch attribute. */
11932 (define_insn "sp_switch_2"
11933 [(const_int 2)]
11934 "TARGET_SH1"
11935 "mov.l @r15+,r15\;mov.l @r15+,r0"
11936 [(set_attr "length" "4")])
11937
11938 ;; Integer vector moves
11939
11940 (define_expand "movv8qi"
11941 [(set (match_operand:V8QI 0 "general_movdst_operand" "")
11942 (match_operand:V8QI 1 "general_movsrc_operand" ""))]
11943 "TARGET_SHMEDIA"
11944 {
11945 prepare_move_operands (operands, V8QImode);
11946 })
11947
11948 (define_insn "movv8qi_i"
11949 [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
11950 (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11951 "TARGET_SHMEDIA
11952 && (register_operand (operands[0], V8QImode)
11953 || sh_register_operand (operands[1], V8QImode))"
11954 "@
11955 add %1, r63, %0
11956 movi %1, %0
11957 #
11958 ld%M1.q %m1, %0
11959 st%M0.q %m0, %N1"
11960 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
11961 (set_attr "length" "4,4,16,4,4")])
11962
11963 (define_split
11964 [(set (match_operand:V8QI 0 "arith_reg_dest" "")
11965 (subreg:V8QI (const_int 0) 0))]
11966 "TARGET_SHMEDIA"
11967 [(set (match_dup 0)
11968 (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
11969 (const_int 0) (const_int 0) (const_int 0)
11970 (const_int 0) (const_int 0)]))])
11971
11972 (define_split
11973 [(set (match_operand 0 "arith_reg_dest" "")
11974 (match_operand 1 "sh_rep_vec" ""))]
11975 "TARGET_SHMEDIA && reload_completed
11976 && GET_MODE (operands[0]) == GET_MODE (operands[1])
11977 && sh_vector_mode_supported_p (GET_MODE (operands[0]))
11978 && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
11979 && (XVECEXP (operands[1], 0, 0) != const0_rtx
11980 || XVECEXP (operands[1], 0, 1) != const0_rtx)
11981 && (XVECEXP (operands[1], 0, 0) != constm1_rtx
11982 || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
11983 [(set (match_dup 0) (match_dup 1))
11984 (match_dup 2)]
11985 {
11986 int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
11987 rtx elt1 = XVECEXP (operands[1], 0, 1);
11988
11989 if (unit_size > 2)
11990 operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
11991 else
11992 {
11993 if (unit_size < 2)
11994 operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
11995 operands[2] = gen_mperm_w0 (operands[0], operands[0]);
11996 }
11997 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
11998 operands[1] = XVECEXP (operands[1], 0, 0);
11999 if (unit_size < 2)
12000 {
12001 if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
12002 operands[1]
12003 = GEN_INT (TARGET_LITTLE_ENDIAN
12004 ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
12005 : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
12006 else
12007 {
12008 operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
12009 operands[1]
12010 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
12011 }
12012 }
12013 })
12014
12015 (define_split
12016 [(set (match_operand 0 "arith_reg_dest" "")
12017 (match_operand 1 "sh_const_vec" ""))]
12018 "TARGET_SHMEDIA && reload_completed
12019 && GET_MODE (operands[0]) == GET_MODE (operands[1])
12020 && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
12021 [(set (match_dup 0) (match_dup 1))]
12022 {
12023 rtx v = operands[1];
12024 enum machine_mode new_mode
12025 = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
12026
12027 operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
12028 operands[1]
12029 = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
12030 })
12031
12032 (define_expand "movv2hi"
12033 [(set (match_operand:V2HI 0 "general_movdst_operand" "")
12034 (match_operand:V2HI 1 "general_movsrc_operand" ""))]
12035 "TARGET_SHMEDIA"
12036 {
12037 prepare_move_operands (operands, V2HImode);
12038 })
12039
12040 (define_insn "movv2hi_i"
12041 [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
12042 (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
12043 "TARGET_SHMEDIA
12044 && (register_operand (operands[0], V2HImode)
12045 || sh_register_operand (operands[1], V2HImode))"
12046 "@
12047 add.l %1, r63, %0
12048 movi %1, %0
12049 #
12050 ld%M1.l %m1, %0
12051 st%M0.l %m0, %N1"
12052 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
12053 (set_attr "length" "4,4,16,4,4")
12054 (set (attr "highpart")
12055 (cond [(match_test "sh_contains_memref_p (insn)")
12056 (const_string "user")]
12057 (const_string "ignore")))])
12058
12059 (define_expand "movv4hi"
12060 [(set (match_operand:V4HI 0 "general_movdst_operand" "")
12061 (match_operand:V4HI 1 "general_movsrc_operand" ""))]
12062 "TARGET_SHMEDIA"
12063 {
12064 prepare_move_operands (operands, V4HImode);
12065 })
12066
12067 (define_insn "movv4hi_i"
12068 [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
12069 (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
12070 "TARGET_SHMEDIA
12071 && (register_operand (operands[0], V4HImode)
12072 || sh_register_operand (operands[1], V4HImode))"
12073 "@
12074 add %1, r63, %0
12075 movi %1, %0
12076 #
12077 ld%M1.q %m1, %0
12078 st%M0.q %m0, %N1"
12079 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
12080 (set_attr "length" "4,4,16,4,4")
12081 (set_attr "highpart" "depend")])
12082
12083 (define_expand "movv2si"
12084 [(set (match_operand:V2SI 0 "general_movdst_operand" "")
12085 (match_operand:V2SI 1 "general_movsrc_operand" ""))]
12086 "TARGET_SHMEDIA"
12087 {
12088 prepare_move_operands (operands, V2SImode);
12089 })
12090
12091 (define_insn "movv2si_i"
12092 [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
12093 (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
12094 "TARGET_SHMEDIA
12095 && (register_operand (operands[0], V2SImode)
12096 || sh_register_operand (operands[1], V2SImode))"
12097 "@
12098 add %1, r63, %0
12099 #
12100 #
12101 ld%M1.q %m1, %0
12102 st%M0.q %m0, %N1"
12103 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
12104 (set_attr "length" "4,4,16,4,4")
12105 (set_attr "highpart" "depend")])
12106
12107 ;; Multimedia Intrinsics
12108
12109 (define_insn "absv2si2"
12110 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12111 (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
12112 "TARGET_SHMEDIA"
12113 "mabs.l %1, %0"
12114 [(set_attr "type" "mcmp_media")
12115 (set_attr "highpart" "depend")])
12116
12117 (define_insn "absv4hi2"
12118 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12119 (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
12120 "TARGET_SHMEDIA"
12121 "mabs.w %1, %0"
12122 [(set_attr "type" "mcmp_media")
12123 (set_attr "highpart" "depend")])
12124
12125 (define_insn "addv2si3"
12126 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12127 (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
12128 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12129 "TARGET_SHMEDIA"
12130 "madd.l %1, %2, %0"
12131 [(set_attr "type" "arith_media")
12132 (set_attr "highpart" "depend")])
12133
12134 (define_insn "addv4hi3"
12135 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12136 (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
12137 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12138 "TARGET_SHMEDIA"
12139 "madd.w %1, %2, %0"
12140 [(set_attr "type" "arith_media")
12141 (set_attr "highpart" "depend")])
12142
12143 (define_insn_and_split "addv2hi3"
12144 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
12145 (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
12146 (match_operand:V2HI 2 "extend_reg_operand" "r")))]
12147 "TARGET_SHMEDIA"
12148 "#"
12149 "TARGET_SHMEDIA"
12150 [(const_int 0)]
12151 {
12152 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
12153 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
12154 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
12155 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
12156 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
12157
12158 emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
12159 emit_insn (gen_truncdisi2 (si_dst, di_dst));
12160 DONE;
12161 }
12162 [(set_attr "highpart" "must_split")])
12163
12164 (define_insn "ssaddv2si3"
12165 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12166 (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
12167 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12168 "TARGET_SHMEDIA"
12169 "madds.l %1, %2, %0"
12170 [(set_attr "type" "mcmp_media")
12171 (set_attr "highpart" "depend")])
12172
12173 (define_insn "usaddv8qi3"
12174 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12175 (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
12176 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
12177 "TARGET_SHMEDIA"
12178 "madds.ub %1, %2, %0"
12179 [(set_attr "type" "mcmp_media")
12180 (set_attr "highpart" "depend")])
12181
12182 (define_insn "ssaddv4hi3"
12183 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12184 (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
12185 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12186 "TARGET_SHMEDIA"
12187 "madds.w %1, %2, %0"
12188 [(set_attr "type" "mcmp_media")
12189 (set_attr "highpart" "depend")])
12190
12191 (define_insn "negcmpeqv8qi"
12192 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12193 (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
12194 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
12195 "TARGET_SHMEDIA"
12196 "mcmpeq.b %N1, %N2, %0"
12197 [(set_attr "type" "mcmp_media")
12198 (set_attr "highpart" "depend")])
12199
12200 (define_insn "negcmpeqv2si"
12201 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12202 (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
12203 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
12204 "TARGET_SHMEDIA"
12205 "mcmpeq.l %N1, %N2, %0"
12206 [(set_attr "type" "mcmp_media")
12207 (set_attr "highpart" "depend")])
12208
12209 (define_insn "negcmpeqv4hi"
12210 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12211 (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
12212 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
12213 "TARGET_SHMEDIA"
12214 "mcmpeq.w %N1, %N2, %0"
12215 [(set_attr "type" "mcmp_media")
12216 (set_attr "highpart" "depend")])
12217
12218 (define_insn "negcmpgtuv8qi"
12219 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12220 (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
12221 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
12222 "TARGET_SHMEDIA"
12223 "mcmpgt.ub %N1, %N2, %0"
12224 [(set_attr "type" "mcmp_media")
12225 (set_attr "highpart" "depend")])
12226
12227 (define_insn "negcmpgtv2si"
12228 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12229 (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
12230 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
12231 "TARGET_SHMEDIA"
12232 "mcmpgt.l %N1, %N2, %0"
12233 [(set_attr "type" "mcmp_media")
12234 (set_attr "highpart" "depend")])
12235
12236 (define_insn "negcmpgtv4hi"
12237 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12238 (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
12239 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
12240 "TARGET_SHMEDIA"
12241 "mcmpgt.w %N1, %N2, %0"
12242 [(set_attr "type" "mcmp_media")
12243 (set_attr "highpart" "depend")])
12244
12245 (define_insn "mcmv"
12246 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12247 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12248 (match_operand:DI 2 "arith_reg_operand" "r"))
12249 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
12250 (not:DI (match_dup 2)))))]
12251 "TARGET_SHMEDIA"
12252 "mcmv %N1, %2, %0"
12253 [(set_attr "type" "arith_media")
12254 (set_attr "highpart" "depend")])
12255
12256 (define_insn "mcnvs_lw"
12257 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12258 (vec_concat:V4HI
12259 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
12260 (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
12261 "TARGET_SHMEDIA"
12262 "mcnvs.lw %N1, %N2, %0"
12263 [(set_attr "type" "mcmp_media")])
12264
12265 (define_insn "mcnvs_wb"
12266 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12267 (vec_concat:V8QI
12268 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
12269 (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
12270 "TARGET_SHMEDIA"
12271 "mcnvs.wb %N1, %N2, %0"
12272 [(set_attr "type" "mcmp_media")])
12273
12274 (define_insn "mcnvs_wub"
12275 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12276 (vec_concat:V8QI
12277 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
12278 (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
12279 "TARGET_SHMEDIA"
12280 "mcnvs.wub %N1, %N2, %0"
12281 [(set_attr "type" "mcmp_media")])
12282
12283 (define_insn "mextr_rl"
12284 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12285 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12286 (match_operand:HI 3 "mextr_bit_offset" "i"))
12287 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12288 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
12289 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
12290 {
12291 static char templ[21];
12292 sprintf (templ, "mextr%d\\t%%N1, %%N2, %%0", (int) INTVAL (operands[3]) >> 3);
12293 return templ;
12294 }
12295 [(set_attr "type" "arith_media")])
12296
12297 (define_insn "*mextr_lr"
12298 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12299 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12300 (match_operand:HI 3 "mextr_bit_offset" "i"))
12301 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12302 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
12303 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
12304 {
12305 static char templ[21];
12306 sprintf (templ, "mextr%d\\t%%N2, %%N1, %%0", (int) INTVAL (operands[4]) >> 3);
12307 return templ;
12308 }
12309 [(set_attr "type" "arith_media")])
12310
12311 ; mextrN can be modelled with vec_select / vec_concat, but the selection
12312 ; vector then varies depending on endianness.
12313 (define_expand "mextr1"
12314 [(match_operand:DI 0 "arith_reg_dest" "")
12315 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12316 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12317 "TARGET_SHMEDIA"
12318 {
12319 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12320 GEN_INT (1 * 8), GEN_INT (7 * 8)));
12321 DONE;
12322 })
12323
12324 (define_expand "mextr2"
12325 [(match_operand:DI 0 "arith_reg_dest" "")
12326 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12327 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12328 "TARGET_SHMEDIA"
12329 {
12330 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12331 GEN_INT (2 * 8), GEN_INT (6 * 8)));
12332 DONE;
12333 })
12334
12335 (define_expand "mextr3"
12336 [(match_operand:DI 0 "arith_reg_dest" "")
12337 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12338 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12339 "TARGET_SHMEDIA"
12340 {
12341 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12342 GEN_INT (3 * 8), GEN_INT (5 * 8)));
12343 DONE;
12344 })
12345
12346 (define_expand "mextr4"
12347 [(match_operand:DI 0 "arith_reg_dest" "")
12348 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12349 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12350 "TARGET_SHMEDIA"
12351 {
12352 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12353 GEN_INT (4 * 8), GEN_INT (4 * 8)));
12354 DONE;
12355 })
12356
12357 (define_expand "mextr5"
12358 [(match_operand:DI 0 "arith_reg_dest" "")
12359 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12360 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12361 "TARGET_SHMEDIA"
12362 {
12363 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12364 GEN_INT (5 * 8), GEN_INT (3 * 8)));
12365 DONE;
12366 })
12367
12368 (define_expand "mextr6"
12369 [(match_operand:DI 0 "arith_reg_dest" "")
12370 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12371 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12372 "TARGET_SHMEDIA"
12373 {
12374 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12375 GEN_INT (6 * 8), GEN_INT (2 * 8)));
12376 DONE;
12377 })
12378
12379 (define_expand "mextr7"
12380 [(match_operand:DI 0 "arith_reg_dest" "")
12381 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12382 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12383 "TARGET_SHMEDIA"
12384 {
12385 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12386 GEN_INT (7 * 8), GEN_INT (1 * 8)));
12387 DONE;
12388 })
12389
12390 (define_expand "mmacfx_wl"
12391 [(match_operand:V2SI 0 "arith_reg_dest" "")
12392 (match_operand:V2HI 1 "extend_reg_operand" "")
12393 (match_operand:V2HI 2 "extend_reg_operand" "")
12394 (match_operand:V2SI 3 "arith_reg_operand" "")]
12395 "TARGET_SHMEDIA"
12396 {
12397 emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
12398 operands[1], operands[2]));
12399 DONE;
12400 })
12401
12402 ;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
12403 ;; is depend
12404 (define_insn "mmacfx_wl_i"
12405 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12406 (ss_plus:V2SI
12407 (match_operand:V2SI 1 "arith_reg_operand" "0")
12408 (ss_truncate:V2SI
12409 (ashift:V2DI
12410 (sign_extend:V2DI
12411 (mult:V2SI
12412 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
12413 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
12414 (const_int 1)))))]
12415 "TARGET_SHMEDIA"
12416 "mmacfx.wl %2, %3, %0"
12417 [(set_attr "type" "mac_media")
12418 (set_attr "highpart" "depend")])
12419
12420 (define_expand "mmacnfx_wl"
12421 [(match_operand:V2SI 0 "arith_reg_dest" "")
12422 (match_operand:V2HI 1 "extend_reg_operand" "")
12423 (match_operand:V2HI 2 "extend_reg_operand" "")
12424 (match_operand:V2SI 3 "arith_reg_operand" "")]
12425 "TARGET_SHMEDIA"
12426 {
12427 emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
12428 operands[1], operands[2]));
12429 DONE;
12430 })
12431
12432 (define_insn "mmacnfx_wl_i"
12433 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12434 (ss_minus:V2SI
12435 (match_operand:V2SI 1 "arith_reg_operand" "0")
12436 (ss_truncate:V2SI
12437 (ashift:V2DI
12438 (sign_extend:V2DI
12439 (mult:V2SI
12440 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
12441 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
12442 (const_int 1)))))]
12443 "TARGET_SHMEDIA"
12444 "mmacnfx.wl %2, %3, %0"
12445 [(set_attr "type" "mac_media")
12446 (set_attr "highpart" "depend")])
12447
12448 (define_insn "mulv2si3"
12449 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12450 (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12451 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12452 "TARGET_SHMEDIA"
12453 "mmul.l %1, %2, %0"
12454 [(set_attr "type" "d2mpy_media")
12455 (set_attr "highpart" "depend")])
12456
12457 (define_insn "mulv4hi3"
12458 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12459 (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12460 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12461 "TARGET_SHMEDIA"
12462 "mmul.w %1, %2, %0"
12463 [(set_attr "type" "dmpy_media")
12464 (set_attr "highpart" "depend")])
12465
12466 (define_insn "mmulfx_l"
12467 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12468 (ss_truncate:V2SI
12469 (ashiftrt:V2DI
12470 (mult:V2DI
12471 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12472 (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
12473 (const_int 31))))]
12474 "TARGET_SHMEDIA"
12475 "mmulfx.l %1, %2, %0"
12476 [(set_attr "type" "d2mpy_media")
12477 (set_attr "highpart" "depend")])
12478
12479 (define_insn "mmulfx_w"
12480 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12481 (ss_truncate:V4HI
12482 (ashiftrt:V4SI
12483 (mult:V4SI
12484 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12485 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12486 (const_int 15))))]
12487 "TARGET_SHMEDIA"
12488 "mmulfx.w %1, %2, %0"
12489 [(set_attr "type" "dmpy_media")
12490 (set_attr "highpart" "depend")])
12491
12492 (define_insn "mmulfxrp_w"
12493 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12494 (ss_truncate:V4HI
12495 (ashiftrt:V4SI
12496 (plus:V4SI
12497 (mult:V4SI
12498 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12499 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12500 (const_int 16384))
12501 (const_int 15))))]
12502 "TARGET_SHMEDIA"
12503 "mmulfxrp.w %1, %2, %0"
12504 [(set_attr "type" "dmpy_media")
12505 (set_attr "highpart" "depend")])
12506
12507
12508 (define_expand "mmulhi_wl"
12509 [(match_operand:V2SI 0 "arith_reg_dest" "")
12510 (match_operand:V4HI 1 "arith_reg_operand" "")
12511 (match_operand:V4HI 2 "arith_reg_operand" "")]
12512 "TARGET_SHMEDIA"
12513 {
12514 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
12515 (operands[0], operands[1], operands[2]));
12516 DONE;
12517 })
12518
12519 (define_expand "mmullo_wl"
12520 [(match_operand:V2SI 0 "arith_reg_dest" "")
12521 (match_operand:V4HI 1 "arith_reg_operand" "")
12522 (match_operand:V4HI 2 "arith_reg_operand" "")]
12523 "TARGET_SHMEDIA"
12524 {
12525 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
12526 (operands[0], operands[1], operands[2]));
12527 DONE;
12528 })
12529
12530 (define_insn "mmul23_wl"
12531 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12532 (vec_select:V2SI
12533 (mult:V4SI
12534 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12535 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12536 (parallel [(const_int 2) (const_int 3)])))]
12537 "TARGET_SHMEDIA"
12538 {
12539 return (TARGET_LITTLE_ENDIAN
12540 ? "mmulhi.wl %1, %2, %0"
12541 : "mmullo.wl %1, %2, %0");
12542 }
12543 [(set_attr "type" "dmpy_media")
12544 (set (attr "highpart")
12545 (cond [(eq_attr "endian" "big") (const_string "ignore")]
12546 (const_string "user")))])
12547
12548 (define_insn "mmul01_wl"
12549 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12550 (vec_select:V2SI
12551 (mult:V4SI
12552 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12553 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12554 (parallel [(const_int 0) (const_int 1)])))]
12555 "TARGET_SHMEDIA"
12556 {
12557 return (TARGET_LITTLE_ENDIAN
12558 ? "mmullo.wl %1, %2, %0"
12559 : "mmulhi.wl %1, %2, %0");
12560 }
12561 [(set_attr "type" "dmpy_media")
12562 (set (attr "highpart")
12563 (cond [(eq_attr "endian" "little") (const_string "ignore")]
12564 (const_string "user")))])
12565
12566
12567 (define_expand "mmulsum_wq"
12568 [(match_operand:DI 0 "arith_reg_dest" "")
12569 (match_operand:V4HI 1 "arith_reg_operand" "")
12570 (match_operand:V4HI 2 "arith_reg_operand" "")
12571 (match_operand:DI 3 "arith_reg_operand" "")]
12572 "TARGET_SHMEDIA"
12573 {
12574 emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
12575 operands[1], operands[2]));
12576 DONE;
12577 })
12578
12579 (define_insn "mmulsum_wq_i"
12580 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12581 (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
12582 (plus:DI
12583 (plus:DI
12584 (vec_select:DI
12585 (mult:V4DI
12586 (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
12587 (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
12588 (parallel [(const_int 0)]))
12589 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12590 (sign_extend:V4DI (match_dup 3)))
12591 (parallel [(const_int 1)])))
12592 (plus:DI
12593 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12594 (sign_extend:V4DI (match_dup 3)))
12595 (parallel [(const_int 2)]))
12596 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12597 (sign_extend:V4DI (match_dup 3)))
12598 (parallel [(const_int 3)]))))))]
12599 "TARGET_SHMEDIA"
12600 "mmulsum.wq %2, %3, %0"
12601 [(set_attr "type" "mac_media")])
12602
12603 (define_expand "mperm_w"
12604 [(match_operand:V4HI 0 "arith_reg_dest" "=r")
12605 (match_operand:V4HI 1 "arith_reg_operand" "r")
12606 (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
12607 "TARGET_SHMEDIA"
12608 {
12609 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
12610 (operands[0], operands[1], operands[2]));
12611 DONE;
12612 })
12613
12614 ; This use of vec_select isn't exactly correct according to rtl.texi
12615 ; (because not constant), but it seems a straightforward extension.
12616 (define_insn "mperm_w_little"
12617 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12618 (vec_select:V4HI
12619 (match_operand:V4HI 1 "arith_reg_operand" "r")
12620 (parallel
12621 [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
12622 (const_int 2) (const_int 0))
12623 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
12624 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
12625 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
12626 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
12627 "mperm.w %1, %N2, %0"
12628 [(set_attr "type" "arith_media")])
12629
12630 (define_insn "mperm_w_big"
12631 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12632 (vec_select:V4HI
12633 (match_operand:V4HI 1 "arith_reg_operand" "r")
12634 (parallel
12635 [(zero_extract:QI (not:QI (match_operand:QI 2
12636 "extend_reg_or_0_operand" "rZ"))
12637 (const_int 2) (const_int 0))
12638 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
12639 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
12640 (zero_extract:QI (not:QI (match_dup 2))
12641 (const_int 2) (const_int 6))])))]
12642 "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
12643 "mperm.w %1, %N2, %0"
12644 [(set_attr "type" "arith_media")])
12645
12646 (define_insn "mperm_w0"
12647 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12648 (vec_duplicate:V4HI (truncate:HI (match_operand 1
12649 "trunc_hi_operand" "r"))))]
12650 "TARGET_SHMEDIA"
12651 "mperm.w %1, r63, %0"
12652 [(set_attr "type" "arith_media")
12653 (set_attr "highpart" "ignore")])
12654
12655 (define_expand "msad_ubq"
12656 [(match_operand:DI 0 "arith_reg_dest" "")
12657 (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
12658 (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
12659 (match_operand:DI 3 "arith_reg_operand" "")]
12660 "TARGET_SHMEDIA"
12661 {
12662 emit_insn (gen_msad_ubq_i (operands[0], operands[3],
12663 operands[1], operands[2]));
12664 DONE;
12665 })
12666
12667 (define_insn "msad_ubq_i"
12668 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12669 (plus:DI
12670 (plus:DI
12671 (plus:DI
12672 (plus:DI
12673 (match_operand:DI 1 "arith_reg_operand" "0")
12674 (abs:DI (vec_select:DI
12675 (minus:V8DI
12676 (zero_extend:V8DI
12677 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12678 (zero_extend:V8DI
12679 (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
12680 (parallel [(const_int 0)]))))
12681 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12682 (zero_extend:V8DI (match_dup 3)))
12683 (parallel [(const_int 1)]))))
12684 (plus:DI
12685 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12686 (zero_extend:V8DI (match_dup 3)))
12687 (parallel [(const_int 2)])))
12688 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12689 (zero_extend:V8DI (match_dup 3)))
12690 (parallel [(const_int 3)])))))
12691 (plus:DI
12692 (plus:DI
12693 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12694 (zero_extend:V8DI (match_dup 3)))
12695 (parallel [(const_int 4)])))
12696 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12697 (zero_extend:V8DI (match_dup 3)))
12698 (parallel [(const_int 5)]))))
12699 (plus:DI
12700 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12701 (zero_extend:V8DI (match_dup 3)))
12702 (parallel [(const_int 6)])))
12703 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12704 (zero_extend:V8DI (match_dup 3)))
12705 (parallel [(const_int 7)])))))))]
12706 "TARGET_SHMEDIA"
12707 "msad.ubq %N2, %N3, %0"
12708 [(set_attr "type" "mac_media")])
12709
12710 (define_insn "mshalds_l"
12711 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12712 (ss_truncate:V2SI
12713 (ashift:V2DI
12714 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12715 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12716 (const_int 31)))))]
12717 "TARGET_SHMEDIA"
12718 "mshalds.l %1, %2, %0"
12719 [(set_attr "type" "mcmp_media")
12720 (set_attr "highpart" "depend")])
12721
12722 (define_insn "mshalds_w"
12723 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12724 (ss_truncate:V4HI
12725 (ashift:V4SI
12726 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12727 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12728 (const_int 15)))))]
12729 "TARGET_SHMEDIA"
12730 "mshalds.w %1, %2, %0"
12731 [(set_attr "type" "mcmp_media")
12732 (set_attr "highpart" "depend")])
12733
12734 (define_insn "ashrv2si3"
12735 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12736 (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12737 (match_operand:DI 2 "arith_reg_operand" "r")))]
12738 "TARGET_SHMEDIA"
12739 "mshard.l %1, %2, %0"
12740 [(set_attr "type" "arith_media")
12741 (set_attr "highpart" "depend")])
12742
12743 (define_insn "ashrv4hi3"
12744 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12745 (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12746 (match_operand:DI 2 "arith_reg_operand" "r")))]
12747 "TARGET_SHMEDIA"
12748 "mshard.w %1, %2, %0"
12749 [(set_attr "type" "arith_media")
12750 (set_attr "highpart" "depend")])
12751
12752 (define_insn "mshards_q"
12753 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
12754 (ss_truncate:HI
12755 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
12756 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
12757 "TARGET_SHMEDIA"
12758 "mshards.q %1, %N2, %0"
12759 [(set_attr "type" "mcmp_media")])
12760
12761 (define_expand "mshfhi_b"
12762 [(match_operand:V8QI 0 "arith_reg_dest" "")
12763 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12764 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12765 "TARGET_SHMEDIA"
12766 {
12767 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
12768 (operands[0], operands[1], operands[2]));
12769 DONE;
12770 })
12771
12772 (define_expand "mshflo_b"
12773 [(match_operand:V8QI 0 "arith_reg_dest" "")
12774 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12775 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12776 "TARGET_SHMEDIA"
12777 {
12778 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
12779 (operands[0], operands[1], operands[2]));
12780 DONE;
12781 })
12782
12783 (define_insn "mshf4_b"
12784 [(set
12785 (match_operand:V8QI 0 "arith_reg_dest" "=r")
12786 (vec_select:V8QI
12787 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12788 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12789 (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
12790 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
12791 "TARGET_SHMEDIA"
12792 {
12793 return (TARGET_LITTLE_ENDIAN
12794 ? "mshfhi.b %N1, %N2, %0"
12795 : "mshflo.b %N1, %N2, %0");
12796 }
12797 [(set_attr "type" "arith_media")
12798 (set (attr "highpart")
12799 (cond [(eq_attr "endian" "big") (const_string "ignore")]
12800 (const_string "user")))])
12801
12802 (define_insn "mshf0_b"
12803 [(set
12804 (match_operand:V8QI 0 "arith_reg_dest" "=r")
12805 (vec_select:V8QI
12806 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12807 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12808 (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
12809 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
12810 "TARGET_SHMEDIA"
12811 {
12812 return (TARGET_LITTLE_ENDIAN
12813 ? "mshflo.b %N1, %N2, %0"
12814 : "mshfhi.b %N1, %N2, %0");
12815 }
12816 [(set_attr "type" "arith_media")
12817 (set (attr "highpart")
12818 (cond [(eq_attr "endian" "little") (const_string "ignore")]
12819 (const_string "user")))])
12820
12821 (define_expand "mshfhi_l"
12822 [(match_operand:V2SI 0 "arith_reg_dest" "")
12823 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12824 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12825 "TARGET_SHMEDIA"
12826 {
12827 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
12828 (operands[0], operands[1], operands[2]));
12829 DONE;
12830 })
12831
12832 (define_expand "mshflo_l"
12833 [(match_operand:V2SI 0 "arith_reg_dest" "")
12834 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12835 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12836 "TARGET_SHMEDIA"
12837 {
12838 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
12839 (operands[0], operands[1], operands[2]));
12840 DONE;
12841 })
12842
12843 (define_insn "mshf4_l"
12844 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12845 (vec_select:V2SI
12846 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12847 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12848 (parallel [(const_int 1) (const_int 3)])))]
12849 "TARGET_SHMEDIA"
12850 {
12851 return (TARGET_LITTLE_ENDIAN
12852 ? "mshfhi.l %N1, %N2, %0"
12853 : "mshflo.l %N1, %N2, %0");
12854 }
12855 [(set_attr "type" "arith_media")
12856 (set (attr "highpart")
12857 (cond [(eq_attr "endian" "big") (const_string "ignore")]
12858 (const_string "user")))])
12859
12860 (define_insn "mshf0_l"
12861 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12862 (vec_select:V2SI
12863 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12864 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12865 (parallel [(const_int 0) (const_int 2)])))]
12866 "TARGET_SHMEDIA"
12867 {
12868 return (TARGET_LITTLE_ENDIAN
12869 ? "mshflo.l %N1, %N2, %0"
12870 : "mshfhi.l %N1, %N2, %0");
12871 }
12872 [(set_attr "type" "arith_media")
12873 (set (attr "highpart")
12874 (cond [(eq_attr "endian" "little") (const_string "ignore")]
12875 (const_string "user")))])
12876
12877 (define_expand "mshfhi_w"
12878 [(match_operand:V4HI 0 "arith_reg_dest" "")
12879 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12880 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12881 "TARGET_SHMEDIA"
12882 {
12883 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
12884 (operands[0], operands[1], operands[2]));
12885 DONE;
12886 })
12887
12888 (define_expand "mshflo_w"
12889 [(match_operand:V4HI 0 "arith_reg_dest" "")
12890 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12891 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12892 "TARGET_SHMEDIA"
12893 {
12894 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
12895 (operands[0], operands[1], operands[2]));
12896 DONE;
12897 })
12898
12899 (define_insn "mshf4_w"
12900 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12901 (vec_select:V4HI
12902 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12903 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12904 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
12905 "TARGET_SHMEDIA"
12906 {
12907 return (TARGET_LITTLE_ENDIAN
12908 ? "mshfhi.w %N1, %N2, %0"
12909 : "mshflo.w %N1, %N2, %0");
12910 }
12911 [(set_attr "type" "arith_media")
12912 (set (attr "highpart")
12913 (cond [(eq_attr "endian" "big") (const_string "ignore")]
12914 (const_string "user")))])
12915
12916 (define_insn "mshf0_w"
12917 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12918 (vec_select:V4HI
12919 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12920 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12921 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
12922 "TARGET_SHMEDIA"
12923 {
12924 return (TARGET_LITTLE_ENDIAN
12925 ? "mshflo.w %N1, %N2, %0"
12926 : "mshfhi.w %N1, %N2, %0");
12927 }
12928 [(set_attr "type" "arith_media")
12929 (set (attr "highpart")
12930 (cond [(eq_attr "endian" "little") (const_string "ignore")]
12931 (const_string "user")))])
12932
12933 (define_insn "mshflo_w_x"
12934 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12935 (vec_select:V4HI
12936 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
12937 (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
12938 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
12939 "TARGET_SHMEDIA"
12940 "mshflo.w %N1, %N2, %0"
12941 [(set_attr "type" "arith_media")
12942 (set_attr "highpart" "ignore")])
12943
12944 ;; These are useful to expand ANDs and as combiner patterns.
12945 (define_insn_and_split "mshfhi_l_di"
12946 [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
12947 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
12948 (const_int 32))
12949 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
12950 (const_int -4294967296))))]
12951 "TARGET_SHMEDIA"
12952 "@
12953 mshfhi.l %N1, %N2, %0
12954 #"
12955 "TARGET_SHMEDIA && reload_completed
12956 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12957 [(set (match_dup 3) (match_dup 4))
12958 (set (match_dup 5) (match_dup 6))]
12959 {
12960 operands[3] = gen_lowpart (SImode, operands[0]);
12961 operands[4] = gen_highpart (SImode, operands[1]);
12962 operands[5] = gen_highpart (SImode, operands[0]);
12963 operands[6] = gen_highpart (SImode, operands[2]);
12964 }
12965 [(set_attr "type" "arith_media")])
12966
12967 (define_insn "*mshfhi_l_di_rev"
12968 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12969 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12970 (const_int -4294967296))
12971 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12972 (const_int 32))))]
12973 "TARGET_SHMEDIA"
12974 "mshfhi.l %N2, %N1, %0"
12975 [(set_attr "type" "arith_media")])
12976
12977 (define_split
12978 [(set (match_operand:DI 0 "arith_reg_dest" "")
12979 (ior:DI (zero_extend:DI (match_operand:SI 1
12980 "extend_reg_or_0_operand" ""))
12981 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
12982 (const_int -4294967296))))
12983 (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
12984 "TARGET_SHMEDIA"
12985 [(const_int 0)]
12986 {
12987 emit_insn (gen_ashldi3_media (operands[3],
12988 simplify_gen_subreg (DImode, operands[1],
12989 SImode, 0),
12990 GEN_INT (32)));
12991 emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
12992 DONE;
12993 })
12994
12995 (define_insn "mshflo_l_di"
12996 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12997 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12998 (const_int 4294967295))
12999 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
13000 (const_int 32))))]
13001
13002 "TARGET_SHMEDIA"
13003 "mshflo.l %N1, %N2, %0"
13004 [(set_attr "type" "arith_media")
13005 (set_attr "highpart" "ignore")])
13006
13007 (define_insn "*mshflo_l_di_rev"
13008 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13009 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13010 (const_int 32))
13011 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
13012 (const_int 4294967295))))]
13013
13014 "TARGET_SHMEDIA"
13015 "mshflo.l %N2, %N1, %0"
13016 [(set_attr "type" "arith_media")
13017 (set_attr "highpart" "ignore")])
13018
13019 ;; Combiner pattern for trampoline initialization.
13020 (define_insn_and_split "*double_shori"
13021 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13022 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
13023 (const_int 32))
13024 (match_operand:DI 2 "const_int_operand" "n")))]
13025 "TARGET_SHMEDIA
13026 && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
13027 "#"
13028 "rtx_equal_p (operands[0], operands[1])"
13029 [(const_int 0)]
13030 {
13031 HOST_WIDE_INT v = INTVAL (operands[2]);
13032
13033 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
13034 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
13035 DONE;
13036 }
13037 [(set_attr "highpart" "ignore")])
13038
13039
13040 (define_insn "*mshflo_l_di_x"
13041 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13042 (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
13043 "rZ"))
13044 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
13045 (const_int 32))))]
13046
13047 "TARGET_SHMEDIA"
13048 "mshflo.l %N1, %N2, %0"
13049 [(set_attr "type" "arith_media")
13050 (set_attr "highpart" "ignore")])
13051
13052 (define_insn_and_split "concat_v2sf"
13053 [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
13054 ;; (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
13055 (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
13056 (match_operand:SF 2 "register_operand" "rZ,f,f")))]
13057
13058 "TARGET_SHMEDIA"
13059 "@
13060 mshflo.l %N1, %N2, %0
13061 #
13062 #"
13063 "TARGET_SHMEDIA && reload_completed
13064 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
13065 [(set (match_dup 3) (match_dup 1))
13066 (set (match_dup 4) (match_dup 2))]
13067 {
13068 operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
13069 operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
13070 }
13071 [(set_attr "type" "arith_media")
13072 (set_attr "highpart" "ignore")])
13073
13074 (define_insn "*mshflo_l_di_x_rev"
13075 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13076 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13077 (const_int 32))
13078 (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
13079
13080 "TARGET_SHMEDIA"
13081 "mshflo.l %N2, %N1, %0"
13082 [(set_attr "type" "arith_media")
13083 (set_attr "highpart" "ignore")])
13084
13085 (define_insn "ashlv2si3"
13086 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13087 (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
13088 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
13089 "TARGET_SHMEDIA"
13090 "mshlld.l %1, %2, %0"
13091 [(set_attr "type" "arith_media")
13092 (set_attr "highpart" "depend")])
13093
13094 (define_split
13095 [(set (match_operand 0 "any_register_operand" "")
13096 (match_operator 3 "shift_operator"
13097 [(match_operand 1 "any_register_operand" "")
13098 (match_operand 2 "shift_count_reg_operand" "")]))]
13099 "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
13100 [(set (match_dup 0) (match_dup 3))]
13101 {
13102 rtx count = operands[2];
13103 enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
13104
13105 while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
13106 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
13107 || GET_CODE (count) == TRUNCATE)
13108 count = XEXP (count, 0);
13109 inner_mode = GET_MODE (count);
13110 count = simplify_gen_subreg (outer_mode, count, inner_mode,
13111 subreg_lowpart_offset (outer_mode, inner_mode));
13112 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
13113 operands[1], count);
13114 })
13115
13116 (define_insn "ashlv4hi3"
13117 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13118 (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
13119 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
13120 "TARGET_SHMEDIA"
13121 "mshlld.w %1, %2, %0"
13122 [(set_attr "type" "arith_media")
13123 (set_attr "highpart" "depend")])
13124
13125 (define_insn "lshrv2si3"
13126 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13127 (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
13128 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
13129 "TARGET_SHMEDIA"
13130 "mshlrd.l %1, %2, %0"
13131 [(set_attr "type" "arith_media")
13132 (set_attr "highpart" "depend")])
13133
13134 (define_insn "lshrv4hi3"
13135 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13136 (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
13137 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
13138 "TARGET_SHMEDIA"
13139 "mshlrd.w %1, %2, %0"
13140 [(set_attr "type" "arith_media")
13141 (set_attr "highpart" "depend")])
13142
13143 (define_insn "subv2si3"
13144 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13145 (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
13146 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
13147 "TARGET_SHMEDIA"
13148 "msub.l %N1, %2, %0"
13149 [(set_attr "type" "arith_media")
13150 (set_attr "highpart" "depend")])
13151
13152 (define_insn "subv4hi3"
13153 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13154 (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
13155 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
13156 "TARGET_SHMEDIA"
13157 "msub.w %N1, %2, %0"
13158 [(set_attr "type" "arith_media")
13159 (set_attr "highpart" "depend")])
13160
13161 (define_insn_and_split "subv2hi3"
13162 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
13163 (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
13164 (match_operand:V2HI 2 "arith_reg_operand" "r")))]
13165 "TARGET_SHMEDIA"
13166 "#"
13167 "TARGET_SHMEDIA"
13168 [(const_int 0)]
13169 {
13170 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
13171 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
13172 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
13173 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
13174 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
13175
13176 emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
13177 emit_insn (gen_truncdisi2 (si_dst, di_dst));
13178 DONE;
13179 }
13180 [(set_attr "highpart" "must_split")])
13181
13182 (define_insn "sssubv2si3"
13183 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13184 (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
13185 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
13186 "TARGET_SHMEDIA"
13187 "msubs.l %N1, %2, %0"
13188 [(set_attr "type" "mcmp_media")
13189 (set_attr "highpart" "depend")])
13190
13191 (define_insn "ussubv8qi3"
13192 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13193 (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
13194 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
13195 "TARGET_SHMEDIA"
13196 "msubs.ub %N1, %2, %0"
13197 [(set_attr "type" "mcmp_media")
13198 (set_attr "highpart" "depend")])
13199
13200 (define_insn "sssubv4hi3"
13201 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13202 (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
13203 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
13204 "TARGET_SHMEDIA"
13205 "msubs.w %N1, %2, %0"
13206 [(set_attr "type" "mcmp_media")
13207 (set_attr "highpart" "depend")])
13208
13209 ;; Floating Point Intrinsics
13210
13211 (define_insn "fcosa_s"
13212 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13213 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
13214 UNSPEC_FCOSA))]
13215 "TARGET_SHMEDIA"
13216 "fcosa.s %1, %0"
13217 [(set_attr "type" "atrans_media")])
13218
13219 (define_insn "fsina_s"
13220 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13221 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
13222 UNSPEC_FSINA))]
13223 "TARGET_SHMEDIA"
13224 "fsina.s %1, %0"
13225 [(set_attr "type" "atrans_media")])
13226
13227 (define_insn "fipr"
13228 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13229 (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
13230 "fp_arith_reg_operand" "f")
13231 (match_operand:V4SF 2
13232 "fp_arith_reg_operand" "f"))
13233 (parallel [(const_int 0)]))
13234 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
13235 (parallel [(const_int 1)])))
13236 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
13237 (parallel [(const_int 2)]))
13238 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
13239 (parallel [(const_int 3)])))))]
13240 "TARGET_SHMEDIA"
13241 "fipr.s %1, %2, %0"
13242 [(set_attr "type" "fparith_media")])
13243
13244 (define_insn "fsrra_s"
13245 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13246 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
13247 UNSPEC_FSRRA))]
13248 "TARGET_SHMEDIA"
13249 "fsrra.s %1, %0"
13250 [(set_attr "type" "atrans_media")])
13251
13252 (define_insn "ftrv"
13253 [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
13254 (plus:V4SF
13255 (plus:V4SF
13256 (mult:V4SF
13257 (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
13258 (parallel [(const_int 0) (const_int 5)
13259 (const_int 10) (const_int 15)]))
13260 (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
13261 (mult:V4SF
13262 (vec_select:V4SF (match_dup 1)
13263 (parallel [(const_int 4) (const_int 9)
13264 (const_int 14) (const_int 3)]))
13265 (vec_select:V4SF (match_dup 2)
13266 (parallel [(const_int 1) (const_int 2)
13267 (const_int 3) (const_int 0)]))))
13268 (plus:V4SF
13269 (mult:V4SF
13270 (vec_select:V4SF (match_dup 1)
13271 (parallel [(const_int 8) (const_int 13)
13272 (const_int 2) (const_int 7)]))
13273 (vec_select:V4SF (match_dup 2)
13274 (parallel [(const_int 2) (const_int 3)
13275 (const_int 0) (const_int 1)])))
13276 (mult:V4SF
13277 (vec_select:V4SF (match_dup 1)
13278 (parallel [(const_int 12) (const_int 1)
13279 (const_int 6) (const_int 11)]))
13280 (vec_select:V4SF (match_dup 2)
13281 (parallel [(const_int 3) (const_int 0)
13282 (const_int 1) (const_int 2)]))))))]
13283 "TARGET_SHMEDIA"
13284 "ftrv.s %1, %2, %0"
13285 [(set_attr "type" "fparith_media")])
13286
13287 (define_insn "ldhi_l"
13288 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13289 (zero_extract:SI
13290 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
13291 (const_int 3))
13292 (const_int -3)))
13293 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
13294 (const_int 0)))]
13295 "TARGET_SHMEDIA32"
13296 "ldhi.l %U1, %0"
13297 [(set_attr "type" "load_media")])
13298
13299 (define_insn "ldhi_q"
13300 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13301 (zero_extract:DI
13302 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
13303 (const_int 7))
13304 (const_int -7)))
13305 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
13306 (const_int 0)))]
13307 "TARGET_SHMEDIA32"
13308 "ldhi.q %U1, %0"
13309 [(set_attr "type" "load_media")])
13310
13311 (define_insn_and_split "*ldhi_q_comb0"
13312 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13313 (zero_extract:DI
13314 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
13315 "register_operand" "r")
13316 (match_operand:SI 2
13317 "ua_offset" "I06"))
13318 (const_int 7))
13319 (const_int -7)))
13320 (plus:SI (and:SI (match_dup 1) (const_int 7))
13321 (const_int 1))
13322 (const_int 0)))]
13323 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
13324 "#"
13325 ""
13326 [(pc)]
13327 {
13328 emit_insn (gen_ldhi_q (operands[0],
13329 gen_rtx_PLUS (SImode, operands[1], operands[2])));
13330 DONE;
13331 })
13332
13333 (define_insn_and_split "*ldhi_q_comb1"
13334 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13335 (zero_extract:DI
13336 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
13337 "register_operand" "r")
13338 (match_operand:SI 2
13339 "ua_offset" "I06"))
13340 (const_int 7))
13341 (const_int -7)))
13342 (plus:SI (and:SI (plus:SI (match_dup 1) (match_operand:SI 3
13343 "ua_offset" "I06"))
13344 (const_int 7))
13345 (const_int 1))
13346 (const_int 0)))]
13347 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
13348 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
13349 "#"
13350 ""
13351 [(pc)]
13352 {
13353 emit_insn (gen_ldhi_q (operands[0],
13354 gen_rtx_PLUS (SImode, operands[1], operands[2])));
13355 DONE;
13356 })
13357
13358 (define_insn "ldlo_l"
13359 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13360 (zero_extract:SI
13361 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
13362 (const_int -4)))
13363 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
13364 (and:SI (match_dup 1) (const_int 3))))]
13365 "TARGET_SHMEDIA32"
13366 "ldlo.l %U1, %0"
13367 [(set_attr "type" "load_media")])
13368
13369 (define_insn "ldlo_q"
13370 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13371 (zero_extract:DI
13372 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
13373 (const_int -8)))
13374 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
13375 (and:SI (match_dup 1) (const_int 7))))]
13376 "TARGET_SHMEDIA32"
13377 "ldlo.q %U1, %0"
13378 [(set_attr "type" "load_media")])
13379
13380 (define_insn_and_split "*ldlo_q_comb0"
13381 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13382 (zero_extract:DI
13383 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
13384 (match_operand:SI 2 "ua_offset" "I06"))
13385 (const_int -8)))
13386 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
13387 (and:SI (match_dup 1) (const_int 7))))]
13388 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
13389 "#"
13390 ""
13391 [(pc)]
13392 {
13393 emit_insn (gen_ldlo_q (operands[0],
13394 gen_rtx_PLUS (SImode, operands[1], operands[2])));
13395 DONE;
13396 })
13397
13398 (define_insn_and_split "*ldlo_q_comb1"
13399 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13400 (zero_extract:DI
13401 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
13402 (match_operand:SI 2 "ua_offset" "I06"))
13403 (const_int -8)))
13404 (minus:SI (const_int 8)
13405 (and:SI (plus:SI (match_dup 1)
13406 (match_operand:SI 3 "ua_offset" "I06"))
13407 (const_int 7)))
13408 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
13409 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
13410 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
13411 "#"
13412 ""
13413 [(pc)]
13414 {
13415 emit_insn (gen_ldlo_q (operands[0],
13416 gen_rtx_PLUS (SImode, operands[1], operands[2])));
13417 DONE;
13418 })
13419
13420 (define_insn "sthi_l"
13421 [(set (zero_extract:SI
13422 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
13423 (const_int 3))
13424 (const_int -3)))
13425 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
13426 (const_int 0))
13427 (match_operand:SI 1 "arith_reg_operand" "r"))]
13428 "TARGET_SHMEDIA32"
13429 "sthi.l %U0, %1"
13430 [(set_attr "type" "ustore_media")])
13431
13432 ;; All unaligned stores are considered to be 'narrow' because they typically
13433 ;; operate on less that a quadword, and when they operate on a full quadword,
13434 ;; the vanilla store high / store low sequence will cause a stall if not
13435 ;; scheduled apart.
13436 (define_insn "sthi_q"
13437 [(set (zero_extract:DI
13438 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
13439 (const_int 7))
13440 (const_int -7)))
13441 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
13442 (const_int 0))
13443 (match_operand:DI 1 "arith_reg_operand" "r"))]
13444 "TARGET_SHMEDIA32"
13445 "sthi.q %U0, %1"
13446 [(set_attr "type" "ustore_media")])
13447
13448 (define_insn_and_split "*sthi_q_comb0"
13449 [(set (zero_extract:DI
13450 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
13451 "register_operand" "r")
13452 (match_operand:SI 1 "ua_offset"
13453 "I06"))
13454 (const_int 7))
13455 (const_int -7)))
13456 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
13457 (const_int 0))
13458 (match_operand:DI 2 "arith_reg_operand" "r"))]
13459 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
13460 "#"
13461 ""
13462 [(pc)]
13463 {
13464 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13465 operands[2]));
13466 DONE;
13467 })
13468
13469 (define_insn_and_split "*sthi_q_comb1"
13470 [(set (zero_extract:DI
13471 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
13472 "register_operand" "r")
13473 (match_operand:SI 1 "ua_offset"
13474 "I06"))
13475 (const_int 7))
13476 (const_int -7)))
13477 (plus:SI (and:SI (plus:SI (match_dup 0)
13478 (match_operand:SI 2 "ua_offset" "I06"))
13479 (const_int 7))
13480 (const_int 1))
13481 (const_int 0))
13482 (match_operand:DI 3 "arith_reg_operand" "r"))]
13483 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
13484 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
13485 "#"
13486 ""
13487 [(pc)]
13488 {
13489 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13490 operands[3]));
13491 DONE;
13492 })
13493
13494 ;; This is highpart user because the address is used as full 64 bit.
13495 (define_insn "stlo_l"
13496 [(set (zero_extract:SI
13497 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
13498 (const_int -4)))
13499 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
13500 (and:SI (match_dup 0) (const_int 3)))
13501 (match_operand:SI 1 "arith_reg_operand" "r"))]
13502 "TARGET_SHMEDIA32"
13503 "stlo.l %U0, %1"
13504 [(set_attr "type" "ustore_media")])
13505
13506 (define_insn "stlo_q"
13507 [(set (zero_extract:DI
13508 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
13509 (const_int -8)))
13510 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
13511 (and:SI (match_dup 0) (const_int 7)))
13512 (match_operand:DI 1 "arith_reg_operand" "r"))]
13513 "TARGET_SHMEDIA32"
13514 "stlo.q %U0, %1"
13515 [(set_attr "type" "ustore_media")])
13516
13517 (define_insn_and_split "*stlo_q_comb0"
13518 [(set (zero_extract:DI
13519 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
13520 (match_operand:SI 1 "ua_offset" "I06"))
13521 (const_int -8)))
13522 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
13523 (and:SI (match_dup 0) (const_int 7)))
13524 (match_operand:DI 2 "arith_reg_operand" "r"))]
13525 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
13526 "#"
13527 ""
13528 [(pc)]
13529 {
13530 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13531 operands[2]));
13532 DONE;
13533 })
13534
13535 (define_insn_and_split "*stlo_q_comb1"
13536 [(set (zero_extract:DI
13537 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
13538 (match_operand:SI 1 "ua_offset" "I06"))
13539 (const_int -8)))
13540 (minus:SI (const_int 8) (and:SI (plus:SI (match_dup 0)
13541 (match_operand:SI 2
13542 "ua_offset" "I06"))
13543 (const_int 7)))
13544 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
13545 (match_operand:DI 3 "arith_reg_operand" "r"))]
13546 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
13547 "#"
13548 ""
13549 [(pc)]
13550 {
13551 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13552 operands[3]));
13553 DONE;
13554 })
13555
13556 (define_insn "ldhi_l64"
13557 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13558 (zero_extract:SI
13559 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13560 (const_int 3))
13561 (const_int -3)))
13562 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
13563 (const_int 0)))]
13564 "TARGET_SHMEDIA64"
13565 "ldhi.l %U1, %0"
13566 [(set_attr "type" "load_media")])
13567
13568 (define_insn "ldhi_q64"
13569 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13570 (zero_extract:DI
13571 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13572 (const_int 7))
13573 (const_int -7)))
13574 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
13575 (const_int 0)))]
13576 "TARGET_SHMEDIA64"
13577 "ldhi.q %U1, %0"
13578 [(set_attr "type" "load_media")])
13579
13580 (define_insn "ldlo_l64"
13581 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13582 (zero_extract:SI
13583 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13584 (const_int -4)))
13585 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
13586 (and:DI (match_dup 1) (const_int 3))))]
13587 "TARGET_SHMEDIA64"
13588 "ldlo.l %U1, %0"
13589 [(set_attr "type" "load_media")])
13590
13591 (define_insn "ldlo_q64"
13592 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13593 (zero_extract:DI
13594 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13595 (const_int -8)))
13596 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
13597 (and:DI (match_dup 1) (const_int 7))))]
13598 "TARGET_SHMEDIA64"
13599 "ldlo.q %U1, %0"
13600 [(set_attr "type" "load_media")])
13601
13602 (define_insn "sthi_l64"
13603 [(set (zero_extract:SI
13604 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13605 (const_int 3))
13606 (const_int -3)))
13607 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
13608 (const_int 0))
13609 (match_operand:SI 1 "arith_reg_operand" "r"))]
13610 "TARGET_SHMEDIA64"
13611 "sthi.l %U0, %1"
13612 [(set_attr "type" "ustore_media")])
13613
13614 (define_insn "sthi_q64"
13615 [(set (zero_extract:DI
13616 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13617 (const_int 7))
13618 (const_int -7)))
13619 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
13620 (const_int 0))
13621 (match_operand:DI 1 "arith_reg_operand" "r"))]
13622 "TARGET_SHMEDIA64"
13623 "sthi.q %U0, %1"
13624 [(set_attr "type" "ustore_media")])
13625
13626 (define_insn "stlo_l64"
13627 [(set (zero_extract:SI
13628 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13629 (const_int -4)))
13630 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
13631 (and:DI (match_dup 0) (const_int 3)))
13632 (match_operand:SI 1 "arith_reg_operand" "r"))]
13633 "TARGET_SHMEDIA64"
13634 "stlo.l %U0, %1"
13635 [(set_attr "type" "ustore_media")])
13636
13637 (define_insn "stlo_q64"
13638 [(set (zero_extract:DI
13639 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13640 (const_int -8)))
13641 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
13642 (and:DI (match_dup 0) (const_int 7)))
13643 (match_operand:DI 1 "arith_reg_operand" "r"))]
13644 "TARGET_SHMEDIA64"
13645 "stlo.q %U0, %1"
13646 [(set_attr "type" "ustore_media")])
13647
13648 (define_insn "nsb"
13649 [(set (match_operand:QI 0 "arith_reg_dest" "=r")
13650 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13651 UNSPEC_NSB))]
13652 "TARGET_SHMEDIA"
13653 "nsb %1, %0"
13654 [(set_attr "type" "arith_media")])
13655
13656 (define_insn "nsbsi"
13657 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13658 (zero_extend:SI
13659 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13660 UNSPEC_NSB)))]
13661 "TARGET_SHMEDIA"
13662 "nsb %1, %0"
13663 [(set_attr "type" "arith_media")])
13664
13665 (define_insn "nsbdi"
13666 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13667 (zero_extend:DI
13668 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13669 UNSPEC_NSB)))]
13670 "TARGET_SHMEDIA"
13671 "nsb %1, %0"
13672 [(set_attr "type" "arith_media")])
13673
13674 (define_expand "ffsdi2"
13675 [(set (match_operand:DI 0 "arith_reg_dest" "")
13676 (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
13677 "TARGET_SHMEDIA"
13678 {
13679 rtx scratch = gen_reg_rtx (DImode);
13680 rtx last;
13681
13682 emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
13683 emit_insn (gen_xordi3 (scratch, operands[1], scratch));
13684 emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
13685 emit_insn (gen_nsbdi (scratch, scratch));
13686 emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
13687 emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
13688 last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
13689 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
13690
13691 DONE;
13692 })
13693
13694 (define_expand "ffssi2"
13695 [(set (match_operand:SI 0 "arith_reg_dest" "")
13696 (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
13697 "TARGET_SHMEDIA"
13698 {
13699 rtx scratch = gen_reg_rtx (SImode);
13700 rtx discratch = gen_reg_rtx (DImode);
13701 rtx last;
13702
13703 emit_insn (gen_adddi3 (discratch,
13704 simplify_gen_subreg (DImode, operands[1], SImode, 0),
13705 constm1_rtx));
13706 emit_insn (gen_andcdi3 (discratch,
13707 simplify_gen_subreg (DImode, operands[1], SImode, 0),
13708 discratch));
13709 emit_insn (gen_nsbsi (scratch, discratch));
13710 last = emit_insn (gen_subsi3 (operands[0],
13711 force_reg (SImode, GEN_INT (63)), scratch));
13712 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
13713
13714 DONE;
13715 })
13716
13717 (define_insn "byterev"
13718 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13719 (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
13720 (parallel [(const_int 7) (const_int 6) (const_int 5)
13721 (const_int 4) (const_int 3) (const_int 2)
13722 (const_int 1) (const_int 0)])))]
13723 "TARGET_SHMEDIA"
13724 "byterev %1, %0"
13725 [(set_attr "type" "arith_media")])
13726
13727 (define_insn "*prefetch_media"
13728 [(prefetch (match_operand:QI 0 "address_operand" "p")
13729 (match_operand:SI 1 "const_int_operand" "n")
13730 (match_operand:SI 2 "const_int_operand" "n"))]
13731 "TARGET_SHMEDIA"
13732 {
13733 operands[0] = gen_rtx_MEM (QImode, operands[0]);
13734 output_asm_insn ("ld%M0.b %m0,r63", operands);
13735 return "";
13736 }
13737 [(set_attr "type" "other")])
13738
13739 ;; In user mode, the "pref" instruction will raise a RADDERR exception
13740 ;; for accesses to [0x80000000,0xffffffff]. This makes it an unsuitable
13741 ;; implementation of __builtin_prefetch for VxWorks RTPs.
13742 (define_expand "prefetch"
13743 [(prefetch (match_operand 0 "address_operand" "p")
13744 (match_operand:SI 1 "const_int_operand" "n")
13745 (match_operand:SI 2 "const_int_operand" "n"))]
13746 "TARGET_SH2A || ((TARGET_HARD_SH4 || TARGET_SH5)
13747 && (TARGET_SHMEDIA || !TARGET_VXWORKS_RTP))"
13748 {
13749 if (GET_MODE (operands[0]) != Pmode
13750 || !CONST_INT_P (operands[1])
13751 || !CONST_INT_P (operands[2]))
13752 FAIL;
13753 if (! TARGET_SHMEDIA)
13754 operands[0] = force_reg (Pmode, operands[0]);
13755 })
13756
13757 (define_insn "*prefetch"
13758 [(prefetch (match_operand:SI 0 "register_operand" "r")
13759 (match_operand:SI 1 "const_int_operand" "n")
13760 (match_operand:SI 2 "const_int_operand" "n"))]
13761 "(TARGET_SH2A || TARGET_HARD_SH4 || TARGET_SHCOMPACT) && !TARGET_VXWORKS_RTP"
13762 "pref @%0"
13763 [(set_attr "type" "other")])
13764
13765 (define_insn "alloco_i"
13766 [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
13767 (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
13768 "TARGET_SHMEDIA32"
13769 {
13770 rtx xops[2];
13771
13772 if (GET_CODE (operands[0]) == PLUS)
13773 {
13774 xops[0] = XEXP (operands[0], 0);
13775 xops[1] = XEXP (operands[0], 1);
13776 }
13777 else
13778 {
13779 xops[0] = operands[0];
13780 xops[1] = const0_rtx;
13781 }
13782 output_asm_insn ("alloco %0, %1", xops);
13783 return "";
13784 }
13785 [(set_attr "type" "other")])
13786
13787 (define_split
13788 [(set (match_operand 0 "any_register_operand" "")
13789 (match_operand 1 "" ""))]
13790 "TARGET_SHMEDIA && reload_completed"
13791 [(set (match_dup 0) (match_dup 1))]
13792 {
13793 int n_changes = 0;
13794
13795 for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
13796 if (!n_changes)
13797 FAIL;
13798 })
13799
13800 ; Stack Protector Patterns
13801
13802 (define_expand "stack_protect_set"
13803 [(set (match_operand 0 "memory_operand" "")
13804 (match_operand 1 "memory_operand" ""))]
13805 ""
13806 {
13807 if (TARGET_SHMEDIA)
13808 {
13809 if (TARGET_SHMEDIA64)
13810 emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
13811 else
13812 emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
13813 }
13814 else
13815 emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
13816
13817 DONE;
13818 })
13819
13820 (define_insn "stack_protect_set_si"
13821 [(set (match_operand:SI 0 "memory_operand" "=m")
13822 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13823 (set (match_scratch:SI 2 "=&r") (const_int 0))]
13824 "!TARGET_SHMEDIA"
13825 "mov.l\t%1, %2\;mov.l\t%2, %0\;mov\t#0, %2"
13826 [(set_attr "type" "other")
13827 (set_attr "length" "6")])
13828
13829 (define_insn "stack_protect_set_si_media"
13830 [(set (match_operand:SI 0 "memory_operand" "=m")
13831 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13832 (set (match_scratch:SI 2 "=&r") (const_int 0))]
13833 "TARGET_SHMEDIA"
13834 "ld%M1.l\t%m1, %2\;st%M0.l\t%m0, %2\;movi\t0, %2"
13835 [(set_attr "type" "other")
13836 (set_attr "length" "12")])
13837
13838 (define_insn "stack_protect_set_di_media"
13839 [(set (match_operand:DI 0 "memory_operand" "=m")
13840 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13841 (set (match_scratch:DI 2 "=&r") (const_int 0))]
13842 "TARGET_SHMEDIA64"
13843 "ld%M1.q\t%m1, %2\;st%M0.q\t%m0, %2\;movi\t0, %2"
13844 [(set_attr "type" "other")
13845 (set_attr "length" "12")])
13846
13847 (define_expand "stack_protect_test"
13848 [(match_operand 0 "memory_operand" "")
13849 (match_operand 1 "memory_operand" "")
13850 (match_operand 2 "" "")]
13851 ""
13852 {
13853 if (TARGET_SHMEDIA)
13854 {
13855 rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
13856 rtx test;
13857
13858 test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
13859 if (TARGET_SHMEDIA64)
13860 {
13861 emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
13862 operands[1]));
13863 emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
13864 }
13865 else
13866 {
13867 emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
13868 operands[1]));
13869 emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
13870 }
13871 }
13872 else
13873 {
13874 emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
13875 emit_jump_insn (gen_branch_true (operands[2], get_t_reg_rtx ()));
13876 }
13877
13878 DONE;
13879 })
13880
13881 (define_insn "stack_protect_test_si"
13882 [(set (reg:SI T_REG)
13883 (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
13884 (match_operand:SI 1 "memory_operand" "m")]
13885 UNSPEC_SP_TEST))
13886 (set (match_scratch:SI 2 "=&r") (const_int 0))
13887 (set (match_scratch:SI 3 "=&r") (const_int 0))]
13888 "!TARGET_SHMEDIA"
13889 "mov.l\t%0, %2\;mov.l\t%1, %3\;cmp/eq\t%2, %3\;mov\t#0, %2\;mov\t#0, %3"
13890 [(set_attr "type" "other")
13891 (set_attr "length" "10")])
13892
13893 (define_insn "stack_protect_test_si_media"
13894 [(set (match_operand:SI 0 "register_operand" "=&r")
13895 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
13896 (match_operand:SI 2 "memory_operand" "m")]
13897 UNSPEC_SP_TEST))
13898 (set (match_scratch:SI 3 "=&r") (const_int 0))]
13899 "TARGET_SHMEDIA"
13900 "ld%M1.l\t%m1, %0\;ld%M2.l\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13901 [(set_attr "type" "other")
13902 (set_attr "length" "16")])
13903
13904 (define_insn "stack_protect_test_di_media"
13905 [(set (match_operand:DI 0 "register_operand" "=&r")
13906 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
13907 (match_operand:DI 2 "memory_operand" "m")]
13908 UNSPEC_SP_TEST))
13909 (set (match_scratch:DI 3 "=&r") (const_int 0))]
13910 "TARGET_SHMEDIA64"
13911 "ld%M1.q\t%m1, %0\;ld%M2.q\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13912 [(set_attr "type" "other")
13913 (set_attr "length" "16")])
13914
13915 (include "sync.md")