31160b0d1d4884b66072137882ba920e6eac96e7
[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 ;; annuled 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 unecessary 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 {
687 if (GET_MODE (operands[0]) == QImode)
688 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
689 }")
690
691 ;; Extract single bit, negate and store it in the T bit.
692 ;; Not used for SH4A.
693
694 (define_insn "tstsi_t_zero_extract_xor"
695 [(set (reg:SI T_REG)
696 (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
697 (match_operand:SI 3 "const_int_operand"))
698 (match_operand:SI 1 "const_int_operand")
699 (match_operand:SI 2 "const_int_operand")))]
700 "TARGET_SH1
701 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
702 && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
703 "tst %3,%0"
704 [(set_attr "type" "mt_group")])
705
706 ;; Extract single bit, negate and store it in the T bit.
707 ;; Used for SH4A little endian.
708
709 (define_insn "tstsi_t_zero_extract_subreg_xor_little"
710 [(set (reg:SI T_REG)
711 (zero_extract:SI
712 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
713 (match_operand:SI 3 "const_int_operand")) 0)
714 (match_operand:SI 1 "const_int_operand")
715 (match_operand:SI 2 "const_int_operand")))]
716 "TARGET_SH1 && TARGET_LITTLE_ENDIAN
717 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
718 == (INTVAL (operands[3]) & 255)
719 && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
720 {
721 operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
722 return "tst %3,%0";
723 }
724 [(set_attr "type" "mt_group")])
725
726 ;; Extract single bit, negate and store it in the T bit.
727 ;; Used for SH4A big endian.
728
729 (define_insn "tstsi_t_zero_extract_subreg_xor_big"
730 [(set (reg:SI T_REG)
731 (zero_extract:SI
732 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
733 (match_operand:SI 3 "const_int_operand")) 3)
734 (match_operand:SI 1 "const_int_operand")
735 (match_operand:SI 2 "const_int_operand")))]
736 "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN
737 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
738 == (INTVAL (operands[3]) & 255)
739 && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
740 {
741 operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
742 return "tst %3,%0";
743 }
744 [(set_attr "type" "mt_group")])
745
746 ;; ??? Perhaps should only accept reg/constant if the register is reg 0.
747 ;; That would still allow reload to create cmpi instructions, but would
748 ;; perhaps allow forcing the constant into a register when that is better.
749 ;; Probably should use r0 for mem/imm compares, but force constant into a
750 ;; register for pseudo/imm compares.
751
752 (define_insn "cmpeqsi_t"
753 [(set (reg:SI T_REG)
754 (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
755 (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
756 "TARGET_SH1"
757 "@
758 tst %0,%0
759 cmp/eq %1,%0
760 cmp/eq %1,%0"
761 [(set_attr "type" "mt_group")])
762
763 (define_insn "cmpgtsi_t"
764 [(set (reg:SI T_REG)
765 (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
766 (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
767 "TARGET_SH1"
768 "@
769 cmp/gt %1,%0
770 cmp/pl %0"
771 [(set_attr "type" "mt_group")])
772
773 (define_insn "cmpgesi_t"
774 [(set (reg:SI T_REG)
775 (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
776 (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
777 "TARGET_SH1"
778 "@
779 cmp/ge %1,%0
780 cmp/pz %0"
781 [(set_attr "type" "mt_group")])
782
783 ;; -------------------------------------------------------------------------
784 ;; SImode compare and branch
785 ;; -------------------------------------------------------------------------
786
787 (define_expand "cbranchsi4"
788 [(set (pc)
789 (if_then_else (match_operator 0 "comparison_operator"
790 [(match_operand:SI 1 "arith_operand" "")
791 (match_operand:SI 2 "arith_operand" "")])
792 (label_ref (match_operand 3 "" ""))
793 (pc)))
794 (clobber (reg:SI T_REG))]
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 ;; SImode unsigned integer comparisons
807 ;; -------------------------------------------------------------------------
808
809 (define_insn_and_split "cmpgeusi_t"
810 [(set (reg:SI T_REG)
811 (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
812 (match_operand:SI 1 "arith_reg_or_0_operand" "rN")))]
813 "TARGET_SH1"
814 "cmp/hs %1,%0"
815 "&& operands[1] == CONST0_RTX (SImode)"
816 [(pc)]
817 "
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 {
855 enum rtx_code comparison;
856
857 if (TARGET_SHMEDIA)
858 {
859 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
860 operands[2], operands[3]));
861 DONE;
862 }
863
864 else if (!TARGET_CBRANCHDI4)
865 {
866 sh_emit_compare_and_branch (operands, DImode);
867 DONE;
868 }
869
870 else
871 {
872 if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
873 DONE;
874
875 comparison = prepare_cbranch_operands (operands, DImode,
876 LAST_AND_UNUSED_RTX_CODE);
877 if (comparison != GET_CODE (operands[0]))
878 operands[0]
879 = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
880 operands[4] = gen_rtx_SCRATCH (SImode);
881 }
882 }")
883
884 (define_insn_and_split "cbranchdi4_i"
885 [(set (pc)
886 (if_then_else (match_operator 0 "comparison_operator"
887 [(match_operand:DI 1 "arith_operand" "r,r")
888 (match_operand:DI 2 "arith_operand" "rN,I08")])
889 (label_ref (match_operand 3 "" ""))
890 (pc)))
891 (clobber (match_scratch:SI 4 "=X,&r"))
892 (clobber (reg:SI T_REG))]
893 "TARGET_CBRANCHDI4"
894 "#"
895 "&& reload_completed"
896 [(pc)]
897 "
898 {
899 if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
900 FAIL;
901 DONE;
902 }")
903
904 ;; -------------------------------------------------------------------------
905 ;; DImode signed integer comparisons
906 ;; -------------------------------------------------------------------------
907
908 (define_insn ""
909 [(set (reg:SI T_REG)
910 (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
911 (match_operand:DI 1 "arith_operand" "r"))
912 (const_int 0)))]
913 "TARGET_SH1"
914 "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",
915 insn, operands);"
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 {
946 operands[2]
947 = gen_rtx_REG (SImode,
948 true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
949 operands[3]
950 = (operands[1] == const0_rtx
951 ? const0_rtx
952 : gen_rtx_REG (SImode,
953 true_regnum (operands[1])
954 + (TARGET_LITTLE_ENDIAN ? 1 : 0)));
955 operands[4] = gen_lowpart (SImode, operands[0]);
956 operands[5] = gen_lowpart (SImode, operands[1]);
957 operands[6] = gen_label_rtx ();
958 }")
959
960 (define_insn "cmpgtdi_t"
961 [(set (reg:SI T_REG)
962 (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
963 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
964 "TARGET_SH2"
965 "@
966 cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:
967 tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"
968 [(set_attr "length" "8")
969 (set_attr "type" "arith3")])
970
971 (define_insn "cmpgedi_t"
972 [(set (reg:SI T_REG)
973 (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
974 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
975 "TARGET_SH2"
976 "@
977 cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:
978 cmp/pz\\t%S0"
979 [(set_attr "length" "8,2")
980 (set_attr "type" "arith3,mt_group")])
981 \f
982 ;; -------------------------------------------------------------------------
983 ;; DImode unsigned integer comparisons
984 ;; -------------------------------------------------------------------------
985
986 (define_insn "cmpgeudi_t"
987 [(set (reg:SI T_REG)
988 (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
989 (match_operand:DI 1 "arith_reg_operand" "r")))]
990 "TARGET_SH2"
991 "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"
992 [(set_attr "length" "8")
993 (set_attr "type" "arith3")])
994
995 (define_insn "cmpgtudi_t"
996 [(set (reg:SI T_REG)
997 (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
998 (match_operand:DI 1 "arith_reg_operand" "r")))]
999 "TARGET_SH2"
1000 "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"
1001 [(set_attr "length" "8")
1002 (set_attr "type" "arith3")])
1003
1004 (define_insn "cmpeqsi_media"
1005 [(set (match_operand:SI 0 "register_operand" "=r")
1006 (eq:SI (match_operand:SI 1 "logical_operand" "%r")
1007 (match_operand:SI 2 "cmp_operand" "Nr")))]
1008 "TARGET_SHMEDIA"
1009 "cmpeq %1, %N2, %0"
1010 [(set_attr "type" "cmp_media")])
1011
1012 (define_insn "cmpeqdi_media"
1013 [(set (match_operand:SI 0 "register_operand" "=r")
1014 (eq:SI (match_operand:DI 1 "register_operand" "%r")
1015 (match_operand:DI 2 "cmp_operand" "Nr")))]
1016 "TARGET_SHMEDIA"
1017 "cmpeq %1, %N2, %0"
1018 [(set_attr "type" "cmp_media")])
1019
1020 (define_insn "cmpgtsi_media"
1021 [(set (match_operand:SI 0 "register_operand" "=r")
1022 (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
1023 (match_operand:SI 2 "cmp_operand" "rN")))]
1024 "TARGET_SHMEDIA"
1025 "cmpgt %N1, %N2, %0"
1026 [(set_attr "type" "cmp_media")])
1027
1028 (define_insn "cmpgtdi_media"
1029 [(set (match_operand:SI 0 "register_operand" "=r")
1030 (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1031 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1032 "TARGET_SHMEDIA"
1033 "cmpgt %N1, %N2, %0"
1034 [(set_attr "type" "cmp_media")])
1035
1036 (define_insn "cmpgtusi_media"
1037 [(set (match_operand:SI 0 "register_operand" "=r")
1038 (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
1039 (match_operand:SI 2 "cmp_operand" "rN")))]
1040 "TARGET_SHMEDIA"
1041 "cmpgtu %N1, %N2, %0"
1042 [(set_attr "type" "cmp_media")])
1043
1044 (define_insn "cmpgtudi_media"
1045 [(set (match_operand:SI 0 "register_operand" "=r")
1046 (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1047 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1048 "TARGET_SHMEDIA"
1049 "cmpgtu %N1, %N2, %0"
1050 [(set_attr "type" "cmp_media")])
1051
1052 ; These two patterns are for combine.
1053 (define_insn "*cmpne0sisi_media"
1054 [(set (match_operand:SI 0 "register_operand" "=r")
1055 (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
1056 "TARGET_SHMEDIA"
1057 "cmpgtu %1,r63,%0"
1058 [(set_attr "type" "cmp_media")])
1059
1060 ;; -------------------------------------------------------------------------
1061 ;; Conditional move instructions
1062 ;; -------------------------------------------------------------------------
1063
1064 ;; The insn names may seem reversed, but note that cmveq performs the move
1065 ;; if op1 == 0, and cmvne does it if op1 != 0.
1066
1067 (define_insn "movdicc_false"
1068 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1069 (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
1070 (const_int 0))
1071 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1072 (match_operand:DI 3 "arith_reg_operand" "0")))]
1073 "TARGET_SHMEDIA"
1074 "cmveq %1, %N2, %0"
1075 [(set_attr "type" "arith_media")])
1076
1077 (define_insn "movdicc_true"
1078 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1079 (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
1080 (const_int 0))
1081 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1082 (match_operand:DI 3 "arith_reg_operand" "0")))]
1083 "TARGET_SHMEDIA"
1084 "cmvne %1, %N2, %0"
1085 [(set_attr "type" "arith_media")])
1086
1087 (define_peephole2
1088 [(set (match_operand:DI 0 "arith_reg_dest" "")
1089 (if_then_else:DI (match_operator 3 "equality_comparison_operator"
1090 [(match_operand:DI 1 "arith_reg_operand" "")
1091 (const_int 0)])
1092 (match_operand:DI 2 "arith_reg_dest" "")
1093 (match_dup 0)))
1094 (set (match_dup 2) (match_dup 0))]
1095 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1096 [(set (match_dup 2)
1097 (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
1098 "
1099 {
1100 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1101 VOIDmode, operands[1], CONST0_RTX (DImode));
1102 }")
1103
1104 (define_peephole2
1105 [(set (match_operand:DI 0 "general_movdst_operand" "")
1106 (match_operand:DI 1 "arith_reg_or_0_operand" ""))
1107 (set (match_operand:DI 2 "arith_reg_dest" "")
1108 (if_then_else:DI (match_operator 4 "equality_comparison_operator"
1109 [(match_operand:DI 3 "arith_reg_operand" "")
1110 (const_int 0)])
1111 (match_dup 0)
1112 (match_dup 2)))]
1113 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1114 [(set (match_dup 2)
1115 (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
1116 "")
1117
1118 (define_expand "movdicc"
1119 [(set (match_operand:DI 0 "register_operand" "")
1120 (if_then_else:DI (match_operand 1 "comparison_operator" "")
1121 (match_operand:DI 2 "register_operand" "")
1122 (match_operand:DI 3 "register_operand" "")))]
1123 "TARGET_SHMEDIA"
1124 "
1125 {
1126 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1127 && GET_MODE (XEXP (operands[1], 0)) == DImode
1128 && XEXP (operands[1], 1) == const0_rtx)
1129 ;
1130 else
1131 {
1132 if (!can_create_pseudo_p ())
1133 FAIL;
1134
1135 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1136 GET_CODE (operands[1]),
1137 XEXP (operands[1], 0),
1138 XEXP (operands[1], 1));
1139 if (!operands[1])
1140 FAIL;
1141 }
1142 }")
1143
1144 ;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1145 ;; SImode to DImode.
1146 (define_insn "movsicc_false"
1147 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1148 (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1149 (const_int 0))
1150 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1151 (match_operand:SI 3 "arith_reg_operand" "0")))]
1152 "TARGET_SHMEDIA"
1153 "cmveq %1, %N2, %0"
1154 [(set_attr "type" "arith_media")])
1155
1156 (define_insn "movsicc_true"
1157 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1158 (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1159 (const_int 0))
1160 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1161 (match_operand:SI 3 "arith_reg_operand" "0")))]
1162 "TARGET_SHMEDIA"
1163 "cmvne %1, %N2, %0"
1164 [(set_attr "type" "arith_media")])
1165
1166 (define_peephole2
1167 [(set (match_operand:SI 0 "arith_reg_dest" "")
1168 (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1169 [(match_operand:SI 1 "arith_reg_operand" "")
1170 (const_int 0)])
1171 (match_operand:SI 2 "arith_reg_dest" "")
1172 (match_dup 0)))
1173 (set (match_dup 2) (match_dup 0))]
1174 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1175 [(set (match_dup 2)
1176 (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1177 "
1178 {
1179 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1180 VOIDmode, operands[1], CONST0_RTX (SImode));
1181 }")
1182
1183 (define_peephole2
1184 [(set (match_operand:SI 0 "general_movdst_operand" "")
1185 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1186 (set (match_operand:SI 2 "arith_reg_dest" "")
1187 (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1188 [(match_operand:SI 3 "arith_reg_operand" "")
1189 (const_int 0)])
1190 (match_dup 0)
1191 (match_dup 2)))]
1192 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1193 && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1194 [(set (match_dup 2)
1195 (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1196 "
1197 {
1198 replace_rtx (operands[4], operands[0], operands[1]);
1199 }")
1200
1201 (define_peephole2
1202 [(set (match_operand 0 "any_register_operand" "")
1203 (match_operand 1 "any_register_operand" ""))
1204 (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1205 (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1206 "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1207 <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1208 && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1209 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1210 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1211 && ! reg_overlap_mentioned_p (operands[0], operands[3])
1212 && ! reg_overlap_mentioned_p (operands[2], operands[0])
1213 && ! reg_overlap_mentioned_p (operands[0], operands[1])
1214 && (REGNO_REG_CLASS (REGNO (operands[0]))
1215 == REGNO_REG_CLASS (REGNO (operands[2])))
1216 && (REGNO_REG_CLASS (REGNO (operands[1]))
1217 == REGNO_REG_CLASS (REGNO (operands[0])))"
1218 [(set (match_dup 0) (match_dup 3))
1219 (set (match_dup 4) (match_dup 5))]
1220 "
1221 {
1222 rtx set1, set2, insn2;
1223 rtx replacements[4];
1224
1225 /* We want to replace occurrences of operands[0] with operands[1] and
1226 operands[2] with operands[0] in operands[4]/operands[5].
1227 Doing just two replace_rtx calls naively would result in the second
1228 replacement undoing all that the first did if operands[1] and operands[2]
1229 are identical, so we must do this simultaneously. */
1230 replacements[0] = operands[0];
1231 replacements[1] = operands[1];
1232 replacements[2] = operands[2];
1233 replacements[3] = operands[0];
1234 if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1235 || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1236 || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1237 FAIL;
1238
1239 operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1240 replace_n_hard_rtx (operands[4], replacements, 2, 1);
1241 operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1242 /* The operands array is aliased to recog_data.operand, which gets
1243 clobbered by extract_insn, so finish with it now. */
1244 set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1245 set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1246 /* ??? The last insn might be a jump insn, but the generic peephole2 code
1247 always uses emit_insn. */
1248 /* Check that we don't violate matching constraints or earlyclobbers. */
1249 extract_insn (emit_insn (set1));
1250 if (! constrain_operands (1))
1251 goto failure;
1252 insn2 = emit (set2);
1253 if (GET_CODE (insn2) == BARRIER)
1254 goto failure;
1255 extract_insn (insn2);
1256 if (! constrain_operands (1))
1257 {
1258 rtx tmp;
1259 failure:
1260 tmp = replacements[0];
1261 replacements[0] = replacements[1];
1262 replacements[1] = tmp;
1263 tmp = replacements[2];
1264 replacements[2] = replacements[3];
1265 replacements[3] = tmp;
1266 replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1267 replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1268 replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1269 FAIL;
1270 }
1271 DONE;
1272 }")
1273
1274 ;; The register allocator is rather clumsy in handling multi-way conditional
1275 ;; moves, so allow the combiner to make them, and we split them up after
1276 ;; reload. */
1277 (define_insn_and_split "*movsicc_umin"
1278 [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1279 (umin:SI (if_then_else:SI
1280 (eq (match_operand:SI 1 "arith_reg_operand" "r")
1281 (const_int 0))
1282 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1283 (match_operand:SI 3 "register_operand" "0"))
1284 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1285 (clobber (match_scratch:SI 5 "=&r"))]
1286 "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1287 "#"
1288 "TARGET_SHMEDIA && reload_completed"
1289 [(pc)]
1290 "
1291 {
1292 emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1293 operands[3]));
1294 emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1295 emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1296 operands[0]));
1297 DONE;
1298 }")
1299
1300 (define_insn "*movsicc_t_false"
1301 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1302 (if_then_else (eq (reg:SI T_REG) (const_int 0))
1303 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1304 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1305 "TARGET_PRETEND_CMOVE
1306 && (arith_reg_operand (operands[1], SImode)
1307 || (immediate_operand (operands[1], SImode)
1308 && satisfies_constraint_I08 (operands[1])))"
1309 "bt 0f\;mov %1,%0\\n0:"
1310 [(set_attr "type" "mt_group,arith") ;; poor approximation
1311 (set_attr "length" "4")])
1312
1313 (define_insn "*movsicc_t_true"
1314 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1315 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1316 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1317 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1318 "TARGET_PRETEND_CMOVE
1319 && (arith_reg_operand (operands[1], SImode)
1320 || (immediate_operand (operands[1], SImode)
1321 && satisfies_constraint_I08 (operands[1])))"
1322 "bf 0f\;mov %1,%0\\n0:"
1323 [(set_attr "type" "mt_group,arith") ;; poor approximation
1324 (set_attr "length" "4")])
1325
1326 (define_expand "movsicc"
1327 [(set (match_operand:SI 0 "arith_reg_dest" "")
1328 (if_then_else:SI (match_operand 1 "comparison_operator" "")
1329 (match_operand:SI 2 "arith_reg_or_0_operand" "")
1330 (match_operand:SI 3 "arith_reg_operand" "")))]
1331 "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1332 "
1333 {
1334 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1335 && GET_MODE (XEXP (operands[1], 0)) == SImode
1336 && (TARGET_SHMEDIA
1337 || (REG_P (XEXP (operands[1], 0))
1338 && REGNO (XEXP (operands[1], 0)) == T_REG))
1339 && XEXP (operands[1], 1) == const0_rtx)
1340 ;
1341
1342 else if (TARGET_PRETEND_CMOVE)
1343 {
1344 enum rtx_code code = GET_CODE (operands[1]);
1345 enum rtx_code new_code = code;
1346 rtx op0 = XEXP (operands[1], 0);
1347 rtx op1 = XEXP (operands[1], 1);
1348
1349 if (! currently_expanding_to_rtl)
1350 FAIL;
1351 switch (code)
1352 {
1353 case LT: case LE: case LEU: case LTU:
1354 if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1355 break;
1356 case NE:
1357 new_code = reverse_condition (code);
1358 break;
1359 case EQ: case GT: case GE: case GEU: case GTU:
1360 break;
1361 default:
1362 FAIL;
1363 }
1364 sh_emit_scc_to_t (new_code, op0, op1);
1365 operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1366 gen_rtx_REG (SImode, T_REG), const0_rtx);
1367 }
1368 else
1369 {
1370 if (!can_create_pseudo_p ())
1371 FAIL;
1372
1373 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1374 GET_CODE (operands[1]),
1375 XEXP (operands[1], 0),
1376 XEXP (operands[1], 1));
1377 if (!operands[1])
1378 FAIL;
1379 }
1380 }")
1381
1382 (define_expand "movqicc"
1383 [(set (match_operand:QI 0 "register_operand" "")
1384 (if_then_else:QI (match_operand 1 "comparison_operator" "")
1385 (match_operand:QI 2 "register_operand" "")
1386 (match_operand:QI 3 "register_operand" "")))]
1387 "TARGET_SHMEDIA"
1388 "
1389 {
1390 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1391 operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1392 operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1393 emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1394 DONE;
1395 }")
1396 \f
1397 ;; -------------------------------------------------------------------------
1398 ;; Addition instructions
1399 ;; -------------------------------------------------------------------------
1400
1401 (define_expand "adddi3"
1402 [(set (match_operand:DI 0 "arith_reg_operand" "")
1403 (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1404 (match_operand:DI 2 "arith_operand" "")))]
1405 ""
1406 "
1407 {
1408 if (TARGET_SH1)
1409 {
1410 if (!can_create_pseudo_p () && ! arith_reg_operand (operands[2], DImode))
1411 FAIL;
1412 operands[2] = force_reg (DImode, operands[2]);
1413 emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1414 DONE;
1415 }
1416 }")
1417
1418 (define_insn "*adddi3_media"
1419 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1420 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1421 (match_operand:DI 2 "arith_operand" "r,I10")))]
1422 "TARGET_SHMEDIA"
1423 "@
1424 add %1, %2, %0
1425 addi %1, %2, %0"
1426 [(set_attr "type" "arith_media")])
1427
1428 (define_insn "*adddisi3_media"
1429 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1430 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1431 (match_operand:DI 2 "arith_operand" "r,I10")))]
1432 "TARGET_SHMEDIA"
1433 "@
1434 add.l %1, %2, %0
1435 addi.l %1, %2, %0"
1436 [(set_attr "type" "arith_media")
1437 (set_attr "highpart" "ignore")])
1438
1439 (define_insn "adddi3z_media"
1440 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1441 (zero_extend:DI
1442 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1443 (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1444 "TARGET_SHMEDIA"
1445 "addz.l %1, %N2, %0"
1446 [(set_attr "type" "arith_media")
1447 (set_attr "highpart" "ignore")])
1448
1449 (define_insn "adddi3_compact"
1450 [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1451 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1452 (match_operand:DI 2 "arith_reg_operand" "r")))
1453 (clobber (reg:SI T_REG))]
1454 "TARGET_SH1"
1455 "#"
1456 [(set_attr "length" "6")])
1457
1458 (define_split
1459 [(set (match_operand:DI 0 "arith_reg_dest" "")
1460 (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1461 (match_operand:DI 2 "arith_reg_operand" "")))
1462 (clobber (reg:SI T_REG))]
1463 "TARGET_SH1 && reload_completed"
1464 [(const_int 0)]
1465 "
1466 {
1467 rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1468 high0 = gen_rtx_REG (SImode,
1469 true_regnum (operands[0])
1470 + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1471 high2 = gen_rtx_REG (SImode,
1472 true_regnum (operands[2])
1473 + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1474 emit_insn (gen_clrt ());
1475 emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
1476 emit_insn (gen_addc1 (high0, high0, high2));
1477 DONE;
1478 }")
1479
1480 (define_insn "addc"
1481 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1482 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1483 (match_operand:SI 2 "arith_reg_operand" "r"))
1484 (reg:SI T_REG)))
1485 (set (reg:SI T_REG)
1486 (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1487 "TARGET_SH1"
1488 "addc %2,%0"
1489 [(set_attr "type" "arith")])
1490
1491 (define_insn "addc1"
1492 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1493 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1494 (match_operand:SI 2 "arith_reg_operand" "r"))
1495 (reg:SI T_REG)))
1496 (clobber (reg:SI T_REG))]
1497 "TARGET_SH1"
1498 "addc %2,%0"
1499 [(set_attr "type" "arith")])
1500
1501 (define_expand "addsi3"
1502 [(set (match_operand:SI 0 "arith_reg_operand" "")
1503 (plus:SI (match_operand:SI 1 "arith_operand" "")
1504 (match_operand:SI 2 "arith_operand" "")))]
1505 ""
1506 "
1507 {
1508 if (TARGET_SHMEDIA)
1509 operands[1] = force_reg (SImode, operands[1]);
1510 }")
1511
1512 (define_insn "addsi3_media"
1513 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1514 (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1515 (match_operand:SI 2 "arith_operand" "r,I10")))]
1516 "TARGET_SHMEDIA"
1517 "@
1518 add.l %1, %2, %0
1519 addi.l %1, %2, %0"
1520 [(set_attr "type" "arith_media")
1521 (set_attr "highpart" "ignore")])
1522
1523 (define_insn "addsidi3_media"
1524 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1525 (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
1526 "%r,r")
1527 (match_operand:SI 2 "arith_operand"
1528 "r,I10"))))]
1529 "TARGET_SHMEDIA"
1530 "@
1531 add.l %1, %2, %0
1532 addi.l %1, %2, %0"
1533 [(set_attr "type" "arith_media")
1534 (set_attr "highpart" "ignore")])
1535
1536 (define_insn "*addsi3_compact"
1537 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1538 (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1539 (match_operand:SI 2 "arith_operand" "rI08")))]
1540 "TARGET_SH1"
1541 "add %2,%0"
1542 [(set_attr "type" "arith")])
1543
1544 ;; -------------------------------------------------------------------------
1545 ;; Subtraction instructions
1546 ;; -------------------------------------------------------------------------
1547
1548 (define_expand "subdi3"
1549 [(set (match_operand:DI 0 "arith_reg_operand" "")
1550 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1551 (match_operand:DI 2 "arith_reg_operand" "")))]
1552 ""
1553 "
1554 {
1555 if (TARGET_SH1)
1556 {
1557 operands[1] = force_reg (DImode, operands[1]);
1558 emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1559 DONE;
1560 }
1561 }")
1562
1563 (define_insn "*subdi3_media"
1564 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1565 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1566 (match_operand:DI 2 "arith_reg_operand" "r")))]
1567 "TARGET_SHMEDIA"
1568 "sub %N1, %2, %0"
1569 [(set_attr "type" "arith_media")])
1570
1571 (define_insn "subdisi3_media"
1572 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
1573 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1574 (match_operand:DI 2 "arith_reg_operand" "r")))]
1575 "TARGET_SHMEDIA"
1576 "sub.l %N1, %2, %0"
1577 [(set_attr "type" "arith_media")
1578 (set_attr "highpart" "ignore")])
1579
1580 (define_insn "subdi3_compact"
1581 [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1582 (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1583 (match_operand:DI 2 "arith_reg_operand" "r")))
1584 (clobber (reg:SI T_REG))]
1585 "TARGET_SH1"
1586 "#"
1587 [(set_attr "length" "6")])
1588
1589 (define_split
1590 [(set (match_operand:DI 0 "arith_reg_dest" "")
1591 (minus:DI (match_operand:DI 1 "arith_reg_operand" "")
1592 (match_operand:DI 2 "arith_reg_operand" "")))
1593 (clobber (reg:SI T_REG))]
1594 "TARGET_SH1 && reload_completed"
1595 [(const_int 0)]
1596 "
1597 {
1598 rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1599 high0 = gen_rtx_REG (SImode,
1600 true_regnum (operands[0])
1601 + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1602 high2 = gen_rtx_REG (SImode,
1603 true_regnum (operands[2])
1604 + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1605 emit_insn (gen_clrt ());
1606 emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1607 emit_insn (gen_subc1 (high0, high0, high2));
1608 DONE;
1609 }")
1610
1611 (define_insn "subc"
1612 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1613 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1614 (match_operand:SI 2 "arith_reg_operand" "r"))
1615 (reg:SI T_REG)))
1616 (set (reg:SI T_REG)
1617 (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1618 (reg:SI T_REG))
1619 (match_dup 1)))]
1620 "TARGET_SH1"
1621 "subc %2,%0"
1622 [(set_attr "type" "arith")])
1623
1624 (define_insn "subc1"
1625 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1626 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1627 (match_operand:SI 2 "arith_reg_operand" "r"))
1628 (reg:SI T_REG)))
1629 (clobber (reg:SI T_REG))]
1630 "TARGET_SH1"
1631 "subc %2,%0"
1632 [(set_attr "type" "arith")])
1633
1634 ;; life_analysis thinks rn is live before subc rn,rn, so make a special
1635 ;; pattern for this case. This helps multimedia applications that compute
1636 ;; the sum of absolute differences.
1637 (define_insn "mov_neg_si_t"
1638 [(set (match_operand:SI 0 "arith_reg_dest" "=r") (neg:SI (reg:SI T_REG)))]
1639 "TARGET_SH1"
1640 "subc %0,%0"
1641 [(set_attr "type" "arith")])
1642
1643 (define_insn "*subsi3_internal"
1644 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1645 (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1646 (match_operand:SI 2 "arith_reg_operand" "r")))]
1647 "TARGET_SH1"
1648 "sub %2,%0"
1649 [(set_attr "type" "arith")])
1650
1651 (define_insn_and_split "*subsi3_media"
1652 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1653 (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
1654 (match_operand:SI 2 "extend_reg_operand" "r")))]
1655 "TARGET_SHMEDIA
1656 && (operands[1] != constm1_rtx
1657 || (GET_CODE (operands[2]) != TRUNCATE
1658 && GET_CODE (operands[2]) != SUBREG))"
1659 "sub.l %N1, %2, %0"
1660 "operands[1] == constm1_rtx"
1661 [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
1662 ""
1663 [(set_attr "type" "arith_media")
1664 (set_attr "highpart" "ignore")])
1665
1666 (define_split
1667 [(set (match_operand:SI 0 "arith_reg_dest" "")
1668 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1669 "general_extend_operand"
1670 "") 0)) 0)))]
1671 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
1672 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1673 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1674 "")
1675
1676 (define_split
1677 [(set (match_operand:SI 0 "arith_reg_dest" "")
1678 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1679 "general_extend_operand"
1680 "") 0)) 3)))]
1681 "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
1682 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1683 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1684 "")
1685 ;; Convert `constant - reg' to `neg rX; add rX, #const' since this
1686 ;; will sometimes save one instruction. Otherwise we might get
1687 ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
1688 ;; are the same.
1689
1690 (define_expand "subsi3"
1691 [(set (match_operand:SI 0 "arith_reg_operand" "")
1692 (minus:SI (match_operand:SI 1 "arith_operand" "")
1693 (match_operand:SI 2 "arith_reg_operand" "")))]
1694 ""
1695 "
1696 {
1697 if (TARGET_SH1 && CONST_INT_P (operands[1]))
1698 {
1699 emit_insn (gen_negsi2 (operands[0], operands[2]));
1700 emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
1701 DONE;
1702 }
1703 if (TARGET_SHMEDIA)
1704 {
1705 if (!can_create_pseudo_p ()
1706 && ! arith_reg_or_0_operand (operands[1], SImode))
1707 FAIL;
1708 if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
1709 operands[1] = force_reg (SImode, operands[1]);
1710 }
1711 }")
1712 \f
1713 ;; -------------------------------------------------------------------------
1714 ;; Division instructions
1715 ;; -------------------------------------------------------------------------
1716
1717 ;; We take advantage of the library routines which don't clobber as many
1718 ;; registers as a normal function call would.
1719
1720 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
1721 ;; also has an effect on the register that holds the address of the sfunc.
1722 ;; To make this work, we have an extra dummy insn that shows the use
1723 ;; of this register for reorg.
1724
1725 (define_insn "use_sfunc_addr"
1726 [(set (reg:SI PR_REG)
1727 (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
1728 "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
1729 ""
1730 [(set_attr "length" "0")])
1731
1732 (define_insn "udivsi3_sh2a"
1733 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1734 (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
1735 (match_operand:SI 2 "arith_reg_operand" "z")))]
1736 "TARGET_SH2A"
1737 "divu %2,%1"
1738 [(set_attr "type" "arith")
1739 (set_attr "in_delay_slot" "no")])
1740
1741 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
1742 ;; hard register 0. If we used hard register 0, then the next instruction
1743 ;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg
1744 ;; gets allocated to a stack slot that needs its address reloaded, then
1745 ;; there is nothing to prevent reload from using r0 to reload the address.
1746 ;; This reload would clobber the value in r0 we are trying to store.
1747 ;; If we let reload allocate r0, then this problem can never happen.
1748
1749 (define_insn "udivsi3_i1"
1750 [(set (match_operand:SI 0 "register_operand" "=z")
1751 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1752 (clobber (reg:SI T_REG))
1753 (clobber (reg:SI PR_REG))
1754 (clobber (reg:SI R4_REG))
1755 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1756 "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
1757 "jsr @%1%#"
1758 [(set_attr "type" "sfunc")
1759 (set_attr "needs_delay_slot" "yes")])
1760
1761 ; Since shmedia-nofpu code could be linked against shcompact code, and
1762 ; the udivsi3 libcall has the same name, we must consider all registers
1763 ; clobbered that are in the union of the registers clobbered by the
1764 ; shmedia and the shcompact implementation. Note, if the shcompact
1765 ; implementation actually used shcompact code, we'd need to clobber
1766 ; also r23 and fr23.
1767 (define_insn "udivsi3_i1_media"
1768 [(set (match_operand:SI 0 "register_operand" "=z")
1769 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1770 (clobber (reg:SI T_MEDIA_REG))
1771 (clobber (reg:SI PR_MEDIA_REG))
1772 (clobber (reg:SI R20_REG))
1773 (clobber (reg:SI R21_REG))
1774 (clobber (reg:SI R22_REG))
1775 (clobber (reg:DI TR0_REG))
1776 (clobber (reg:DI TR1_REG))
1777 (clobber (reg:DI TR2_REG))
1778 (use (match_operand 1 "target_reg_operand" "b"))]
1779 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1780 "blink %1, r18"
1781 [(set_attr "type" "sfunc")
1782 (set_attr "needs_delay_slot" "yes")])
1783
1784 (define_expand "udivsi3_i4_media"
1785 [(set (match_dup 3)
1786 (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
1787 (set (match_dup 4)
1788 (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1789 (set (match_dup 5) (float:DF (match_dup 3)))
1790 (set (match_dup 6) (float:DF (match_dup 4)))
1791 (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
1792 (set (match_dup 8) (fix:DI (match_dup 7)))
1793 (set (match_operand:SI 0 "register_operand" "")
1794 (truncate:SI (match_dup 8)))]
1795 "TARGET_SHMEDIA_FPU"
1796 "
1797 {
1798 operands[3] = gen_reg_rtx (DImode);
1799 operands[4] = gen_reg_rtx (DImode);
1800 operands[5] = gen_reg_rtx (DFmode);
1801 operands[6] = gen_reg_rtx (DFmode);
1802 operands[7] = gen_reg_rtx (DFmode);
1803 operands[8] = gen_reg_rtx (DImode);
1804 }")
1805
1806 (define_insn "udivsi3_i4"
1807 [(set (match_operand:SI 0 "register_operand" "=y")
1808 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1809 (clobber (reg:SI T_REG))
1810 (clobber (reg:SI PR_REG))
1811 (clobber (reg:DF DR0_REG))
1812 (clobber (reg:DF DR2_REG))
1813 (clobber (reg:DF DR4_REG))
1814 (clobber (reg:SI R0_REG))
1815 (clobber (reg:SI R1_REG))
1816 (clobber (reg:SI R4_REG))
1817 (clobber (reg:SI R5_REG))
1818 (use (reg:PSI FPSCR_REG))
1819 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1820 "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1821 "jsr @%1%#"
1822 [(set_attr "type" "sfunc")
1823 (set_attr "fp_mode" "double")
1824 (set_attr "needs_delay_slot" "yes")])
1825
1826 (define_insn "udivsi3_i4_single"
1827 [(set (match_operand:SI 0 "register_operand" "=y")
1828 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1829 (clobber (reg:SI T_REG))
1830 (clobber (reg:SI PR_REG))
1831 (clobber (reg:DF DR0_REG))
1832 (clobber (reg:DF DR2_REG))
1833 (clobber (reg:DF DR4_REG))
1834 (clobber (reg:SI R0_REG))
1835 (clobber (reg:SI R1_REG))
1836 (clobber (reg:SI R4_REG))
1837 (clobber (reg:SI R5_REG))
1838 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1839 "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1840 "jsr @%1%#"
1841 [(set_attr "type" "sfunc")
1842 (set_attr "needs_delay_slot" "yes")])
1843
1844 (define_insn "udivsi3_i4_int"
1845 [(set (match_operand:SI 0 "register_operand" "=z")
1846 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1847 (clobber (reg:SI T_REG))
1848 (clobber (reg:SI R1_REG))
1849 (clobber (reg:SI PR_REG))
1850 (clobber (reg:SI MACH_REG))
1851 (clobber (reg:SI MACL_REG))
1852 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1853 "TARGET_SH1"
1854 "jsr @%1%#"
1855 [(set_attr "type" "sfunc")
1856 (set_attr "needs_delay_slot" "yes")])
1857
1858
1859 (define_expand "udivsi3"
1860 [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
1861 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1862 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1863 (parallel [(set (match_operand:SI 0 "register_operand" "")
1864 (udiv:SI (reg:SI R4_REG)
1865 (reg:SI R5_REG)))
1866 (clobber (reg:SI T_REG))
1867 (clobber (reg:SI PR_REG))
1868 (clobber (reg:SI R4_REG))
1869 (use (match_dup 3))])]
1870 ""
1871 "
1872 {
1873 rtx last;
1874
1875 operands[3] = gen_reg_rtx (Pmode);
1876 /* Emit the move of the address to a pseudo outside of the libcall. */
1877 if (TARGET_DIVIDE_CALL_TABLE)
1878 {
1879 /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
1880 that causes problems when the divide code is supposed to come from a
1881 separate library. Division by zero is undefined, so dividing 1 can be
1882 implemented by comparing with the divisor. */
1883 if (operands[1] == const1_rtx && currently_expanding_to_rtl)
1884 {
1885 rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
1886 emit_insn (gen_cstoresi4 (operands[0], test,
1887 operands[1], operands[2]));
1888 DONE;
1889 }
1890 else if (operands[2] == const0_rtx)
1891 {
1892 emit_move_insn (operands[0], operands[2]);
1893 DONE;
1894 }
1895 function_symbol (operands[3], \"__udivsi3_i4i\", SFUNC_GOT);
1896 last = gen_udivsi3_i4_int (operands[0], operands[3]);
1897 }
1898 else if (TARGET_DIVIDE_CALL_FP)
1899 {
1900 function_symbol (operands[3], \"__udivsi3_i4\", SFUNC_STATIC);
1901 if (TARGET_FPU_SINGLE)
1902 last = gen_udivsi3_i4_single (operands[0], operands[3]);
1903 else
1904 last = gen_udivsi3_i4 (operands[0], operands[3]);
1905 }
1906 else if (TARGET_SHMEDIA_FPU)
1907 {
1908 operands[1] = force_reg (SImode, operands[1]);
1909 operands[2] = force_reg (SImode, operands[2]);
1910 emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
1911 DONE;
1912 }
1913 else if (TARGET_SH2A)
1914 {
1915 operands[1] = force_reg (SImode, operands[1]);
1916 operands[2] = force_reg (SImode, operands[2]);
1917 emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
1918 DONE;
1919 }
1920 else if (TARGET_SH5)
1921 {
1922 function_symbol (operands[3],
1923 TARGET_FPU_ANY ? \"__udivsi3_i4\" : \"__udivsi3\",
1924 SFUNC_STATIC);
1925
1926 if (TARGET_SHMEDIA)
1927 last = gen_udivsi3_i1_media (operands[0], operands[3]);
1928 else if (TARGET_FPU_ANY)
1929 last = gen_udivsi3_i4_single (operands[0], operands[3]);
1930 else
1931 last = gen_udivsi3_i1 (operands[0], operands[3]);
1932 }
1933 else
1934 {
1935 function_symbol (operands[3], \"__udivsi3\", SFUNC_STATIC);
1936 last = gen_udivsi3_i1 (operands[0], operands[3]);
1937 }
1938 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1939 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1940 emit_insn (last);
1941 DONE;
1942 }")
1943
1944 (define_insn "divsi3_sh2a"
1945 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1946 (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
1947 (match_operand:SI 2 "arith_reg_operand" "z")))]
1948 "TARGET_SH2A"
1949 "divs %2,%1"
1950 [(set_attr "type" "arith")
1951 (set_attr "in_delay_slot" "no")])
1952
1953 (define_insn "divsi3_i1"
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_REG))
1957 (clobber (reg:SI PR_REG))
1958 (clobber (reg:SI R1_REG))
1959 (clobber (reg:SI R2_REG))
1960 (clobber (reg:SI R3_REG))
1961 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1962 "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
1963 "jsr @%1%#"
1964 [(set_attr "type" "sfunc")
1965 (set_attr "needs_delay_slot" "yes")])
1966
1967 (define_insn "divsi3_i1_media"
1968 [(set (match_operand:SI 0 "register_operand" "=z")
1969 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1970 (clobber (reg:SI T_MEDIA_REG))
1971 (clobber (reg:SI PR_MEDIA_REG))
1972 (clobber (reg:SI R1_REG))
1973 (clobber (reg:SI R20_REG))
1974 (clobber (reg:SI R21_REG))
1975 (clobber (reg:SI TR0_REG))
1976 (use (match_operand 1 "target_reg_operand" "b"))]
1977 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1978 "blink %1, r18"
1979 [(set_attr "type" "sfunc")])
1980
1981 (define_insn "divsi3_media_2"
1982 [(set (match_operand:SI 0 "register_operand" "=z")
1983 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1984 (clobber (reg:SI T_MEDIA_REG))
1985 (clobber (reg:SI PR_MEDIA_REG))
1986 (clobber (reg:SI R1_REG))
1987 (clobber (reg:SI R21_REG))
1988 (clobber (reg:SI TR0_REG))
1989 (use (reg:SI R20_REG))
1990 (use (match_operand 1 "target_reg_operand" "b"))]
1991 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1992 "blink %1, r18"
1993 [(set_attr "type" "sfunc")])
1994
1995 ;; This pattern acts as a placeholder for -mdiv=inv:call to carry
1996 ;; hard reg clobbers and data dependencies that we need when we want
1997 ;; to rematerialize the division into a call.
1998 (define_insn_and_split "divsi_inv_call"
1999 [(set (match_operand:SI 0 "register_operand" "=r")
2000 (div:SI (match_operand:SI 1 "register_operand" "r")
2001 (match_operand:SI 2 "register_operand" "r")))
2002 (clobber (reg:SI R4_REG))
2003 (clobber (reg:SI R5_REG))
2004 (clobber (reg:SI T_MEDIA_REG))
2005 (clobber (reg:SI PR_MEDIA_REG))
2006 (clobber (reg:SI R1_REG))
2007 (clobber (reg:SI R21_REG))
2008 (clobber (reg:SI TR0_REG))
2009 (clobber (reg:SI R20_REG))
2010 (use (match_operand:SI 3 "register_operand" "r"))]
2011 "TARGET_SHMEDIA"
2012 "#"
2013 "&& (high_life_started || reload_completed)"
2014 [(set (match_dup 0) (match_dup 3))]
2015 ""
2016 [(set_attr "highpart" "must_split")])
2017
2018 ;; This is the combiner pattern for -mdiv=inv:call .
2019 (define_insn_and_split "*divsi_inv_call_combine"
2020 [(set (match_operand:SI 0 "register_operand" "=z")
2021 (div:SI (match_operand:SI 1 "register_operand" "r")
2022 (match_operand:SI 2 "register_operand" "r")))
2023 (clobber (reg:SI R4_REG))
2024 (clobber (reg:SI R5_REG))
2025 (clobber (reg:SI T_MEDIA_REG))
2026 (clobber (reg:SI PR_MEDIA_REG))
2027 (clobber (reg:SI R1_REG))
2028 (clobber (reg:SI R21_REG))
2029 (clobber (reg:SI TR0_REG))
2030 (clobber (reg:SI R20_REG))
2031 (use (unspec:SI [(match_dup 1)
2032 (match_operand:SI 3 "" "")
2033 (unspec:SI [(match_operand:SI 4 "" "")
2034 (match_dup 3)
2035 (match_operand:DI 5 "" "")]
2036 UNSPEC_DIV_INV_M2)
2037 (match_operand:DI 6 "" "")
2038 (const_int 0)
2039 (const_int 0)]
2040 UNSPEC_DIV_INV_M3))]
2041 "TARGET_SHMEDIA"
2042 "#"
2043 "&& (high_life_started || reload_completed)"
2044 [(pc)]
2045 "
2046 {
2047 const char *name = sh_divsi3_libfunc;
2048 enum sh_function_kind kind = SFUNC_GOT;
2049 rtx sym;
2050
2051 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2052 emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2053 while (TARGET_DIVIDE_INV_CALL2)
2054 {
2055 rtx x = operands[3];
2056
2057 if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2058 break;
2059 x = XVECEXP (x, 0, 0);
2060 name = \"__sdivsi3_2\";
2061 kind = SFUNC_STATIC;
2062 emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2063 break;
2064 }
2065 sym = function_symbol (NULL, name, kind);
2066 emit_insn (gen_divsi3_media_2 (operands[0], sym));
2067 DONE;
2068 }"
2069 [(set_attr "highpart" "must_split")])
2070
2071 (define_expand "divsi3_i4_media"
2072 [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2073 (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2074 (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2075 (set (match_operand:SI 0 "register_operand" "=r")
2076 (fix:SI (match_dup 5)))]
2077 "TARGET_SHMEDIA_FPU"
2078 "
2079 {
2080 operands[3] = gen_reg_rtx (DFmode);
2081 operands[4] = gen_reg_rtx (DFmode);
2082 operands[5] = gen_reg_rtx (DFmode);
2083 }")
2084
2085 (define_insn "divsi3_i4"
2086 [(set (match_operand:SI 0 "register_operand" "=y")
2087 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2088 (clobber (reg:SI PR_REG))
2089 (clobber (reg:DF DR0_REG))
2090 (clobber (reg:DF DR2_REG))
2091 (use (reg:PSI FPSCR_REG))
2092 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2093 "TARGET_SH4 && ! TARGET_FPU_SINGLE"
2094 "jsr @%1%#"
2095 [(set_attr "type" "sfunc")
2096 (set_attr "fp_mode" "double")
2097 (set_attr "needs_delay_slot" "yes")])
2098
2099 (define_insn "divsi3_i4_single"
2100 [(set (match_operand:SI 0 "register_operand" "=y")
2101 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2102 (clobber (reg:SI PR_REG))
2103 (clobber (reg:DF DR0_REG))
2104 (clobber (reg:DF DR2_REG))
2105 (clobber (reg:SI R2_REG))
2106 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2107 "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
2108 "jsr @%1%#"
2109 [(set_attr "type" "sfunc")
2110 (set_attr "needs_delay_slot" "yes")])
2111
2112 (define_insn "divsi3_i4_int"
2113 [(set (match_operand:SI 0 "register_operand" "=z")
2114 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2115 (clobber (reg:SI T_REG))
2116 (clobber (reg:SI PR_REG))
2117 (clobber (reg:SI R1_REG))
2118 (clobber (reg:SI MACH_REG))
2119 (clobber (reg:SI MACL_REG))
2120 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2121 "TARGET_SH1"
2122 "jsr @%1%#"
2123 [(set_attr "type" "sfunc")
2124 (set_attr "needs_delay_slot" "yes")])
2125
2126 (define_expand "divsi3"
2127 [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2128 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2129 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2130 (parallel [(set (match_operand:SI 0 "register_operand" "")
2131 (div:SI (reg:SI R4_REG)
2132 (reg:SI R5_REG)))
2133 (clobber (reg:SI T_REG))
2134 (clobber (reg:SI PR_REG))
2135 (clobber (reg:SI R1_REG))
2136 (clobber (reg:SI R2_REG))
2137 (clobber (reg:SI R3_REG))
2138 (use (match_dup 3))])]
2139 ""
2140 "
2141 {
2142 rtx last;
2143
2144 operands[3] = gen_reg_rtx (Pmode);
2145 /* Emit the move of the address to a pseudo outside of the libcall. */
2146 if (TARGET_DIVIDE_CALL_TABLE)
2147 {
2148 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2149 last = gen_divsi3_i4_int (operands[0], operands[3]);
2150 }
2151 else if (TARGET_DIVIDE_CALL_FP)
2152 {
2153 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2154 if (TARGET_FPU_SINGLE)
2155 last = gen_divsi3_i4_single (operands[0], operands[3]);
2156 else
2157 last = gen_divsi3_i4 (operands[0], operands[3]);
2158 }
2159 else if (TARGET_SH2A)
2160 {
2161 operands[1] = force_reg (SImode, operands[1]);
2162 operands[2] = force_reg (SImode, operands[2]);
2163 emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2164 DONE;
2165 }
2166 else if (TARGET_DIVIDE_INV)
2167 {
2168 rtx dividend = operands[1];
2169 rtx divisor = operands[2];
2170 rtx tab_base;
2171 rtx nsb_res = gen_reg_rtx (DImode);
2172 rtx norm64 = gen_reg_rtx (DImode);
2173 rtx tab_ix = gen_reg_rtx (DImode);
2174 rtx norm32 = gen_reg_rtx (SImode);
2175 rtx i92 = force_reg (DImode, GEN_INT (92));
2176 rtx scratch0a = gen_reg_rtx (DImode);
2177 rtx scratch0b = gen_reg_rtx (DImode);
2178 rtx inv0 = gen_reg_rtx (SImode);
2179 rtx scratch1a = gen_reg_rtx (DImode);
2180 rtx scratch1b = gen_reg_rtx (DImode);
2181 rtx shift = gen_reg_rtx (DImode);
2182 rtx i2p27, i43;
2183 rtx inv1 = gen_reg_rtx (SImode);
2184 rtx scratch2a = gen_reg_rtx (DImode);
2185 rtx scratch2b = gen_reg_rtx (SImode);
2186 rtx inv2 = gen_reg_rtx (SImode);
2187 rtx scratch3a = gen_reg_rtx (DImode);
2188 rtx scratch3b = gen_reg_rtx (DImode);
2189 rtx scratch3c = gen_reg_rtx (DImode);
2190 rtx scratch3d = gen_reg_rtx (SImode);
2191 rtx scratch3e = gen_reg_rtx (DImode);
2192 rtx result = gen_reg_rtx (SImode);
2193
2194 if (! arith_reg_or_0_operand (dividend, SImode))
2195 dividend = force_reg (SImode, dividend);
2196 if (! arith_reg_operand (divisor, SImode))
2197 divisor = force_reg (SImode, divisor);
2198 if (flag_pic && Pmode != DImode)
2199 {
2200 tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2201 tab_base = gen_datalabel_ref (tab_base);
2202 tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2203 }
2204 else
2205 {
2206 tab_base = gen_rtx_SYMBOL_REF (DImode, \"__div_table\");
2207 tab_base = gen_datalabel_ref (tab_base);
2208 tab_base = force_reg (DImode, tab_base);
2209 }
2210 if (TARGET_DIVIDE_INV20U)
2211 i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2212 else
2213 i2p27 = GEN_INT (0);
2214 if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2215 i43 = force_reg (DImode, GEN_INT (43));
2216 else
2217 i43 = GEN_INT (0);
2218 emit_insn (gen_nsbdi (nsb_res,
2219 simplify_gen_subreg (DImode, divisor, SImode, 0)));
2220 emit_insn (gen_ashldi3_media (norm64,
2221 gen_rtx_SUBREG (DImode, divisor, 0),
2222 nsb_res));
2223 emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2224 emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2225 emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2226 inv0, scratch0a, scratch0b,
2227 scratch1a, scratch1b));
2228 emit_insn (gen_subdi3 (shift, i92, nsb_res));
2229 emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2230 scratch2a));
2231 emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2232 i2p27, i43,
2233 scratch3a, scratch3b, scratch3c,
2234 scratch2a, scratch2b, scratch3d, scratch3e));
2235 if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2236 emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2237 else if (TARGET_DIVIDE_INV_FP)
2238 emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2239 gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2240 gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2241 gen_reg_rtx (DFmode)));
2242 else
2243 emit_move_insn (operands[0], result);
2244 DONE;
2245 }
2246 else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2247 {
2248 operands[1] = force_reg (SImode, operands[1]);
2249 operands[2] = force_reg (SImode, operands[2]);
2250 emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2251 DONE;
2252 }
2253 else if (TARGET_SH5)
2254 {
2255 if (TARGET_DIVIDE_CALL2)
2256 {
2257 rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2258 tab_base = gen_datalabel_ref (tab_base);
2259 emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2260 }
2261 if (TARGET_FPU_ANY && TARGET_SH1)
2262 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2263 else if (TARGET_DIVIDE_CALL2)
2264 function_symbol (operands[3], \"__sdivsi3_2\", SFUNC_STATIC);
2265 else
2266 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2267
2268 if (TARGET_SHMEDIA)
2269 last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2270 (operands[0], operands[3]));
2271 else if (TARGET_FPU_ANY)
2272 last = gen_divsi3_i4_single (operands[0], operands[3]);
2273 else
2274 last = gen_divsi3_i1 (operands[0], operands[3]);
2275 }
2276 else
2277 {
2278 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2279 last = gen_divsi3_i1 (operands[0], operands[3]);
2280 }
2281 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2282 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2283 emit_insn (last);
2284 DONE;
2285 }")
2286
2287 ;; operands: scratch, tab_base, tab_ix
2288 ;; These are unspecs because we could generate an indexed addressing mode
2289 ;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2290 ;; confuse reload. See PR27117.
2291
2292 (define_insn "divsi_inv_qitable"
2293 [(set (match_operand:DI 0 "register_operand" "=r")
2294 (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2295 (match_operand:DI 2 "register_operand" "r")]
2296 UNSPEC_DIV_INV_TABLE)))]
2297 "TARGET_SHMEDIA"
2298 "@
2299 ldx.ub %1, %2, %0"
2300 [(set_attr "type" "load_media")
2301 (set_attr "highpart" "user")])
2302
2303 ;; operands: scratch, tab_base, tab_ix
2304 (define_insn "divsi_inv_hitable"
2305 [(set (match_operand:DI 0 "register_operand" "=r")
2306 (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2307 (match_operand:DI 2 "register_operand" "r")]
2308 UNSPEC_DIV_INV_TABLE)))]
2309 "TARGET_SHMEDIA"
2310 "@
2311 ldx.w %1, %2, %0"
2312 [(set_attr "type" "load_media")
2313 (set_attr "highpart" "user")])
2314
2315 ;; operands: inv0, tab_base, tab_ix, norm32
2316 ;; scratch equiv in sdivsi3_2: r19, r21
2317 (define_expand "divsi_inv_m0"
2318 [(set (match_operand:SI 0 "register_operand" "=r")
2319 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2320 (match_operand:DI 2 "register_operand" "r")
2321 (match_operand:SI 3 "register_operand" "r")]
2322 UNSPEC_DIV_INV_M0))
2323 (clobber (match_operand:DI 4 "register_operand" "=r"))
2324 (clobber (match_operand:DI 5 "register_operand" "=r"))]
2325 "TARGET_SHMEDIA"
2326 "
2327 {
2328 /*
2329 tab_base: r20
2330 tab_ix: r21
2331 norm32: r25
2332 ldx.ub r20, r21, r19 // u0.8
2333 shlli r21, 1, r21
2334 muls.l r25, r19, r19 // s2.38
2335 ldx.w r20, r21, r21 // s2.14
2336 shari r19, 24, r19 // truncate to s2.14
2337 sub r21, r19, r19 // some 11 bit inverse in s1.14
2338 */
2339
2340 rtx inv0 = operands[0];
2341 rtx tab_base = operands[1];
2342 rtx tab_ix = operands[2];
2343 rtx norm32 = operands[3];
2344 rtx scratch0 = operands[4];
2345 rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2346 rtx scratch1 = operands[5];
2347
2348 emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2349 emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2350 emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2351 emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2352 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2353 emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2354 DONE;
2355 }")
2356
2357 ;; operands: inv1, tab_base, tab_ix, norm32
2358 (define_insn_and_split "divsi_inv_m1"
2359 [(set (match_operand:SI 0 "register_operand" "=r")
2360 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2361 (match_operand:DI 2 "register_operand" "r")
2362 (match_operand:SI 3 "register_operand" "r")]
2363 UNSPEC_DIV_INV_M1))
2364 (clobber (match_operand:SI 4 "register_operand" "=r"))
2365 (clobber (match_operand:DI 5 "register_operand" "=r"))
2366 (clobber (match_operand:DI 6 "register_operand" "=r"))
2367 (clobber (match_operand:DI 7 "register_operand" "=r"))
2368 (clobber (match_operand:DI 8 "register_operand" "=r"))]
2369 "TARGET_SHMEDIA"
2370 "#"
2371 "&& !can_create_pseudo_p ()"
2372 [(pc)]
2373 "
2374 {
2375 /* inv0: r19
2376 muls.l r19, r19, r18 // u0.28
2377 muls.l r25, r18, r18 // s2.58
2378 shlli r19, 45, r0 // multiply by two and convert to s2.58
2379 sub r0, r18, r18
2380 shari r18, 28, r18 // some 18 bit inverse in s1.30
2381 */
2382
2383 rtx inv1 = operands[0];
2384 rtx tab_base = operands[1];
2385 rtx tab_ix = operands[2];
2386 rtx norm32 = operands[3];
2387 rtx inv0 = operands[4];
2388 rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2389 rtx scratch0a = operands[5];
2390 rtx scratch0b = operands[6];
2391 rtx scratch0 = operands[7];
2392 rtx scratch1 = operands[8];
2393 rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2394
2395 emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2396 scratch0a, scratch0b));
2397 emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2398 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2399 emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2400 emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2401 emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2402 DONE;
2403 }")
2404
2405 ;; operands: inv2, norm32, inv1, i92
2406 (define_insn_and_split "divsi_inv_m2"
2407 [(set (match_operand:SI 0 "register_operand" "=r")
2408 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2409 (match_operand:SI 2 "register_operand" "r")
2410 (match_operand:DI 3 "register_operand" "r")]
2411 UNSPEC_DIV_INV_M2))
2412 (clobber (match_operand:DI 4 "register_operand" "=r"))]
2413 "TARGET_SHMEDIA"
2414 "#"
2415 "&& !can_create_pseudo_p ()"
2416 [(pc)]
2417 "
2418 {
2419 /*
2420 muls.l r18, r25, r0 // s2.60
2421 shari r0, 16, r0 // s-16.44
2422 sub
2423 muls.l r0, r18, r19 // s-16.74
2424 shari r19, 30, r19 // s-16.44
2425 */
2426 rtx inv2 = operands[0];
2427 rtx norm32 = operands[1];
2428 rtx inv1 = operands[2];
2429 rtx i92 = operands[3];
2430 rtx scratch0 = operands[4];
2431 rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2432
2433 emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2434 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2435 emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2436 emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2437 emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2438 DONE;
2439 }")
2440
2441 (define_insn_and_split "divsi_inv_m3"
2442 [(set (match_operand:SI 0 "register_operand" "=r")
2443 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2444 (match_operand:SI 2 "register_operand" "r")
2445 (match_operand:SI 3 "register_operand" "r")
2446 (match_operand:DI 4 "register_operand" "r")
2447 (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
2448 (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
2449 UNSPEC_DIV_INV_M3))
2450 (clobber (match_operand:DI 7 "register_operand" "=r"))
2451 (clobber (match_operand:DI 8 "register_operand" "=r"))
2452 (clobber (match_operand:DI 9 "register_operand" "=r"))
2453 (clobber (match_operand:DI 10 "register_operand" "=r"))
2454 (clobber (match_operand:SI 11 "register_operand" "=r"))
2455 (clobber (match_operand:SI 12 "register_operand" "=r"))
2456 (clobber (match_operand:DI 13 "register_operand" "=r"))]
2457 "TARGET_SHMEDIA"
2458 "#"
2459 "&& !can_create_pseudo_p ()"
2460 [(pc)]
2461 "
2462 {
2463 /*
2464 r0: result r1: shift r4: dividend r18: inv1 r19: inv2
2465 r0: scratch0 r19: scratch1 r21: scratch2
2466
2467 muls.l r18, r4, r25 // s32.30
2468 muls.l r19, r4, r19 // s15.30
2469 shari r25, 63, r21
2470 shari r19, 14, r19 // s18.-14
2471 sub r25, r19, r0
2472 shard r0, r1, r0
2473 sub r0, r21, r0
2474 */
2475
2476 rtx result = operands[0];
2477 rtx dividend = operands[1];
2478 rtx inv1 = operands[2];
2479 rtx inv2 = operands[3];
2480 rtx shift = operands[4];
2481 rtx scratch0 = operands[7];
2482 rtx scratch1 = operands[8];
2483 rtx scratch2 = operands[9];
2484
2485 if (satisfies_constraint_N (dividend))
2486 {
2487 emit_move_insn (result, dividend);
2488 DONE;
2489 }
2490
2491 emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
2492 emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
2493 emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
2494 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
2495 emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
2496 emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
2497 emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
2498 DONE;
2499 }")
2500
2501 ;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
2502 ;; inv1: tab_base, tab_ix, norm32
2503 ;; inv2: norm32, inv1, i92
2504 (define_insn_and_split "divsi_inv_m1_3"
2505 [(set (match_operand:SI 0 "register_operand" "=r")
2506 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2507 (unspec:SI [(match_operand:DI 2 "register_operand" "r")
2508 (match_operand:DI 3 "register_operand" "r")
2509 (match_operand:SI 4 "register_operand" "r")]
2510 UNSPEC_DIV_INV_M1)
2511 (unspec:SI [(match_dup 4)
2512 (unspec:SI [(match_dup 2)
2513 (match_dup 3)
2514 (match_dup 4)] UNSPEC_DIV_INV_M1)
2515 (match_operand:SI 5 "" "")]
2516 UNSPEC_DIV_INV_M2)
2517 (match_operand:DI 6 "register_operand" "r")
2518 (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
2519 (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
2520 UNSPEC_DIV_INV_M3))
2521 (clobber (match_operand:DI 9 "register_operand" "=r"))
2522 (clobber (match_operand:DI 10 "register_operand" "=r"))
2523 (clobber (match_operand:DI 11 "register_operand" "=r"))
2524 (clobber (match_operand:DI 12 "register_operand" "=r"))
2525 (clobber (match_operand:SI 13 "register_operand" "=r"))
2526 (clobber (match_operand:SI 14 "register_operand" "=r"))
2527 (clobber (match_operand:DI 15 "register_operand" "=r"))]
2528 "TARGET_SHMEDIA
2529 && (TARGET_DIVIDE_INV_MINLAT
2530 || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2531 "#"
2532 "&& !can_create_pseudo_p ()"
2533 [(pc)]
2534 "
2535 {
2536 rtx result = operands[0];
2537 rtx dividend = operands[1];
2538 rtx tab_base = operands[2];
2539 rtx tab_ix = operands[3];
2540 rtx norm32 = operands[4];
2541 /* rtx i92 = operands[5]; */
2542 rtx shift = operands[6];
2543 rtx i2p27 = operands[7];
2544 rtx i43 = operands[8];
2545 rtx scratch0 = operands[9];
2546 rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2547 rtx scratch1 = operands[10];
2548 rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2549 rtx scratch2 = operands[11];
2550 rtx scratch3 = operands[12];
2551 rtx scratch4 = operands[13];
2552 rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
2553 rtx scratch5 = operands[14];
2554 rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
2555 rtx scratch6 = operands[15];
2556
2557 emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
2558 scratch0, scratch1));
2559 /* inv0 == scratch4 */
2560 if (! TARGET_DIVIDE_INV20U)
2561 {
2562 emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
2563 i2p27 = scratch0;
2564 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
2565 }
2566 else
2567 {
2568 emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
2569 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2570 }
2571 emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
2572 emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
2573 emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
2574 /* inv1 == scratch4 */
2575
2576 if (TARGET_DIVIDE_INV_MINLAT)
2577 {
2578 emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
2579 emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
2580 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
2581 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
2582 emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
2583 emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
2584 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
2585 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
2586 emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
2587 emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
2588 emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
2589 }
2590 else
2591 {
2592 rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
2593 /* Use separate scratch regs for nsb and sign to allow scheduling. */
2594 emit_insn (gen_nsbdi (scratch6,
2595 simplify_gen_subreg (DImode, dividend, SImode, 0)));
2596 emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
2597 emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
2598 emit_insn (gen_divsi_inv20 (scratch2,
2599 norm32, scratch4, dividend,
2600 scratch6, scratch3, i43,
2601 /* scratch0 may be shared with i2p27. */
2602 scratch0, scratch1, scratch5,
2603 label, label, i2p27));
2604 }
2605 emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
2606 emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
2607 DONE;
2608 }")
2609
2610 (define_insn "divsi_inv20"
2611 [(set (match_operand:DI 0 "register_operand" "=&r")
2612 (unspec:DI [(match_operand:SI 1 "register_operand" "r")
2613 (match_operand:SI 2 "register_operand" "r")
2614 (match_operand:SI 3 "register_operand" "r")
2615 (match_operand:DI 4 "register_operand" "r")
2616 (match_operand:DI 5 "register_operand" "r")
2617 (match_operand:DI 6 "register_operand" "r")
2618 (match_operand:DI 12 "register_operand" "r")
2619 (match_operand 10 "target_operand" "b")
2620 (match_operand 11 "immediate_operand" "i")]
2621 UNSPEC_DIV_INV20))
2622 (clobber (match_operand:DI 7 "register_operand" "=&r"))
2623 (clobber (match_operand:DI 8 "register_operand" "=&r"))
2624 (clobber (match_operand:SI 9 "register_operand" "=r"))]
2625 "TARGET_SHMEDIA
2626 && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2627 "*
2628 {
2629 /* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
2630 %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
2631 %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
2632 %10 label (tr), %11 label (imm)
2633
2634 muls.l inv1, norm32, scratch0 // s2.60
2635 muls.l inv1, dividend, result // s32.30
2636 xor i2p27, result_sign, round_scratch
2637 bge/u dividend_nsb, i43, tr.. (label)
2638 shari scratch0, 16, scratch0 // s-16.44
2639 muls.l sratch0_si, inv1, scratch0 // s-16.74
2640 sub result, round_scratch, result
2641 shari dividend, 14, scratch1 // s19.-14
2642 shari scratch0, 30, scratch0 // s-16.44
2643 muls.l scratch0, scratch1, round_scratch // s15.30
2644 label:
2645 sub result, round_scratch, result */
2646
2647 int likely = TARGET_DIVIDE_INV20L;
2648
2649 if (! likely) output_asm_insn (\"muls.l\t%2, %1 , %8\", operands);
2650 output_asm_insn (\"muls.l\t%2, %3, %0\;xor\t%12, %5, %7\", operands);
2651 output_asm_insn (likely
2652 ? \"bge/l\t%4, %6, %10\;muls.l\t%2, %1 , %8\"
2653 : \"bge/u\t%4, %6, %10\", operands);
2654 output_asm_insn (\"shari\t%8, 16, %8\;muls.l\t%8, %2, %8\", operands);
2655 if (! likely) output_asm_insn (\"sub\t%0, %7, %0\", operands);
2656 output_asm_insn (\"shari\t%3, 14, %9\;shari\t%8, 30, %8\", operands);
2657 return (likely
2658 ? \"muls.l\t%8, %9, %8\;sub\t%0, %8, %0\n%11:\tadd\t%0, %7, %0\"
2659 : \"muls.l\t%8, %9, %7\n%11:\tsub\t%0, %7, %0\");
2660 }")
2661
2662 (define_insn_and_split "divsi_inv_fp"
2663 [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
2664 (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
2665 (match_operand:SI 2 "register_operand" "rf")))
2666 (use (match_operand:SI 3 "general_movsrc_operand" "r"))
2667 (clobber (match_operand:SI 4 "register_operand" "=r"))
2668 (clobber (match_operand:SI 5 "register_operand" "=r"))
2669 (clobber (match_operand:DF 6 "register_operand" "=r"))
2670 (clobber (match_operand:DF 7 "register_operand" "=r"))
2671 (clobber (match_operand:DF 8 "register_operand" "=r"))]
2672 "TARGET_SHMEDIA_FPU"
2673 "#"
2674 "&& (high_life_started || reload_completed)"
2675 [(set (match_dup 0) (match_dup 3))]
2676 ""
2677 [(set_attr "highpart" "must_split")])
2678
2679 ;; If a matching group of divide-by-inverse instructions is in the same
2680 ;; basic block after gcse & loop optimizations, we want to transform them
2681 ;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
2682 (define_insn_and_split "*divsi_inv_fp_combine"
2683 [(set (match_operand:SI 0 "register_operand" "=f")
2684 (div:SI (match_operand:SI 1 "register_operand" "f")
2685 (match_operand:SI 2 "register_operand" "f")))
2686 (use (unspec:SI [(match_dup 1)
2687 (match_operand:SI 3 "" "")
2688 (unspec:SI [(match_operand:SI 4 "" "")
2689 (match_dup 3)
2690 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
2691 (match_operand:DI 6 "" "")
2692 (const_int 0)
2693 (const_int 0)] UNSPEC_DIV_INV_M3))
2694 (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
2695 (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
2696 (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
2697 (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
2698 (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
2699 "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
2700 "#"
2701 "&& 1"
2702 [(set (match_dup 9) (float:DF (match_dup 1)))
2703 (set (match_dup 10) (float:DF (match_dup 2)))
2704 (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
2705 (set (match_dup 8)
2706 (fix:SI (match_dup 11)))
2707 (set (match_dup 0) (match_dup 8))]
2708 "
2709 {
2710 if (! fp_arith_reg_operand (operands[1], SImode))
2711 {
2712 emit_move_insn (operands[7], operands[1]);
2713 operands[1] = operands[7];
2714 }
2715 if (! fp_arith_reg_operand (operands[2], SImode))
2716 {
2717 emit_move_insn (operands[8], operands[2]);
2718 operands[2] = operands[8];
2719 }
2720 }"
2721 [(set_attr "highpart" "must_split")])
2722 \f
2723 ;; -------------------------------------------------------------------------
2724 ;; Multiplication instructions
2725 ;; -------------------------------------------------------------------------
2726
2727 (define_insn "umulhisi3_i"
2728 [(set (reg:SI MACL_REG)
2729 (mult:SI (zero_extend:SI
2730 (match_operand:HI 0 "arith_reg_operand" "r"))
2731 (zero_extend:SI
2732 (match_operand:HI 1 "arith_reg_operand" "r"))))]
2733 "TARGET_SH1"
2734 "mulu.w %1,%0"
2735 [(set_attr "type" "smpy")])
2736
2737 (define_insn "mulhisi3_i"
2738 [(set (reg:SI MACL_REG)
2739 (mult:SI (sign_extend:SI
2740 (match_operand:HI 0 "arith_reg_operand" "r"))
2741 (sign_extend:SI
2742 (match_operand:HI 1 "arith_reg_operand" "r"))))]
2743 "TARGET_SH1"
2744 "muls.w %1,%0"
2745 [(set_attr "type" "smpy")])
2746
2747 (define_expand "mulhisi3"
2748 [(set (reg:SI MACL_REG)
2749 (mult:SI (sign_extend:SI
2750 (match_operand:HI 1 "arith_reg_operand" ""))
2751 (sign_extend:SI
2752 (match_operand:HI 2 "arith_reg_operand" ""))))
2753 (set (match_operand:SI 0 "arith_reg_operand" "")
2754 (reg:SI MACL_REG))]
2755 "TARGET_SH1"
2756 "
2757 {
2758 rtx insn, macl;
2759
2760 macl = gen_rtx_REG (SImode, MACL_REG);
2761 start_sequence ();
2762 emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
2763 insn = get_insns ();
2764 end_sequence ();
2765 /* expand_binop can't find a suitable code in umul_widen_optab to
2766 make a REG_EQUAL note from, so make one here.
2767 See also smulsi3_highpart.
2768 ??? Alternatively, we could put this at the calling site of expand_binop,
2769 i.e. expand_expr. */
2770 /* Use emit_libcall_block for loop invariant code motion and to make
2771 a REG_EQUAL note. */
2772 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
2773
2774 DONE;
2775 }")
2776
2777 (define_expand "umulhisi3"
2778 [(set (reg:SI MACL_REG)
2779 (mult:SI (zero_extend:SI
2780 (match_operand:HI 1 "arith_reg_operand" ""))
2781 (zero_extend:SI
2782 (match_operand:HI 2 "arith_reg_operand" ""))))
2783 (set (match_operand:SI 0 "arith_reg_operand" "")
2784 (reg:SI MACL_REG))]
2785 "TARGET_SH1"
2786 "
2787 {
2788 rtx insn, macl;
2789
2790 macl = gen_rtx_REG (SImode, MACL_REG);
2791 start_sequence ();
2792 emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
2793 insn = get_insns ();
2794 end_sequence ();
2795 /* expand_binop can't find a suitable code in umul_widen_optab to
2796 make a REG_EQUAL note from, so make one here.
2797 See also smulsi3_highpart.
2798 ??? Alternatively, we could put this at the calling site of expand_binop,
2799 i.e. expand_expr. */
2800 /* Use emit_libcall_block for loop invariant code motion and to make
2801 a REG_EQUAL note. */
2802 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
2803
2804 DONE;
2805 }")
2806
2807 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
2808 ;; a call to a routine which clobbers known registers.
2809
2810 (define_insn ""
2811 [(set (match_operand:SI 1 "register_operand" "=z")
2812 (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2813 (clobber (reg:SI MACL_REG))
2814 (clobber (reg:SI T_REG))
2815 (clobber (reg:SI PR_REG))
2816 (clobber (reg:SI R3_REG))
2817 (clobber (reg:SI R2_REG))
2818 (clobber (reg:SI R1_REG))
2819 (use (match_operand:SI 0 "arith_reg_operand" "r"))]
2820 "TARGET_SH1"
2821 "jsr @%0%#"
2822 [(set_attr "type" "sfunc")
2823 (set_attr "needs_delay_slot" "yes")])
2824
2825 (define_expand "mulsi3_call"
2826 [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2827 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2828 (parallel[(set (match_operand:SI 0 "register_operand" "")
2829 (mult:SI (reg:SI R4_REG)
2830 (reg:SI R5_REG)))
2831 (clobber (reg:SI MACL_REG))
2832 (clobber (reg:SI T_REG))
2833 (clobber (reg:SI PR_REG))
2834 (clobber (reg:SI R3_REG))
2835 (clobber (reg:SI R2_REG))
2836 (clobber (reg:SI R1_REG))
2837 (use (match_operand:SI 3 "register_operand" ""))])]
2838 "TARGET_SH1"
2839 "")
2840
2841 (define_insn "mul_r"
2842 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2843 (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
2844 (match_operand:SI 2 "arith_reg_operand" "z")))]
2845 "TARGET_SH2A"
2846 "mulr %2,%0"
2847 [(set_attr "type" "dmpy")])
2848
2849 (define_insn "mul_l"
2850 [(set (reg:SI MACL_REG)
2851 (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
2852 (match_operand:SI 1 "arith_reg_operand" "r")))]
2853 "TARGET_SH2"
2854 "mul.l %1,%0"
2855 [(set_attr "type" "dmpy")])
2856
2857 (define_expand "mulsi3"
2858 [(set (reg:SI MACL_REG)
2859 (mult:SI (match_operand:SI 1 "arith_reg_operand" "")
2860 (match_operand:SI 2 "arith_reg_operand" "")))
2861 (set (match_operand:SI 0 "arith_reg_operand" "")
2862 (reg:SI MACL_REG))]
2863 "TARGET_SH1"
2864 "
2865 {
2866 if (!TARGET_SH2)
2867 {
2868 /* The address must be set outside the libcall,
2869 since it goes into a pseudo. */
2870 rtx sym = function_symbol (NULL, \"__mulsi3\", SFUNC_STATIC);
2871 rtx addr = force_reg (SImode, sym);
2872 rtx insns = gen_mulsi3_call (operands[0], operands[1],
2873 operands[2], addr);
2874 emit_insn (insns);
2875 }
2876 else
2877 {
2878 rtx macl = gen_rtx_REG (SImode, MACL_REG);
2879
2880 emit_insn (gen_mul_l (operands[1], operands[2]));
2881 /* consec_sets_giv can only recognize the first insn that sets a
2882 giv as the giv insn. So we must tag this also with a REG_EQUAL
2883 note. */
2884 emit_insn (gen_movsi_i ((operands[0]), macl));
2885 }
2886 DONE;
2887 }")
2888
2889 (define_insn "mulsidi3_i"
2890 [(set (reg:SI MACH_REG)
2891 (truncate:SI
2892 (lshiftrt:DI
2893 (mult:DI
2894 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2895 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2896 (const_int 32))))
2897 (set (reg:SI MACL_REG)
2898 (mult:SI (match_dup 0)
2899 (match_dup 1)))]
2900 "TARGET_SH2"
2901 "dmuls.l %1,%0"
2902 [(set_attr "type" "dmpy")])
2903
2904 (define_expand "mulsidi3"
2905 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2906 (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2907 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2908 "TARGET_SH2 || TARGET_SHMEDIA"
2909 "
2910 {
2911 if (TARGET_SH2)
2912 {
2913 emit_insn (gen_mulsidi3_compact (operands[0], operands[1],
2914 operands[2]));
2915 DONE;
2916 }
2917 }")
2918
2919 (define_insn "mulsidi3_media"
2920 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2921 (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2922 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2923 "TARGET_SHMEDIA"
2924 "muls.l %1, %2, %0"
2925 [(set_attr "type" "dmpy_media")
2926 (set_attr "highpart" "ignore")])
2927
2928 (define_insn "mulsidi3_compact"
2929 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2930 (mult:DI
2931 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2932 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2933 (clobber (reg:SI MACH_REG))
2934 (clobber (reg:SI MACL_REG))]
2935 "TARGET_SH2"
2936 "#")
2937
2938 (define_split
2939 [(set (match_operand:DI 0 "arith_reg_dest" "")
2940 (mult:DI
2941 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2942 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2943 (clobber (reg:SI MACH_REG))
2944 (clobber (reg:SI MACL_REG))]
2945 "TARGET_SH2"
2946 [(const_int 0)]
2947 "
2948 {
2949 rtx low_dst = gen_lowpart (SImode, operands[0]);
2950 rtx high_dst = gen_highpart (SImode, operands[0]);
2951
2952 emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
2953
2954 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
2955 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
2956 /* We need something to tag the possible REG_EQUAL notes on to. */
2957 emit_move_insn (operands[0], operands[0]);
2958 DONE;
2959 }")
2960
2961 (define_insn "umulsidi3_i"
2962 [(set (reg:SI MACH_REG)
2963 (truncate:SI
2964 (lshiftrt:DI
2965 (mult:DI
2966 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2967 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2968 (const_int 32))))
2969 (set (reg:SI MACL_REG)
2970 (mult:SI (match_dup 0)
2971 (match_dup 1)))]
2972 "TARGET_SH2"
2973 "dmulu.l %1,%0"
2974 [(set_attr "type" "dmpy")])
2975
2976 (define_expand "umulsidi3"
2977 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2978 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2979 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2980 "TARGET_SH2 || TARGET_SHMEDIA"
2981 "
2982 {
2983 if (TARGET_SH2)
2984 {
2985 emit_insn (gen_umulsidi3_compact (operands[0], operands[1],
2986 operands[2]));
2987 DONE;
2988 }
2989 }")
2990
2991 (define_insn "umulsidi3_media"
2992 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2993 (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2994 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2995 "TARGET_SHMEDIA"
2996 "mulu.l %1, %2, %0"
2997 [(set_attr "type" "dmpy_media")
2998 (set_attr "highpart" "ignore")])
2999
3000 (define_insn "umulsidi3_compact"
3001 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3002 (mult:DI
3003 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3004 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3005 (clobber (reg:SI MACH_REG))
3006 (clobber (reg:SI MACL_REG))]
3007 "TARGET_SH2"
3008 "#")
3009
3010 (define_split
3011 [(set (match_operand:DI 0 "arith_reg_dest" "")
3012 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3013 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
3014 (clobber (reg:SI MACH_REG))
3015 (clobber (reg:SI MACL_REG))]
3016 "TARGET_SH2"
3017 [(const_int 0)]
3018 "
3019 {
3020 rtx low_dst = gen_lowpart (SImode, operands[0]);
3021 rtx high_dst = gen_highpart (SImode, operands[0]);
3022
3023 emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
3024
3025 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3026 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3027 /* We need something to tag the possible REG_EQUAL notes on to. */
3028 emit_move_insn (operands[0], operands[0]);
3029 DONE;
3030 }")
3031
3032 (define_insn "smulsi3_highpart_i"
3033 [(set (reg:SI MACH_REG)
3034 (truncate:SI
3035 (lshiftrt:DI
3036 (mult:DI
3037 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3038 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3039 (const_int 32))))
3040 (clobber (reg:SI MACL_REG))]
3041 "TARGET_SH2"
3042 "dmuls.l %1,%0"
3043 [(set_attr "type" "dmpy")])
3044
3045 (define_expand "smulsi3_highpart"
3046 [(parallel
3047 [(set (reg:SI MACH_REG)
3048 (truncate:SI
3049 (lshiftrt:DI
3050 (mult:DI
3051 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3052 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3053 (const_int 32))))
3054 (clobber (reg:SI MACL_REG))])
3055 (set (match_operand:SI 0 "arith_reg_operand" "")
3056 (reg:SI MACH_REG))]
3057 "TARGET_SH2"
3058 "
3059 {
3060 rtx insn, mach;
3061
3062 mach = gen_rtx_REG (SImode, MACH_REG);
3063 start_sequence ();
3064 emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3065 insn = get_insns ();
3066 end_sequence ();
3067 /* expand_binop can't find a suitable code in mul_highpart_optab to
3068 make a REG_EQUAL note from, so make one here.
3069 See also {,u}mulhisi.
3070 ??? Alternatively, we could put this at the calling site of expand_binop,
3071 i.e. expand_mult_highpart. */
3072 /* Use emit_libcall_block for loop invariant code motion and to make
3073 a REG_EQUAL note. */
3074 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3075
3076 DONE;
3077 }")
3078
3079 (define_insn "umulsi3_highpart_i"
3080 [(set (reg:SI MACH_REG)
3081 (truncate:SI
3082 (lshiftrt:DI
3083 (mult:DI
3084 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3085 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3086 (const_int 32))))
3087 (clobber (reg:SI MACL_REG))]
3088 "TARGET_SH2"
3089 "dmulu.l %1,%0"
3090 [(set_attr "type" "dmpy")])
3091
3092 (define_expand "umulsi3_highpart"
3093 [(parallel
3094 [(set (reg:SI MACH_REG)
3095 (truncate:SI
3096 (lshiftrt:DI
3097 (mult:DI
3098 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3099 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3100 (const_int 32))))
3101 (clobber (reg:SI MACL_REG))])
3102 (set (match_operand:SI 0 "arith_reg_operand" "")
3103 (reg:SI MACH_REG))]
3104 "TARGET_SH2"
3105 "
3106 {
3107 rtx insn, mach;
3108
3109 mach = gen_rtx_REG (SImode, MACH_REG);
3110 start_sequence ();
3111 emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3112 insn = get_insns ();
3113 end_sequence ();
3114 /* Use emit_libcall_block for loop invariant code motion and to make
3115 a REG_EQUAL note. */
3116 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3117
3118 DONE;
3119 }")
3120
3121 (define_insn_and_split "muldi3"
3122 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3123 (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3124 (match_operand:DI 2 "arith_reg_operand" "r")))
3125 (clobber (match_scratch:DI 3 "=&r"))
3126 (clobber (match_scratch:DI 4 "=r"))]
3127 "TARGET_SHMEDIA"
3128 "#"
3129 "reload_completed"
3130 [(const_int 0)]
3131 "
3132 {
3133 rtx op3_v2si, op2_v2si;
3134
3135 op3_v2si = operands[3];
3136 if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3137 {
3138 op3_v2si = XEXP (op3_v2si, 0);
3139 op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3140 }
3141 op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3142 op2_v2si = operands[2];
3143 if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3144 {
3145 op2_v2si = XEXP (op2_v2si, 0);
3146 op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3147 }
3148 op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3149 emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3150 emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3151 emit_insn (gen_umulsidi3_media (operands[4],
3152 sh_gen_truncate (SImode, operands[1], 0),
3153 sh_gen_truncate (SImode, operands[2], 0)));
3154 emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3155 emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3156 emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3157 emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3158 DONE;
3159 }")
3160
3161 \f
3162 ;; -------------------------------------------------------------------------
3163 ;; Logical operations
3164 ;; -------------------------------------------------------------------------
3165
3166 (define_insn "*andsi3_compact"
3167 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3168 (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3169 (match_operand:SI 2 "logical_operand" "K08,r")))]
3170 "TARGET_SH1"
3171 "and %2,%0"
3172 [(set_attr "type" "arith")])
3173
3174 (define_insn "*andsi3_media"
3175 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3176 (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3177 (match_operand:SI 2 "logical_operand" "r,I10")))]
3178 "TARGET_SHMEDIA"
3179 "@
3180 and %1, %2, %0
3181 andi %1, %2, %0"
3182 [(set_attr "type" "arith_media")])
3183
3184 (define_insn "*andsi3_bclr"
3185 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3186 (and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3187 (match_operand:SI 2 "const_int_operand" "Psz")))]
3188 "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
3189 "bclr\\t%W2,%0"
3190 [(set_attr "type" "arith")])
3191
3192 ;; If the constant is 255, then emit an extu.b instruction instead of an
3193 ;; and, since that will give better code.
3194
3195 (define_expand "andsi3"
3196 [(set (match_operand:SI 0 "arith_reg_operand" "")
3197 (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3198 (match_operand:SI 2 "logical_operand" "")))]
3199 ""
3200 "
3201 {
3202 if (TARGET_SH1
3203 && CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 255)
3204 {
3205 emit_insn (gen_zero_extendqisi2 (operands[0],
3206 gen_lowpart (QImode, operands[1])));
3207 DONE;
3208 }
3209 }")
3210
3211 (define_insn_and_split "anddi3"
3212 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3213 (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3214 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
3215 "TARGET_SHMEDIA"
3216 "@
3217 and %1, %2, %0
3218 andi %1, %2, %0
3219 #"
3220 "reload_completed
3221 && ! logical_operand (operands[2], DImode)"
3222 [(const_int 0)]
3223 "
3224 {
3225 if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3226 emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3227 else
3228 emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3229 DONE;
3230 }"
3231 [(set_attr "type" "arith_media")])
3232
3233 (define_insn "andcsi3"
3234 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3235 (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3236 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3237 "TARGET_SHMEDIA"
3238 "andc %1,%2,%0"
3239 [(set_attr "type" "arith_media")])
3240
3241 (define_insn "andcdi3"
3242 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3243 (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3244 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3245 "TARGET_SHMEDIA"
3246 "andc %1,%2,%0"
3247 [(set_attr "type" "arith_media")])
3248
3249 (define_expand "iorsi3"
3250 [(set (match_operand:SI 0 "arith_reg_operand" "")
3251 (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3252 (match_operand:SI 2 "logical_operand" "")))]
3253 ""
3254 "")
3255
3256 (define_insn "*iorsi3_compact"
3257 [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3258 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3259 (match_operand:SI 2 "logical_operand" "r,K08")))]
3260 "TARGET_SH1
3261 && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
3262 "or %2,%0"
3263 [(set_attr "type" "arith")])
3264
3265 (define_insn "*iorsi3_media"
3266 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3267 (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3268 (match_operand:SI 2 "logical_operand" "r,I10")))]
3269 "TARGET_SHMEDIA"
3270 "@
3271 or %1, %2, %0
3272 ori %1, %2, %0"
3273 [(set_attr "type" "arith_media")])
3274
3275 (define_insn "*iorsi3_bset"
3276 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3277 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3278 (match_operand:SI 2 "const_int_operand" "Pso")))]
3279 "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
3280 "bset\\t%V2,%0"
3281 [(set_attr "type" "arith")])
3282
3283 (define_insn "iordi3"
3284 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3285 (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3286 (match_operand:DI 2 "logical_operand" "r,I10")))]
3287 "TARGET_SHMEDIA"
3288 "@
3289 or %1, %2, %0
3290 ori %1, %2, %0"
3291 [(set_attr "type" "arith_media")])
3292
3293 (define_insn_and_split "*logical_sidi3"
3294 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3295 (sign_extend:DI (match_operator:SI 3 "logical_operator"
3296 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3297 (match_operand:SI 2 "logical_operand" "r,I10")])))]
3298 "TARGET_SHMEDIA"
3299 "#"
3300 "&& reload_completed"
3301 [(set (match_dup 0) (match_dup 3))]
3302 "
3303 {
3304 operands[3]
3305 = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3306 simplify_gen_subreg (DImode, operands[1], SImode, 0),
3307 simplify_gen_subreg (DImode, operands[2], SImode, 0));
3308 }")
3309
3310 (define_insn_and_split "*logical_sidisi3"
3311 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3312 (truncate:SI (sign_extend:DI
3313 (match_operator:SI 3 "logical_operator"
3314 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3315 (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3316 "TARGET_SHMEDIA"
3317 "#"
3318 "&& 1"
3319 [(set (match_dup 0) (match_dup 3))])
3320
3321 (define_insn_and_split "*logical_sidi3_2"
3322 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3323 (sign_extend:DI (truncate:SI (sign_extend:DI
3324 (match_operator:SI 3 "logical_operator"
3325 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3326 (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3327 "TARGET_SHMEDIA"
3328 "#"
3329 "&& 1"
3330 [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3331
3332 (define_expand "xorsi3"
3333 [(set (match_operand:SI 0 "arith_reg_operand" "")
3334 (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3335 (match_operand:SI 2 "xor_operand" "")))]
3336 ""
3337 "")
3338
3339 (define_insn "*xorsi3_compact"
3340 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3341 (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3342 (match_operand:SI 2 "logical_operand" "K08,r")))]
3343 "TARGET_SH1"
3344 "xor %2,%0"
3345 [(set_attr "type" "arith")])
3346
3347 (define_insn "*xorsi3_media"
3348 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3349 (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3350 (match_operand:SI 2 "xor_operand" "r,I06")))]
3351 "TARGET_SHMEDIA"
3352 "@
3353 xor %1, %2, %0
3354 xori %1, %2, %0"
3355 [(set_attr "type" "arith_media")])
3356
3357 (define_insn "xordi3"
3358 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3359 (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3360 (match_operand:DI 2 "xor_operand" "r,I06")))]
3361 "TARGET_SHMEDIA"
3362 "@
3363 xor %1, %2, %0
3364 xori %1, %2, %0"
3365 [(set_attr "type" "arith_media")])
3366
3367 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3368 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
3369 (define_split
3370 [(set (match_operand:DI 0 "arith_reg_dest" "")
3371 (sign_extend:DI (match_operator 4 "binary_logical_operator"
3372 [(match_operand 1 "any_register_operand" "")
3373 (match_operand 2 "any_register_operand" "")])))]
3374 "TARGET_SHMEDIA"
3375 [(set (match_dup 5) (match_dup 4))
3376 (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3377 "
3378 {
3379 enum machine_mode inmode = GET_MODE (operands[1]);
3380 int offset = 0;
3381
3382 if (GET_CODE (operands[0]) == SUBREG)
3383 {
3384 offset = SUBREG_BYTE (operands[0]);
3385 operands[0] = SUBREG_REG (operands[0]);
3386 }
3387 gcc_assert (REG_P (operands[0]));
3388 if (! TARGET_LITTLE_ENDIAN)
3389 offset += 8 - GET_MODE_SIZE (inmode);
3390 operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3391 }")
3392 \f
3393 ;; -------------------------------------------------------------------------
3394 ;; Shifts and rotates
3395 ;; -------------------------------------------------------------------------
3396
3397 (define_expand "rotldi3"
3398 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3399 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3400 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3401 "TARGET_SHMEDIA"
3402 "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3403
3404 (define_insn "rotldi3_mextr"
3405 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3406 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3407 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3408 "TARGET_SHMEDIA"
3409 "*
3410 {
3411 static char templ[16];
3412
3413 sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\",
3414 8 - (int) (INTVAL (operands[2]) >> 3));
3415 return templ;
3416 }"
3417 [(set_attr "type" "arith_media")])
3418
3419 (define_expand "rotrdi3"
3420 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3421 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3422 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3423 "TARGET_SHMEDIA"
3424 "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3425
3426 (define_insn "rotrdi3_mextr"
3427 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3428 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3429 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3430 "TARGET_SHMEDIA"
3431 "*
3432 {
3433 static char templ[16];
3434
3435 sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\", (int) INTVAL (operands[2]) >> 3);
3436 return templ;
3437 }"
3438 [(set_attr "type" "arith_media")])
3439
3440 (define_split
3441 [(set (match_operand:DI 0 "arith_reg_dest" "")
3442 (ior:DI (zero_extend:DI (mem:QI (match_operand 1
3443 "ua_address_operand" "")))
3444 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
3445 (const_int 8))))
3446 (clobber (match_operand:DI 3 "register_operand" ""))]
3447 "TARGET_SHMEDIA"
3448 [(match_dup 4) (match_dup 5)]
3449 "
3450 {
3451 operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
3452 (operands[3], operands[1]));
3453 operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
3454 GEN_INT (56), GEN_INT (8));
3455 }")
3456
3457 (define_insn "rotlsi3_1"
3458 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3459 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3460 (const_int 1)))
3461 (set (reg:SI T_REG)
3462 (lshiftrt:SI (match_dup 1) (const_int 31)))]
3463 "TARGET_SH1"
3464 "rotl %0"
3465 [(set_attr "type" "arith")])
3466
3467 (define_insn "rotlsi3_31"
3468 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3469 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3470 (const_int 31)))
3471 (clobber (reg:SI T_REG))]
3472 "TARGET_SH1"
3473 "rotr %0"
3474 [(set_attr "type" "arith")])
3475
3476 (define_insn "rotlsi3_16"
3477 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3478 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
3479 (const_int 16)))]
3480 "TARGET_SH1"
3481 "swap.w %1,%0"
3482 [(set_attr "type" "arith")])
3483
3484 (define_expand "rotlsi3"
3485 [(set (match_operand:SI 0 "arith_reg_dest" "")
3486 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
3487 (match_operand:SI 2 "immediate_operand" "")))]
3488 "TARGET_SH1"
3489 "
3490 {
3491 static const char rot_tab[] = {
3492 000, 000, 000, 000, 000, 000, 010, 001,
3493 001, 001, 011, 013, 003, 003, 003, 003,
3494 003, 003, 003, 003, 003, 013, 012, 002,
3495 002, 002, 010, 000, 000, 000, 000, 000,
3496 };
3497
3498 int count, choice;
3499
3500 if (!CONST_INT_P (operands[2]))
3501 FAIL;
3502 count = INTVAL (operands[2]);
3503 choice = rot_tab[count];
3504 if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
3505 FAIL;
3506 choice &= 7;
3507 switch (choice)
3508 {
3509 case 0:
3510 emit_move_insn (operands[0], operands[1]);
3511 count -= (count & 16) * 2;
3512 break;
3513 case 3:
3514 emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
3515 count -= 16;
3516 break;
3517 case 1:
3518 case 2:
3519 {
3520 rtx parts[2];
3521 parts[0] = gen_reg_rtx (SImode);
3522 parts[1] = gen_reg_rtx (SImode);
3523 emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
3524 emit_move_insn (parts[choice-1], operands[1]);
3525 emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
3526 emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
3527 emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
3528 count = (count & ~16) - 8;
3529 }
3530 }
3531
3532 for (; count > 0; count--)
3533 emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
3534 for (; count < 0; count++)
3535 emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
3536
3537 DONE;
3538 }")
3539
3540 (define_insn "*rotlhi3_8"
3541 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3542 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
3543 (const_int 8)))]
3544 "TARGET_SH1"
3545 "swap.b %1,%0"
3546 [(set_attr "type" "arith")])
3547
3548 (define_expand "rotlhi3"
3549 [(set (match_operand:HI 0 "arith_reg_operand" "")
3550 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "")
3551 (match_operand:HI 2 "immediate_operand" "")))]
3552 "TARGET_SH1"
3553 "
3554 {
3555 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 8)
3556 FAIL;
3557 }")
3558
3559 ;;
3560 ;; shift left
3561
3562 ;; This pattern is used by init_expmed for computing the costs of shift
3563 ;; insns.
3564
3565 (define_insn_and_split "ashlsi3_std"
3566 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,r,r")
3567 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
3568 (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
3569 (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
3570 "(TARGET_SH3 || TARGET_SH2A)
3571 || (TARGET_SH1 && satisfies_constraint_P27 (operands[2]))"
3572 "@
3573 shld %2,%0
3574 add %0,%0
3575 shll%O2 %0
3576 #"
3577 "(TARGET_SH3 || TARGET_SH2A)
3578 && reload_completed
3579 && CONST_INT_P (operands[2])
3580 && ! satisfies_constraint_P27 (operands[2])"
3581 [(set (match_dup 3) (match_dup 2))
3582 (parallel
3583 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
3584 (clobber (match_dup 4))])]
3585 "operands[4] = gen_rtx_SCRATCH (SImode);"
3586 [(set_attr "length" "*,*,*,4")
3587 (set_attr "type" "dyn_shift,arith,arith,arith")])
3588
3589 (define_insn "ashlhi3_k"
3590 [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
3591 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
3592 (match_operand:HI 2 "const_int_operand" "M,P27")))]
3593 "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
3594 "@
3595 add %0,%0
3596 shll%O2 %0"
3597 [(set_attr "type" "arith")])
3598
3599 (define_insn "ashlsi3_n"
3600 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3601 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3602 (match_operand:SI 2 "const_int_operand" "n")))
3603 (clobber (reg:SI T_REG))]
3604 "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3605 "#"
3606 [(set (attr "length")
3607 (cond [(match_test "shift_insns_rtx (insn)")
3608 (const_string "2")
3609 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3610 (const_string "4")
3611 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3612 (const_string "6")]
3613 (const_string "8")))
3614 (set_attr "type" "arith")])
3615
3616 (define_split
3617 [(set (match_operand:SI 0 "arith_reg_dest" "")
3618 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3619 (match_operand:SI 2 "const_int_operand" "")))
3620 (clobber (reg:SI T_REG))]
3621 "TARGET_SH1 && reload_completed"
3622 [(use (reg:SI R0_REG))]
3623 "
3624 {
3625 gen_shifty_op (ASHIFT, operands);
3626 DONE;
3627 }")
3628
3629 (define_insn "ashlsi3_media"
3630 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3631 (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3632 (match_operand:SI 2 "shift_count_operand" "r,n")))]
3633 "TARGET_SHMEDIA"
3634 "@
3635 shlld.l %1, %2, %0
3636 shlli.l %1, %2, %0"
3637 [(set_attr "type" "arith_media")
3638 (set_attr "highpart" "ignore")])
3639
3640 (define_expand "ashlsi3"
3641 [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3642 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3643 (match_operand:SI 2 "nonmemory_operand" "")))
3644 (clobber (reg:SI T_REG))])]
3645 ""
3646 "
3647 {
3648 if (TARGET_SHMEDIA)
3649 {
3650 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
3651 DONE;
3652 }
3653 if (CONST_INT_P (operands[2])
3654 && sh_dynamicalize_shift_p (operands[2]))
3655 operands[2] = force_reg (SImode, operands[2]);
3656 if (TARGET_SH3 || TARGET_SH2A)
3657 {
3658 emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
3659 DONE;
3660 }
3661 if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3662 FAIL;
3663 }")
3664
3665 (define_insn "*ashlhi3_n"
3666 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3667 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
3668 (match_operand:HI 2 "const_int_operand" "n")))
3669 (clobber (reg:SI T_REG))]
3670 "TARGET_SH1"
3671 "#"
3672 [(set (attr "length")
3673 (cond [(match_test "shift_insns_rtx (insn)")
3674 (const_string "2")
3675 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3676 (const_string "4")]
3677 (const_string "6")))
3678 (set_attr "type" "arith")])
3679
3680 (define_expand "ashlhi3"
3681 [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
3682 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3683 (match_operand:SI 2 "nonmemory_operand" "")))
3684 (clobber (reg:SI T_REG))])]
3685 "TARGET_SH1"
3686 "
3687 {
3688 if (!CONST_INT_P (operands[2]))
3689 FAIL;
3690 /* It may be possible to call gen_ashlhi3 directly with more generic
3691 operands. Make sure operands[1] is a HImode register here. */
3692 if (!arith_reg_operand (operands[1], HImode))
3693 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3694 }")
3695
3696 (define_split
3697 [(set (match_operand:HI 0 "arith_reg_dest" "")
3698 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3699 (match_operand:HI 2 "const_int_operand" "")))
3700 (clobber (reg:SI T_REG))]
3701 "TARGET_SH1 && reload_completed"
3702 [(use (reg:SI R0_REG))]
3703 "
3704 {
3705 gen_shifty_hi_op (ASHIFT, operands);
3706 DONE;
3707 }")
3708
3709 ;
3710 ; arithmetic shift right
3711 ;
3712
3713 (define_insn "ashrsi3_k"
3714 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3715 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3716 (match_operand:SI 2 "const_int_operand" "M")))
3717 (clobber (reg:SI T_REG))]
3718 "TARGET_SH1 && INTVAL (operands[2]) == 1"
3719 "shar %0"
3720 [(set_attr "type" "arith")])
3721
3722 ;; We can't do HImode right shifts correctly unless we start out with an
3723 ;; explicit zero / sign extension; doing that would result in worse overall
3724 ;; code, so just let the machine independent code widen the mode.
3725 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
3726
3727
3728 ;; ??? This should be a define expand.
3729
3730 (define_insn "ashrsi2_16"
3731 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3732 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
3733 (const_int 16)))]
3734 "TARGET_SH1"
3735 "#"
3736 [(set_attr "length" "4")])
3737
3738 (define_split
3739 [(set (match_operand:SI 0 "arith_reg_dest" "")
3740 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3741 (const_int 16)))]
3742 "TARGET_SH1"
3743 [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
3744 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3745 "operands[2] = gen_lowpart (HImode, operands[0]);")
3746
3747 ;; ??? This should be a define expand.
3748
3749 (define_insn "ashrsi2_31"
3750 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3751 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3752 (const_int 31)))
3753 (clobber (reg:SI T_REG))]
3754 "TARGET_SH1"
3755 "#"
3756 [(set_attr "length" "4")])
3757
3758 (define_split
3759 [(set (match_operand:SI 0 "arith_reg_dest" "")
3760 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3761 (const_int 31)))
3762 (clobber (reg:SI T_REG))]
3763 "TARGET_SH1"
3764 [(const_int 0)]
3765 "
3766 {
3767 emit_insn (gen_ashlsi_c (operands[0], operands[1]));
3768 emit_insn (gen_mov_neg_si_t (copy_rtx (operands[0])));
3769 DONE;
3770 }")
3771
3772 (define_peephole2
3773 [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
3774 (set (reg:SI T_REG)
3775 (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
3776 "TARGET_SH1
3777 && peep2_reg_dead_p (2, operands[0])
3778 && peep2_reg_dead_p (2, operands[1])"
3779 [(const_int 0)]
3780 "
3781 {
3782 emit_insn (gen_ashlsi_c (operands[1], operands[1]));
3783 DONE;
3784 }")
3785
3786 (define_insn "ashlsi_c"
3787 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3788 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
3789 (set (reg:SI T_REG)
3790 (lt:SI (match_dup 1) (const_int 0)))]
3791 "TARGET_SH1"
3792 "shll %0"
3793 [(set_attr "type" "arith")])
3794
3795 (define_insn "*ashlsi_c_void"
3796 [(set (reg:SI T_REG)
3797 (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
3798 (clobber (match_scratch:SI 1 "=0"))]
3799 "TARGET_SH1 && cse_not_expected"
3800 "shll %0"
3801 [(set_attr "type" "arith")])
3802
3803 (define_insn "ashrsi3_d"
3804 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3805 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3806 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3807 "TARGET_SH3 || TARGET_SH2A"
3808 "shad %2,%0"
3809 [(set_attr "type" "dyn_shift")])
3810
3811 (define_insn "ashrsi3_n"
3812 [(set (reg:SI R4_REG)
3813 (ashiftrt:SI (reg:SI R4_REG)
3814 (match_operand:SI 0 "const_int_operand" "i")))
3815 (clobber (reg:SI T_REG))
3816 (clobber (reg:SI PR_REG))
3817 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
3818 "TARGET_SH1"
3819 "jsr @%1%#"
3820 [(set_attr "type" "sfunc")
3821 (set_attr "needs_delay_slot" "yes")])
3822
3823 (define_insn "ashrsi3_media"
3824 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3825 (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3826 (match_operand:SI 2 "shift_count_operand" "r,n")))]
3827 "TARGET_SHMEDIA"
3828 "@
3829 shard.l %1, %2, %0
3830 shari.l %1, %2, %0"
3831 [(set_attr "type" "arith_media")
3832 (set_attr "highpart" "ignore")])
3833
3834 (define_expand "ashrsi3"
3835 [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3836 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3837 (match_operand:SI 2 "nonmemory_operand" "")))
3838 (clobber (reg:SI T_REG))])]
3839 ""
3840 "
3841 {
3842 if (TARGET_SHMEDIA)
3843 {
3844 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
3845 DONE;
3846 }
3847 if (expand_ashiftrt (operands))
3848 DONE;
3849 else
3850 FAIL;
3851 }")
3852
3853 ;; logical shift right
3854
3855 (define_insn "lshrsi3_d"
3856 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3857 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3858 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3859 "TARGET_SH3 || TARGET_SH2A"
3860 "shld %2,%0"
3861 [(set_attr "type" "dyn_shift")])
3862
3863 ;; Only the single bit shift clobbers the T bit.
3864
3865 (define_insn "lshrsi3_m"
3866 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3867 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3868 (match_operand:SI 2 "const_int_operand" "M")))
3869 (clobber (reg:SI T_REG))]
3870 "TARGET_SH1 && satisfies_constraint_M (operands[2])"
3871 "shlr %0"
3872 [(set_attr "type" "arith")])
3873
3874 (define_insn "lshrsi3_k"
3875 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3876 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3877 (match_operand:SI 2 "const_int_operand" "P27")))]
3878 "TARGET_SH1 && satisfies_constraint_P27 (operands[2])
3879 && ! satisfies_constraint_M (operands[2])"
3880 "shlr%O2 %0"
3881 [(set_attr "type" "arith")])
3882
3883 (define_insn "lshrsi3_n"
3884 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3885 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3886 (match_operand:SI 2 "const_int_operand" "n")))
3887 (clobber (reg:SI T_REG))]
3888 "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3889 "#"
3890 [(set (attr "length")
3891 (cond [(match_test "shift_insns_rtx (insn)")
3892 (const_string "2")
3893 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3894 (const_string "4")
3895 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3896 (const_string "6")]
3897 (const_string "8")))
3898 (set_attr "type" "arith")])
3899
3900 (define_split
3901 [(set (match_operand:SI 0 "arith_reg_dest" "")
3902 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3903 (match_operand:SI 2 "const_int_operand" "")))
3904 (clobber (reg:SI T_REG))]
3905 "TARGET_SH1 && reload_completed"
3906 [(use (reg:SI R0_REG))]
3907 "
3908 {
3909 gen_shifty_op (LSHIFTRT, operands);
3910 DONE;
3911 }")
3912
3913 (define_insn "lshrsi3_media"
3914 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3915 (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3916 (match_operand:SI 2 "shift_count_operand" "r,n")))]
3917 "TARGET_SHMEDIA"
3918 "@
3919 shlrd.l %1, %2, %0
3920 shlri.l %1, %2, %0"
3921 [(set_attr "type" "arith_media")
3922 (set_attr "highpart" "ignore")])
3923
3924 (define_expand "lshrsi3"
3925 [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
3926 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3927 (match_operand:SI 2 "nonmemory_operand" "")))
3928 (clobber (reg:SI T_REG))])]
3929 ""
3930 "
3931 {
3932 if (TARGET_SHMEDIA)
3933 {
3934 emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
3935 DONE;
3936 }
3937 if (CONST_INT_P (operands[2])
3938 && sh_dynamicalize_shift_p (operands[2]))
3939 operands[2] = force_reg (SImode, operands[2]);
3940 if ((TARGET_SH3 || TARGET_SH2A)
3941 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
3942 {
3943 rtx count = copy_to_mode_reg (SImode, operands[2]);
3944 emit_insn (gen_negsi2 (count, count));
3945 emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
3946 DONE;
3947 }
3948 if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3949 FAIL;
3950 }")
3951
3952 ;; ??? This should be a define expand.
3953
3954 (define_insn "ashldi3_k"
3955 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3956 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
3957 (const_int 1)))
3958 (clobber (reg:SI T_REG))]
3959 "TARGET_SH1"
3960 "shll %R0\;rotcl %S0"
3961 [(set_attr "length" "4")
3962 (set_attr "type" "arith")])
3963
3964 ;; Expander for DImode shift left with SImode operations.
3965
3966 (define_expand "ashldi3_std"
3967 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3968 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
3969 (match_operand:DI 2 "const_int_operand" "n")))]
3970 "TARGET_SH1 && INTVAL (operands[2]) < 32"
3971 "
3972 {
3973 int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
3974 int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
3975 rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
3976 rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
3977 rtx dst = gen_reg_rtx (DImode);
3978 rtx low_dst = operand_subword (dst, low_word, 1, DImode);
3979 rtx high_dst = operand_subword (dst, high_word, 1, DImode);
3980 rtx tmp0, tmp1;
3981
3982 tmp0 = gen_reg_rtx (SImode);
3983 tmp1 = gen_reg_rtx (SImode);
3984 emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
3985 emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));
3986 emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));
3987 emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
3988 emit_move_insn (operands[0], dst);
3989 DONE;
3990 }")
3991
3992 (define_insn "ashldi3_media"
3993 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3994 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3995 (match_operand:DI 2 "shift_count_operand" "r,n")))]
3996 "TARGET_SHMEDIA"
3997 "@
3998 shlld %1, %2, %0
3999 shlli %1, %2, %0"
4000 [(set_attr "type" "arith_media")])
4001
4002 (define_insn "*ashldisi3_media"
4003 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4004 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4005 (match_operand:DI 2 "const_int_operand" "n")))]
4006 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4007 "shlli.l %1, %2, %0"
4008 [(set_attr "type" "arith_media")
4009 (set_attr "highpart" "ignore")])
4010
4011 (define_expand "ashldi3"
4012 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4013 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
4014 (match_operand:DI 2 "immediate_operand" "")))
4015 (clobber (reg:SI T_REG))])]
4016 ""
4017 "
4018 {
4019 if (TARGET_SHMEDIA)
4020 {
4021 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
4022 DONE;
4023 }
4024 if (CONST_INT_P (operands[2])
4025 && INTVAL (operands[2]) == 1)
4026 {
4027 emit_insn (gen_ashldi3_k (operands[0], operands[1]));
4028 DONE;
4029 }
4030 else if (CONST_INT_P (operands[2])
4031 && INTVAL (operands[2]) < 32)
4032 {
4033 emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
4034 DONE;
4035 }
4036 else
4037 FAIL;
4038 }")
4039
4040 ;; ??? This should be a define expand.
4041
4042 (define_insn "lshrdi3_k"
4043 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4044 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4045 (const_int 1)))
4046 (clobber (reg:SI T_REG))]
4047 "TARGET_SH1"
4048 "shlr %S0\;rotcr %R0"
4049 [(set_attr "length" "4")
4050 (set_attr "type" "arith")])
4051
4052 (define_insn "lshrdi3_media"
4053 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4054 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4055 (match_operand:DI 2 "shift_count_operand" "r,n")))]
4056 "TARGET_SHMEDIA
4057 && (arith_reg_dest (operands[0], DImode)
4058 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
4059 "@
4060 shlrd %1, %2, %0
4061 shlri %1, %2, %0"
4062 [(set_attr "type" "arith_media")])
4063
4064 (define_insn "*lshrdisi3_media"
4065 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4066 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4067 (match_operand:DI 2 "const_int_operand" "n")))]
4068 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4069 "shlri.l %1, %2, %0"
4070 [(set_attr "type" "arith_media")
4071 (set_attr "highpart" "ignore")])
4072
4073 (define_expand "lshrdi3"
4074 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4075 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4076 (match_operand:DI 2 "immediate_operand" "")))
4077 (clobber (reg:SI T_REG))])]
4078 ""
4079 "
4080 {
4081 if (TARGET_SHMEDIA)
4082 {
4083 emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
4084 DONE;
4085 }
4086 if (!CONST_INT_P (operands[2])
4087 || INTVAL (operands[2]) != 1)
4088 FAIL;
4089 }")
4090
4091 ;; ??? This should be a define expand.
4092
4093 (define_insn "ashrdi3_k"
4094 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4095 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4096 (const_int 1)))
4097 (clobber (reg:SI T_REG))]
4098 "TARGET_SH1"
4099 "shar %S0\;rotcr %R0"
4100 [(set_attr "length" "4")
4101 (set_attr "type" "arith")])
4102
4103 (define_insn "ashrdi3_media"
4104 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4105 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4106 (match_operand:DI 2 "shift_count_operand" "r,n")))]
4107 "TARGET_SHMEDIA
4108 && (arith_reg_dest (operands[0], DImode)
4109 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
4110 "@
4111 shard %1, %2, %0
4112 shari %1, %2, %0"
4113 [(set_attr "type" "arith_media")])
4114
4115 (define_insn "*ashrdisi3_media"
4116 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4117 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4118 (match_operand:DI 2 "const_int_operand" "n")))]
4119 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4120 "shari.l %1, %2, %0"
4121 [(set_attr "type" "arith_media")
4122 (set_attr "highpart" "ignore")])
4123
4124 (define_insn "ashrdisi3_media_high"
4125 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4126 (truncate:SI
4127 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4128 (match_operand:DI 2 "const_int_operand" "n"))))]
4129 "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
4130 "shari %1, %2, %0"
4131 [(set_attr "type" "arith_media")])
4132
4133 (define_insn "ashrdisi3_media_opaque"
4134 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4135 (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
4136 (match_operand:DI 2 "const_int_operand" "n")]
4137 UNSPEC_ASHIFTRT))]
4138 "TARGET_SHMEDIA"
4139 "shari %1, %2, %0"
4140 [(set_attr "type" "arith_media")])
4141
4142 (define_expand "ashrdi3"
4143 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4144 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4145 (match_operand:DI 2 "immediate_operand" "")))
4146 (clobber (reg:SI T_REG))])]
4147 ""
4148 "
4149 {
4150 if (TARGET_SHMEDIA)
4151 {
4152 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4153 DONE;
4154 }
4155 if (!CONST_INT_P (operands[2])
4156 || INTVAL (operands[2]) != 1)
4157 FAIL;
4158 }")
4159
4160 ;; combined left/right shift
4161
4162 (define_split
4163 [(set (match_operand:SI 0 "register_operand" "")
4164 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4165 (match_operand:SI 2 "const_int_operand" ""))
4166 (match_operand:SI 3 "const_int_operand" "")))]
4167 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4168 [(use (reg:SI R0_REG))]
4169 "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4170 DONE;")
4171
4172 (define_split
4173 [(set (match_operand:SI 0 "register_operand" "")
4174 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4175 (match_operand:SI 2 "const_int_operand" ""))
4176 (match_operand:SI 3 "const_int_operand" "")))
4177 (clobber (reg:SI T_REG))]
4178 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4179 [(use (reg:SI R0_REG))]
4180 "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4181 DONE;")
4182
4183 (define_insn ""
4184 [(set (match_operand:SI 0 "register_operand" "=r")
4185 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4186 (match_operand:SI 2 "const_int_operand" "n"))
4187 (match_operand:SI 3 "const_int_operand" "n")))
4188 (clobber (reg:SI T_REG))]
4189 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
4190 "#"
4191 [(set (attr "length")
4192 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4193 (const_string "4")
4194 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4195 (const_string "6")
4196 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4197 (const_string "8")
4198 (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
4199 (const_string "10")
4200 (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
4201 (const_string "12")
4202 (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
4203 (const_string "14")
4204 (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
4205 (const_string "16")]
4206 (const_string "18")))
4207 (set_attr "type" "arith")])
4208
4209 (define_insn ""
4210 [(set (match_operand:SI 0 "register_operand" "=z")
4211 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4212 (match_operand:SI 2 "const_int_operand" "n"))
4213 (match_operand:SI 3 "const_int_operand" "n")))
4214 (clobber (reg:SI T_REG))]
4215 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
4216 "#"
4217 [(set (attr "length")
4218 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4219 (const_string "4")
4220 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4221 (const_string "6")
4222 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4223 (const_string "8")]
4224 (const_string "10")))
4225 (set_attr "type" "arith")])
4226
4227 ;; shift left / and combination with a scratch register: The combine pass
4228 ;; does not accept the individual instructions, even though they are
4229 ;; cheap. But it needs a precise description so that it is usable after
4230 ;; reload.
4231 (define_insn "and_shl_scratch"
4232 [(set (match_operand:SI 0 "register_operand" "=r,&r")
4233 (lshiftrt:SI
4234 (ashift:SI
4235 (and:SI
4236 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
4237 (match_operand:SI 2 "const_int_operand" "N,n"))
4238 (match_operand:SI 3 "" "0,r"))
4239 (match_operand:SI 4 "const_int_operand" "n,n"))
4240 (match_operand:SI 5 "const_int_operand" "n,n")))
4241 (clobber (reg:SI T_REG))]
4242 "TARGET_SH1"
4243 "#"
4244 [(set (attr "length")
4245 (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
4246 (const_string "4")
4247 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
4248 (const_string "6")
4249 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
4250 (const_string "8")
4251 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
4252 (const_string "10")]
4253 (const_string "12")))
4254 (set_attr "type" "arith")])
4255
4256 (define_split
4257 [(set (match_operand:SI 0 "register_operand" "")
4258 (lshiftrt:SI
4259 (ashift:SI
4260 (and:SI
4261 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
4262 (match_operand:SI 2 "const_int_operand" ""))
4263 (match_operand:SI 3 "register_operand" ""))
4264 (match_operand:SI 4 "const_int_operand" ""))
4265 (match_operand:SI 5 "const_int_operand" "")))
4266 (clobber (reg:SI T_REG))]
4267 "TARGET_SH1"
4268 [(use (reg:SI R0_REG))]
4269 "
4270 {
4271 rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
4272
4273 if (INTVAL (operands[2]))
4274 {
4275 gen_shifty_op (LSHIFTRT, operands);
4276 }
4277 emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
4278 operands[2] = operands[4];
4279 gen_shifty_op (ASHIFT, operands);
4280 if (INTVAL (operands[5]))
4281 {
4282 operands[2] = operands[5];
4283 gen_shifty_op (LSHIFTRT, operands);
4284 }
4285 DONE;
4286 }")
4287
4288 ;; signed left/right shift combination.
4289 (define_split
4290 [(set (match_operand:SI 0 "register_operand" "")
4291 (sign_extract:SI
4292 (ashift:SI (match_operand:SI 1 "register_operand" "")
4293 (match_operand:SI 2 "const_int_operand" ""))
4294 (match_operand:SI 3 "const_int_operand" "")
4295 (const_int 0)))
4296 (clobber (reg:SI T_REG))]
4297 "TARGET_SH1"
4298 [(use (reg:SI R0_REG))]
4299 "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL;
4300 DONE;")
4301
4302 (define_insn "shl_sext_ext"
4303 [(set (match_operand:SI 0 "register_operand" "=r")
4304 (sign_extract:SI
4305 (ashift:SI (match_operand:SI 1 "register_operand" "0")
4306 (match_operand:SI 2 "const_int_operand" "n"))
4307 (match_operand:SI 3 "const_int_operand" "n")
4308 (const_int 0)))
4309 (clobber (reg:SI T_REG))]
4310 "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
4311 "#"
4312 [(set (attr "length")
4313 (cond [(match_test "shl_sext_length (insn)")
4314 (const_string "2")
4315 (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
4316 (const_string "4")
4317 (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4318 (const_string "6")
4319 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4320 (const_string "8")
4321 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4322 (const_string "10")
4323 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4324 (const_string "12")
4325 (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
4326 (const_string "14")
4327 (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
4328 (const_string "16")]
4329 (const_string "18")))
4330 (set_attr "type" "arith")])
4331
4332 (define_insn "shl_sext_sub"
4333 [(set (match_operand:SI 0 "register_operand" "=z")
4334 (sign_extract:SI
4335 (ashift:SI (match_operand:SI 1 "register_operand" "0")
4336 (match_operand:SI 2 "const_int_operand" "n"))
4337 (match_operand:SI 3 "const_int_operand" "n")
4338 (const_int 0)))
4339 (clobber (reg:SI T_REG))]
4340 "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
4341 "#"
4342 [(set (attr "length")
4343 (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4344 (const_string "6")
4345 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4346 (const_string "8")
4347 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4348 (const_string "10")
4349 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4350 (const_string "12")]
4351 (const_string "14")))
4352 (set_attr "type" "arith")])
4353
4354 ;; These patterns are found in expansions of DImode shifts by 16, and
4355 ;; allow the xtrct instruction to be generated from C source.
4356
4357 (define_insn "xtrct_left"
4358 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4359 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
4360 (const_int 16))
4361 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
4362 (const_int 16))))]
4363 "TARGET_SH1"
4364 "xtrct %1,%0"
4365 [(set_attr "type" "arith")])
4366
4367 (define_insn "xtrct_right"
4368 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4369 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4370 (const_int 16))
4371 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
4372 (const_int 16))))]
4373 "TARGET_SH1"
4374 "xtrct %2,%0"
4375 [(set_attr "type" "arith")])
4376
4377 ;; -------------------------------------------------------------------------
4378 ;; Unary arithmetic
4379 ;; -------------------------------------------------------------------------
4380
4381 (define_expand "negc"
4382 [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
4383 (neg:SI (plus:SI (reg:SI T_REG)
4384 (match_operand:SI 1 "arith_reg_operand" ""))))
4385 (set (reg:SI T_REG)
4386 (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
4387 (const_int 0)))])]
4388 ""
4389 "")
4390
4391 (define_insn "*negc"
4392 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4393 (neg:SI (plus:SI (reg:SI T_REG)
4394 (match_operand:SI 1 "arith_reg_operand" "r"))))
4395 (set (reg:SI T_REG)
4396 (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
4397 (const_int 0)))]
4398 "TARGET_SH1"
4399 "negc %1,%0"
4400 [(set_attr "type" "arith")])
4401
4402 (define_insn "*negdi_media"
4403 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4404 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
4405 "TARGET_SHMEDIA"
4406 "sub r63, %1, %0"
4407 [(set_attr "type" "arith_media")])
4408
4409 ;; Don't expand immediately because otherwise neg:DI (abs:DI) will not be
4410 ;; combined.
4411 (define_expand "negdi2"
4412 [(set (match_operand:DI 0 "arith_reg_dest" "")
4413 (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))
4414 (clobber (reg:SI T_REG))]
4415 "TARGET_SH1"
4416 "")
4417
4418 (define_insn_and_split "*negdi2"
4419 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4420 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
4421 "TARGET_SH1"
4422 "#"
4423 "TARGET_SH1"
4424 [(const_int 0)]
4425 "
4426 {
4427 int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
4428 int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
4429
4430 rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
4431 rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
4432
4433 rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
4434 rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
4435
4436 emit_insn (gen_clrt ());
4437 emit_insn (gen_negc (low_dst, low_src));
4438 emit_insn (gen_negc (high_dst, high_src));
4439 DONE;
4440 }")
4441
4442 (define_insn "negsi2"
4443 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4444 (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4445 "TARGET_SH1"
4446 "neg %1,%0"
4447 [(set_attr "type" "arith")])
4448
4449 (define_insn "one_cmplsi2"
4450 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4451 (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4452 "TARGET_SH1"
4453 "not %1,%0"
4454 [(set_attr "type" "arith")])
4455
4456 (define_expand "one_cmpldi2"
4457 [(set (match_operand:DI 0 "arith_reg_dest" "")
4458 (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
4459 (const_int -1)))]
4460 "TARGET_SHMEDIA" "")
4461
4462 (define_expand "abssi2"
4463 [(set (match_operand:SI 0 "arith_reg_dest" "")
4464 (abs:SI (match_operand:SI 1 "arith_reg_operand" "")))
4465 (clobber (reg:SI T_REG))]
4466 "TARGET_SH1"
4467 "")
4468
4469 (define_insn_and_split "*abssi2"
4470 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4471 (abs:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4472 "TARGET_SH1"
4473 "#"
4474 "TARGET_SH1"
4475 [(const_int 0)]
4476 "
4477 {
4478 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
4479 emit_insn (gen_negsi_cond (operands[0], operands[1], operands[1],
4480 const1_rtx));
4481 DONE;
4482 }")
4483
4484 (define_insn_and_split "*negabssi2"
4485 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4486 (neg:SI (abs:SI (match_operand:SI 1 "arith_reg_operand" "r"))))]
4487 "TARGET_SH1"
4488 "#"
4489 "TARGET_SH1"
4490 [(const_int 0)]
4491 "
4492 {
4493 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
4494 emit_insn (gen_negsi_cond (operands[0], operands[1], operands[1],
4495 const0_rtx));
4496 DONE;
4497 }")
4498
4499 ;; The SH4 202 can do zero-offset branches without pipeline stalls.
4500 ;; This can be used as some kind of conditional execution, which is useful
4501 ;; for abs.
4502 ;; Actually the instruction scheduling should decide whether to use a
4503 ;; zero-offset branch or not for any generic case involving a single
4504 ;; instruction on SH4 202.
4505
4506 (define_insn_and_split "negsi_cond"
4507 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4508 (if_then_else:SI (eq:SI (reg:SI T_REG)
4509 (match_operand:SI 3 "const_int_operand" "M,N"))
4510 (match_operand:SI 1 "arith_reg_operand" "0,0")
4511 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
4512 "TARGET_HARD_SH4"
4513 "@
4514 bt\\t0f\;neg\\t%2,%0\\n0:
4515 bf\\t0f\;neg\\t%2,%0\\n0:"
4516 "!TARGET_HARD_SH4"
4517 [(const_int 0)]
4518 "
4519 {
4520 rtx skip_neg_label = gen_label_rtx ();
4521
4522 emit_insn (gen_movsi (operands[0], operands[1]));
4523
4524 emit_jump_insn (INTVAL (operands[3])
4525 ? gen_branch_true (skip_neg_label)
4526 : gen_branch_false (skip_neg_label));
4527
4528 emit_label_after (skip_neg_label,
4529 emit_insn (gen_negsi2 (operands[0], operands[1])));
4530 DONE;
4531 }"
4532 [(set_attr "type" "arith") ;; poor approximation
4533 (set_attr "length" "4")])
4534
4535 (define_expand "absdi2"
4536 [(set (match_operand:DI 0 "arith_reg_dest" "")
4537 (abs:DI (match_operand:DI 1 "arith_reg_operand" "")))
4538 (clobber (reg:SI T_REG))]
4539 "TARGET_SH1"
4540 "")
4541
4542 (define_insn_and_split "*absdi2"
4543 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4544 (abs:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
4545 "TARGET_SH1"
4546 "#"
4547 "&& reload_completed"
4548 [(const_int 0)]
4549 {
4550 int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
4551 rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
4552 emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
4553 emit_insn (gen_negdi_cond (operands[0], operands[1], operands[1],
4554 const1_rtx));
4555 DONE;
4556 })
4557
4558 (define_insn_and_split "*negabsdi2"
4559 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4560 (neg:DI (abs:DI (match_operand:DI 1 "arith_reg_operand" "r"))))]
4561 "TARGET_SH1"
4562 "#"
4563 "&& reload_completed"
4564 [(const_int 0)]
4565 {
4566 int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
4567 rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
4568
4569 emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
4570 emit_insn (gen_negdi_cond (operands[0], operands[1], operands[1],
4571 const0_rtx));
4572 DONE;
4573 })
4574
4575 (define_insn_and_split "negdi_cond"
4576 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4577 (if_then_else:DI (eq:SI (reg:SI T_REG)
4578 (match_operand:SI 3 "const_int_operand" "M,N"))
4579 (match_operand:DI 1 "arith_reg_operand" "r,r")
4580 (neg:DI (match_operand:DI 2 "arith_reg_operand" "1,1"))))]
4581 "TARGET_SH1"
4582 "#"
4583 "TARGET_SH1"
4584 [(const_int 0)]
4585 {
4586 int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
4587 int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
4588
4589 rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
4590 rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
4591
4592 rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
4593 rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
4594
4595 rtx skip_neg_label = gen_label_rtx ();
4596
4597 emit_insn (gen_movsi (low_dst, low_src));
4598 emit_insn (gen_movsi (high_dst, high_src));
4599
4600 emit_jump_insn (INTVAL (operands[3])
4601 ? gen_branch_true (skip_neg_label)
4602 : gen_branch_false (skip_neg_label));
4603
4604 if (!INTVAL (operands[3]))
4605 emit_insn (gen_clrt ());
4606
4607 emit_insn (gen_negc (low_dst, low_src));
4608 emit_label_after (skip_neg_label, emit_insn (gen_negc (high_dst, high_src)));
4609 DONE;
4610 })
4611 \f
4612 ;; -------------------------------------------------------------------------
4613 ;; Zero extension instructions
4614 ;; -------------------------------------------------------------------------
4615
4616 (define_insn "zero_extendsidi2"
4617 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4618 (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
4619 "TARGET_SHMEDIA"
4620 "addz.l %1, r63, %0"
4621 [(set_attr "type" "arith_media")
4622 (set_attr "highpart" "extend")])
4623
4624 (define_insn "zero_extendhidi2"
4625 [(set (match_operand:DI 0 "register_operand" "=r,r")
4626 (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4627 "TARGET_SHMEDIA"
4628 "@
4629 #
4630 ld%M1.uw %m1, %0"
4631 [(set_attr "type" "*,load_media")
4632 (set (attr "highpart")
4633 (cond [(match_test "sh_contains_memref_p (insn)")
4634 (const_string "user")]
4635 (const_string "ignore")))])
4636
4637 (define_split
4638 [(set (match_operand:DI 0 "register_operand" "")
4639 (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4640 "TARGET_SHMEDIA && reload_completed"
4641 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4642 (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
4643 "
4644 {
4645 if (GET_CODE (operands[1]) == TRUNCATE)
4646 operands[1] = XEXP (operands[1], 0);
4647 }")
4648
4649 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
4650 ;; reload the entire truncate expression.
4651 (define_insn_and_split "*loaddi_trunc"
4652 [(set (match_operand 0 "any_register_operand" "=r")
4653 (truncate (match_operand:DI 1 "memory_operand" "m")))]
4654 "TARGET_SHMEDIA && reload_completed"
4655 "#"
4656 "TARGET_SHMEDIA && reload_completed"
4657 [(set (match_dup 0) (match_dup 1))]
4658 "operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));")
4659
4660 (define_insn "zero_extendqidi2"
4661 [(set (match_operand:DI 0 "register_operand" "=r,r")
4662 (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4663 "TARGET_SHMEDIA"
4664 "@
4665 andi %1, 255, %0
4666 ld%M1.ub %m1, %0"
4667 [(set_attr "type" "arith_media,load_media")
4668 (set (attr "highpart")
4669 (cond [(match_test "sh_contains_memref_p (insn)")
4670 (const_string "user")]
4671 (const_string "ignore")))])
4672
4673 (define_expand "zero_extendhisi2"
4674 [(set (match_operand:SI 0 "arith_reg_operand" "")
4675 (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "")))]
4676 ""
4677 "
4678 {
4679 if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], HImode))
4680 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4681 }")
4682
4683 (define_insn "*zero_extendhisi2_compact"
4684 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4685 (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))]
4686 "TARGET_SH1"
4687 "extu.w %1,%0"
4688 [(set_attr "type" "arith")])
4689
4690 (define_insn "*zero_extendhisi2_media"
4691 [(set (match_operand:SI 0 "register_operand" "=r,r")
4692 (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4693 "TARGET_SHMEDIA"
4694 "@
4695 #
4696 ld%M1.uw %m1, %0"
4697 [(set_attr "type" "arith_media,load_media")
4698 (set (attr "highpart")
4699 (cond [(match_test "sh_contains_memref_p (insn)")
4700 (const_string "user")]
4701 (const_string "ignore")))])
4702
4703 (define_split
4704 [(set (match_operand:SI 0 "register_operand" "")
4705 (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4706 "TARGET_SHMEDIA && reload_completed"
4707 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4708 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4709 "
4710 {
4711 rtx op1 = operands[1];
4712
4713 if (GET_CODE (op1) == TRUNCATE)
4714 op1 = XEXP (op1, 0);
4715 operands[2]
4716 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4717 subreg_lowpart_offset (SImode, GET_MODE (op1)));
4718 }")
4719
4720 (define_expand "zero_extendqisi2"
4721 [(set (match_operand:SI 0 "arith_reg_operand" "")
4722 (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
4723 ""
4724 "
4725 {
4726 if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], QImode))
4727 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4728 }")
4729
4730 (define_insn "*zero_extendqisi2_compact"
4731 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4732 (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))]
4733 "TARGET_SH1"
4734 "extu.b %1,%0"
4735 [(set_attr "type" "arith")])
4736
4737 (define_insn "*zero_extendqisi2_media"
4738 [(set (match_operand:SI 0 "register_operand" "=r,r")
4739 (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4740 "TARGET_SHMEDIA"
4741 "@
4742 andi %1, 255, %0
4743 ld%M1.ub %m1, %0"
4744 [(set_attr "type" "arith_media,load_media")
4745 (set (attr "highpart")
4746 (cond [(match_test "sh_contains_memref_p (insn)")
4747 (const_string "user")]
4748 (const_string "ignore")))])
4749
4750 (define_insn "zero_extendqihi2"
4751 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4752 (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
4753 "TARGET_SH1"
4754 "extu.b %1,%0"
4755 [(set_attr "type" "arith")])
4756
4757 ;; -------------------------------------------------------------------------
4758 ;; Sign extension instructions
4759 ;; -------------------------------------------------------------------------
4760
4761 ;; ??? This should be a define expand.
4762 ;; ??? Or perhaps it should be dropped?
4763
4764 ;; convert_move generates good code for SH[1-4].
4765 (define_insn "extendsidi2"
4766 [(set (match_operand:DI 0 "register_operand" "=r,r,r")
4767 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
4768 "TARGET_SHMEDIA"
4769 "@
4770 add.l %1, r63, %0
4771 ld%M1.l %m1, %0
4772 fmov.sl %1, %0"
4773 [(set_attr "type" "arith_media,load_media,fpconv_media")
4774 (set (attr "highpart")
4775 (cond [(match_test "sh_contains_memref_p (insn)")
4776 (const_string "user")]
4777 (const_string "extend")))])
4778
4779 (define_insn "extendhidi2"
4780 [(set (match_operand:DI 0 "register_operand" "=r,r")
4781 (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4782 "TARGET_SHMEDIA"
4783 "@
4784 #
4785 ld%M1.w %m1, %0"
4786 [(set_attr "type" "*,load_media")
4787 (set (attr "highpart")
4788 (cond [(match_test "sh_contains_memref_p (insn)")
4789 (const_string "user")]
4790 (const_string "ignore")))])
4791
4792 (define_split
4793 [(set (match_operand:DI 0 "register_operand" "")
4794 (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4795 "TARGET_SHMEDIA && reload_completed"
4796 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4797 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
4798 "
4799 {
4800 if (GET_CODE (operands[1]) == TRUNCATE)
4801 operands[1] = XEXP (operands[1], 0);
4802 }")
4803
4804 (define_insn "extendqidi2"
4805 [(set (match_operand:DI 0 "register_operand" "=r,r")
4806 (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4807 "TARGET_SHMEDIA"
4808 "@
4809 #
4810 ld%M1.b %m1, %0"
4811 [(set_attr "type" "*,load_media")
4812 (set (attr "highpart")
4813 (cond [(match_test "sh_contains_memref_p (insn)")
4814 (const_string "user")]
4815 (const_string "ignore")))])
4816
4817 (define_split
4818 [(set (match_operand:DI 0 "register_operand" "")
4819 (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
4820 "TARGET_SHMEDIA && reload_completed"
4821 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
4822 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
4823 "
4824 {
4825 if (GET_CODE (operands[1]) == TRUNCATE)
4826 operands[1] = XEXP (operands[1], 0);
4827 }")
4828
4829 (define_expand "extendhisi2"
4830 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4831 (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4832 ""
4833 "")
4834
4835 (define_insn "*extendhisi2_compact"
4836 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4837 (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))]
4838 "TARGET_SH1"
4839 "@
4840 exts.w %1,%0
4841 mov.w %1,%0"
4842 [(set_attr "type" "arith,load")])
4843
4844 (define_insn "*extendhisi2_media"
4845 [(set (match_operand:SI 0 "register_operand" "=r,r")
4846 (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4847 "TARGET_SHMEDIA"
4848 "@
4849 #
4850 ld%M1.w %m1, %0"
4851 [(set_attr "type" "arith_media,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:SI 0 "register_operand" "")
4859 (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4860 "TARGET_SHMEDIA && reload_completed"
4861 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4862 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4863 "
4864 {
4865 rtx op1 = operands[1];
4866 if (GET_CODE (op1) == TRUNCATE)
4867 op1 = XEXP (op1, 0);
4868 operands[2]
4869 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4870 subreg_lowpart_offset (SImode, GET_MODE (op1)));
4871 }")
4872
4873 (define_expand "extendqisi2"
4874 [(set (match_operand:SI 0 "arith_reg_dest" "")
4875 (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
4876 ""
4877 "")
4878
4879 (define_insn "*extendqisi2_compact_reg"
4880 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4881 (sign_extend:SI (match_operand:QI 1 "register_operand" "r,t")))]
4882 "TARGET_SH1"
4883 "@
4884 exts.b %1,%0
4885 movt %0"
4886 [(set_attr "type" "arith,arith")])
4887
4888 ;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute.
4889 ;; See movqi insns.
4890 (define_insn "*extendqisi2_compact_mem_disp"
4891 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
4892 (sign_extend:SI
4893 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
4894 (match_operand:SI 2 "const_int_operand" "K04,N")))))]
4895 "TARGET_SH1 && ! TARGET_SH2A && CONST_OK_FOR_K04 (INTVAL (operands[2]))"
4896 "@
4897 mov.b @(%O2,%1),%0
4898 mov.b @%1,%0"
4899 [(set_attr "type" "load")])
4900
4901 (define_insn "*extendqisi2_compact_mem_disp"
4902 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
4903 (sign_extend:SI
4904 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
4905 (match_operand:SI 2 "const_int_operand" "K04,N,K12")))))]
4906 "TARGET_SH2A
4907 && (CONST_OK_FOR_K04 (INTVAL (operands[2]))
4908 || (CONST_OK_FOR_K12 (INTVAL (operands[2]))))"
4909 "@
4910 mov.b @(%O2,%1),%0
4911 mov.b @%1,%0
4912 mov.b @(%O2,%1),%0"
4913 [(set_attr "type" "load")
4914 (set_attr "length" "2,2,4")])
4915
4916 ;; This will take care of other QImode addressing modes than displacement
4917 ;; addressing.
4918 (define_insn "*extendqisi2_compact_snd"
4919 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4920 (sign_extend:SI (match_operand:QI 1 "movsrc_no_disp_mem_operand" "Snd")))]
4921 "TARGET_SH1"
4922 "mov.b %1,%0"
4923 [(set_attr "type" "load")])
4924
4925 (define_insn "*extendqisi2_media"
4926 [(set (match_operand:SI 0 "register_operand" "=r,r")
4927 (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4928 "TARGET_SHMEDIA"
4929 "@
4930 #
4931 ld%M1.b %m1, %0"
4932 [(set_attr "type" "arith_media,load_media")
4933 (set (attr "highpart")
4934 (cond [(match_test "sh_contains_memref_p (insn)")
4935 (const_string "user")]
4936 (const_string "ignore")))])
4937
4938 (define_split
4939 [(set (match_operand:SI 0 "register_operand" "")
4940 (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
4941 "TARGET_SHMEDIA && reload_completed"
4942 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4943 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4944 "
4945 {
4946 rtx op1 = operands[1];
4947 if (GET_CODE (op1) == TRUNCATE)
4948 op1 = XEXP (op1, 0);
4949 operands[2]
4950 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4951 subreg_lowpart_offset (SImode, GET_MODE (op1)));
4952 }")
4953
4954 (define_expand "extendqihi2"
4955 [(set (match_operand:HI 0 "arith_reg_dest" "")
4956 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "")))]
4957 ""
4958 "")
4959
4960 (define_insn "*extendqihi2_compact_reg"
4961 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4962 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
4963 "TARGET_SH1"
4964 "exts.b %1,%0"
4965 [(set_attr "type" "arith")])
4966
4967 /* It would seem useful to combine the truncXi patterns into the movXi
4968 patterns, but unary operators are ignored when matching constraints,
4969 so we need separate patterns. */
4970 (define_insn "truncdisi2"
4971 [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
4972 (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
4973 "TARGET_SHMEDIA"
4974 "@
4975 add.l %1, r63, %0
4976 st%M0.l %m0, %1
4977 fst%M0.s %m0, %T1
4978 fmov.ls %1, %0
4979 fmov.sl %T1, %0
4980 fmov.s %T1, %0"
4981 [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")
4982 (set (attr "highpart")
4983 (cond [(match_test "sh_contains_memref_p (insn)")
4984 (const_string "user")]
4985 (const_string "extend")))])
4986
4987 (define_insn "truncdihi2"
4988 [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
4989 (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
4990 "TARGET_SHMEDIA"
4991 "@
4992 shlli\\t%1,48,%0\;shlri\\t%0,48,%0
4993 st%M0.w %m0, %1"
4994 [(set_attr "type" "arith_media,store_media")
4995 (set_attr "length" "8,4")
4996 (set (attr "highpart")
4997 (cond [(match_test "sh_contains_memref_p (insn)")
4998 (const_string "user")]
4999 (const_string "extend")))])
5000
5001 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
5002 ; Because we use zero extension, we can't provide signed QImode compares
5003 ; using a simple compare or conditional branch insn.
5004 (define_insn "truncdiqi2"
5005 [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
5006 (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
5007 "TARGET_SHMEDIA"
5008 "@
5009 andi %1, 255, %0
5010 st%M0.b %m0, %1"
5011 [(set_attr "type" "arith_media,store")
5012 (set (attr "highpart")
5013 (cond [(match_test "sh_contains_memref_p (insn)")
5014 (const_string "user")]
5015 (const_string "extend")))])
5016 ;; -------------------------------------------------------------------------
5017 ;; Move instructions
5018 ;; -------------------------------------------------------------------------
5019
5020 ;; define push and pop so it is easy for sh.c
5021 ;; We can't use push and pop on SHcompact because the stack must always
5022 ;; be 8-byte aligned.
5023
5024 (define_expand "push"
5025 [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
5026 (match_operand:SI 0 "register_operand" "r,l,x"))]
5027 "TARGET_SH1 && ! TARGET_SH5"
5028 "")
5029
5030 (define_expand "pop"
5031 [(set (match_operand:SI 0 "register_operand" "=r,l,x")
5032 (mem:SI (post_inc:SI (reg:SI SP_REG))))]
5033 "TARGET_SH1 && ! TARGET_SH5"
5034 "")
5035
5036 (define_expand "push_e"
5037 [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
5038 (match_operand:SF 0 "" ""))
5039 (use (reg:PSI FPSCR_REG))
5040 (clobber (scratch:SI))])]
5041 "TARGET_SH1 && ! TARGET_SH5"
5042 "")
5043
5044 (define_insn "push_fpul"
5045 [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
5046 "TARGET_SH2E && ! TARGET_SH5"
5047 "sts.l fpul,@-r15"
5048 [(set_attr "type" "fstore")
5049 (set_attr "late_fp_use" "yes")
5050 (set_attr "hit_stack" "yes")])
5051
5052 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
5053 ;; so use that.
5054 (define_expand "push_4"
5055 [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
5056 (match_operand:DF 0 "" ""))
5057 (use (reg:PSI FPSCR_REG))
5058 (clobber (scratch:SI))])]
5059 "TARGET_SH1 && ! TARGET_SH5"
5060 "")
5061
5062 (define_expand "pop_e"
5063 [(parallel [(set (match_operand:SF 0 "" "")
5064 (mem:SF (post_inc:SI (reg:SI SP_REG))))
5065 (use (reg:PSI FPSCR_REG))
5066 (clobber (scratch:SI))])]
5067 "TARGET_SH1 && ! TARGET_SH5"
5068 "")
5069
5070 (define_insn "pop_fpul"
5071 [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
5072 "TARGET_SH2E && ! TARGET_SH5"
5073 "lds.l @r15+,fpul"
5074 [(set_attr "type" "load")
5075 (set_attr "hit_stack" "yes")])
5076
5077 (define_expand "pop_4"
5078 [(parallel [(set (match_operand:DF 0 "" "")
5079 (mem:DF (post_inc:SI (reg:SI SP_REG))))
5080 (use (reg:PSI FPSCR_REG))
5081 (clobber (scratch:SI))])]
5082 "TARGET_SH1 && ! TARGET_SH5"
5083 "")
5084
5085 (define_expand "push_fpscr"
5086 [(const_int 0)]
5087 "TARGET_SH2E"
5088 "
5089 {
5090 rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
5091 gen_rtx_PRE_DEC (Pmode,
5092 stack_pointer_rtx)),
5093 get_fpscr_rtx ()));
5094 add_reg_note (insn, REG_INC, stack_pointer_rtx);
5095 DONE;
5096 }")
5097
5098 (define_expand "pop_fpscr"
5099 [(const_int 0)]
5100 "TARGET_SH2E"
5101 "
5102 {
5103 rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
5104 gen_frame_mem (PSImode,
5105 gen_rtx_POST_INC (Pmode,
5106 stack_pointer_rtx))));
5107 add_reg_note (insn, REG_INC, stack_pointer_rtx);
5108 DONE;
5109 }")
5110
5111 ;; These two patterns can happen as the result of optimization, when
5112 ;; comparisons get simplified to a move of zero or 1 into the T reg.
5113 ;; They don't disappear completely, because the T reg is a fixed hard reg.
5114
5115 (define_insn "clrt"
5116 [(set (reg:SI T_REG) (const_int 0))]
5117 "TARGET_SH1"
5118 "clrt")
5119
5120 (define_insn "sett"
5121 [(set (reg:SI T_REG) (const_int 1))]
5122 "TARGET_SH1"
5123 "sett")
5124
5125 ;; Define additional pop for SH1 and SH2 so it does not get
5126 ;; placed in the delay slot.
5127 (define_insn "*movsi_pop"
5128 [(set (match_operand:SI 0 "register_operand" "=r,x,l")
5129 (match_operand:SI 1 "sh_no_delay_pop_operand" ">,>,>"))]
5130 "(TARGET_SH1 || TARGET_SH2E || TARGET_SH2A)
5131 && ! TARGET_SH3"
5132 "@
5133 mov.l %1,%0
5134 lds.l %1,%0
5135 lds.l %1,%0"
5136 [(set_attr "type" "load_si,mem_mac,pload")
5137 (set_attr "length" "2,2,2")
5138 (set_attr "in_delay_slot" "no,no,no")])
5139
5140 ;; t/r must come after r/r, lest reload will try to reload stuff like
5141 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
5142 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
5143 (define_insn "movsi_i"
5144 [(set (match_operand:SI 0 "general_movdst_operand"
5145 "=r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
5146 (match_operand:SI 1 "general_movsrc_operand"
5147 "Q,r,I08,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
5148 "TARGET_SH1
5149 && ! TARGET_SH2E
5150 && ! TARGET_SH2A
5151 && (register_operand (operands[0], SImode)
5152 || register_operand (operands[1], SImode))"
5153 "@
5154 mov.l %1,%0
5155 mov %1,%0
5156 mov %1,%0
5157 cmp/pl %1
5158 mov.l %1,%0
5159 sts %1,%0
5160 sts %1,%0
5161 movt %0
5162 mov.l %1,%0
5163 sts.l %1,%0
5164 sts.l %1,%0
5165 lds %1,%0
5166 lds %1,%0
5167 lds.l %1,%0
5168 lds.l %1,%0
5169 fake %1,%0"
5170 [(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")
5171 (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
5172
5173 ;; t/r must come after r/r, lest reload will try to reload stuff like
5174 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
5175 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
5176 ;; will require a reload.
5177 ;; ??? We can't include f/f because we need the proper FPSCR setting when
5178 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
5179 (define_insn "movsi_ie"
5180 [(set (match_operand:SI 0 "general_movdst_operand"
5181 "=r,r,r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
5182 (match_operand:SI 1 "general_movsrc_operand"
5183 "Q,r,I08,I20,I28,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
5184 "(TARGET_SH2E || TARGET_SH2A)
5185 && (register_operand (operands[0], SImode)
5186 || register_operand (operands[1], SImode))"
5187 "@
5188 mov.l %1,%0
5189 mov %1,%0
5190 mov %1,%0
5191 movi20 %1,%0
5192 movi20s %1,%0
5193 cmp/pl %1
5194 mov.l %1,%0
5195 sts %1,%0
5196 sts %1,%0
5197 movt %0
5198 mov.l %1,%0
5199 sts.l %1,%0
5200 sts.l %1,%0
5201 lds %1,%0
5202 lds %1,%0
5203 lds.l %1,%0
5204 lds.l %1,%0
5205 lds.l %1,%0
5206 sts.l %1,%0
5207 fake %1,%0
5208 lds %1,%0
5209 sts %1,%0
5210 fsts fpul,%0
5211 flds %1,fpul
5212 fmov %1,%0
5213 ! move optimized away"
5214 [(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")
5215 (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
5216 (set_attr_alternative "length"
5217 [(const_int 2)
5218 (const_int 2)
5219 (const_int 2)
5220 (const_int 4)
5221 (const_int 4)
5222 (const_int 2)
5223 (if_then_else
5224 (match_test "TARGET_SH2A")
5225 (const_int 4) (const_int 2))
5226 (const_int 2)
5227 (const_int 2)
5228 (const_int 2)
5229 (if_then_else
5230 (match_test "TARGET_SH2A")
5231 (const_int 4) (const_int 2))
5232 (const_int 2)
5233 (const_int 2)
5234 (const_int 2)
5235 (const_int 2)
5236 (const_int 2)
5237 (const_int 2)
5238 (const_int 2)
5239 (const_int 2)
5240 (const_int 2)
5241 (const_int 2)
5242 (const_int 2)
5243 (const_int 2)
5244 (const_int 2)
5245 (const_int 2)
5246 (const_int 0)])])
5247
5248 (define_insn "movsi_i_lowpart"
5249 [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,r,m,r"))
5250 (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,t,r,i"))]
5251 "TARGET_SH1
5252 && (register_operand (operands[0], SImode)
5253 || register_operand (operands[1], SImode))"
5254 "@
5255 mov.l %1,%0
5256 mov %1,%0
5257 mov %1,%0
5258 mov.l %1,%0
5259 sts %1,%0
5260 sts %1,%0
5261 movt %0
5262 mov.l %1,%0
5263 fake %1,%0"
5264 [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,arith,store,pcload")])
5265
5266 (define_insn_and_split "load_ra"
5267 [(set (match_operand:SI 0 "general_movdst_operand" "")
5268 (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
5269 "TARGET_SH1"
5270 "#"
5271 "&& ! currently_expanding_to_rtl"
5272 [(set (match_dup 0) (match_dup 1))]
5273 "
5274 {
5275 if (TARGET_SHCOMPACT && crtl->saves_all_registers)
5276 operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
5277 }")
5278
5279 ;; The '?'s in the following constraints may not reflect the time taken
5280 ;; to perform the move. They are there to discourage the use of floating-
5281 ;; point registers for storing integer values.
5282 (define_insn "*movsi_media"
5283 [(set (match_operand:SI 0 "general_movdst_operand"
5284 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
5285 (match_operand:SI 1 "general_movsrc_operand"
5286 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5287 "TARGET_SHMEDIA_FPU
5288 && (register_operand (operands[0], SImode)
5289 || sh_register_operand (operands[1], SImode)
5290 || GET_CODE (operands[1]) == TRUNCATE)"
5291 "@
5292 add.l %1, r63, %0
5293 movi %1, %0
5294 #
5295 ld%M1.l %m1, %0
5296 st%M0.l %m0, %N1
5297 fld%M1.s %m1, %0
5298 fst%M0.s %m0, %1
5299 fmov.ls %N1, %0
5300 fmov.sl %1, %0
5301 fmov.s %1, %0
5302 ptabs %1, %0
5303 gettr %1, %0
5304 pt %1, %0"
5305 [(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")
5306 (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
5307 (set (attr "highpart")
5308 (cond [(match_test "sh_contains_memref_p (insn)")
5309 (const_string "user")]
5310 (const_string "ignore")))])
5311
5312 (define_insn "*movsi_media_nofpu"
5313 [(set (match_operand:SI 0 "general_movdst_operand"
5314 "=r,r,r,r,m,*b,r,*b")
5315 (match_operand:SI 1 "general_movsrc_operand"
5316 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
5317 "TARGET_SHMEDIA
5318 && (register_operand (operands[0], SImode)
5319 || sh_register_operand (operands[1], SImode)
5320 || GET_CODE (operands[1]) == TRUNCATE)"
5321 "@
5322 add.l %1, r63, %0
5323 movi %1, %0
5324 #
5325 ld%M1.l %m1, %0
5326 st%M0.l %m0, %N1
5327 ptabs %1, %0
5328 gettr %1, %0
5329 pt %1, %0"
5330 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5331 (set_attr "length" "4,4,8,4,4,4,4,12")
5332 (set (attr "highpart")
5333 (cond [(match_test "sh_contains_memref_p (insn)")
5334 (const_string "user")]
5335 (const_string "ignore")))])
5336
5337 (define_expand "movsi_const"
5338 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5339 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
5340 (const_int 16)] UNSPEC_EXTRACT_S16)))
5341 (set (match_dup 0)
5342 (ior:SI (ashift:SI (match_dup 0) (const_int 16))
5343 (const:SI (unspec:SI [(match_dup 1)
5344 (const_int 0)] UNSPEC_EXTRACT_U16))))]
5345 "TARGET_SHMEDIA && reload_completed
5346 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5347 "
5348 {
5349 if (GET_CODE (operands[1]) == LABEL_REF
5350 && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
5351 LABEL_NUSES (XEXP (operands[1], 0)) += 2;
5352 else if (GOTOFF_P (operands[1]))
5353 {
5354 rtx unspec = XEXP (operands[1], 0);
5355
5356 if (! UNSPEC_GOTOFF_P (unspec))
5357 {
5358 unspec = XEXP (unspec, 0);
5359 if (! UNSPEC_GOTOFF_P (unspec))
5360 abort ();
5361 }
5362 if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
5363 && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
5364 LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
5365 }
5366 }")
5367
5368 (define_expand "movsi_const_16bit"
5369 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5370 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
5371 (const_int 0)] UNSPEC_EXTRACT_S16)))]
5372 "TARGET_SHMEDIA && flag_pic && reload_completed
5373 && GET_CODE (operands[1]) == SYMBOL_REF"
5374 "")
5375
5376 (define_split
5377 [(set (match_operand:SI 0 "arith_reg_dest" "")
5378 (match_operand:SI 1 "immediate_operand" ""))]
5379 "TARGET_SHMEDIA && reload_completed
5380 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5381 [(const_int 0)]
5382 "
5383 {
5384 rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
5385
5386 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
5387
5388 DONE;
5389 }")
5390
5391 (define_split
5392 [(set (match_operand:SI 0 "register_operand" "")
5393 (match_operand:SI 1 "immediate_operand" ""))]
5394 "TARGET_SHMEDIA && reload_completed
5395 && ((CONST_INT_P (operands[1])
5396 && ! satisfies_constraint_I16 (operands[1]))
5397 || GET_CODE (operands[1]) == CONST_DOUBLE)"
5398 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5399
5400 (define_expand "movsi"
5401 [(set (match_operand:SI 0 "general_movdst_operand" "")
5402 (match_operand:SI 1 "general_movsrc_operand" ""))]
5403 ""
5404 "{ if (prepare_move_operands (operands, SImode)) DONE; }")
5405
5406 (define_expand "ic_invalidate_line"
5407 [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
5408 (match_dup 1)] UNSPEC_ICACHE)
5409 (clobber (scratch:SI))])]
5410 "TARGET_HARD_SH4 || TARGET_SH5"
5411 "
5412 {
5413 if (TARGET_SHMEDIA)
5414 {
5415 emit_insn (gen_ic_invalidate_line_media (operands[0]));
5416 DONE;
5417 }
5418 else if (TARGET_SHCOMPACT)
5419 {
5420 operands[1] = function_symbol (NULL, \"__ic_invalidate\", SFUNC_STATIC);
5421 operands[1] = force_reg (Pmode, operands[1]);
5422 emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
5423 DONE;
5424 }
5425 else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
5426 {
5427 emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
5428 DONE;
5429 }
5430 operands[0] = force_reg (Pmode, operands[0]);
5431 operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
5432 Pmode)));
5433 }")
5434
5435 ;; The address %0 is assumed to be 4-aligned at least. Thus, by ORing
5436 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
5437 ;; the requirement *1*00 for associative address writes. The alignment of
5438 ;; %0 implies that its least significant bit is cleared,
5439 ;; thus we clear the V bit of a matching entry if there is one.
5440 (define_insn "ic_invalidate_line_i"
5441 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
5442 (match_operand:SI 1 "register_operand" "r")]
5443 UNSPEC_ICACHE)
5444 (clobber (match_scratch:SI 2 "=&r"))]
5445 "TARGET_HARD_SH4"
5446 "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
5447 [(set_attr "length" "8")
5448 (set_attr "type" "cwb")])
5449
5450 (define_insn "ic_invalidate_line_sh4a"
5451 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
5452 UNSPEC_ICACHE)]
5453 "TARGET_SH4A_ARCH || TARGET_SH4_300"
5454 "ocbwb\\t@%0\;synco\;icbi\\t@%0"
5455 [(set_attr "length" "16")
5456 (set_attr "type" "cwb")])
5457
5458 ;; ??? could make arg 0 an offsettable memory operand to allow to save
5459 ;; an add in the code that calculates the address.
5460 (define_insn "ic_invalidate_line_media"
5461 [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
5462 UNSPEC_ICACHE)]
5463 "TARGET_SHMEDIA"
5464 "ocbwb %0,0\;synco\;icbi %0, 0\;synci"
5465 [(set_attr "length" "16")
5466 (set_attr "type" "invalidate_line_media")])
5467
5468 (define_insn "ic_invalidate_line_compact"
5469 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5470 (match_operand:SI 1 "register_operand" "r")]
5471 UNSPEC_ICACHE)
5472 (clobber (reg:SI PR_REG))]
5473 "TARGET_SHCOMPACT"
5474 "jsr @%1%#"
5475 [(set_attr "type" "sfunc")
5476 (set_attr "needs_delay_slot" "yes")])
5477
5478 (define_expand "initialize_trampoline"
5479 [(match_operand:SI 0 "" "")
5480 (match_operand:SI 1 "" "")
5481 (match_operand:SI 2 "" "")]
5482 "TARGET_SHCOMPACT"
5483 "
5484 {
5485 rtx sfun, tramp;
5486
5487 tramp = force_reg (Pmode, operands[0]);
5488 sfun = force_reg (Pmode, function_symbol (NULL, \"__init_trampoline\",
5489 SFUNC_STATIC));
5490 emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
5491 emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
5492
5493 emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
5494 DONE;
5495 }")
5496
5497 (define_insn "initialize_trampoline_compact"
5498 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5499 (match_operand:SI 1 "register_operand" "r")
5500 (reg:SI R2_REG) (reg:SI R3_REG)]
5501 UNSPEC_INIT_TRAMP)
5502
5503 (clobber (reg:SI PR_REG))]
5504 "TARGET_SHCOMPACT"
5505 "jsr @%1%#"
5506 [(set_attr "type" "sfunc")
5507 (set_attr "needs_delay_slot" "yes")])
5508
5509 (define_expand "movqi"
5510 [(set (match_operand:QI 0 "general_operand" "")
5511 (match_operand:QI 1 "general_operand" ""))]
5512 ""
5513 "{ if (prepare_move_operands (operands, QImode)) DONE; }")
5514
5515 ;; If movqi_reg_reg is specified as an alternative of movqi, movqi will be
5516 ;; selected to copy QImode regs. If one of them happens to be allocated
5517 ;; on the stack, reload will stick to movqi insn and generate wrong
5518 ;; displacement addressing because of the generic m alternatives.
5519 ;; With the movqi_reg_reg being specified before movqi it will be intially
5520 ;; picked to load/store regs. If the regs regs are on the stack reload will
5521 ;; try other insns and not stick to movqi_reg_reg.
5522 (define_insn "*movqi_reg_reg"
5523 [(set (match_operand:QI 0 "arith_reg_dest" "=r,r")
5524 (match_operand:QI 1 "register_operand" "r,t"))]
5525 "TARGET_SH1"
5526 "@
5527 mov %1,%0
5528 movt %0"
5529 [(set_attr "type" "move,arith")])
5530
5531 ;; FIXME: The non-SH2A and SH2A variants should be combined by adding
5532 ;; "enabled" attribute as it is done in other targets.
5533 (define_insn "*movqi_store_mem_disp04"
5534 [(set (mem:QI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
5535 (match_operand:SI 1 "const_int_operand" "K04,N")))
5536 (match_operand:QI 2 "arith_reg_operand" "z,r"))]
5537 "TARGET_SH1 && CONST_OK_FOR_K04 (INTVAL (operands[1]))"
5538 "@
5539 mov.b %2,@(%O1,%0)
5540 mov.b %2,@%0"
5541 [(set_attr "type" "store")])
5542
5543 (define_insn "*movqi_store_mem_disp12"
5544 [(set (mem:QI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
5545 (match_operand:SI 1 "const_int_operand" "K12")))
5546 (match_operand:QI 2 "arith_reg_operand" "r"))]
5547 "TARGET_SH2A && CONST_OK_FOR_K12 (INTVAL (operands[1]))"
5548 "mov.b %2,@(%O1,%0)"
5549 [(set_attr "type" "store")
5550 (set_attr "length" "4")])
5551
5552 (define_insn "*movqi_load_mem_disp"
5553 [(set (match_operand:QI 0 "arith_reg_dest" "=z,r")
5554 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
5555 (match_operand:SI 2 "const_int_operand" "K04,N"))))]
5556 "TARGET_SH1 && ! TARGET_SH2A && CONST_OK_FOR_K04 (INTVAL (operands[2]))"
5557 "@
5558 mov.b @(%O2,%1),%0
5559 mov.b @%1,%0"
5560 [(set_attr "type" "load")])
5561
5562 (define_insn "*movqi_load_mem_disp"
5563 [(set (match_operand:QI 0 "arith_reg_dest" "=z,r,r")
5564 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
5565 (match_operand:SI 2 "const_int_operand" "K04,N,K12"))))]
5566 "TARGET_SH2A
5567 && (CONST_OK_FOR_K04 (INTVAL (operands[2]))
5568 || CONST_OK_FOR_K12 (INTVAL (operands[2])))"
5569 "@
5570 mov.b @(%O2,%1),%0
5571 mov.b @%1,%0
5572 mov.b @(%O2,%1),%0"
5573 [(set_attr "type" "load")
5574 (set_attr "length" "2,2,4")])
5575
5576 ;; The m constraints basically allow any kind of addresses to be used with any
5577 ;; source/target register as the other operand. This is not true for
5578 ;; displacement addressing modes on anything but SH2A. That's why the
5579 ;; specialized load/store insns are specified above.
5580 (define_insn "*movqi"
5581 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,l")
5582 (match_operand:QI 1 "general_movsrc_operand" "i,m,r,l,r"))]
5583 "TARGET_SH1
5584 && (arith_reg_operand (operands[0], QImode)
5585 || arith_reg_operand (operands[1], QImode))"
5586 "@
5587 mov %1,%0
5588 mov.b %1,%0
5589 mov.b %1,%0
5590 sts %1,%0
5591 lds %1,%0"
5592 [(set_attr "type" "movi8,load,store,prget,prset")])
5593
5594 (define_insn "*movqi_media"
5595 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
5596 (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
5597 "TARGET_SHMEDIA
5598 && (arith_reg_operand (operands[0], QImode)
5599 || extend_reg_or_0_operand (operands[1], QImode))"
5600 "@
5601 add.l %1, r63, %0
5602 movi %1, %0
5603 ld%M1.ub %m1, %0
5604 st%M0.b %m0, %N1"
5605 [(set_attr "type" "arith_media,arith_media,load_media,store_media")
5606 (set (attr "highpart")
5607 (cond [(match_test "sh_contains_memref_p (insn)")
5608 (const_string "user")]
5609 (const_string "ignore")))])
5610
5611 (define_expand "reload_inqi"
5612 [(set (match_operand:SI 2 "" "=&r")
5613 (match_operand:QI 1 "inqhi_operand" ""))
5614 (set (match_operand:QI 0 "arith_reg_operand" "=r")
5615 (truncate:QI (match_dup 3)))]
5616 "TARGET_SHMEDIA"
5617 "
5618 {
5619 rtx inner = XEXP (operands[1], 0);
5620 int regno = REGNO (inner);
5621
5622 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5623 operands[1] = gen_rtx_REG (SImode, regno);
5624 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5625 }")
5626
5627 ;; When storing r0, we have to avoid reg+reg addressing.
5628 (define_insn "movhi_i"
5629 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m,r,l,r")
5630 (match_operand:HI 1 "general_movsrc_operand" "Q,rI08,m,t,r,l,r,i"))]
5631 "TARGET_SH1
5632 && (arith_reg_operand (operands[0], HImode)
5633 || arith_reg_operand (operands[1], HImode))
5634 && (!MEM_P (operands[0])
5635 || GET_CODE (XEXP (operands[0], 0)) != PLUS
5636 || !REG_P (XEXP (XEXP (operands[0], 0), 1))
5637 || ! refers_to_regno_p (R0_REG, R0_REG + 1, operands[1], (rtx *)0))"
5638 "@
5639 mov.w %1,%0
5640 mov %1,%0
5641 mov.w %1,%0
5642 movt %0
5643 mov.w %1,%0
5644 sts %1,%0
5645 lds %1,%0
5646 fake %1,%0"
5647 [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
5648
5649 (define_insn "*movhi_media"
5650 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m")
5651 (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
5652 "TARGET_SHMEDIA
5653 && (arith_reg_operand (operands[0], HImode)
5654 || arith_reg_or_0_operand (operands[1], HImode))"
5655 "@
5656 add.l %1, r63, %0
5657 movi %1, %0
5658 #
5659 ld%M1.w %m1, %0
5660 st%M0.w %m0, %N1"
5661 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
5662 (set (attr "highpart")
5663 (cond [(match_test "sh_contains_memref_p (insn)")
5664 (const_string "user")]
5665 (const_string "ignore")))])
5666
5667 (define_split
5668 [(set (match_operand:HI 0 "register_operand" "")
5669 (match_operand:HI 1 "immediate_operand" ""))]
5670 "TARGET_SHMEDIA && reload_completed
5671 && ! satisfies_constraint_I16 (operands[1])"
5672 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5673
5674 (define_expand "movhi"
5675 [(set (match_operand:HI 0 "general_movdst_operand" "")
5676 (match_operand:HI 1 "general_movsrc_operand" ""))]
5677 ""
5678 "{ if (prepare_move_operands (operands, HImode)) DONE; }")
5679
5680 (define_expand "reload_inhi"
5681 [(set (match_operand:SI 2 "" "=&r")
5682 (match_operand:HI 1 "inqhi_operand" ""))
5683 (set (match_operand:HI 0 "arith_reg_operand" "=r")
5684 (truncate:HI (match_dup 3)))]
5685 "TARGET_SHMEDIA"
5686 "
5687 {
5688 rtx inner = XEXP (operands[1], 0);
5689 int regno = REGNO (inner);
5690
5691 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5692 operands[1] = gen_rtx_REG (SImode, regno);
5693 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5694 }")
5695
5696 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
5697 ;; compiled with -m2 -ml -O3 -funroll-loops
5698 (define_insn "*movdi_i"
5699 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
5700 (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
5701 "TARGET_SH1
5702 && (arith_reg_operand (operands[0], DImode)
5703 || arith_reg_operand (operands[1], DImode))"
5704 "* return output_movedouble (insn, operands, DImode);"
5705 [(set_attr "length" "4")
5706 (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
5707
5708 ;; If the output is a register and the input is memory or a register, we have
5709 ;; to be careful and see which word needs to be loaded first.
5710
5711 (define_split
5712 [(set (match_operand:DI 0 "general_movdst_operand" "")
5713 (match_operand:DI 1 "general_movsrc_operand" ""))]
5714 "TARGET_SH1 && reload_completed"
5715 [(set (match_dup 2) (match_dup 3))
5716 (set (match_dup 4) (match_dup 5))]
5717 "
5718 {
5719 int regno;
5720
5721 if ((MEM_P (operands[0])
5722 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
5723 || (MEM_P (operands[1])
5724 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
5725 FAIL;
5726
5727 switch (GET_CODE (operands[0]))
5728 {
5729 case REG:
5730 regno = REGNO (operands[0]);
5731 break;
5732 case SUBREG:
5733 regno = subreg_regno (operands[0]);
5734 break;
5735 case MEM:
5736 regno = -1;
5737 break;
5738 default:
5739 gcc_unreachable ();
5740 }
5741
5742 if (regno == -1
5743 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
5744 {
5745 operands[2] = operand_subword (operands[0], 0, 0, DImode);
5746 operands[3] = operand_subword (operands[1], 0, 0, DImode);
5747 operands[4] = operand_subword (operands[0], 1, 0, DImode);
5748 operands[5] = operand_subword (operands[1], 1, 0, DImode);
5749 }
5750 else
5751 {
5752 operands[2] = operand_subword (operands[0], 1, 0, DImode);
5753 operands[3] = operand_subword (operands[1], 1, 0, DImode);
5754 operands[4] = operand_subword (operands[0], 0, 0, DImode);
5755 operands[5] = operand_subword (operands[1], 0, 0, DImode);
5756 }
5757
5758 if (operands[2] == 0 || operands[3] == 0
5759 || operands[4] == 0 || operands[5] == 0)
5760 FAIL;
5761 }")
5762
5763 ;; The '?'s in the following constraints may not reflect the time taken
5764 ;; to perform the move. They are there to discourage the use of floating-
5765 ;; point registers for storing integer values.
5766 (define_insn "*movdi_media"
5767 [(set (match_operand:DI 0 "general_movdst_operand"
5768 "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
5769 (match_operand:DI 1 "general_movsrc_operand"
5770 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5771 "TARGET_SHMEDIA_FPU
5772 && (register_operand (operands[0], DImode)
5773 || sh_register_operand (operands[1], DImode))"
5774 "@
5775 add %1, r63, %0
5776 movi %1, %0
5777 #
5778 ld%M1.q %m1, %0
5779 st%M0.q %m0, %N1
5780 fld%M1.d %m1, %0
5781 fst%M0.d %m0, %1
5782 fmov.qd %N1, %0
5783 fmov.dq %1, %0
5784 fmov.d %1, %0
5785 ptabs %1, %0
5786 gettr %1, %0
5787 pt %1, %0"
5788 [(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")
5789 (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
5790
5791 (define_insn "*movdi_media_nofpu"
5792 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
5793 (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
5794 "TARGET_SHMEDIA
5795 && (register_operand (operands[0], DImode)
5796 || sh_register_operand (operands[1], DImode))"
5797 "@
5798 add %1, r63, %0
5799 movi %1, %0
5800 #
5801 ld%M1.q %m1, %0
5802 st%M0.q %m0, %N1
5803 ptabs %1, %0
5804 gettr %1, %0
5805 pt %1, %0"
5806 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5807 (set_attr "length" "4,4,16,4,4,4,4,*")])
5808
5809 (define_insn "*movdi_media_I16"
5810 [(set (match_operand:DI 0 "ext_dest_operand" "=r")
5811 (match_operand:DI 1 "const_int_operand" "I16"))]
5812 "TARGET_SHMEDIA && reload_completed"
5813 "movi %1, %0"
5814 [(set_attr "type" "arith_media")
5815 (set_attr "length" "4")])
5816
5817 (define_split
5818 [(set (match_operand:DI 0 "arith_reg_dest" "")
5819 (match_operand:DI 1 "immediate_operand" ""))]
5820 "TARGET_SHMEDIA && reload_completed
5821 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5822 [(set (match_dup 0) (match_dup 1))]
5823 "
5824 {
5825 rtx insn;
5826
5827 if (TARGET_SHMEDIA64)
5828 insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
5829 else
5830 insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
5831
5832 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
5833
5834 DONE;
5835 }")
5836
5837 (define_expand "movdi_const"
5838 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5839 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5840 (const_int 48)] UNSPEC_EXTRACT_S16)))
5841 (set (match_dup 0)
5842 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5843 (const:DI (unspec:DI [(match_dup 1)
5844 (const_int 32)] UNSPEC_EXTRACT_U16))))
5845 (set (match_dup 0)
5846 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5847 (const:DI (unspec:DI [(match_dup 1)
5848 (const_int 16)] UNSPEC_EXTRACT_U16))))
5849 (set (match_dup 0)
5850 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5851 (const:DI (unspec:DI [(match_dup 1)
5852 (const_int 0)] UNSPEC_EXTRACT_U16))))]
5853 "TARGET_SHMEDIA64 && reload_completed
5854 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5855 "
5856 {
5857 sh_mark_label (operands[1], 4);
5858 }")
5859
5860 (define_expand "movdi_const_32bit"
5861 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5862 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5863 (const_int 16)] UNSPEC_EXTRACT_S16)))
5864 (set (match_dup 0)
5865 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5866 (const:DI (unspec:DI [(match_dup 1)
5867 (const_int 0)] UNSPEC_EXTRACT_U16))))]
5868 "TARGET_SHMEDIA32 && reload_completed
5869 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5870 "
5871 {
5872 sh_mark_label (operands[1], 2);
5873 }")
5874
5875 (define_expand "movdi_const_16bit"
5876 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5877 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5878 (const_int 0)] UNSPEC_EXTRACT_S16)))]
5879 "TARGET_SHMEDIA && flag_pic && reload_completed
5880 && GET_CODE (operands[1]) == SYMBOL_REF"
5881 "")
5882
5883 (define_split
5884 [(set (match_operand:DI 0 "ext_dest_operand" "")
5885 (match_operand:DI 1 "immediate_operand" ""))]
5886 "TARGET_SHMEDIA && reload_completed
5887 && CONST_INT_P (operands[1])
5888 && ! satisfies_constraint_I16 (operands[1])"
5889 [(set (match_dup 0) (match_dup 2))
5890 (match_dup 1)]
5891 "
5892 {
5893 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
5894 unsigned HOST_WIDE_INT low = val;
5895 unsigned HOST_WIDE_INT high = val;
5896 unsigned HOST_WIDE_INT sign;
5897 unsigned HOST_WIDE_INT val2 = val ^ (val-1);
5898
5899 /* Zero-extend the 16 least-significant bits. */
5900 low &= 0xffff;
5901
5902 /* Arithmetic shift right the word by 16 bits. */
5903 high >>= 16;
5904 if (GET_CODE (operands[0]) == SUBREG
5905 && GET_MODE (SUBREG_REG (operands[0])) == SImode)
5906 {
5907 high &= 0xffff;
5908 high ^= 0x8000;
5909 high -= 0x8000;
5910 }
5911 else
5912 {
5913 sign = 1;
5914 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5915 high ^= sign;
5916 high -= sign;
5917 }
5918 do
5919 {
5920 /* If we can't generate the constant with a two-insn movi / shori
5921 sequence, try some other strategies. */
5922 if (! CONST_OK_FOR_I16 (high))
5923 {
5924 /* Try constant load / left shift. We know VAL != 0. */
5925 val2 = val ^ (val-1);
5926 if (val2 > 0x1ffff)
5927 {
5928 int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
5929
5930 if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
5931 || (! CONST_OK_FOR_I16 (high >> 16)
5932 && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
5933 {
5934 val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
5935 operands[1] = gen_ashldi3_media (operands[0], operands[0],
5936 GEN_INT (trailing_zeroes));
5937 break;
5938 }
5939 }
5940 /* Try constant load / right shift. */
5941 val2 = (val >> 15) + 1;
5942 if (val2 == (val2 & -val2))
5943 {
5944 int shift = 49 - exact_log2 (val2);
5945
5946 val2 = trunc_int_for_mode (val << shift, DImode);
5947 if (CONST_OK_FOR_I16 (val2))
5948 {
5949 operands[1] = gen_lshrdi3_media (operands[0], operands[0],
5950 GEN_INT (shift));
5951 break;
5952 }
5953 }
5954 /* Try mperm.w . */
5955 val2 = val & 0xffff;
5956 if ((val >> 16 & 0xffff) == val2
5957 && (val >> 32 & 0xffff) == val2
5958 && (val >> 48 & 0xffff) == val2)
5959 {
5960 val2 = (HOST_WIDE_INT) val >> 48;
5961 operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
5962 operands[1] = gen_mperm_w0 (operands[1], operands[1]);
5963 break;
5964 }
5965 /* Try movi / mshflo.l */
5966 val2 = (HOST_WIDE_INT) val >> 32;
5967 if (val2 == ((unsigned HOST_WIDE_INT)
5968 trunc_int_for_mode (val, SImode)))
5969 {
5970 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5971 operands[0]);
5972 break;
5973 }
5974 /* Try movi / mshflo.l w/ r63. */
5975 val2 = val + ((HOST_WIDE_INT) -1 << 32);
5976 if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
5977 {
5978 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5979 const0_rtx);
5980 break;
5981 }
5982 }
5983 val2 = high;
5984 operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
5985 }
5986 while (0);
5987 operands[2] = GEN_INT (val2);
5988 }")
5989
5990 (define_split
5991 [(set (match_operand:DI 0 "ext_dest_operand" "")
5992 (match_operand:DI 1 "immediate_operand" ""))]
5993 "TARGET_SHMEDIA && reload_completed
5994 && GET_CODE (operands[1]) == CONST_DOUBLE"
5995 [(set (match_dup 0) (match_dup 2))
5996 (set (match_dup 0)
5997 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
5998 "
5999 {
6000 unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
6001 unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
6002 unsigned HOST_WIDE_INT val = low;
6003 unsigned HOST_WIDE_INT sign;
6004
6005 /* Zero-extend the 16 least-significant bits. */
6006 val &= 0xffff;
6007 operands[1] = GEN_INT (val);
6008
6009 /* Arithmetic shift right the double-word by 16 bits. */
6010 low >>= 16;
6011 low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
6012 high >>= 16;
6013 sign = 1;
6014 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
6015 high ^= sign;
6016 high -= sign;
6017
6018 /* This will only be true if high is a sign-extension of low, i.e.,
6019 it must be either 0 or (unsigned)-1, and be zero iff the
6020 most-significant bit of low is set. */
6021 if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
6022 operands[2] = GEN_INT (low);
6023 else
6024 operands[2] = immed_double_const (low, high, DImode);
6025 }")
6026
6027 (define_insn "shori_media"
6028 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
6029 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
6030 (const_int 16))
6031 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
6032 "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
6033 "@
6034 shori %u2, %0
6035 #"
6036 [(set_attr "type" "arith_media,*")])
6037
6038 (define_insn "*shori_media_si"
6039 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6040 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
6041 (const_int 16))
6042 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
6043 "TARGET_SHMEDIA"
6044 "shori %u2, %0")
6045
6046 (define_expand "movdi"
6047 [(set (match_operand:DI 0 "general_movdst_operand" "")
6048 (match_operand:DI 1 "general_movsrc_operand" ""))]
6049 ""
6050 "{ if (prepare_move_operands (operands, DImode)) DONE; }")
6051
6052 (define_insn "movdf_media"
6053 [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
6054 (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
6055 "TARGET_SHMEDIA_FPU
6056 && (register_operand (operands[0], DFmode)
6057 || sh_register_operand (operands[1], DFmode))"
6058 "@
6059 fmov.d %1, %0
6060 fmov.qd %N1, %0
6061 fmov.dq %1, %0
6062 add %1, r63, %0
6063 #
6064 fld%M1.d %m1, %0
6065 fst%M0.d %m0, %1
6066 ld%M1.q %m1, %0
6067 st%M0.q %m0, %N1"
6068 [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
6069
6070 (define_insn "movdf_media_nofpu"
6071 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
6072 (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
6073 "TARGET_SHMEDIA
6074 && (register_operand (operands[0], DFmode)
6075 || sh_register_operand (operands[1], DFmode))"
6076 "@
6077 add %1, r63, %0
6078 #
6079 ld%M1.q %m1, %0
6080 st%M0.q %m0, %N1"
6081 [(set_attr "type" "arith_media,*,load_media,store_media")])
6082
6083 (define_split
6084 [(set (match_operand:DF 0 "arith_reg_dest" "")
6085 (match_operand:DF 1 "immediate_operand" ""))]
6086 "TARGET_SHMEDIA && reload_completed"
6087 [(set (match_dup 3) (match_dup 2))]
6088 "
6089 {
6090 int endian = WORDS_BIG_ENDIAN ? 1 : 0;
6091 long values[2];
6092 REAL_VALUE_TYPE value;
6093
6094 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
6095 REAL_VALUE_TO_TARGET_DOUBLE (value, values);
6096
6097 if (HOST_BITS_PER_WIDE_INT >= 64)
6098 operands[2] = immed_double_const ((unsigned long) values[endian]
6099 | ((HOST_WIDE_INT) values[1 - endian]
6100 << 32), 0, DImode);
6101 else
6102 {
6103 gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
6104 operands[2] = immed_double_const (values[endian], values[1 - endian],
6105 DImode);
6106 }
6107
6108 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6109 }")
6110
6111 ;; ??? This should be a define expand.
6112
6113 (define_insn "movdf_k"
6114 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
6115 (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
6116 "TARGET_SH1
6117 && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
6118 /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
6119 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
6120 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
6121 && (arith_reg_operand (operands[0], DFmode)
6122 || arith_reg_operand (operands[1], DFmode))"
6123 "* return output_movedouble (insn, operands, DFmode);"
6124 [(set_attr "length" "4")
6125 (set_attr "type" "move,pcload,load,store")])
6126
6127 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
6128 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
6129 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
6130 ;; the d/m/c/X alternative, which is split later into single-precision
6131 ;; instructions. And when not optimizing, no splits are done before fixing
6132 ;; up pcloads, so we need usable length information for that.
6133 (define_insn "movdf_i4"
6134 [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
6135 (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
6136 (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
6137 (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
6138 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
6139 && (arith_reg_operand (operands[0], DFmode)
6140 || arith_reg_operand (operands[1], DFmode))"
6141 {
6142 switch (which_alternative)
6143 {
6144 case 0:
6145 if (TARGET_FMOVD)
6146 return "fmov %1,%0";
6147 else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
6148 return "fmov %R1,%R0\n\tfmov %S1,%S0";
6149 else
6150 return "fmov %S1,%S0\n\tfmov %R1,%R0";
6151 case 3:
6152 case 4:
6153 return "fmov.d %1,%0";
6154 default:
6155 return "#";
6156 }
6157 }
6158 [(set_attr_alternative "length"
6159 [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
6160 (const_int 4)
6161 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
6162 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
6163 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
6164 (const_int 4)
6165 (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
6166 ;; We can't use 4-byte push/pop on SHcompact, so we have to
6167 ;; increment or decrement r15 explicitly.
6168 (if_then_else
6169 (match_test "TARGET_SHCOMPACT")
6170 (const_int 10) (const_int 8))
6171 (if_then_else
6172 (match_test "TARGET_SHCOMPACT")
6173 (const_int 10) (const_int 8))])
6174 (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
6175 (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
6176 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
6177 (const_string "double")
6178 (const_string "none")))])
6179
6180 ;; Moving DFmode between fp/general registers through memory
6181 ;; (the top of the stack) is faster than moving through fpul even for
6182 ;; little endian. Because the type of an instruction is important for its
6183 ;; scheduling, it is beneficial to split these operations, rather than
6184 ;; emitting them in one single chunk, even if this will expose a stack
6185 ;; use that will prevent scheduling of other stack accesses beyond this
6186 ;; instruction.
6187 (define_split
6188 [(set (match_operand:DF 0 "register_operand" "")
6189 (match_operand:DF 1 "register_operand" ""))
6190 (use (match_operand:PSI 2 "fpscr_operand" ""))
6191 (clobber (match_scratch:SI 3 "=X"))]
6192 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
6193 && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
6194 [(const_int 0)]
6195 "
6196 {
6197 rtx insn, tos;
6198
6199 if (TARGET_SH5 && true_regnum (operands[1]) < 16)
6200 {
6201 emit_move_insn (stack_pointer_rtx,
6202 plus_constant (stack_pointer_rtx, -8));
6203 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
6204 }
6205 else
6206 tos = gen_tmp_stack_mem (DFmode,
6207 gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
6208 insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
6209 if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
6210 add_reg_note (insn, REG_INC, stack_pointer_rtx);
6211 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
6212 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
6213 else
6214 tos = gen_tmp_stack_mem (DFmode,
6215 gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
6216 insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
6217 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
6218 emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
6219 else
6220 add_reg_note (insn, REG_INC, stack_pointer_rtx);
6221 DONE;
6222 }")
6223
6224 ;; local-alloc sometimes allocates scratch registers even when not required,
6225 ;; so we must be prepared to handle these.
6226
6227 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
6228 (define_split
6229 [(set (match_operand:DF 0 "general_movdst_operand" "")
6230 (match_operand:DF 1 "general_movsrc_operand" ""))
6231 (use (match_operand:PSI 2 "fpscr_operand" ""))
6232 (clobber (match_scratch:SI 3 ""))]
6233 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
6234 && reload_completed
6235 && true_regnum (operands[0]) < 16
6236 && true_regnum (operands[1]) < 16"
6237 [(set (match_dup 0) (match_dup 1))]
6238 "
6239 {
6240 /* If this was a reg <-> mem operation with base + index reg addressing,
6241 we have to handle this in a special way. */
6242 rtx mem = operands[0];
6243 int store_p = 1;
6244 if (! memory_operand (mem, DFmode))
6245 {
6246 mem = operands[1];
6247 store_p = 0;
6248 }
6249 if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
6250 mem = SUBREG_REG (mem);
6251 if (MEM_P (mem))
6252 {
6253 rtx addr = XEXP (mem, 0);
6254 if (GET_CODE (addr) == PLUS
6255 && REG_P (XEXP (addr, 0))
6256 && REG_P (XEXP (addr, 1)))
6257 {
6258 int offset;
6259 rtx reg0 = gen_rtx_REG (Pmode, 0);
6260 rtx regop = operands[store_p], word0 ,word1;
6261
6262 if (GET_CODE (regop) == SUBREG)
6263 alter_subreg (&regop);
6264 if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
6265 offset = 2;
6266 else
6267 offset = 4;
6268 mem = copy_rtx (mem);
6269 PUT_MODE (mem, SImode);
6270 word0 = gen_rtx_SUBREG (SImode, regop, 0);
6271 alter_subreg (&word0);
6272 word1 = gen_rtx_SUBREG (SImode, regop, 4);
6273 alter_subreg (&word1);
6274 if (store_p || ! refers_to_regno_p (REGNO (word0),
6275 REGNO (word0) + 1, addr, 0))
6276 {
6277 emit_insn (store_p
6278 ? gen_movsi_ie (mem, word0)
6279 : gen_movsi_ie (word0, mem));
6280 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
6281 mem = copy_rtx (mem);
6282 emit_insn (store_p
6283 ? gen_movsi_ie (mem, word1)
6284 : gen_movsi_ie (word1, mem));
6285 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
6286 }
6287 else
6288 {
6289 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
6290 emit_insn (gen_movsi_ie (word1, mem));
6291 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
6292 mem = copy_rtx (mem);
6293 emit_insn (gen_movsi_ie (word0, mem));
6294 }
6295 DONE;
6296 }
6297 }
6298 }")
6299
6300 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
6301 (define_split
6302 [(set (match_operand:DF 0 "register_operand" "")
6303 (match_operand:DF 1 "memory_operand" ""))
6304 (use (match_operand:PSI 2 "fpscr_operand" ""))
6305 (clobber (reg:SI R0_REG))]
6306 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
6307 [(parallel [(set (match_dup 0) (match_dup 1))
6308 (use (match_dup 2))
6309 (clobber (scratch:SI))])]
6310 "")
6311
6312 (define_expand "reload_indf__frn"
6313 [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
6314 (match_operand:DF 1 "immediate_operand" "FQ"))
6315 (use (reg:PSI FPSCR_REG))
6316 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6317 "TARGET_SH1"
6318 "")
6319
6320 (define_expand "reload_outdf__RnFRm"
6321 [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
6322 (match_operand:DF 1 "register_operand" "af,r"))
6323 (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
6324 "TARGET_SH1"
6325 "")
6326
6327 ;; Simplify no-op moves.
6328 (define_split
6329 [(set (match_operand:SF 0 "register_operand" "")
6330 (match_operand:SF 1 "register_operand" ""))
6331 (use (match_operand:PSI 2 "fpscr_operand" ""))
6332 (clobber (match_scratch:SI 3 ""))]
6333 "TARGET_SH2E && reload_completed
6334 && true_regnum (operands[0]) == true_regnum (operands[1])"
6335 [(set (match_dup 0) (match_dup 0))]
6336 "")
6337
6338 ;; fmovd substitute post-reload splits
6339 (define_split
6340 [(set (match_operand:DF 0 "register_operand" "")
6341 (match_operand:DF 1 "register_operand" ""))
6342 (use (match_operand:PSI 2 "fpscr_operand" ""))
6343 (clobber (match_scratch:SI 3 ""))]
6344 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
6345 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
6346 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6347 [(const_int 0)]
6348 "
6349 {
6350 int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
6351 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
6352 gen_rtx_REG (SFmode, src), operands[2]));
6353 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
6354 gen_rtx_REG (SFmode, src + 1), operands[2]));
6355 DONE;
6356 }")
6357
6358 (define_split
6359 [(set (match_operand:DF 0 "register_operand" "")
6360 (mem:DF (match_operand:SI 1 "register_operand" "")))
6361 (use (match_operand:PSI 2 "fpscr_operand" ""))
6362 (clobber (match_scratch:SI 3 ""))]
6363 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6364 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
6365 && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
6366 [(const_int 0)]
6367 "
6368 {
6369 int regno = true_regnum (operands[0]);
6370 rtx insn;
6371 rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
6372 rtx mem2
6373 = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
6374 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6375 regno + !! TARGET_LITTLE_ENDIAN),
6376 mem2, operands[2]));
6377 add_reg_note (insn, REG_INC, operands[1]);
6378 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6379 regno + ! TARGET_LITTLE_ENDIAN),
6380 change_address (mem, SFmode, NULL_RTX),
6381 operands[2]));
6382 DONE;
6383 }")
6384
6385 (define_split
6386 [(set (match_operand:DF 0 "register_operand" "")
6387 (match_operand:DF 1 "memory_operand" ""))
6388 (use (match_operand:PSI 2 "fpscr_operand" ""))
6389 (clobber (match_scratch:SI 3 ""))]
6390 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6391 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
6392 [(const_int 0)]
6393 {
6394 int regno = true_regnum (operands[0]);
6395 rtx addr, insn;
6396 rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
6397 rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
6398 rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
6399
6400 operands[1] = copy_rtx (mem2);
6401 addr = XEXP (mem2, 0);
6402
6403 switch (GET_CODE (addr))
6404 {
6405 case REG:
6406 /* This is complicated. If the register is an arithmetic register
6407 we can just fall through to the REG+DISP case below. Otherwise
6408 we have to use a combination of POST_INC and REG addressing... */
6409 if (! arith_reg_operand (operands[1], SFmode))
6410 {
6411 XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
6412 insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
6413 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6414
6415 emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6416
6417 /* If we have modified the stack pointer, the value that we have
6418 read with post-increment might be modified by an interrupt,
6419 so write it back. */
6420 if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
6421 emit_insn (gen_push_e (reg0));
6422 else
6423 emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0), GEN_INT (-4)));
6424 break;
6425 }
6426 /* Fall through. */
6427
6428 case PLUS:
6429 emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
6430 operands[1] = copy_rtx (operands[1]);
6431 XEXP (operands[1], 0) = plus_constant (addr, 4);
6432 emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6433 break;
6434
6435 case POST_INC:
6436 insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
6437 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6438
6439 insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6440 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6441 break;
6442
6443 default:
6444 debug_rtx (addr);
6445 gcc_unreachable ();
6446 }
6447
6448 DONE;
6449 })
6450
6451 (define_split
6452 [(set (match_operand:DF 0 "memory_operand" "")
6453 (match_operand:DF 1 "register_operand" ""))
6454 (use (match_operand:PSI 2 "fpscr_operand" ""))
6455 (clobber (match_scratch:SI 3 ""))]
6456 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6457 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6458 [(const_int 0)]
6459 {
6460 int regno = true_regnum (operands[1]);
6461 rtx insn, addr;
6462 rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
6463 rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
6464
6465 operands[0] = copy_rtx (operands[0]);
6466 PUT_MODE (operands[0], SFmode);
6467 addr = XEXP (operands[0], 0);
6468
6469 switch (GET_CODE (addr))
6470 {
6471 case REG:
6472 /* This is complicated. If the register is an arithmetic register
6473 we can just fall through to the REG+DISP case below. Otherwise
6474 we have to use a combination of REG and PRE_DEC addressing... */
6475 if (! arith_reg_operand (operands[0], SFmode))
6476 {
6477 emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
6478 emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
6479
6480 operands[0] = copy_rtx (operands[0]);
6481 XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
6482
6483 insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6484 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6485 break;
6486 }
6487 /* Fall through. */
6488
6489 case PLUS:
6490 /* Since REG+DISP addressing has already been decided upon by gcc
6491 we can rely upon it having chosen an arithmetic register as the
6492 register component of the address. Just emit the lower numbered
6493 register first, to the lower address, then the higher numbered
6494 register to the higher address. */
6495 emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6496
6497 operands[0] = copy_rtx (operands[0]);
6498 XEXP (operands[0], 0) = plus_constant (addr, 4);
6499
6500 emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
6501 break;
6502
6503 case PRE_DEC:
6504 /* This is easy. Output the word to go to the higher address
6505 first (ie the word in the higher numbered register) then the
6506 word to go to the lower address. */
6507
6508 insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
6509 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6510
6511 insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6512 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6513 break;
6514
6515 default:
6516 /* FAIL; */
6517 debug_rtx (addr);
6518 gcc_unreachable ();
6519 }
6520
6521 DONE;
6522 })
6523
6524 ;; If the output is a register and the input is memory or a register, we have
6525 ;; to be careful and see which word needs to be loaded first.
6526
6527 (define_split
6528 [(set (match_operand:DF 0 "general_movdst_operand" "")
6529 (match_operand:DF 1 "general_movsrc_operand" ""))]
6530 "TARGET_SH1 && reload_completed"
6531 [(set (match_dup 2) (match_dup 3))
6532 (set (match_dup 4) (match_dup 5))]
6533 "
6534 {
6535 int regno;
6536
6537 if ((MEM_P (operands[0])
6538 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
6539 || (MEM_P (operands[1])
6540 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
6541 FAIL;
6542
6543 switch (GET_CODE (operands[0]))
6544 {
6545 case REG:
6546 regno = REGNO (operands[0]);
6547 break;
6548 case SUBREG:
6549 regno = subreg_regno (operands[0]);
6550 break;
6551 case MEM:
6552 regno = -1;
6553 break;
6554 default:
6555 gcc_unreachable ();
6556 }
6557
6558 if (regno == -1
6559 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
6560 {
6561 operands[2] = operand_subword (operands[0], 0, 0, DFmode);
6562 operands[3] = operand_subword (operands[1], 0, 0, DFmode);
6563 operands[4] = operand_subword (operands[0], 1, 0, DFmode);
6564 operands[5] = operand_subword (operands[1], 1, 0, DFmode);
6565 }
6566 else
6567 {
6568 operands[2] = operand_subword (operands[0], 1, 0, DFmode);
6569 operands[3] = operand_subword (operands[1], 1, 0, DFmode);
6570 operands[4] = operand_subword (operands[0], 0, 0, DFmode);
6571 operands[5] = operand_subword (operands[1], 0, 0, DFmode);
6572 }
6573
6574 if (operands[2] == 0 || operands[3] == 0
6575 || operands[4] == 0 || operands[5] == 0)
6576 FAIL;
6577 }")
6578
6579 ;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is
6580 ;; used only once, let combine add in the index again.
6581
6582 (define_split
6583 [(set (match_operand:SI 0 "register_operand" "")
6584 (match_operand:SI 1 "" ""))
6585 (clobber (match_operand 2 "register_operand" ""))]
6586 "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6587 && ALLOW_INDEXED_ADDRESS"
6588 [(use (reg:SI R0_REG))]
6589 "
6590 {
6591 rtx addr, reg, const_int;
6592
6593 if (!MEM_P (operands[1]))
6594 FAIL;
6595 addr = XEXP (operands[1], 0);
6596 if (GET_CODE (addr) != PLUS)
6597 FAIL;
6598 reg = XEXP (addr, 0);
6599 const_int = XEXP (addr, 1);
6600 if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6601 && CONST_INT_P (const_int)))
6602 FAIL;
6603 emit_move_insn (operands[2], const_int);
6604 emit_move_insn (operands[0],
6605 change_address (operands[1], VOIDmode,
6606 gen_rtx_PLUS (SImode, reg, operands[2])));
6607 DONE;
6608 }")
6609
6610 (define_split
6611 [(set (match_operand:SI 1 "" "")
6612 (match_operand:SI 0 "register_operand" ""))
6613 (clobber (match_operand 2 "register_operand" ""))]
6614 "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6615 && ALLOW_INDEXED_ADDRESS"
6616 [(use (reg:SI R0_REG))]
6617 "
6618 {
6619 rtx addr, reg, const_int;
6620
6621 if (!MEM_P (operands[1]))
6622 FAIL;
6623 addr = XEXP (operands[1], 0);
6624 if (GET_CODE (addr) != PLUS)
6625 FAIL;
6626 reg = XEXP (addr, 0);
6627 const_int = XEXP (addr, 1);
6628 if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6629 && CONST_INT_P (const_int)))
6630 FAIL;
6631 emit_move_insn (operands[2], const_int);
6632 emit_move_insn (change_address (operands[1], VOIDmode,
6633 gen_rtx_PLUS (SImode, reg, operands[2])),
6634 operands[0]);
6635 DONE;
6636 }")
6637
6638 (define_expand "movdf"
6639 [(set (match_operand:DF 0 "general_movdst_operand" "")
6640 (match_operand:DF 1 "general_movsrc_operand" ""))]
6641 ""
6642 "
6643 {
6644 if (prepare_move_operands (operands, DFmode)) DONE;
6645 if (TARGET_SHMEDIA)
6646 {
6647 if (TARGET_SHMEDIA_FPU)
6648 emit_insn (gen_movdf_media (operands[0], operands[1]));
6649 else
6650 emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
6651 DONE;
6652 }
6653 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
6654 {
6655 emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
6656 DONE;
6657 }
6658 }")
6659
6660 ;;This is incompatible with the way gcc uses subregs.
6661 ;;(define_insn "movv2sf_i"
6662 ;; [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
6663 ;; (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
6664 ;; "TARGET_SHMEDIA_FPU
6665 ;; && (fp_arith_reg_operand (operands[0], V2SFmode)
6666 ;; || fp_arith_reg_operand (operands[1], V2SFmode))"
6667 ;; "@
6668 ;; #
6669 ;; fld%M1.p %m1, %0
6670 ;; fst%M0.p %m0, %1"
6671 ;; [(set_attr "type" "*,fload_media,fstore_media")])
6672
6673 (define_insn_and_split "movv2sf_i"
6674 [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6675 (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6676 "TARGET_SHMEDIA_FPU"
6677 "#"
6678 "TARGET_SHMEDIA_FPU && reload_completed"
6679 [(set (match_dup 0) (match_dup 1))]
6680 "
6681 {
6682 operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
6683 operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
6684 }")
6685
6686 (define_expand "movv2sf"
6687 [(set (match_operand:V2SF 0 "general_movdst_operand" "")
6688 (match_operand:V2SF 1 "nonimmediate_operand" ""))]
6689 "TARGET_SHMEDIA_FPU"
6690 "
6691 {
6692 if (prepare_move_operands (operands, V2SFmode))
6693 DONE;
6694 }")
6695
6696 (define_expand "addv2sf3"
6697 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6698 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6699 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6700 "TARGET_SHMEDIA_FPU"
6701 "
6702 {
6703 sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
6704 DONE;
6705 }")
6706
6707 (define_expand "subv2sf3"
6708 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6709 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6710 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6711 "TARGET_SHMEDIA_FPU"
6712 "
6713 {
6714 sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
6715 DONE;
6716 }")
6717
6718 (define_expand "mulv2sf3"
6719 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6720 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6721 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6722 "TARGET_SHMEDIA_FPU"
6723 "
6724 {
6725 sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
6726 DONE;
6727 }")
6728
6729 (define_expand "divv2sf3"
6730 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6731 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6732 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6733 "TARGET_SHMEDIA_FPU"
6734 "
6735 {
6736 sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
6737 DONE;
6738 }")
6739
6740 (define_insn_and_split "*movv4sf_i"
6741 [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6742 (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6743 "TARGET_SHMEDIA_FPU"
6744 "#"
6745 "&& reload_completed"
6746 [(const_int 0)]
6747 "
6748 {
6749 int i;
6750
6751 for (i = 0; i < 4/2; i++)
6752 {
6753 rtx x, y;
6754
6755 if (MEM_P (operands[0]))
6756 x = adjust_address (operands[0], V2SFmode,
6757 i * GET_MODE_SIZE (V2SFmode));
6758 else
6759 x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
6760
6761 if (MEM_P (operands[1]))
6762 y = adjust_address (operands[1], V2SFmode,
6763 i * GET_MODE_SIZE (V2SFmode));
6764 else
6765 y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
6766
6767 emit_insn (gen_movv2sf_i (x, y));
6768 }
6769
6770 DONE;
6771 }"
6772 [(set_attr "length" "8")])
6773
6774 (define_expand "movv4sf"
6775 [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
6776 (match_operand:V4SF 1 "general_operand" ""))]
6777 "TARGET_SHMEDIA_FPU"
6778 "
6779 {
6780 if (prepare_move_operands (operands, V4SFmode))
6781 DONE;
6782 }")
6783
6784 (define_insn_and_split "*movv16sf_i"
6785 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6786 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6787 "TARGET_SHMEDIA_FPU"
6788 "#"
6789 "&& reload_completed"
6790 [(const_int 0)]
6791 "
6792 {
6793 int i;
6794
6795 for (i = 0; i < 16/2; i++)
6796 {
6797 rtx x,y;
6798
6799 if (MEM_P (operands[0]))
6800 x = adjust_address (operands[0], V2SFmode,
6801 i * GET_MODE_SIZE (V2SFmode));
6802 else
6803 {
6804 x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
6805 alter_subreg (&x);
6806 }
6807
6808 if (MEM_P (operands[1]))
6809 y = adjust_address (operands[1], V2SFmode,
6810 i * GET_MODE_SIZE (V2SFmode));
6811 else
6812 {
6813 y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
6814 alter_subreg (&y);
6815 }
6816
6817 emit_insn (gen_movv2sf_i (x, y));
6818 }
6819
6820 DONE;
6821 }"
6822 [(set_attr "length" "32")])
6823
6824 (define_expand "movv16sf"
6825 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6826 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6827 "TARGET_SHMEDIA_FPU"
6828 "
6829 {
6830 if (prepare_move_operands (operands, V16SFmode))
6831 DONE;
6832 }")
6833
6834 (define_insn "movsf_media"
6835 [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
6836 (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
6837 "TARGET_SHMEDIA_FPU
6838 && (register_operand (operands[0], SFmode)
6839 || sh_register_operand (operands[1], SFmode))"
6840 "@
6841 fmov.s %1, %0
6842 fmov.ls %N1, %0
6843 fmov.sl %1, %0
6844 add.l %1, r63, %0
6845 #
6846 fld%M1.s %m1, %0
6847 fst%M0.s %m0, %1
6848 ld%M1.l %m1, %0
6849 st%M0.l %m0, %N1"
6850 [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
6851 (set (attr "highpart")
6852 (cond [(match_test "sh_contains_memref_p (insn)")
6853 (const_string "user")]
6854 (const_string "ignore")))])
6855
6856 (define_insn "movsf_media_nofpu"
6857 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
6858 (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
6859 "TARGET_SHMEDIA
6860 && (register_operand (operands[0], SFmode)
6861 || sh_register_operand (operands[1], SFmode))"
6862 "@
6863 add.l %1, r63, %0
6864 #
6865 ld%M1.l %m1, %0
6866 st%M0.l %m0, %N1"
6867 [(set_attr "type" "arith_media,*,load_media,store_media")
6868 (set (attr "highpart")
6869 (cond [(match_test "sh_contains_memref_p (insn)")
6870 (const_string "user")]
6871 (const_string "ignore")))])
6872
6873 (define_split
6874 [(set (match_operand:SF 0 "arith_reg_dest" "")
6875 (match_operand:SF 1 "immediate_operand" ""))]
6876 "TARGET_SHMEDIA && reload_completed
6877 && ! FP_REGISTER_P (true_regnum (operands[0]))"
6878 [(set (match_dup 3) (match_dup 2))]
6879 "
6880 {
6881 long values;
6882 REAL_VALUE_TYPE value;
6883
6884 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
6885 REAL_VALUE_TO_TARGET_SINGLE (value, values);
6886 operands[2] = GEN_INT (values);
6887
6888 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6889 }")
6890
6891 (define_insn "movsf_i"
6892 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
6893 (match_operand:SF 1 "general_movsrc_operand" "r,G,FQ,mr,r,r,l"))]
6894 "TARGET_SH1
6895 && (! TARGET_SH2E
6896 /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
6897 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
6898 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
6899 && (arith_reg_operand (operands[0], SFmode)
6900 || arith_reg_operand (operands[1], SFmode))"
6901 "@
6902 mov %1,%0
6903 mov #0,%0
6904 mov.l %1,%0
6905 mov.l %1,%0
6906 mov.l %1,%0
6907 lds %1,%0
6908 sts %1,%0"
6909 [(set_attr "type" "move,move,pcload,load,store,move,move")])
6910
6911 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
6912 ;; update_flow_info would not know where to put REG_EQUAL notes
6913 ;; when the destination changes mode.
6914 (define_insn "movsf_ie"
6915 [(set (match_operand:SF 0 "general_movdst_operand"
6916 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
6917 (match_operand:SF 1 "general_movsrc_operand"
6918 "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
6919 (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"))
6920 (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
6921
6922 "TARGET_SH2E
6923 && (arith_reg_operand (operands[0], SFmode)
6924 || arith_reg_operand (operands[1], SFmode)
6925 || arith_reg_operand (operands[3], SImode)
6926 || (fpul_operand (operands[0], SFmode)
6927 && memory_operand (operands[1], SFmode)
6928 && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
6929 || (fpul_operand (operands[1], SFmode)
6930 && memory_operand (operands[0], SFmode)
6931 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
6932 "@
6933 fmov %1,%0
6934 mov %1,%0
6935 fldi0 %0
6936 fldi1 %0
6937 #
6938 fmov.s %1,%0
6939 fmov.s %1,%0
6940 mov.l %1,%0
6941 mov.l %1,%0
6942 mov.l %1,%0
6943 fsts fpul,%0
6944 flds %1,fpul
6945 lds.l %1,%0
6946 #
6947 sts %1,%0
6948 lds %1,%0
6949 sts.l %1,%0
6950 lds.l %1,%0
6951 ! move optimized away"
6952 [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
6953 (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
6954 (set_attr_alternative "length"
6955 [(const_int 2)
6956 (const_int 2)
6957 (const_int 2)
6958 (const_int 2)
6959 (const_int 4)
6960 (if_then_else
6961 (match_test "TARGET_SH2A")
6962 (const_int 4) (const_int 2))
6963 (if_then_else
6964 (match_test "TARGET_SH2A")
6965 (const_int 4) (const_int 2))
6966 (const_int 2)
6967 (if_then_else
6968 (match_test "TARGET_SH2A")
6969 (const_int 4) (const_int 2))
6970 (if_then_else
6971 (match_test "TARGET_SH2A")
6972 (const_int 4) (const_int 2))
6973 (const_int 2)
6974 (const_int 2)
6975 (const_int 2)
6976 (const_int 4)
6977 (const_int 2)
6978 (const_int 2)
6979 (const_int 2)
6980 (const_int 2)
6981 (const_int 0)])
6982 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
6983 (const_string "single")
6984 (const_string "single")))])
6985
6986 (define_split
6987 [(set (match_operand:SF 0 "register_operand" "")
6988 (match_operand:SF 1 "register_operand" ""))
6989 (use (match_operand:PSI 2 "fpscr_operand" ""))
6990 (clobber (reg:SI FPUL_REG))]
6991 "TARGET_SH1"
6992 [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
6993 (use (match_dup 2))
6994 (clobber (scratch:SI))])
6995 (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
6996 (use (match_dup 2))
6997 (clobber (scratch:SI))])]
6998 "")
6999
7000 (define_expand "movsf"
7001 [(set (match_operand:SF 0 "general_movdst_operand" "")
7002 (match_operand:SF 1 "general_movsrc_operand" ""))]
7003 ""
7004 "
7005 {
7006 if (prepare_move_operands (operands, SFmode))
7007 DONE;
7008 if (TARGET_SHMEDIA)
7009 {
7010 if (TARGET_SHMEDIA_FPU)
7011 emit_insn (gen_movsf_media (operands[0], operands[1]));
7012 else
7013 emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
7014 DONE;
7015 }
7016 if (TARGET_SH2E)
7017 {
7018 emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
7019 DONE;
7020 }
7021 }")
7022
7023 (define_insn "mov_nop"
7024 [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
7025 "TARGET_SH2E"
7026 ""
7027 [(set_attr "length" "0")
7028 (set_attr "type" "nil")])
7029
7030 (define_expand "reload_insf__frn"
7031 [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
7032 (match_operand:SF 1 "immediate_operand" "FQ"))
7033 (use (reg:PSI FPSCR_REG))
7034 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
7035 "TARGET_SH1"
7036 "")
7037
7038 (define_expand "reload_insi__i_fpul"
7039 [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
7040 (match_operand:SI 1 "immediate_operand" "i"))
7041 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
7042 "TARGET_SH1"
7043 "")
7044
7045 (define_expand "ptabs"
7046 [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
7047 "TARGET_SHMEDIA"
7048 "
7049 {
7050 if (!TARGET_PT_FIXED)
7051 {
7052 rtx eq = operands[1];
7053
7054 /* ??? For canonical RTL we really should remove any CONST from EQ
7055 before wrapping it in the AND, and finally wrap the EQ into a
7056 const if is constant. However, for reload we must expose the
7057 input register or symbolic constant, and we can't have
7058 different insn structures outside of the operands for different
7059 alternatives of the same pattern. */
7060 eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
7061 GEN_INT (3));
7062 operands[1]
7063 = (gen_rtx_IF_THEN_ELSE
7064 (PDImode,
7065 eq,
7066 gen_rtx_MEM (PDImode, operands[1]),
7067 gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
7068 PDImode, operands[1])));
7069 }
7070 }")
7071
7072 ;; expanded by ptabs expander.
7073 (define_insn "*extendsipdi_media"
7074 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
7075 (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
7076 "r,Csy")
7077 (const_int 3))
7078 (const_int 3))
7079 (mem:PDI (match_dup 1))
7080 (sign_extend:PDI (match_dup 1))))]
7081 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
7082 "@
7083 ptabs %1, %0
7084 pt %1, %0"
7085 [(set_attr "type" "ptabs_media,pt_media")
7086 (set_attr "length" "4,*")])
7087
7088 (define_insn "*truncdipdi_media"
7089 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
7090 (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
7091 "r,Csy")
7092 (const_int 3))
7093 (const_int 3))
7094 (mem:PDI (match_dup 1))
7095 (truncate:PDI (match_dup 1))))]
7096 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
7097 "@
7098 ptabs %1, %0
7099 pt %1, %0"
7100 [(set_attr "type" "ptabs_media,pt_media")
7101 (set_attr "length" "4,*")])
7102
7103 (define_insn "*movsi_y"
7104 [(set (match_operand:SI 0 "register_operand" "=y,y")
7105 (match_operand:SI 1 "immediate_operand" "Qi,I08"))
7106 (clobber (match_scratch:SI 2 "=&z,r"))]
7107 "TARGET_SH2E
7108 && (reload_in_progress || reload_completed)"
7109 "#"
7110 [(set_attr "length" "4")
7111 (set_attr "type" "pcload,move")])
7112
7113 (define_split
7114 [(set (match_operand:SI 0 "register_operand" "")
7115 (match_operand:SI 1 "immediate_operand" ""))
7116 (clobber (match_operand:SI 2 "register_operand" ""))]
7117 "TARGET_SH1"
7118 [(set (match_dup 2) (match_dup 1))
7119 (set (match_dup 0) (match_dup 2))]
7120 "")
7121 \f
7122 ;; ------------------------------------------------------------------------
7123 ;; Define the real conditional branch instructions.
7124 ;; ------------------------------------------------------------------------
7125
7126 (define_insn "branch_true"
7127 [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
7128 (label_ref (match_operand 0 "" ""))
7129 (pc)))]
7130 "TARGET_SH1"
7131 "* return output_branch (1, insn, operands);"
7132 [(set_attr "type" "cbranch")])
7133
7134 (define_insn "branch_false"
7135 [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
7136 (label_ref (match_operand 0 "" ""))
7137 (pc)))]
7138 "TARGET_SH1"
7139 "* return output_branch (0, insn, operands);"
7140 [(set_attr "type" "cbranch")])
7141
7142 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
7143 ;; which destination is too far away.
7144 ;; The const_int_operand is distinct for each branch target; it avoids
7145 ;; unwanted matches with redundant_insn.
7146 (define_insn "block_branch_redirect"
7147 [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
7148 "TARGET_SH1"
7149 ""
7150 [(set_attr "length" "0")])
7151
7152 ;; This one has the additional purpose to record a possible scratch register
7153 ;; for the following branch.
7154 ;; ??? Unfortunately, just setting the scratch register is not good enough,
7155 ;; because the insn then might be deemed dead and deleted. And we can't
7156 ;; make the use in the jump insn explicit because that would disable
7157 ;; delay slot scheduling from the target.
7158 (define_insn "indirect_jump_scratch"
7159 [(set (match_operand:SI 0 "register_operand" "=r")
7160 (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
7161 (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
7162 "TARGET_SH1"
7163 ""
7164 [(set_attr "length" "0")])
7165
7166 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
7167 ;; being pulled into the delay slot of a condbranch that has been made to
7168 ;; jump around the unconditional jump because it was out of range.
7169 (define_insn "stuff_delay_slot"
7170 [(set (pc)
7171 (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
7172 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
7173 "TARGET_SH1"
7174 ""
7175 [(set_attr "length" "0")
7176 (set_attr "cond_delay_slot" "yes")])
7177 \f
7178 ;; Conditional branch insns
7179
7180 (define_expand "cbranchint4_media"
7181 [(set (pc)
7182 (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
7183 [(match_operand 1 "" "")
7184 (match_operand 2 "" "")])
7185 (match_operand 3 "" "")
7186 (pc)))]
7187 "TARGET_SHMEDIA"
7188 "
7189 {
7190 enum machine_mode mode = GET_MODE (operands[1]);
7191 if (mode == VOIDmode)
7192 mode = GET_MODE (operands[2]);
7193 if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
7194 {
7195 operands[1] = force_reg (mode, operands[1]);
7196 if (CONSTANT_P (operands[2])
7197 && (! satisfies_constraint_I06 (operands[2])))
7198 operands[2] = force_reg (mode, operands[2]);
7199 }
7200 else
7201 {
7202 if (operands[1] != const0_rtx)
7203 operands[1] = force_reg (mode, operands[1]);
7204 if (operands[2] != const0_rtx)
7205 operands[2] = force_reg (mode, operands[2]);
7206 }
7207 switch (GET_CODE (operands[0]))
7208 {
7209 case LEU:
7210 case LE:
7211 case LTU:
7212 case LT:
7213 operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
7214 VOIDmode, operands[2], operands[1]);
7215 operands[1] = XEXP (operands[0], 0);
7216 operands[2] = XEXP (operands[0], 1);
7217 break;
7218 default:
7219 operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
7220 VOIDmode, operands[1], operands[2]);
7221 break;
7222 }
7223 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
7224 }")
7225
7226 (define_expand "cbranchfp4_media"
7227 [(set (pc)
7228 (if_then_else (match_operator 0 "sh_float_comparison_operator"
7229 [(match_operand 1 "" "")
7230 (match_operand 2 "" "")])
7231 (match_operand 3 "" "")
7232 (pc)))]
7233 "TARGET_SHMEDIA"
7234 "
7235 {
7236 rtx tmp = gen_reg_rtx (SImode);
7237 rtx cmp;
7238 if (GET_CODE (operands[0]) == NE)
7239 cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
7240 else
7241 cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
7242 operands[1], operands[2]);
7243
7244 emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
7245
7246 if (GET_CODE (cmp) == GET_CODE (operands[0]))
7247 operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
7248 else
7249 operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
7250 operands[1] = tmp;
7251 operands[2] = const0_rtx;
7252 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
7253 }")
7254
7255 (define_insn "*beq_media_i"
7256 [(set (pc)
7257 (if_then_else (match_operator 3 "equality_comparison_operator"
7258 [(match_operand:DI 1 "arith_reg_operand" "r,r")
7259 (match_operand:DI 2 "arith_operand" "r,I06")])
7260 (match_operand 0 "target_operand" "b,b")
7261 (pc)))]
7262 "TARGET_SHMEDIA"
7263 "@
7264 b%o3%' %1, %2, %0%>
7265 b%o3i%' %1, %2, %0%>"
7266 [(set_attr "type" "cbranch_media")])
7267
7268 (define_insn "*beq_media_i32"
7269 [(set (pc)
7270 (if_then_else (match_operator 3 "equality_comparison_operator"
7271 [(match_operand:SI 1 "arith_reg_operand" "r,r")
7272 (match_operand:SI 2 "arith_operand" "r,I06")])
7273 (match_operand 0 "target_operand" "b,b")
7274 (pc)))]
7275 "TARGET_SHMEDIA"
7276 "@
7277 b%o3%' %1, %2, %0%>
7278 b%o3i%' %1, %2, %0%>"
7279 [(set_attr "type" "cbranch_media")])
7280
7281 (define_insn "*bgt_media_i"
7282 [(set (pc)
7283 (if_then_else (match_operator 3 "greater_comparison_operator"
7284 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
7285 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
7286 (match_operand 0 "target_operand" "b")
7287 (pc)))]
7288 "TARGET_SHMEDIA"
7289 "b%o3%' %N1, %N2, %0%>"
7290 [(set_attr "type" "cbranch_media")])
7291
7292 (define_insn "*bgt_media_i32"
7293 [(set (pc)
7294 (if_then_else (match_operator 3 "greater_comparison_operator"
7295 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
7296 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
7297 (match_operand 0 "target_operand" "b")
7298 (pc)))]
7299 "TARGET_SHMEDIA"
7300 "b%o3%' %N1, %N2, %0%>"
7301 [(set_attr "type" "cbranch_media")])
7302
7303 ;; These are only needed to make invert_jump() happy - otherwise, jump
7304 ;; optimization will be silently disabled.
7305 (define_insn "*blt_media_i"
7306 [(set (pc)
7307 (if_then_else (match_operator 3 "less_comparison_operator"
7308 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
7309 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
7310 (match_operand 0 "target_operand" "b")
7311 (pc)))]
7312 "TARGET_SHMEDIA"
7313 "b%o3%' %N2, %N1, %0%>"
7314 [(set_attr "type" "cbranch_media")])
7315
7316 (define_insn "*blt_media_i32"
7317 [(set (pc)
7318 (if_then_else (match_operator 3 "less_comparison_operator"
7319 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
7320 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
7321 (match_operand 0 "target_operand" "b")
7322 (pc)))]
7323 "TARGET_SHMEDIA"
7324 "b%o3%' %N2, %N1, %0%>"
7325 [(set_attr "type" "cbranch_media")])
7326
7327 ;; combiner splitter for test-and-branch on single bit in register. This
7328 ;; is endian dependent because the non-paradoxical subreg looks different
7329 ;; on big endian.
7330 (define_split
7331 [(set (pc)
7332 (if_then_else
7333 (match_operator 3 "equality_comparison_operator"
7334 [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1
7335 "extend_reg_operand" "")
7336 0)
7337 (const_int 1)
7338 (match_operand 2
7339 "const_int_operand" "")) 0)
7340 (const_int 0)])
7341 (match_operand 0 "target_operand" "")
7342 (pc)))
7343 (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
7344 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
7345 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
7346 (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
7347
7348 "
7349 {
7350 operands[5] = GEN_INT (31 - INTVAL (operands[2]));
7351 operands[6] = (GET_CODE (operands[3]) == EQ
7352 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
7353 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
7354 }")
7355
7356 ; operand 0 is the loop count pseudo register
7357 ; operand 1 is the number of loop iterations or 0 if it is unknown
7358 ; operand 2 is the maximum number of loop iterations
7359 ; operand 3 is the number of levels of enclosed loops
7360 ; operand 4 is the label to jump to at the top of the loop
7361
7362 (define_expand "doloop_end"
7363 [(parallel [(set (pc) (if_then_else
7364 (ne:SI (match_operand:SI 0 "" "")
7365 (const_int 1))
7366 (label_ref (match_operand 4 "" ""))
7367 (pc)))
7368 (set (match_dup 0)
7369 (plus:SI (match_dup 0) (const_int -1)))
7370 (clobber (reg:SI T_REG))])]
7371 "TARGET_SH2"
7372 "
7373 {
7374 if (GET_MODE (operands[0]) != SImode)
7375 FAIL;
7376 }
7377 ")
7378
7379 (define_insn_and_split "doloop_end_split"
7380 [(set (pc)
7381 (if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0")
7382 (const_int 1))
7383 (label_ref (match_operand 1 "" ""))
7384 (pc)))
7385 (set (match_operand:SI 0 "arith_reg_dest" "=r")
7386 (plus (match_dup 2) (const_int -1)))
7387 (clobber (reg:SI T_REG))]
7388 "TARGET_SH2"
7389 "#"
7390 ""
7391 [(parallel [(set (reg:SI T_REG)
7392 (eq:SI (match_dup 2) (const_int 1)))
7393 (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
7394 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
7395 (label_ref (match_dup 1))
7396 (pc)))]
7397 ""
7398 [(set_attr "type" "cbranch")])
7399
7400 \f
7401 ;; ------------------------------------------------------------------------
7402 ;; Jump and linkage insns
7403 ;; ------------------------------------------------------------------------
7404
7405 (define_insn "jump_compact"
7406 [(set (pc)
7407 (label_ref (match_operand 0 "" "")))]
7408 "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
7409 "*
7410 {
7411 /* The length is 16 if the delay slot is unfilled. */
7412 if (get_attr_length(insn) > 4)
7413 return output_far_jump(insn, operands[0]);
7414 else
7415 return \"bra %l0%#\";
7416 }"
7417 [(set_attr "type" "jump")
7418 (set_attr "needs_delay_slot" "yes")])
7419
7420 ;; ??? It would be much saner to explicitly use the scratch register
7421 ;; in the jump insn, and have indirect_jump_scratch only set it,
7422 ;; but fill_simple_delay_slots would refuse to do delay slot filling
7423 ;; from the target then, as it uses simplejump_p.
7424 ;;(define_insn "jump_compact_far"
7425 ;; [(set (pc)
7426 ;; (label_ref (match_operand 0 "" "")))
7427 ;; (use (match_operand 1 "register_operand" "r")]
7428 ;; "TARGET_SH1"
7429 ;; "* return output_far_jump(insn, operands[0], operands[1]);"
7430 ;; [(set_attr "type" "jump")
7431 ;; (set_attr "needs_delay_slot" "yes")])
7432
7433 (define_insn "jump_media"
7434 [(set (pc)
7435 (match_operand 0 "target_operand" "b"))]
7436 "TARGET_SHMEDIA"
7437 "blink %0, r63%>"
7438 [(set_attr "type" "jump_media")])
7439
7440 (define_expand "jump"
7441 [(set (pc)
7442 (label_ref (match_operand 0 "" "")))]
7443 ""
7444 "
7445 {
7446 if (TARGET_SH1)
7447 emit_jump_insn (gen_jump_compact (operands[0]));
7448 else if (TARGET_SHMEDIA)
7449 {
7450 if (reload_in_progress || reload_completed)
7451 FAIL;
7452 emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode,
7453 operands[0])));
7454 }
7455 DONE;
7456 }")
7457
7458 (define_insn "force_mode_for_call"
7459 [(use (reg:PSI FPSCR_REG))]
7460 "TARGET_SHCOMPACT"
7461 ""
7462 [(set_attr "length" "0")
7463 (set (attr "fp_mode")
7464 (if_then_else (eq_attr "fpu_single" "yes")
7465 (const_string "single") (const_string "double")))])
7466
7467 (define_insn "calli"
7468 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7469 (match_operand 1 "" ""))
7470 (use (reg:PSI FPSCR_REG))
7471 (clobber (reg:SI PR_REG))]
7472 "TARGET_SH1"
7473 "*
7474 {
7475 if (TARGET_SH2A && (dbr_sequence_length () == 0))
7476 return \"jsr/n\\t@%0\";
7477 else
7478 return \"jsr\\t@%0%#\";
7479 }"
7480
7481 [(set_attr "type" "call")
7482 (set (attr "fp_mode")
7483 (if_then_else (eq_attr "fpu_single" "yes")
7484 (const_string "single") (const_string "double")))
7485 (set_attr "needs_delay_slot" "yes")
7486 (set_attr "fp_set" "unknown")])
7487
7488 ;; This is TBR relative jump instruction for SH2A architecture.
7489 ;; Its use is enabled assigning an attribute "function_vector"
7490 ;; and the vector number to a function during its declaration.
7491
7492 (define_insn "calli_tbr_rel"
7493 [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
7494 (match_operand 1 "" ""))
7495 (use (reg:PSI FPSCR_REG))
7496 (clobber (reg:SI PR_REG))]
7497 "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
7498 "*
7499 {
7500 unsigned HOST_WIDE_INT vect_num;
7501 vect_num = sh2a_get_function_vector_number (operands[0]);
7502 operands[2] = GEN_INT (vect_num * 4);
7503
7504 return \"jsr/n\\t@@(%O2,tbr)\";
7505 }"
7506 [(set_attr "type" "call")
7507 (set (attr "fp_mode")
7508 (if_then_else (eq_attr "fpu_single" "yes")
7509 (const_string "single") (const_string "double")))
7510 (set_attr "needs_delay_slot" "no")
7511 (set_attr "fp_set" "unknown")])
7512
7513 ;; This is a pc-rel call, using bsrf, for use with PIC.
7514
7515 (define_insn "calli_pcrel"
7516 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7517 (match_operand 1 "" ""))
7518 (use (reg:PSI FPSCR_REG))
7519 (use (reg:SI PIC_REG))
7520 (use (match_operand 2 "" ""))
7521 (clobber (reg:SI PR_REG))]
7522 "TARGET_SH2"
7523 "bsrf %0\\n%O2:%#"
7524 [(set_attr "type" "call")
7525 (set (attr "fp_mode")
7526 (if_then_else (eq_attr "fpu_single" "yes")
7527 (const_string "single") (const_string "double")))
7528 (set_attr "needs_delay_slot" "yes")
7529 (set_attr "fp_set" "unknown")])
7530
7531 (define_insn_and_split "call_pcrel"
7532 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7533 (match_operand 1 "" ""))
7534 (use (reg:PSI FPSCR_REG))
7535 (use (reg:SI PIC_REG))
7536 (clobber (reg:SI PR_REG))
7537 (clobber (match_scratch:SI 2 "=r"))]
7538 "TARGET_SH2"
7539 "#"
7540 "reload_completed"
7541 [(const_int 0)]
7542 "
7543 {
7544 rtx lab = PATTERN (gen_call_site ());
7545
7546 if (SYMBOL_REF_LOCAL_P (operands[0]))
7547 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7548 else
7549 emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
7550 emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
7551 DONE;
7552 }"
7553 [(set_attr "type" "call")
7554 (set (attr "fp_mode")
7555 (if_then_else (eq_attr "fpu_single" "yes")
7556 (const_string "single") (const_string "double")))
7557 (set_attr "needs_delay_slot" "yes")
7558 (set_attr "fp_set" "unknown")])
7559
7560 (define_insn "call_compact"
7561 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7562 (match_operand 1 "" ""))
7563 (match_operand 2 "immediate_operand" "n")
7564 (use (reg:SI R0_REG))
7565 (use (reg:SI R1_REG))
7566 (use (reg:PSI FPSCR_REG))
7567 (clobber (reg:SI PR_REG))]
7568 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7569 "jsr @%0%#"
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
7576 (define_insn "call_compact_rettramp"
7577 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7578 (match_operand 1 "" ""))
7579 (match_operand 2 "immediate_operand" "n")
7580 (use (reg:SI R0_REG))
7581 (use (reg:SI R1_REG))
7582 (use (reg:PSI FPSCR_REG))
7583 (clobber (reg:SI R10_REG))
7584 (clobber (reg:SI PR_REG))]
7585 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7586 "jsr @%0%#"
7587 [(set_attr "type" "call")
7588 (set (attr "fp_mode")
7589 (if_then_else (eq_attr "fpu_single" "yes")
7590 (const_string "single") (const_string "double")))
7591 (set_attr "needs_delay_slot" "yes")])
7592
7593 (define_insn "call_media"
7594 [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
7595 (match_operand 1 "" ""))
7596 (clobber (reg:DI PR_MEDIA_REG))]
7597 "TARGET_SHMEDIA"
7598 "blink %0, r18"
7599 [(set_attr "type" "jump_media")])
7600
7601 (define_insn "call_valuei"
7602 [(set (match_operand 0 "" "=rf")
7603 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7604 (match_operand 2 "" "")))
7605 (use (reg:PSI FPSCR_REG))
7606 (clobber (reg:SI PR_REG))]
7607 "TARGET_SH1"
7608 "*
7609 {
7610 if (TARGET_SH2A && (dbr_sequence_length () == 0))
7611 return \"jsr/n\\t@%1\";
7612 else
7613 return \"jsr\\t@%1%#\";
7614 }"
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 (set_attr "fp_set" "unknown")])
7621
7622 ;; This is TBR relative jump instruction for SH2A architecture.
7623 ;; Its use is enabled by assigning an attribute "function_vector"
7624 ;; and the vector number to a function during its declaration.
7625
7626 (define_insn "call_valuei_tbr_rel"
7627 [(set (match_operand 0 "" "=rf")
7628 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7629 (match_operand 2 "" "")))
7630 (use (reg:PSI FPSCR_REG))
7631 (clobber (reg:SI PR_REG))]
7632 "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
7633 "*
7634 {
7635 unsigned HOST_WIDE_INT vect_num;
7636 vect_num = sh2a_get_function_vector_number (operands[1]);
7637 operands[3] = GEN_INT (vect_num * 4);
7638
7639 return \"jsr/n\\t@@(%O3,tbr)\";
7640 }"
7641 [(set_attr "type" "call")
7642 (set (attr "fp_mode")
7643 (if_then_else (eq_attr "fpu_single" "yes")
7644 (const_string "single") (const_string "double")))
7645 (set_attr "needs_delay_slot" "no")
7646 (set_attr "fp_set" "unknown")])
7647
7648 (define_insn "call_valuei_pcrel"
7649 [(set (match_operand 0 "" "=rf")
7650 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7651 (match_operand 2 "" "")))
7652 (use (reg:PSI FPSCR_REG))
7653 (use (reg:SI PIC_REG))
7654 (use (match_operand 3 "" ""))
7655 (clobber (reg:SI PR_REG))]
7656 "TARGET_SH2"
7657 "bsrf %1\\n%O3:%#"
7658 [(set_attr "type" "call")
7659 (set (attr "fp_mode")
7660 (if_then_else (eq_attr "fpu_single" "yes")
7661 (const_string "single") (const_string "double")))
7662 (set_attr "needs_delay_slot" "yes")
7663 (set_attr "fp_set" "unknown")])
7664
7665 (define_insn_and_split "call_value_pcrel"
7666 [(set (match_operand 0 "" "=rf")
7667 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7668 (match_operand 2 "" "")))
7669 (use (reg:PSI FPSCR_REG))
7670 (use (reg:SI PIC_REG))
7671 (clobber (reg:SI PR_REG))
7672 (clobber (match_scratch:SI 3 "=r"))]
7673 "TARGET_SH2"
7674 "#"
7675 "reload_completed"
7676 [(const_int 0)]
7677 "
7678 {
7679 rtx lab = PATTERN (gen_call_site ());
7680
7681 if (SYMBOL_REF_LOCAL_P (operands[1]))
7682 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
7683 else
7684 emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
7685 emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
7686 operands[2], copy_rtx (lab)));
7687 DONE;
7688 }"
7689 [(set_attr "type" "call")
7690 (set (attr "fp_mode")
7691 (if_then_else (eq_attr "fpu_single" "yes")
7692 (const_string "single") (const_string "double")))
7693 (set_attr "needs_delay_slot" "yes")
7694 (set_attr "fp_set" "unknown")])
7695
7696 (define_insn "call_value_compact"
7697 [(set (match_operand 0 "" "=rf")
7698 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7699 (match_operand 2 "" "")))
7700 (match_operand 3 "immediate_operand" "n")
7701 (use (reg:SI R0_REG))
7702 (use (reg:SI R1_REG))
7703 (use (reg:PSI FPSCR_REG))
7704 (clobber (reg:SI PR_REG))]
7705 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7706 "jsr @%1%#"
7707 [(set_attr "type" "call")
7708 (set (attr "fp_mode")
7709 (if_then_else (eq_attr "fpu_single" "yes")
7710 (const_string "single") (const_string "double")))
7711 (set_attr "needs_delay_slot" "yes")])
7712
7713 (define_insn "call_value_compact_rettramp"
7714 [(set (match_operand 0 "" "=rf")
7715 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7716 (match_operand 2 "" "")))
7717 (match_operand 3 "immediate_operand" "n")
7718 (use (reg:SI R0_REG))
7719 (use (reg:SI R1_REG))
7720 (use (reg:PSI FPSCR_REG))
7721 (clobber (reg:SI R10_REG))
7722 (clobber (reg:SI PR_REG))]
7723 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7724 "jsr @%1%#"
7725 [(set_attr "type" "call")
7726 (set (attr "fp_mode")
7727 (if_then_else (eq_attr "fpu_single" "yes")
7728 (const_string "single") (const_string "double")))
7729 (set_attr "needs_delay_slot" "yes")])
7730
7731 (define_insn "call_value_media"
7732 [(set (match_operand 0 "" "=rf")
7733 (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
7734 (match_operand 2 "" "")))
7735 (clobber (reg:DI PR_MEDIA_REG))]
7736 "TARGET_SHMEDIA"
7737 "blink %1, r18"
7738 [(set_attr "type" "jump_media")])
7739
7740 (define_expand "call"
7741 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7742 (match_operand 1 "" ""))
7743 (match_operand 2 "" "")
7744 (use (reg:PSI FPSCR_REG))
7745 (clobber (reg:SI PR_REG))])]
7746 ""
7747 "
7748 {
7749 if (TARGET_SHMEDIA)
7750 {
7751 operands[0] = shmedia_prepare_call_address (operands[0], 0);
7752 emit_call_insn (gen_call_media (operands[0], operands[1]));
7753 DONE;
7754 }
7755 else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
7756 {
7757 rtx cookie_rtx = operands[2];
7758 long cookie = INTVAL (cookie_rtx);
7759 rtx func = XEXP (operands[0], 0);
7760 rtx r0, r1;
7761
7762 if (flag_pic)
7763 {
7764 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7765 {
7766 rtx reg = gen_reg_rtx (Pmode);
7767
7768 emit_insn (gen_symGOTPLT2reg (reg, func));
7769 func = reg;
7770 }
7771 else
7772 func = legitimize_pic_address (func, Pmode, 0);
7773 }
7774
7775 r0 = gen_rtx_REG (SImode, R0_REG);
7776 r1 = gen_rtx_REG (SImode, R1_REG);
7777
7778 /* Since such a call function may use all call-clobbered
7779 registers, we force a mode switch earlier, so that we don't
7780 run out of registers when adjusting fpscr for the call. */
7781 emit_insn (gen_force_mode_for_call ());
7782
7783 operands[0]
7784 = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7785 SFUNC_GOT);
7786 operands[0] = force_reg (SImode, operands[0]);
7787
7788 emit_move_insn (r0, func);
7789 emit_move_insn (r1, cookie_rtx);
7790
7791 if (cookie & CALL_COOKIE_RET_TRAMP (1))
7792 emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
7793 operands[2]));
7794 else
7795 emit_call_insn (gen_call_compact (operands[0], operands[1],
7796 operands[2]));
7797
7798 DONE;
7799 }
7800 else if (TARGET_SHCOMPACT && flag_pic
7801 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7802 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7803 {
7804 rtx reg = gen_reg_rtx (Pmode);
7805
7806 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
7807 XEXP (operands[0], 0) = reg;
7808 }
7809 if (!flag_pic && TARGET_SH2A
7810 && MEM_P (operands[0])
7811 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
7812 {
7813 if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
7814 {
7815 emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
7816 operands[1]));
7817 DONE;
7818 }
7819 }
7820 if (flag_pic && TARGET_SH2
7821 && MEM_P (operands[0])
7822 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
7823 {
7824 emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
7825 DONE;
7826 }
7827 else
7828 {
7829 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
7830 operands[1] = operands[2];
7831 }
7832
7833 emit_call_insn (gen_calli (operands[0], operands[1]));
7834 DONE;
7835 }")
7836
7837 (define_insn "call_pop_compact"
7838 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7839 (match_operand 1 "" ""))
7840 (match_operand 2 "immediate_operand" "n")
7841 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7842 (match_operand 3 "immediate_operand" "n")))
7843 (use (reg:SI R0_REG))
7844 (use (reg:SI R1_REG))
7845 (use (reg:PSI FPSCR_REG))
7846 (clobber (reg:SI PR_REG))]
7847 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7848 "jsr @%0%#"
7849 [(set_attr "type" "call")
7850 (set (attr "fp_mode")
7851 (if_then_else (eq_attr "fpu_single" "yes")
7852 (const_string "single") (const_string "double")))
7853 (set_attr "needs_delay_slot" "yes")])
7854
7855 (define_insn "call_pop_compact_rettramp"
7856 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7857 (match_operand 1 "" ""))
7858 (match_operand 2 "immediate_operand" "n")
7859 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7860 (match_operand 3 "immediate_operand" "n")))
7861 (use (reg:SI R0_REG))
7862 (use (reg:SI R1_REG))
7863 (use (reg:PSI FPSCR_REG))
7864 (clobber (reg:SI R10_REG))
7865 (clobber (reg:SI PR_REG))]
7866 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7867 "jsr @%0%#"
7868 [(set_attr "type" "call")
7869 (set (attr "fp_mode")
7870 (if_then_else (eq_attr "fpu_single" "yes")
7871 (const_string "single") (const_string "double")))
7872 (set_attr "needs_delay_slot" "yes")])
7873
7874 (define_expand "call_pop"
7875 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7876 (match_operand 1 "" ""))
7877 (match_operand 2 "" "")
7878 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7879 (match_operand 3 "" "")))])]
7880 "TARGET_SHCOMPACT"
7881 "
7882 {
7883 rtx cookie_rtx;
7884 long cookie;
7885 rtx func;
7886 rtx r0, r1;
7887
7888 gcc_assert (operands[2] && INTVAL (operands[2]));
7889 cookie_rtx = operands[2];
7890 cookie = INTVAL (cookie_rtx);
7891 func = XEXP (operands[0], 0);
7892
7893 if (flag_pic)
7894 {
7895 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7896 {
7897 rtx reg = gen_reg_rtx (Pmode);
7898 emit_insn (gen_symGOTPLT2reg (reg, func));
7899 func = reg;
7900 }
7901 else
7902 func = legitimize_pic_address (func, Pmode, 0);
7903 }
7904
7905 r0 = gen_rtx_REG (SImode, R0_REG);
7906 r1 = gen_rtx_REG (SImode, R1_REG);
7907
7908 /* Since such a call function may use all call-clobbered
7909 registers, we force a mode switch earlier, so that we don't
7910 run out of registers when adjusting fpscr for the call. */
7911 emit_insn (gen_force_mode_for_call ());
7912
7913 operands[0] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7914 SFUNC_GOT);
7915 operands[0] = force_reg (SImode, operands[0]);
7916
7917 emit_move_insn (r0, func);
7918 emit_move_insn (r1, cookie_rtx);
7919
7920 if (cookie & CALL_COOKIE_RET_TRAMP (1))
7921 emit_call_insn (gen_call_pop_compact_rettramp
7922 (operands[0], operands[1], operands[2], operands[3]));
7923 else
7924 emit_call_insn (gen_call_pop_compact
7925 (operands[0], operands[1], operands[2], operands[3]));
7926
7927 DONE;
7928 }")
7929
7930 (define_expand "call_value"
7931 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
7932 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
7933 (match_operand 2 "" "")))
7934 (match_operand 3 "" "")
7935 (use (reg:PSI FPSCR_REG))
7936 (clobber (reg:SI PR_REG))])]
7937 ""
7938 "
7939 {
7940 if (TARGET_SHMEDIA)
7941 {
7942 operands[1] = shmedia_prepare_call_address (operands[1], 0);
7943 emit_call_insn (gen_call_value_media (operands[0], operands[1],
7944 operands[2]));
7945 DONE;
7946 }
7947 else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
7948 {
7949 rtx cookie_rtx = operands[3];
7950 long cookie = INTVAL (cookie_rtx);
7951 rtx func = XEXP (operands[1], 0);
7952 rtx r0, r1;
7953
7954 if (flag_pic)
7955 {
7956 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7957 {
7958 rtx reg = gen_reg_rtx (Pmode);
7959
7960 emit_insn (gen_symGOTPLT2reg (reg, func));
7961 func = reg;
7962 }
7963 else
7964 func = legitimize_pic_address (func, Pmode, 0);
7965 }
7966
7967 r0 = gen_rtx_REG (SImode, R0_REG);
7968 r1 = gen_rtx_REG (SImode, R1_REG);
7969
7970 /* Since such a call function may use all call-clobbered
7971 registers, we force a mode switch earlier, so that we don't
7972 run out of registers when adjusting fpscr for the call. */
7973 emit_insn (gen_force_mode_for_call ());
7974
7975 operands[1]
7976 = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7977 SFUNC_GOT);
7978 operands[1] = force_reg (SImode, operands[1]);
7979
7980 emit_move_insn (r0, func);
7981 emit_move_insn (r1, cookie_rtx);
7982
7983 if (cookie & CALL_COOKIE_RET_TRAMP (1))
7984 emit_call_insn (gen_call_value_compact_rettramp (operands[0],
7985 operands[1],
7986 operands[2],
7987 operands[3]));
7988 else
7989 emit_call_insn (gen_call_value_compact (operands[0], operands[1],
7990 operands[2], operands[3]));
7991
7992 DONE;
7993 }
7994 else if (TARGET_SHCOMPACT && flag_pic
7995 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7996 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
7997 {
7998 rtx reg = gen_reg_rtx (Pmode);
7999
8000 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
8001 XEXP (operands[1], 0) = reg;
8002 }
8003 if (!flag_pic && TARGET_SH2A
8004 && MEM_P (operands[1])
8005 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
8006 {
8007 if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
8008 {
8009 emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
8010 XEXP (operands[1], 0), operands[2]));
8011 DONE;
8012 }
8013 }
8014 if (flag_pic && TARGET_SH2
8015 && MEM_P (operands[1])
8016 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
8017 {
8018 emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
8019 operands[2]));
8020 DONE;
8021 }
8022 else
8023 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
8024
8025 emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
8026 DONE;
8027 }")
8028
8029 (define_insn "sibcalli"
8030 [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
8031 (match_operand 1 "" ""))
8032 (use (reg:PSI FPSCR_REG))
8033 (return)]
8034 "TARGET_SH1"
8035 "jmp @%0%#"
8036 [(set_attr "needs_delay_slot" "yes")
8037 (set (attr "fp_mode")
8038 (if_then_else (eq_attr "fpu_single" "yes")
8039 (const_string "single") (const_string "double")))
8040 (set_attr "type" "jump_ind")])
8041
8042 (define_insn "sibcalli_pcrel"
8043 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
8044 (match_operand 1 "" ""))
8045 (use (match_operand 2 "" ""))
8046 (use (reg:PSI FPSCR_REG))
8047 (return)]
8048 "TARGET_SH2"
8049 "braf %0\\n%O2:%#"
8050 [(set_attr "needs_delay_slot" "yes")
8051 (set (attr "fp_mode")
8052 (if_then_else (eq_attr "fpu_single" "yes")
8053 (const_string "single") (const_string "double")))
8054 (set_attr "type" "jump_ind")])
8055
8056 ;; This uses an unspec to describe that the symbol_ref is very close.
8057 (define_insn "sibcalli_thunk"
8058 [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
8059 UNSPEC_THUNK))
8060 (match_operand 1 "" ""))
8061 (use (reg:PSI FPSCR_REG))
8062 (return)]
8063 "TARGET_SH1"
8064 "bra %O0"
8065 [(set_attr "needs_delay_slot" "yes")
8066 (set (attr "fp_mode")
8067 (if_then_else (eq_attr "fpu_single" "yes")
8068 (const_string "single") (const_string "double")))
8069 (set_attr "type" "jump")
8070 (set_attr "length" "2")])
8071
8072 (define_insn_and_split "sibcall_pcrel"
8073 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
8074 (match_operand 1 "" ""))
8075 (use (reg:PSI FPSCR_REG))
8076 (clobber (match_scratch:SI 2 "=k"))
8077 (return)]
8078 "TARGET_SH2"
8079 "#"
8080 "reload_completed"
8081 [(const_int 0)]
8082 "
8083 {
8084 rtx lab = PATTERN (gen_call_site ());
8085 rtx call_insn;
8086
8087 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
8088 call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
8089 copy_rtx (lab)));
8090 SIBLING_CALL_P (call_insn) = 1;
8091 DONE;
8092 }"
8093 [(set_attr "needs_delay_slot" "yes")
8094 (set (attr "fp_mode")
8095 (if_then_else (eq_attr "fpu_single" "yes")
8096 (const_string "single") (const_string "double")))
8097 (set_attr "type" "jump_ind")])
8098
8099 (define_insn "sibcall_compact"
8100 [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
8101 (match_operand 1 "" ""))
8102 (return)
8103 (use (match_operand:SI 2 "register_operand" "z,x"))
8104 (use (reg:SI R1_REG))
8105 (use (reg:PSI FPSCR_REG))
8106 ;; We want to make sure the `x' above will only match MACH_REG
8107 ;; because sibcall_epilogue may clobber MACL_REG.
8108 (clobber (reg:SI MACL_REG))]
8109 "TARGET_SHCOMPACT"
8110 "@
8111 jmp @%0%#
8112 jmp @%0\\n sts %2, r0"
8113 [(set_attr "needs_delay_slot" "yes,no")
8114 (set_attr "length" "2,4")
8115 (set (attr "fp_mode") (const_string "single"))
8116 (set_attr "type" "jump_ind")])
8117
8118 (define_insn "sibcall_media"
8119 [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
8120 (match_operand 1 "" ""))
8121 (use (reg:SI PR_MEDIA_REG))
8122 (return)]
8123 "TARGET_SHMEDIA"
8124 "blink %0, r63"
8125 [(set_attr "type" "jump_media")])
8126
8127 (define_expand "sibcall"
8128 [(parallel
8129 [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
8130 (match_operand 1 "" ""))
8131 (match_operand 2 "" "")
8132 (use (reg:PSI FPSCR_REG))
8133 (return)])]
8134 ""
8135 "
8136 {
8137 if (TARGET_SHMEDIA)
8138 {
8139 operands[0] = shmedia_prepare_call_address (operands[0], 1);
8140 emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
8141 DONE;
8142 }
8143 else if (TARGET_SHCOMPACT && operands[2]
8144 && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
8145 {
8146 rtx cookie_rtx = operands[2];
8147 long cookie = INTVAL (cookie_rtx);
8148 rtx func = XEXP (operands[0], 0);
8149 rtx mach, r1;
8150
8151 if (flag_pic)
8152 {
8153 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8154 {
8155 rtx reg = gen_reg_rtx (Pmode);
8156
8157 emit_insn (gen_symGOT2reg (reg, func));
8158 func = reg;
8159 }
8160 else
8161 func = legitimize_pic_address (func, Pmode, 0);
8162 }
8163
8164 /* FIXME: if we could tell whether all argument registers are
8165 already taken, we could decide whether to force the use of
8166 MACH_REG or to stick to R0_REG. Unfortunately, there's no
8167 simple way to tell. We could use the CALL_COOKIE, but we
8168 can't currently tell a register used for regular argument
8169 passing from one that is unused. If we leave it up to reload
8170 to decide which register to use, it seems to always choose
8171 R0_REG, which leaves no available registers in SIBCALL_REGS
8172 to hold the address of the trampoline. */
8173 mach = gen_rtx_REG (SImode, MACH_REG);
8174 r1 = gen_rtx_REG (SImode, R1_REG);
8175
8176 /* Since such a call function may use all call-clobbered
8177 registers, we force a mode switch earlier, so that we don't
8178 run out of registers when adjusting fpscr for the call. */
8179 emit_insn (gen_force_mode_for_call ());
8180
8181 operands[0]
8182 = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8183 SFUNC_GOT);
8184 operands[0] = force_reg (SImode, operands[0]);
8185
8186 /* We don't need a return trampoline, since the callee will
8187 return directly to the upper caller. */
8188 if (cookie & CALL_COOKIE_RET_TRAMP (1))
8189 {
8190 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
8191 cookie_rtx = GEN_INT (cookie);
8192 }
8193
8194 emit_move_insn (mach, func);
8195 emit_move_insn (r1, cookie_rtx);
8196
8197 emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
8198 DONE;
8199 }
8200 else if (TARGET_SHCOMPACT && flag_pic
8201 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8202 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
8203 {
8204 rtx reg = gen_reg_rtx (Pmode);
8205
8206 emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
8207 XEXP (operands[0], 0) = reg;
8208 }
8209 if (flag_pic && TARGET_SH2
8210 && MEM_P (operands[0])
8211 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8212 /* The PLT needs the PIC register, but the epilogue would have
8213 to restore it, so we can only use PC-relative PIC calls for
8214 static functions. */
8215 && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
8216 {
8217 emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
8218 DONE;
8219 }
8220 else
8221 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
8222
8223 emit_call_insn (gen_sibcalli (operands[0], operands[1]));
8224 DONE;
8225 }")
8226
8227 (define_insn "sibcall_valuei"
8228 [(set (match_operand 0 "" "=rf")
8229 (call (mem:SI (match_operand:SI 1 "register_operand" "k"))
8230 (match_operand 2 "" "")))
8231 (use (reg:PSI FPSCR_REG))
8232 (return)]
8233 "TARGET_SH1"
8234 "jmp @%1%#"
8235 [(set_attr "needs_delay_slot" "yes")
8236 (set (attr "fp_mode")
8237 (if_then_else (eq_attr "fpu_single" "yes")
8238 (const_string "single") (const_string "double")))
8239 (set_attr "type" "jump_ind")])
8240
8241 (define_insn "sibcall_valuei_pcrel"
8242 [(set (match_operand 0 "" "=rf")
8243 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
8244 (match_operand 2 "" "")))
8245 (use (match_operand 3 "" ""))
8246 (use (reg:PSI FPSCR_REG))
8247 (return)]
8248 "TARGET_SH2"
8249 "braf %1\\n%O3:%#"
8250 [(set_attr "needs_delay_slot" "yes")
8251 (set (attr "fp_mode")
8252 (if_then_else (eq_attr "fpu_single" "yes")
8253 (const_string "single") (const_string "double")))
8254 (set_attr "type" "jump_ind")])
8255
8256 (define_insn_and_split "sibcall_value_pcrel"
8257 [(set (match_operand 0 "" "=rf")
8258 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
8259 (match_operand 2 "" "")))
8260 (use (reg:PSI FPSCR_REG))
8261 (clobber (match_scratch:SI 3 "=k"))
8262 (return)]
8263 "TARGET_SH2"
8264 "#"
8265 "reload_completed"
8266 [(const_int 0)]
8267 "
8268 {
8269 rtx lab = PATTERN (gen_call_site ());
8270 rtx call_insn;
8271
8272 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
8273 call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
8274 operands[3],
8275 operands[2],
8276 copy_rtx (lab)));
8277 SIBLING_CALL_P (call_insn) = 1;
8278 DONE;
8279 }"
8280 [(set_attr "needs_delay_slot" "yes")
8281 (set (attr "fp_mode")
8282 (if_then_else (eq_attr "fpu_single" "yes")
8283 (const_string "single") (const_string "double")))
8284 (set_attr "type" "jump_ind")])
8285
8286 (define_insn "sibcall_value_compact"
8287 [(set (match_operand 0 "" "=rf,rf")
8288 (call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
8289 (match_operand 2 "" "")))
8290 (return)
8291 (use (match_operand:SI 3 "register_operand" "z,x"))
8292 (use (reg:SI R1_REG))
8293 (use (reg:PSI FPSCR_REG))
8294 ;; We want to make sure the `x' above will only match MACH_REG
8295 ;; because sibcall_epilogue may clobber MACL_REG.
8296 (clobber (reg:SI MACL_REG))]
8297 "TARGET_SHCOMPACT"
8298 "@
8299 jmp @%1%#
8300 jmp @%1\\n sts %3, r0"
8301 [(set_attr "needs_delay_slot" "yes,no")
8302 (set_attr "length" "2,4")
8303 (set (attr "fp_mode") (const_string "single"))
8304 (set_attr "type" "jump_ind")])
8305
8306 (define_insn "sibcall_value_media"
8307 [(set (match_operand 0 "" "=rf")
8308 (call (mem:DI (match_operand 1 "target_reg_operand" "k"))
8309 (match_operand 2 "" "")))
8310 (use (reg:SI PR_MEDIA_REG))
8311 (return)]
8312 "TARGET_SHMEDIA"
8313 "blink %1, r63"
8314 [(set_attr "type" "jump_media")])
8315
8316 (define_expand "sibcall_value"
8317 [(parallel
8318 [(set (match_operand 0 "arith_reg_operand" "")
8319 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
8320 (match_operand 2 "" "")))
8321 (match_operand 3 "" "")
8322 (use (reg:PSI FPSCR_REG))
8323 (return)])]
8324 ""
8325 "
8326 {
8327 if (TARGET_SHMEDIA)
8328 {
8329 operands[1] = shmedia_prepare_call_address (operands[1], 1);
8330 emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
8331 operands[2]));
8332 DONE;
8333 }
8334 else if (TARGET_SHCOMPACT && operands[3]
8335 && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
8336 {
8337 rtx cookie_rtx = operands[3];
8338 long cookie = INTVAL (cookie_rtx);
8339 rtx func = XEXP (operands[1], 0);
8340 rtx mach, r1;
8341
8342 if (flag_pic)
8343 {
8344 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8345 {
8346 rtx reg = gen_reg_rtx (Pmode);
8347
8348 emit_insn (gen_symGOT2reg (reg, func));
8349 func = reg;
8350 }
8351 else
8352 func = legitimize_pic_address (func, Pmode, 0);
8353 }
8354
8355 /* FIXME: if we could tell whether all argument registers are
8356 already taken, we could decide whether to force the use of
8357 MACH_REG or to stick to R0_REG. Unfortunately, there's no
8358 simple way to tell. We could use the CALL_COOKIE, but we
8359 can't currently tell a register used for regular argument
8360 passing from one that is unused. If we leave it up to reload
8361 to decide which register to use, it seems to always choose
8362 R0_REG, which leaves no available registers in SIBCALL_REGS
8363 to hold the address of the trampoline. */
8364 mach = gen_rtx_REG (SImode, MACH_REG);
8365 r1 = gen_rtx_REG (SImode, R1_REG);
8366
8367 /* Since such a call function may use all call-clobbered
8368 registers, we force a mode switch earlier, so that we don't
8369 run out of registers when adjusting fpscr for the call. */
8370 emit_insn (gen_force_mode_for_call ());
8371
8372 operands[1]
8373 = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8374 SFUNC_GOT);
8375 operands[1] = force_reg (SImode, operands[1]);
8376
8377 /* We don't need a return trampoline, since the callee will
8378 return directly to the upper caller. */
8379 if (cookie & CALL_COOKIE_RET_TRAMP (1))
8380 {
8381 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
8382 cookie_rtx = GEN_INT (cookie);
8383 }
8384
8385 emit_move_insn (mach, func);
8386 emit_move_insn (r1, cookie_rtx);
8387
8388 emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
8389 operands[2], mach));
8390 DONE;
8391 }
8392 else if (TARGET_SHCOMPACT && flag_pic
8393 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8394 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
8395 {
8396 rtx reg = gen_reg_rtx (Pmode);
8397
8398 emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
8399 XEXP (operands[1], 0) = reg;
8400 }
8401 if (flag_pic && TARGET_SH2
8402 && MEM_P (operands[1])
8403 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8404 /* The PLT needs the PIC register, but the epilogue would have
8405 to restore it, so we can only use PC-relative PIC calls for
8406 static functions. */
8407 && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
8408 {
8409 emit_call_insn (gen_sibcall_value_pcrel (operands[0],
8410 XEXP (operands[1], 0),
8411 operands[2]));
8412 DONE;
8413 }
8414 else
8415 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
8416
8417 emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
8418 DONE;
8419 }")
8420
8421 (define_insn "call_value_pop_compact"
8422 [(set (match_operand 0 "" "=rf")
8423 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8424 (match_operand 2 "" "")))
8425 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8426 (match_operand 4 "immediate_operand" "n")))
8427 (match_operand 3 "immediate_operand" "n")
8428 (use (reg:SI R0_REG))
8429 (use (reg:SI R1_REG))
8430 (use (reg:PSI FPSCR_REG))
8431 (clobber (reg:SI PR_REG))]
8432 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8433 "jsr @%1%#"
8434 [(set_attr "type" "call")
8435 (set (attr "fp_mode")
8436 (if_then_else (eq_attr "fpu_single" "yes")
8437 (const_string "single") (const_string "double")))
8438 (set_attr "needs_delay_slot" "yes")])
8439
8440 (define_insn "call_value_pop_compact_rettramp"
8441 [(set (match_operand 0 "" "=rf")
8442 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8443 (match_operand 2 "" "")))
8444 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8445 (match_operand 4 "immediate_operand" "n")))
8446 (match_operand 3 "immediate_operand" "n")
8447 (use (reg:SI R0_REG))
8448 (use (reg:SI R1_REG))
8449 (use (reg:PSI FPSCR_REG))
8450 (clobber (reg:SI R10_REG))
8451 (clobber (reg:SI PR_REG))]
8452 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8453 "jsr @%1%#"
8454 [(set_attr "type" "call")
8455 (set (attr "fp_mode")
8456 (if_then_else (eq_attr "fpu_single" "yes")
8457 (const_string "single") (const_string "double")))
8458 (set_attr "needs_delay_slot" "yes")])
8459
8460 (define_expand "call_value_pop"
8461 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
8462 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
8463 (match_operand 2 "" "")))
8464 (match_operand 3 "" "")
8465 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8466 (match_operand 4 "" "")))])]
8467 "TARGET_SHCOMPACT"
8468 "
8469 {
8470 rtx cookie_rtx;
8471 long cookie;
8472 rtx func;
8473 rtx r0, r1;
8474
8475 gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
8476 cookie_rtx = operands[3];
8477 cookie = INTVAL (cookie_rtx);
8478 func = XEXP (operands[1], 0);
8479
8480 if (flag_pic)
8481 {
8482 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8483 {
8484 rtx reg = gen_reg_rtx (Pmode);
8485
8486 emit_insn (gen_symGOTPLT2reg (reg, func));
8487 func = reg;
8488 }
8489 else
8490 func = legitimize_pic_address (func, Pmode, 0);
8491 }
8492
8493 r0 = gen_rtx_REG (SImode, R0_REG);
8494 r1 = gen_rtx_REG (SImode, R1_REG);
8495
8496 /* Since such a call function may use all call-clobbered
8497 registers, we force a mode switch earlier, so that we don't
8498 run out of registers when adjusting fpscr for the call. */
8499 emit_insn (gen_force_mode_for_call ());
8500
8501 operands[1] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8502 SFUNC_GOT);
8503 operands[1] = force_reg (SImode, operands[1]);
8504
8505 emit_move_insn (r0, func);
8506 emit_move_insn (r1, cookie_rtx);
8507
8508 if (cookie & CALL_COOKIE_RET_TRAMP (1))
8509 emit_call_insn (gen_call_value_pop_compact_rettramp
8510 (operands[0], operands[1], operands[2],
8511 operands[3], operands[4]));
8512 else
8513 emit_call_insn (gen_call_value_pop_compact
8514 (operands[0], operands[1], operands[2],
8515 operands[3], operands[4]));
8516
8517 DONE;
8518 }")
8519
8520 (define_expand "sibcall_epilogue"
8521 [(return)]
8522 ""
8523 "
8524 {
8525 sh_expand_epilogue (1);
8526 if (TARGET_SHCOMPACT)
8527 {
8528 rtx insn, set;
8529
8530 /* If epilogue clobbers r0, preserve it in macl. */
8531 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
8532 if ((set = single_set (insn))
8533 && REG_P (SET_DEST (set))
8534 && REGNO (SET_DEST (set)) == R0_REG)
8535 {
8536 rtx r0 = gen_rtx_REG (SImode, R0_REG);
8537 rtx tmp = gen_rtx_REG (SImode, MACL_REG);
8538
8539 /* We can't tell at this point whether the sibcall is a
8540 sibcall_compact and, if it is, whether it uses r0 or
8541 mach as operand 2, so let the instructions that
8542 preserve r0 be optimized away if r0 turns out to be
8543 dead. */
8544 emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
8545 emit_move_insn (r0, tmp);
8546 break;
8547 }
8548 }
8549 DONE;
8550 }")
8551
8552 (define_insn "indirect_jump_compact"
8553 [(set (pc)
8554 (match_operand:SI 0 "arith_reg_operand" "r"))]
8555 "TARGET_SH1"
8556 "jmp @%0%#"
8557 [(set_attr "needs_delay_slot" "yes")
8558 (set_attr "type" "jump_ind")])
8559
8560 (define_expand "indirect_jump"
8561 [(set (pc)
8562 (match_operand 0 "register_operand" ""))]
8563 ""
8564 "
8565 {
8566 if (GET_MODE (operands[0]) != Pmode)
8567 operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
8568 }")
8569
8570 ;; The use of operand 1 / 2 helps us distinguish case table jumps
8571 ;; which can be present in structured code from indirect jumps which can not
8572 ;; be present in structured code. This allows -fprofile-arcs to work.
8573
8574 ;; For SH1 processors.
8575 (define_insn "casesi_jump_1"
8576 [(set (pc)
8577 (match_operand:SI 0 "register_operand" "r"))
8578 (use (label_ref (match_operand 1 "" "")))]
8579 "TARGET_SH1"
8580 "jmp @%0%#"
8581 [(set_attr "needs_delay_slot" "yes")
8582 (set_attr "type" "jump_ind")])
8583
8584 ;; For all later processors.
8585 (define_insn "casesi_jump_2"
8586 [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
8587 (label_ref (match_operand 1 "" ""))))
8588 (use (label_ref (match_operand 2 "" "")))]
8589 "TARGET_SH2
8590 && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
8591 "braf %0%#"
8592 [(set_attr "needs_delay_slot" "yes")
8593 (set_attr "type" "jump_ind")])
8594
8595 (define_insn "casesi_jump_media"
8596 [(set (pc) (match_operand 0 "target_reg_operand" "b"))
8597 (use (label_ref (match_operand 1 "" "")))]
8598 "TARGET_SHMEDIA"
8599 "blink %0, r63"
8600 [(set_attr "type" "jump_media")])
8601
8602 ;; Call subroutine returning any type.
8603 ;; ??? This probably doesn't work.
8604
8605 (define_expand "untyped_call"
8606 [(parallel [(call (match_operand 0 "" "")
8607 (const_int 0))
8608 (match_operand 1 "" "")
8609 (match_operand 2 "" "")])]
8610 "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
8611 "
8612 {
8613 int i;
8614
8615 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
8616
8617 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8618 {
8619 rtx set = XVECEXP (operands[2], 0, i);
8620 emit_move_insn (SET_DEST (set), SET_SRC (set));
8621 }
8622
8623 /* The optimizer does not know that the call sets the function value
8624 registers we stored in the result block. We avoid problems by
8625 claiming that all hard registers are used and clobbered at this
8626 point. */
8627 emit_insn (gen_blockage ());
8628
8629 DONE;
8630 }")
8631 \f
8632 ;; ------------------------------------------------------------------------
8633 ;; Misc insns
8634 ;; ------------------------------------------------------------------------
8635
8636 (define_insn "dect"
8637 [(set (reg:SI T_REG)
8638 (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
8639 (set (match_operand:SI 0 "arith_reg_dest" "=r")
8640 (plus:SI (match_dup 1) (const_int -1)))]
8641 "TARGET_SH2"
8642 "dt %0"
8643 [(set_attr "type" "arith")])
8644
8645 (define_insn "nop"
8646 [(const_int 0)]
8647 ""
8648 "nop")
8649
8650 ;; Load address of a label. This is only generated by the casesi expand,
8651 ;; and by machine_dependent_reorg (fixing up fp moves).
8652 ;; This must use unspec, because this only works for labels that are
8653 ;; within range,
8654
8655 (define_insn "mova"
8656 [(set (reg:SI R0_REG)
8657 (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
8658 "TARGET_SH1"
8659 "mova %O0,r0"
8660 [(set_attr "in_delay_slot" "no")
8661 (set_attr "type" "arith")])
8662
8663 ;; machine_dependent_reorg will make this a `mova'.
8664 (define_insn "mova_const"
8665 [(set (reg:SI R0_REG)
8666 (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
8667 "TARGET_SH1"
8668 "#"
8669 [(set_attr "in_delay_slot" "no")
8670 (set_attr "type" "arith")])
8671
8672 (define_expand "GOTaddr2picreg"
8673 [(set (reg:SI R0_REG)
8674 (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
8675 UNSPEC_MOVA))
8676 (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
8677 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
8678 "" "
8679 {
8680 if (TARGET_VXWORKS_RTP)
8681 {
8682 rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
8683 rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
8684 emit_insn (gen_vxworks_picreg (gott_base, gott_index));
8685 DONE;
8686 }
8687
8688 operands[0] = gen_rtx_REG (Pmode, PIC_REG);
8689 operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
8690
8691 if (TARGET_SHMEDIA)
8692 {
8693 rtx tr = gen_rtx_REG (Pmode, TR0_REG);
8694 rtx pic = operands[0];
8695 rtx lab = PATTERN (gen_call_site ());
8696 rtx insn, equiv;
8697
8698 equiv = operands[1];
8699 operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
8700 UNSPEC_PCREL_SYMOFF);
8701 operands[1] = gen_rtx_CONST (Pmode, operands[1]);
8702
8703 if (Pmode == SImode)
8704 {
8705 emit_insn (gen_movsi_const (pic, operands[1]));
8706 emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
8707 }
8708 else
8709 {
8710 emit_insn (gen_movdi_const (pic, operands[1]));
8711 emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
8712 }
8713
8714 insn = emit_move_insn (operands[0], tr);
8715
8716 set_unique_reg_note (insn, REG_EQUAL, equiv);
8717
8718 DONE;
8719 }
8720 }
8721 ")
8722
8723 ;; A helper for GOTaddr2picreg to finish up the initialization of the
8724 ;; PIC register.
8725
8726 (define_expand "vxworks_picreg"
8727 [(set (reg:SI PIC_REG)
8728 (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
8729 (set (reg:SI R0_REG)
8730 (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
8731 (set (reg:SI PIC_REG)
8732 (mem:SI (reg:SI PIC_REG)))
8733 (set (reg:SI PIC_REG)
8734 (mem:SI (plus:SI (reg:SI PIC_REG)
8735 (reg:SI R0_REG))))]
8736 "TARGET_VXWORKS_RTP")
8737
8738 (define_insn "*ptb"
8739 [(set (match_operand 0 "target_reg_operand" "=b")
8740 (const (unspec [(match_operand 1 "" "Csy")]
8741 UNSPEC_DATALABEL)))]
8742 "TARGET_SHMEDIA && flag_pic
8743 && satisfies_constraint_Csy (operands[1])"
8744 "ptb/u datalabel %1, %0"
8745 [(set_attr "type" "ptabs_media")
8746 (set_attr "length" "*")])
8747
8748 (define_insn "ptrel_si"
8749 [(set (match_operand:SI 0 "target_reg_operand" "=b")
8750 (plus:SI (match_operand:SI 1 "register_operand" "r")
8751 (pc)))
8752 (match_operand:SI 2 "" "")]
8753 "TARGET_SHMEDIA"
8754 "%O2: ptrel/u %1, %0"
8755 [(set_attr "type" "ptabs_media")])
8756
8757 (define_insn "ptrel_di"
8758 [(set (match_operand:DI 0 "target_reg_operand" "=b")
8759 (plus:DI (match_operand:DI 1 "register_operand" "r")
8760 (pc)))
8761 (match_operand:DI 2 "" "")]
8762 "TARGET_SHMEDIA"
8763 "%O2: ptrel/u %1, %0"
8764 [(set_attr "type" "ptabs_media")])
8765
8766 (define_expand "builtin_setjmp_receiver"
8767 [(match_operand 0 "" "")]
8768 "flag_pic"
8769 "
8770 {
8771 emit_insn (gen_GOTaddr2picreg ());
8772 DONE;
8773 }")
8774
8775 (define_expand "call_site"
8776 [(unspec [(match_dup 0)] UNSPEC_CALLER)]
8777 "TARGET_SH1"
8778 "
8779 {
8780 static HOST_WIDE_INT i = 0;
8781 operands[0] = GEN_INT (i);
8782 i++;
8783 }")
8784
8785 ;; op0 = op1 + r12 but hide it before reload completed. See the comment
8786 ;; in symGOT_load expand.
8787
8788 (define_insn_and_split "chk_guard_add"
8789 [(set (match_operand:SI 0 "register_operand" "=&r")
8790 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
8791 (reg:SI PIC_REG)]
8792 UNSPEC_CHKADD))]
8793 "TARGET_SH1"
8794 "#"
8795 "TARGET_SH1 && reload_completed"
8796 [(set (match_dup 0) (reg:SI PIC_REG))
8797 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8798 ""
8799 [(set_attr "type" "arith")])
8800
8801 (define_expand "sym_label2reg"
8802 [(set (match_operand:SI 0 "" "")
8803 (const:SI (unspec:SI [(match_operand:SI 1 "" "")
8804 (const (plus:SI (match_operand:SI 2 "" "")
8805 (const_int 2)))]
8806 UNSPEC_SYMOFF)))]
8807 "TARGET_SH1" "")
8808
8809 (define_expand "symGOT_load"
8810 [(set (match_dup 2) (match_operand 1 "" ""))
8811 (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
8812 (set (match_operand 0 "" "") (mem (match_dup 3)))]
8813 ""
8814 "
8815 {
8816 rtx mem;
8817
8818 operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
8819 operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
8820
8821 if (TARGET_SHMEDIA)
8822 {
8823 rtx reg = operands[2];
8824
8825 if (Pmode == DImode)
8826 {
8827 if (flag_pic > 1)
8828 emit_insn (gen_movdi_const_32bit (reg, operands[1]));
8829 else
8830 emit_insn (gen_movdi_const_16bit (reg, operands[1]));
8831 }
8832 else
8833 {
8834 if (flag_pic > 1)
8835 emit_insn (gen_movsi_const (reg, operands[1]));
8836 else
8837 emit_insn (gen_movsi_const_16bit (reg, operands[1]));
8838 }
8839 }
8840 else
8841 emit_move_insn (operands[2], operands[1]);
8842
8843 /* When stack protector inserts codes after the result is set to
8844 R0, @(rX, r12) will cause a spill failure for R0. Use a unspec
8845 insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
8846 when rX is a GOT address for the guard symbol. Ugly but doesn't
8847 matter because this is a rare situation. */
8848 if (!TARGET_SHMEDIA
8849 && flag_stack_protect
8850 && GET_CODE (operands[1]) == CONST
8851 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
8852 && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
8853 && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
8854 \"__stack_chk_guard\") == 0)
8855 emit_insn (gen_chk_guard_add (operands[3], operands[2]));
8856 else
8857 emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
8858 gen_rtx_REG (Pmode, PIC_REG)));
8859
8860 /* N.B. This is not constant for a GOTPLT relocation. */
8861 mem = gen_rtx_MEM (Pmode, operands[3]);
8862 MEM_NOTRAP_P (mem) = 1;
8863 /* ??? Should we have a special alias set for the GOT? */
8864 emit_move_insn (operands[0], mem);
8865
8866 DONE;
8867 }")
8868
8869 (define_expand "sym2GOT"
8870 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
8871 ""
8872 "")
8873
8874 (define_expand "symGOT2reg"
8875 [(match_operand 0 "" "") (match_operand 1 "" "")]
8876 ""
8877 "
8878 {
8879 rtx gotsym, insn;
8880
8881 gotsym = gen_sym2GOT (operands[1]);
8882 PUT_MODE (gotsym, Pmode);
8883 insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
8884
8885 MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
8886
8887 DONE;
8888 }")
8889
8890 (define_expand "symGOTPLT2reg"
8891 [(match_operand 0 "" "") (match_operand 1 "" "")]
8892 ""
8893 "
8894 {
8895 rtx pltsym = gen_rtx_CONST (Pmode,
8896 gen_rtx_UNSPEC (Pmode,
8897 gen_rtvec (1, operands[1]),
8898 UNSPEC_GOTPLT));
8899 emit_insn (gen_symGOT_load (operands[0], pltsym));
8900 DONE;
8901 }")
8902
8903 (define_expand "sym2GOTOFF"
8904 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
8905 ""
8906 "")
8907
8908 (define_expand "symGOTOFF2reg"
8909 [(match_operand 0 "" "") (match_operand 1 "" "")]
8910 ""
8911 "
8912 {
8913 rtx gotoffsym, insn;
8914 rtx t = (!can_create_pseudo_p ()
8915 ? operands[0]
8916 : gen_reg_rtx (GET_MODE (operands[0])));
8917
8918 gotoffsym = gen_sym2GOTOFF (operands[1]);
8919 PUT_MODE (gotoffsym, Pmode);
8920 emit_move_insn (t, gotoffsym);
8921 insn = emit_move_insn (operands[0],
8922 gen_rtx_PLUS (Pmode, t,
8923 gen_rtx_REG (Pmode, PIC_REG)));
8924
8925 set_unique_reg_note (insn, REG_EQUAL, operands[1]);
8926
8927 DONE;
8928 }")
8929
8930 (define_expand "symPLT_label2reg"
8931 [(set (match_operand:SI 0 "" "")
8932 (const:SI
8933 (unspec:SI
8934 [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
8935 (const:SI (plus:SI (match_operand:SI 2 "" "")
8936 (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
8937 ;; Even though the PIC register is not really used by the call
8938 ;; sequence in which this is expanded, the PLT code assumes the PIC
8939 ;; register is set, so we must not skip its initialization. Since
8940 ;; we only use this expand as part of calling sequences, and never
8941 ;; to take the address of a function, this is the best point to
8942 ;; insert the (use). Using the PLT to take the address of a
8943 ;; function would be wrong, not only because the PLT entry could
8944 ;; then be called from a function that doesn't initialize the PIC
8945 ;; register to the proper GOT, but also because pointers to the
8946 ;; same function might not compare equal, should they be set by
8947 ;; different shared libraries.
8948 (use (reg:SI PIC_REG))]
8949 "TARGET_SH1"
8950 "")
8951
8952 (define_expand "sym2PIC"
8953 [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
8954 ""
8955 "")
8956
8957 ;; TLS code generation.
8958 ;; ??? this should be a define_insn_and_split
8959 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
8960 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
8961 ;; for details.
8962
8963 (define_insn "tls_global_dynamic"
8964 [(set (match_operand:SI 0 "register_operand" "=&z")
8965 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8966 UNSPEC_TLSGD))
8967 (const_int 0)))
8968 (use (reg:PSI FPSCR_REG))
8969 (use (reg:SI PIC_REG))
8970 (clobber (reg:SI PR_REG))
8971 (clobber (scratch:SI))]
8972 "TARGET_SH1"
8973 "*
8974 {
8975 return \"\\
8976 mov.l\\t1f,r4\\n\\
8977 \\tmova\\t2f,r0\\n\\
8978 \\tmov.l\\t2f,r1\\n\\
8979 \\tadd\\tr0,r1\\n\\
8980 \\tjsr\\t@r1\\n\\
8981 \\tadd\\tr12,r4\\n\\
8982 \\tbra\\t3f\\n\\
8983 \\tnop\\n\\
8984 \\t.align\\t2\\n\\
8985 1:\\t.long\\t%a1@TLSGD\\n\\
8986 2:\\t.long\\t__tls_get_addr@PLT\\n\\
8987 3:\";
8988 }"
8989 [(set_attr "type" "tls_load")
8990 (set_attr "length" "26")])
8991
8992 (define_insn "tls_local_dynamic"
8993 [(set (match_operand:SI 0 "register_operand" "=&z")
8994 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8995 UNSPEC_TLSLDM))
8996 (const_int 0)))
8997 (use (reg:PSI FPSCR_REG))
8998 (use (reg:SI PIC_REG))
8999 (clobber (reg:SI PR_REG))
9000 (clobber (scratch:SI))]
9001 "TARGET_SH1"
9002 "*
9003 {
9004 return \"\\
9005 mov.l\\t1f,r4\\n\\
9006 \\tmova\\t2f,r0\\n\\
9007 \\tmov.l\\t2f,r1\\n\\
9008 \\tadd\\tr0,r1\\n\\
9009 \\tjsr\\t@r1\\n\\
9010 \\tadd\\tr12,r4\\n\\
9011 \\tbra\\t3f\\n\\
9012 \\tnop\\n\\
9013 \\t.align\\t2\\n\\
9014 1:\\t.long\\t%a1@TLSLDM\\n\\
9015 2:\\t.long\\t__tls_get_addr@PLT\\n\\
9016 3:\";
9017 }"
9018 [(set_attr "type" "tls_load")
9019 (set_attr "length" "26")])
9020
9021 (define_expand "sym2DTPOFF"
9022 [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
9023 ""
9024 "")
9025
9026 (define_expand "symDTPOFF2reg"
9027 [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
9028 ""
9029 "
9030 {
9031 rtx dtpoffsym;
9032 rtx t = (!can_create_pseudo_p ()
9033 ? operands[0]
9034 : gen_reg_rtx (GET_MODE (operands[0])));
9035
9036 dtpoffsym = gen_sym2DTPOFF (operands[1]);
9037 PUT_MODE (dtpoffsym, Pmode);
9038 emit_move_insn (t, dtpoffsym);
9039 emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
9040 DONE;
9041 }")
9042
9043 (define_expand "sym2GOTTPOFF"
9044 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
9045 ""
9046 "")
9047
9048 (define_insn "tls_initial_exec"
9049 [(set (match_operand:SI 0 "register_operand" "=&r")
9050 (unspec:SI [(match_operand:SI 1 "" "")]
9051 UNSPEC_TLSIE))
9052 (use (reg:SI GBR_REG))
9053 (use (reg:SI PIC_REG))
9054 (clobber (reg:SI R0_REG))]
9055 ""
9056 "*
9057 {
9058 return \"\\
9059 mov.l\\t1f,r0\\n\\
9060 \\tstc\\tgbr,%0\\n\\
9061 \\tmov.l\\t@(r0,r12),r0\\n\\
9062 \\tbra\\t2f\\n\\
9063 \\tadd\\tr0,%0\\n\\
9064 \\t.align\\t2\\n\\
9065 1:\\t.long\\t%a1\\n\\
9066 2:\";
9067 }"
9068 [(set_attr "type" "tls_load")
9069 (set_attr "length" "16")])
9070
9071 (define_expand "sym2TPOFF"
9072 [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
9073 ""
9074 "")
9075
9076 (define_expand "symTPOFF2reg"
9077 [(match_operand 0 "" "") (match_operand 1 "" "")]
9078 ""
9079 "
9080 {
9081 rtx tpoffsym;
9082
9083 tpoffsym = gen_sym2TPOFF (operands[1]);
9084 PUT_MODE (tpoffsym, Pmode);
9085 emit_move_insn (operands[0], tpoffsym);
9086 DONE;
9087 }")
9088
9089 (define_insn "load_gbr"
9090 [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))
9091 (use (reg:SI GBR_REG))]
9092 ""
9093 "stc gbr,%0"
9094 [(set_attr "type" "tls_load")])
9095
9096 ;; case instruction for switch statements.
9097
9098 ;; Operand 0 is index
9099 ;; operand 1 is the minimum bound
9100 ;; operand 2 is the maximum bound - minimum bound + 1
9101 ;; operand 3 is CODE_LABEL for the table;
9102 ;; operand 4 is the CODE_LABEL to go to if index out of range.
9103
9104 (define_expand "casesi"
9105 [(match_operand:SI 0 "arith_reg_operand" "")
9106 (match_operand:SI 1 "arith_reg_operand" "")
9107 (match_operand:SI 2 "arith_reg_operand" "")
9108 (match_operand 3 "" "") (match_operand 4 "" "")]
9109 ""
9110 "
9111 {
9112 rtx reg = gen_reg_rtx (SImode);
9113 rtx reg2 = gen_reg_rtx (SImode);
9114 if (TARGET_SHMEDIA)
9115 {
9116 rtx reg = gen_reg_rtx (DImode);
9117 rtx reg2 = gen_reg_rtx (DImode);
9118 rtx reg3 = gen_reg_rtx (Pmode);
9119 rtx reg4 = gen_reg_rtx (Pmode);
9120 rtx reg5 = gen_reg_rtx (Pmode);
9121 rtx load, test;
9122
9123 operands[0] = convert_modes (DImode, SImode, operands[0], 0);
9124 operands[1] = convert_modes (DImode, SImode, operands[1], 0);
9125 operands[2] = convert_modes (DImode, SImode, operands[2], 1);
9126
9127 test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
9128 emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0], operands[4]));
9129 emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
9130 test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
9131 emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
9132 emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
9133 emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
9134 (Pmode, operands[3])));
9135 /* Messy: can we subreg to clean this up? */
9136 if (Pmode == DImode)
9137 load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
9138 else
9139 load = gen_casesi_load_media (reg4,
9140 gen_rtx_SUBREG (DImode, reg3, 0),
9141 reg2, operands[3]);
9142 PUT_MODE (SET_SRC (load), Pmode);
9143 emit_insn (load);
9144 /* ??? The following add could be eliminated if we used ptrel. */
9145 emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
9146 emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
9147 emit_barrier ();
9148 DONE;
9149 }
9150 operands[1] = copy_to_mode_reg (SImode, operands[1]);
9151 operands[2] = copy_to_mode_reg (SImode, operands[2]);
9152 /* If optimizing, casesi_worker depends on the mode of the instruction
9153 before label it 'uses' - operands[3]. */
9154 emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
9155 reg));
9156 emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
9157 if (TARGET_SH2)
9158 emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
9159 else
9160 emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
9161 /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
9162 operands[3], but to lab. We will fix this up in
9163 machine_dependent_reorg. */
9164 emit_barrier ();
9165 DONE;
9166 }")
9167
9168 (define_expand "casesi_0"
9169 [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
9170 (set (match_dup 4) (minus:SI (match_dup 4)
9171 (match_operand:SI 1 "arith_operand" "")))
9172 (set (reg:SI T_REG)
9173 (gtu:SI (match_dup 4)
9174 (match_operand:SI 2 "arith_reg_operand" "")))
9175 (set (pc)
9176 (if_then_else (ne (reg:SI T_REG)
9177 (const_int 0))
9178 (label_ref (match_operand 3 "" ""))
9179 (pc)))]
9180 "TARGET_SH1"
9181 "")
9182
9183 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
9184 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
9185 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
9186
9187 (define_insn "casesi_worker_0"
9188 [(set (match_operand:SI 0 "register_operand" "=r,r")
9189 (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
9190 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9191 (clobber (match_scratch:SI 3 "=X,1"))
9192 (clobber (match_scratch:SI 4 "=&z,z"))]
9193 "TARGET_SH1"
9194 "#")
9195
9196 (define_split
9197 [(set (match_operand:SI 0 "register_operand" "")
9198 (unspec:SI [(match_operand:SI 1 "register_operand" "")
9199 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9200 (clobber (match_scratch:SI 3 ""))
9201 (clobber (match_scratch:SI 4 ""))]
9202 "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
9203 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
9204 (parallel [(set (match_dup 0)
9205 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
9206 (label_ref (match_dup 2))] UNSPEC_CASESI))
9207 (clobber (match_dup 3))])
9208 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
9209 "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
9210
9211 (define_split
9212 [(set (match_operand:SI 0 "register_operand" "")
9213 (unspec:SI [(match_operand:SI 1 "register_operand" "")
9214 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9215 (clobber (match_scratch:SI 3 ""))
9216 (clobber (match_scratch:SI 4 ""))]
9217 "TARGET_SH2 && reload_completed"
9218 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
9219 (parallel [(set (match_dup 0)
9220 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
9221 (label_ref (match_dup 2))] UNSPEC_CASESI))
9222 (clobber (match_dup 3))])]
9223 "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
9224
9225 (define_insn "casesi_worker_1"
9226 [(set (match_operand:SI 0 "register_operand" "=r,r")
9227 (unspec:SI [(reg:SI R0_REG)
9228 (match_operand:SI 1 "register_operand" "0,r")
9229 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9230 (clobber (match_scratch:SI 3 "=X,1"))]
9231 "TARGET_SH1"
9232 "*
9233 {
9234 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
9235
9236 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9237
9238 switch (GET_MODE (diff_vec))
9239 {
9240 case SImode:
9241 return \"shll2 %1\;mov.l @(r0,%1),%0\";
9242 case HImode:
9243 return \"add %1,%1\;mov.w @(r0,%1),%0\";
9244 case QImode:
9245 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9246 return \"mov.b @(r0,%1),%0\;extu.b %0,%0\";
9247 return \"mov.b @(r0,%1),%0\";
9248 default:
9249 gcc_unreachable ();
9250 }
9251 }"
9252 [(set_attr "length" "4")])
9253
9254 (define_insn "casesi_worker_2"
9255 [(set (match_operand:SI 0 "register_operand" "=r,r")
9256 (unspec:SI [(reg:SI R0_REG)
9257 (match_operand:SI 1 "register_operand" "0,r")
9258 (label_ref (match_operand 2 "" ""))
9259 (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
9260 (clobber (match_operand:SI 4 "" "=X,1"))]
9261 "TARGET_SH2 && reload_completed && flag_pic"
9262 "*
9263 {
9264 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
9265 const char *load;
9266
9267 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9268
9269 switch (GET_MODE (diff_vec))
9270 {
9271 case SImode:
9272 output_asm_insn (\"shll2 %1\", operands);
9273 load = \"mov.l @(r0,%1),%0\"; break;
9274 case HImode:
9275 output_asm_insn (\"add %1,%1\", operands);
9276 load = \"mov.w @(r0,%1),%0\"; break;
9277 case QImode:
9278 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9279 load = \"mov.b @(r0,%1),%0\;extu.b %0,%0\";
9280 else
9281 load = \"mov.b @(r0,%1),%0\";
9282 break;
9283 default:
9284 gcc_unreachable ();
9285 }
9286 output_asm_insn (\"add\tr0,%1\;mova\t%O3,r0\\n\", operands);
9287 return load;
9288 }"
9289 [(set_attr "length" "8")])
9290
9291 (define_insn "casesi_shift_media"
9292 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9293 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
9294 (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
9295 UNSPEC_CASESI)))]
9296 "TARGET_SHMEDIA"
9297 "*
9298 {
9299 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
9300
9301 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9302
9303 switch (GET_MODE (diff_vec))
9304 {
9305 case SImode:
9306 return \"shlli %1, 2, %0\";
9307 case HImode:
9308 return \"shlli %1, 1, %0\";
9309 case QImode:
9310 if (rtx_equal_p (operands[0], operands[1]))
9311 return \"\";
9312 return \"add %1, r63, %0\";
9313 default:
9314 gcc_unreachable ();
9315 }
9316 }"
9317 [(set_attr "type" "arith_media")])
9318
9319 (define_insn "casesi_load_media"
9320 [(set (match_operand 0 "any_arith_reg_dest" "=r")
9321 (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
9322 (match_operand:DI 2 "arith_reg_operand" "r")
9323 (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
9324 "TARGET_SHMEDIA"
9325 "*
9326 {
9327 rtx diff_vec = PATTERN (next_real_insn (operands[3]));
9328
9329 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9330
9331 switch (GET_MODE (diff_vec))
9332 {
9333 case SImode:
9334 return \"ldx.l %1, %2, %0\";
9335 case HImode:
9336 #if 0
9337 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9338 return \"ldx.uw %1, %2, %0\";
9339 #endif
9340 return \"ldx.w %1, %2, %0\";
9341 case QImode:
9342 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9343 return \"ldx.ub %1, %2, %0\";
9344 return \"ldx.b %1, %2, %0\";
9345 default:
9346 gcc_unreachable ();
9347 }
9348 }"
9349 [(set_attr "type" "load_media")])
9350
9351 (define_expand "return"
9352 [(return)]
9353 "reload_completed && ! sh_need_epilogue ()"
9354 "
9355 {
9356 if (TARGET_SHMEDIA)
9357 {
9358 emit_jump_insn (gen_return_media ());
9359 DONE;
9360 }
9361
9362 if (TARGET_SHCOMPACT
9363 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
9364 {
9365 emit_jump_insn (gen_shcompact_return_tramp ());
9366 DONE;
9367 }
9368 }")
9369
9370 (define_insn "*return_i"
9371 [(return)]
9372 "TARGET_SH1 && ! (TARGET_SHCOMPACT
9373 && (crtl->args.info.call_cookie
9374 & CALL_COOKIE_RET_TRAMP (1)))
9375 && reload_completed
9376 && lookup_attribute (\"trap_exit\",
9377 DECL_ATTRIBUTES (current_function_decl)) == NULL_TREE"
9378 "*
9379 {
9380 if (TARGET_SH2A && (dbr_sequence_length () == 0)
9381 && !current_function_interrupt)
9382 return \"rts/n\";
9383 else
9384 return \"%@ %#\";
9385 }"
9386 [(set_attr "type" "return")
9387 (set_attr "needs_delay_slot" "yes")])
9388
9389 ;; trapa has no delay slot.
9390 (define_insn "*return_trapa"
9391 [(return)]
9392 "TARGET_SH1 && !TARGET_SHCOMPACT
9393 && reload_completed"
9394 "%@"
9395 [(set_attr "type" "return")])
9396
9397 (define_expand "shcompact_return_tramp"
9398 [(return)]
9399 "TARGET_SHCOMPACT
9400 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
9401 "
9402 {
9403 rtx reg = gen_rtx_REG (Pmode, R0_REG);
9404
9405 function_symbol (reg, \"__GCC_shcompact_return_trampoline\", SFUNC_STATIC);
9406 emit_jump_insn (gen_shcompact_return_tramp_i ());
9407 DONE;
9408 }")
9409
9410 (define_insn "shcompact_return_tramp_i"
9411 [(parallel [(return) (use (reg:SI R0_REG))])]
9412 "TARGET_SHCOMPACT
9413 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
9414 "jmp @r0%#"
9415 [(set_attr "type" "jump_ind")
9416 (set_attr "needs_delay_slot" "yes")])
9417
9418 (define_insn "return_media_i"
9419 [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
9420 "TARGET_SHMEDIA && reload_completed"
9421 "blink %0, r63"
9422 [(set_attr "type" "jump_media")])
9423
9424 (define_insn "return_media_rte"
9425 [(return)]
9426 "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
9427 "rte"
9428 [(set_attr "type" "jump_media")])
9429
9430 (define_expand "return_media"
9431 [(return)]
9432 "TARGET_SHMEDIA && reload_completed"
9433 "
9434 {
9435 int tr_regno = sh_media_register_for_return ();
9436 rtx tr;
9437
9438 if (current_function_interrupt)
9439 {
9440 emit_jump_insn (gen_return_media_rte ());
9441 DONE;
9442 }
9443 if (tr_regno < 0)
9444 {
9445 rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
9446
9447 gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
9448 tr_regno = TR0_REG;
9449 tr = gen_rtx_REG (Pmode, tr_regno);
9450 emit_move_insn (tr, r18);
9451 }
9452 else
9453 tr = gen_rtx_REG (Pmode, tr_regno);
9454
9455 emit_jump_insn (gen_return_media_i (tr));
9456 DONE;
9457 }")
9458
9459 (define_insn "shcompact_preserve_incoming_args"
9460 [(set (match_operand:SI 0 "register_operand" "+r")
9461 (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
9462 "TARGET_SHCOMPACT"
9463 ""
9464 [(set_attr "length" "0")])
9465
9466 (define_insn "shcompact_incoming_args"
9467 [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
9468 (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
9469 (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
9470 (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
9471 (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
9472 (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
9473 (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
9474 (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
9475 (set (mem:BLK (reg:SI MACL_REG))
9476 (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
9477 (use (reg:SI R0_REG))
9478 (clobber (reg:SI R0_REG))
9479 (clobber (reg:SI MACL_REG))
9480 (clobber (reg:SI MACH_REG))
9481 (clobber (reg:SI PR_REG))]
9482 "TARGET_SHCOMPACT"
9483 "jsr @r0%#"
9484 [(set_attr "needs_delay_slot" "yes")])
9485
9486 (define_insn "shmedia_save_restore_regs_compact"
9487 [(set (reg:SI SP_REG)
9488 (plus:SI (reg:SI SP_REG)
9489 (match_operand:SI 0 "immediate_operand" "i")))
9490 (use (reg:SI R0_REG))
9491 (clobber (reg:SI PR_REG))]
9492 "TARGET_SHCOMPACT
9493 && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
9494 || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
9495 "jsr @r0%#"
9496 [(set_attr "needs_delay_slot" "yes")])
9497
9498 (define_expand "prologue"
9499 [(const_int 0)]
9500 ""
9501 "sh_expand_prologue (); DONE;")
9502
9503 (define_expand "epilogue"
9504 [(return)]
9505 ""
9506 "
9507 {
9508 sh_expand_epilogue (0);
9509 emit_jump_insn (gen_return ());
9510 DONE;
9511 }")
9512
9513 (define_expand "eh_return"
9514 [(use (match_operand 0 "register_operand" ""))]
9515 ""
9516 {
9517 rtx ra = operands[0];
9518
9519 if (TARGET_SHMEDIA64)
9520 emit_insn (gen_eh_set_ra_di (ra));
9521 else
9522 emit_insn (gen_eh_set_ra_si (ra));
9523
9524 DONE;
9525 })
9526
9527 ;; Clobber the return address on the stack. We can't expand this
9528 ;; until we know where it will be put in the stack frame.
9529
9530 (define_insn "eh_set_ra_si"
9531 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
9532 UNSPECV_EH_RETURN)
9533 (clobber (match_scratch:SI 1 "=&r"))]
9534 "! TARGET_SHMEDIA64"
9535 "#")
9536
9537 (define_insn "eh_set_ra_di"
9538 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
9539 UNSPECV_EH_RETURN)
9540 (clobber (match_scratch:DI 1 "=&r"))]
9541 "TARGET_SHMEDIA64"
9542 "#")
9543
9544 (define_split
9545 [(unspec_volatile [(match_operand 0 "register_operand" "")]
9546 UNSPECV_EH_RETURN)
9547 (clobber (match_scratch 1 ""))]
9548 "reload_completed"
9549 [(const_int 0)]
9550 "
9551 {
9552 sh_set_return_address (operands[0], operands[1]);
9553 DONE;
9554 }")
9555
9556 (define_insn "blockage"
9557 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
9558 ""
9559 ""
9560 [(set_attr "length" "0")])
9561 \f
9562 ;; Define movml instructions for SH2A target. Currently they are
9563 ;; used to push and pop all banked registers only.
9564
9565 (define_insn "movml_push_banked"
9566 [(set (match_operand:SI 0 "register_operand" "=r")
9567 (plus (match_dup 0) (const_int -32)))
9568 (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
9569 (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
9570 (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
9571 (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
9572 (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
9573 (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
9574 (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
9575 (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
9576 "TARGET_SH2A && REGNO (operands[0]) == 15"
9577 "movml.l\tr7,@-r15"
9578 [(set_attr "in_delay_slot" "no")])
9579
9580 (define_insn "movml_pop_banked"
9581 [(set (match_operand:SI 0 "register_operand" "=r")
9582 (plus (match_dup 0) (const_int 32)))
9583 (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
9584 (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
9585 (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
9586 (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
9587 (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
9588 (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
9589 (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
9590 (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
9591 "TARGET_SH2A && REGNO (operands[0]) == 15"
9592 "movml.l\t@r15+,r7"
9593 [(set_attr "in_delay_slot" "no")])
9594 \f
9595 ;; ------------------------------------------------------------------------
9596 ;; Scc instructions
9597 ;; ------------------------------------------------------------------------
9598
9599 (define_insn "movt"
9600 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9601 (eq:SI (reg:SI T_REG) (const_int 1)))]
9602 "TARGET_SH1"
9603 "movt %0"
9604 [(set_attr "type" "arith")])
9605
9606 (define_insn "movrt"
9607 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9608 (xor:SI (reg:SI T_REG) (const_int 1)))]
9609 "TARGET_SH2A"
9610 "movrt %0"
9611 [(set_attr "type" "arith")])
9612
9613 (define_expand "cstore4_media"
9614 [(set (match_operand:SI 0 "register_operand" "=r")
9615 (match_operator:SI 1 "sh_float_comparison_operator"
9616 [(match_operand 2 "logical_operand" "")
9617 (match_operand 3 "cmp_operand" "")]))]
9618 "TARGET_SHMEDIA"
9619 "
9620 {
9621 enum machine_mode mode = GET_MODE (operands[2]);
9622 enum rtx_code code = GET_CODE (operands[1]);
9623 bool invert, swap;
9624 if (mode == VOIDmode)
9625 mode = GET_MODE (operands[3]);
9626 if (operands[2] == const0_rtx)
9627 {
9628 if (code == EQ || code == NE)
9629 operands[2] = operands[3], operands[3] = const0_rtx;
9630 }
9631 else
9632 operands[2] = force_reg (mode, operands[2]);
9633 if (operands[3] != const0_rtx)
9634 operands[3] = force_reg (mode, operands[3]);
9635
9636 switch (code)
9637 {
9638 case GEU:
9639 case GE:
9640 swap = invert = !FLOAT_MODE_P (mode);
9641 break;
9642
9643 case LEU:
9644 case LE:
9645 swap = FLOAT_MODE_P (mode), invert = !swap;
9646 break;
9647
9648 case LTU:
9649 case LT:
9650 swap = true, invert = false;
9651 break;
9652
9653 case GTU:
9654 case GT:
9655 case EQ:
9656 case UNORDERED:
9657 swap = invert = false;
9658 break;
9659
9660 case NE:
9661 swap = invert = true;
9662 break;
9663
9664 default:
9665 gcc_unreachable ();
9666 }
9667
9668 if (swap)
9669 {
9670 rtx tem = operands[2];
9671 operands[2] = operands[3];
9672 operands[3] = tem;
9673 code = swap_condition (code);
9674 }
9675
9676 if (invert)
9677 {
9678 rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
9679 code = reverse_condition (code);
9680 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
9681 emit_insn (gen_cstore4_media (tem, operands[1],
9682 operands[2], operands[3]));
9683 code = EQ;
9684 operands[2] = tem;
9685 operands[3] = const0_rtx;
9686 }
9687
9688 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
9689 }")
9690
9691 (define_expand "cstoresi4"
9692 [(set (match_operand:SI 0 "register_operand" "=r")
9693 (match_operator:SI 1 "comparison_operator"
9694 [(match_operand:SI 2 "cmpsi_operand" "")
9695 (match_operand:SI 3 "arith_operand" "")]))]
9696 "TARGET_SH1 || TARGET_SHMEDIA"
9697 "if (TARGET_SHMEDIA)
9698 {
9699 emit_insn (gen_cstore4_media (operands[0], operands[1],
9700 operands[2], operands[3]));
9701 DONE;
9702 }
9703
9704 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
9705 && sh_expand_t_scc (operands))
9706 DONE;
9707
9708 if (! currently_expanding_to_rtl)
9709 FAIL;
9710
9711 sh_emit_compare_and_set (operands, SImode);
9712 DONE;
9713 ")
9714
9715 (define_expand "cstoredi4"
9716 [(set (match_operand:SI 0 "register_operand" "=r")
9717 (match_operator:SI 1 "comparison_operator"
9718 [(match_operand:DI 2 "arith_operand" "")
9719 (match_operand:DI 3 "arith_operand" "")]))]
9720 "TARGET_SH2 || TARGET_SHMEDIA"
9721 "if (TARGET_SHMEDIA)
9722 {
9723 emit_insn (gen_cstore4_media (operands[0], operands[1],
9724 operands[2], operands[3]));
9725 DONE;
9726 }
9727
9728 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
9729 && sh_expand_t_scc (operands))
9730 DONE;
9731
9732 if (! currently_expanding_to_rtl)
9733 FAIL;
9734
9735 sh_emit_compare_and_set (operands, DImode);
9736 DONE;
9737 ")
9738
9739 ;; Move the complement of the T reg to a reg.
9740 ;; On SH2A the movrt insn can be used.
9741 ;; On anything else than SH2A this has to be done with multiple instructions.
9742 ;; One obvious way would be:
9743 ;; cmp/eq ...
9744 ;; movt r0
9745 ;; xor #1,r0
9746 ;;
9747 ;; However, this puts pressure on r0 in most cases and thus the following is
9748 ;; more appealing:
9749 ;; cmp/eq ...
9750 ;; mov #-1,temp
9751 ;; negc temp,dest
9752 ;;
9753 ;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
9754 ;; becomes a one instruction operation. Moreover, care must be taken that
9755 ;; the insn can still be combined with inverted compare and branch code
9756 ;; around it. On the other hand, if a function returns the complement of
9757 ;; a previous comparison result in the T bit, the xor #1,r0 approach might
9758 ;; lead to better code.
9759
9760 (define_expand "movnegt"
9761 [(set (match_operand:SI 0 "arith_reg_dest" "")
9762 (xor:SI (reg:SI T_REG) (const_int 1)))]
9763 ""
9764 {
9765 if (TARGET_SH2A)
9766 emit_insn (gen_movrt (operands[0]));
9767 else
9768 {
9769 rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
9770 emit_insn (gen_movrt_negc (operands[0], val));
9771 }
9772 DONE;
9773 })
9774
9775 (define_insn "movrt_negc"
9776 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9777 (xor:SI (reg:SI T_REG) (const_int 1)))
9778 (set (reg:SI T_REG) (const_int 1))
9779 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
9780 "TARGET_SH1"
9781 "negc %1,%0"
9782 [(set_attr "type" "arith")])
9783
9784 ;; The *negnegt patterns help the combine pass to figure out how to fold
9785 ;; an explicit double T bit negation.
9786 (define_insn_and_split "*negnegt"
9787 [(set (reg:SI T_REG)
9788 (eq:SI (subreg:QI (xor:SI (reg:SI T_REG) (const_int 1)) 3)
9789 (const_int 0)))]
9790 "! TARGET_LITTLE_ENDIAN"
9791 "#"
9792 ""
9793 [(const_int 0)])
9794
9795 (define_insn_and_split "*negnegt"
9796 [(set (reg:SI T_REG)
9797 (eq:SI (subreg:QI (xor:SI (reg:SI T_REG) (const_int 1)) 0)
9798 (const_int 0)))]
9799 "TARGET_LITTLE_ENDIAN"
9800 "#"
9801 ""
9802 [(const_int 0)])
9803
9804 ;; The *movtt patterns improve code at -O1.
9805 (define_insn_and_split "*movtt"
9806 [(set (reg:SI T_REG)
9807 (eq:SI (zero_extend:SI (subreg:QI (reg:SI T_REG) 3))
9808 (const_int 1)))]
9809 "! TARGET_LITTLE_ENDIAN"
9810 "#"
9811 ""
9812 [(const_int 0)])
9813
9814 (define_insn_and_split "*movtt"
9815 [(set (reg:SI T_REG)
9816 (eq:SI (zero_extend:SI (subreg:QI (reg:SI T_REG) 0))
9817 (const_int 1)))]
9818 "TARGET_LITTLE_ENDIAN"
9819 "#"
9820 ""
9821 [(const_int 0)])
9822
9823 ;; The *movt_qi patterns help the combine pass convert a movrt_negc pattern
9824 ;; into a movt Rn, xor #1 Rn pattern. This can happen when e.g. a function
9825 ;; returns the inverted T bit value.
9826 (define_insn "*movt_qi"
9827 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9828 (zero_extend:SI (subreg:QI (reg:SI T_REG) 3)))]
9829 "! TARGET_LITTLE_ENDIAN"
9830 "movt %0"
9831 [(set_attr "type" "arith")])
9832
9833 (define_insn "*movt_qi"
9834 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9835 (zero_extend:SI (subreg:QI (reg:SI T_REG) 0)))]
9836 "TARGET_LITTLE_ENDIAN"
9837 "movt %0"
9838 [(set_attr "type" "arith")])
9839
9840 (define_expand "cstoresf4"
9841 [(set (match_operand:SI 0 "register_operand" "=r")
9842 (match_operator:SI 1 "sh_float_comparison_operator"
9843 [(match_operand:SF 2 "arith_operand" "")
9844 (match_operand:SF 3 "arith_operand" "")]))]
9845 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
9846 "if (TARGET_SHMEDIA)
9847 {
9848 emit_insn (gen_cstore4_media (operands[0], operands[1],
9849 operands[2], operands[3]));
9850 DONE;
9851 }
9852
9853 if (! currently_expanding_to_rtl)
9854 FAIL;
9855
9856 sh_emit_compare_and_set (operands, SFmode);
9857 DONE;
9858 ")
9859
9860 (define_expand "cstoredf4"
9861 [(set (match_operand:SI 0 "register_operand" "=r")
9862 (match_operator:SI 1 "sh_float_comparison_operator"
9863 [(match_operand:DF 2 "arith_operand" "")
9864 (match_operand:DF 3 "arith_operand" "")]))]
9865 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9866 "if (TARGET_SHMEDIA)
9867 {
9868 emit_insn (gen_cstore4_media (operands[0], operands[1],
9869 operands[2], operands[3]));
9870 DONE;
9871 }
9872
9873 if (! currently_expanding_to_rtl)
9874 FAIL;
9875
9876 sh_emit_compare_and_set (operands, DFmode);
9877 DONE;
9878 ")
9879
9880 ;; -------------------------------------------------------------------------
9881 ;; Instructions to cope with inline literal tables
9882 ;; -------------------------------------------------------------------------
9883
9884 ; 2 byte integer in line
9885
9886 (define_insn "consttable_2"
9887 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9888 (match_operand 1 "" "")]
9889 UNSPECV_CONST2)]
9890 ""
9891 "*
9892 {
9893 if (operands[1] != const0_rtx)
9894 assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
9895 return \"\";
9896 }"
9897 [(set_attr "length" "2")
9898 (set_attr "in_delay_slot" "no")])
9899
9900 ; 4 byte integer in line
9901
9902 (define_insn "consttable_4"
9903 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9904 (match_operand 1 "" "")]
9905 UNSPECV_CONST4)]
9906 ""
9907 "*
9908 {
9909 if (operands[1] != const0_rtx)
9910 {
9911 assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
9912 mark_symbol_refs_as_used (operands[0]);
9913 }
9914 return \"\";
9915 }"
9916 [(set_attr "length" "4")
9917 (set_attr "in_delay_slot" "no")])
9918
9919 ; 8 byte integer in line
9920
9921 (define_insn "consttable_8"
9922 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9923 (match_operand 1 "" "")]
9924 UNSPECV_CONST8)]
9925 ""
9926 "*
9927 {
9928 if (operands[1] != const0_rtx)
9929 assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
9930 return \"\";
9931 }"
9932 [(set_attr "length" "8")
9933 (set_attr "in_delay_slot" "no")])
9934
9935 ; 4 byte floating point
9936
9937 (define_insn "consttable_sf"
9938 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
9939 (match_operand 1 "" "")]
9940 UNSPECV_CONST4)]
9941 ""
9942 "*
9943 {
9944 if (operands[1] != const0_rtx)
9945 {
9946 REAL_VALUE_TYPE d;
9947 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9948 assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
9949 }
9950 return \"\";
9951 }"
9952 [(set_attr "length" "4")
9953 (set_attr "in_delay_slot" "no")])
9954
9955 ; 8 byte floating point
9956
9957 (define_insn "consttable_df"
9958 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
9959 (match_operand 1 "" "")]
9960 UNSPECV_CONST8)]
9961 ""
9962 "*
9963 {
9964 if (operands[1] != const0_rtx)
9965 {
9966 REAL_VALUE_TYPE d;
9967 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9968 assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
9969 }
9970 return \"\";
9971 }"
9972 [(set_attr "length" "8")
9973 (set_attr "in_delay_slot" "no")])
9974
9975 ;; Alignment is needed for some constant tables; it may also be added for
9976 ;; Instructions at the start of loops, or after unconditional branches.
9977 ;; ??? We would get more accurate lengths if we did instruction
9978 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
9979 ;; here is too conservative.
9980
9981 ; align to a two byte boundary
9982
9983 (define_expand "align_2"
9984 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
9985 ""
9986 "")
9987
9988 ; align to a four byte boundary
9989 ;; align_4 and align_log are instructions for the starts of loops, or
9990 ;; after unconditional branches, which may take up extra room.
9991
9992 (define_expand "align_4"
9993 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
9994 ""
9995 "")
9996
9997 ; align to a cache line boundary
9998
9999 (define_insn "align_log"
10000 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
10001 ""
10002 ""
10003 [(set_attr "length" "0")
10004 (set_attr "in_delay_slot" "no")])
10005
10006 ; emitted at the end of the literal table, used to emit the
10007 ; 32bit branch labels if needed.
10008
10009 (define_insn "consttable_end"
10010 [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
10011 ""
10012 "* return output_jump_label_table ();"
10013 [(set_attr "in_delay_slot" "no")])
10014
10015 ; emitted at the end of the window in the literal table.
10016
10017 (define_insn "consttable_window_end"
10018 [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
10019 ""
10020 ""
10021 [(set_attr "length" "0")
10022 (set_attr "in_delay_slot" "no")])
10023
10024 ;; -------------------------------------------------------------------------
10025 ;; Misc
10026 ;; -------------------------------------------------------------------------
10027
10028 ;; String/block move insn.
10029
10030 (define_expand "movmemsi"
10031 [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
10032 (mem:BLK (match_operand:BLK 1 "" "")))
10033 (use (match_operand:SI 2 "nonmemory_operand" ""))
10034 (use (match_operand:SI 3 "immediate_operand" ""))
10035 (clobber (reg:SI PR_REG))
10036 (clobber (reg:SI R4_REG))
10037 (clobber (reg:SI R5_REG))
10038 (clobber (reg:SI R0_REG))])]
10039 "TARGET_SH1 && ! TARGET_SH5"
10040 "
10041 {
10042 if(expand_block_move (operands))
10043 DONE;
10044 else FAIL;
10045 }")
10046
10047 (define_insn "block_move_real"
10048 [(parallel [(set (mem:BLK (reg:SI R4_REG))
10049 (mem:BLK (reg:SI R5_REG)))
10050 (use (match_operand:SI 0 "arith_reg_operand" "r"))
10051 (clobber (reg:SI PR_REG))
10052 (clobber (reg:SI R0_REG))])]
10053 "TARGET_SH1 && ! TARGET_HARD_SH4"
10054 "jsr @%0%#"
10055 [(set_attr "type" "sfunc")
10056 (set_attr "needs_delay_slot" "yes")])
10057
10058 (define_insn "block_lump_real"
10059 [(parallel [(set (mem:BLK (reg:SI R4_REG))
10060 (mem:BLK (reg:SI R5_REG)))
10061 (use (match_operand:SI 0 "arith_reg_operand" "r"))
10062 (use (reg:SI R6_REG))
10063 (clobber (reg:SI PR_REG))
10064 (clobber (reg:SI T_REG))
10065 (clobber (reg:SI R4_REG))
10066 (clobber (reg:SI R5_REG))
10067 (clobber (reg:SI R6_REG))
10068 (clobber (reg:SI R0_REG))])]
10069 "TARGET_SH1 && ! TARGET_HARD_SH4"
10070 "jsr @%0%#"
10071 [(set_attr "type" "sfunc")
10072 (set_attr "needs_delay_slot" "yes")])
10073
10074 (define_insn "block_move_real_i4"
10075 [(parallel [(set (mem:BLK (reg:SI R4_REG))
10076 (mem:BLK (reg:SI R5_REG)))
10077 (use (match_operand:SI 0 "arith_reg_operand" "r"))
10078 (clobber (reg:SI PR_REG))
10079 (clobber (reg:SI R0_REG))
10080 (clobber (reg:SI R1_REG))
10081 (clobber (reg:SI R2_REG))])]
10082 "TARGET_HARD_SH4"
10083 "jsr @%0%#"
10084 [(set_attr "type" "sfunc")
10085 (set_attr "needs_delay_slot" "yes")])
10086
10087 (define_insn "block_lump_real_i4"
10088 [(parallel [(set (mem:BLK (reg:SI R4_REG))
10089 (mem:BLK (reg:SI R5_REG)))
10090 (use (match_operand:SI 0 "arith_reg_operand" "r"))
10091 (use (reg:SI R6_REG))
10092 (clobber (reg:SI PR_REG))
10093 (clobber (reg:SI T_REG))
10094 (clobber (reg:SI R4_REG))
10095 (clobber (reg:SI R5_REG))
10096 (clobber (reg:SI R6_REG))
10097 (clobber (reg:SI R0_REG))
10098 (clobber (reg:SI R1_REG))
10099 (clobber (reg:SI R2_REG))
10100 (clobber (reg:SI R3_REG))])]
10101 "TARGET_HARD_SH4"
10102 "jsr @%0%#"
10103 [(set_attr "type" "sfunc")
10104 (set_attr "needs_delay_slot" "yes")])
10105 \f
10106 ;; -------------------------------------------------------------------------
10107 ;; Floating point instructions.
10108 ;; -------------------------------------------------------------------------
10109
10110 ;; ??? All patterns should have a type attribute.
10111
10112 (define_expand "movpsi"
10113 [(set (match_operand:PSI 0 "register_operand" "")
10114 (match_operand:PSI 1 "general_movsrc_operand" ""))]
10115 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10116 "")
10117
10118 ;; The c / m alternative is a fake to guide reload to load directly into
10119 ;; fpscr, since reload doesn't know how to use post-increment.
10120 ;; TARGET_LEGITIMATE_ADDRESS_P guards about bogus addresses before reload,
10121 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
10122 ;; predicate after reload.
10123 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
10124 ;; like a mac -> gpr move.
10125 (define_insn "fpu_switch"
10126 [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
10127 (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
10128 "TARGET_SH2E
10129 && (! reload_completed
10130 || true_regnum (operands[0]) != FPSCR_REG
10131 || !MEM_P (operands[1])
10132 || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
10133 "@
10134 ! precision stays the same
10135 lds.l %1,fpscr
10136 mov.l %1,%0
10137 #
10138 lds %1,fpscr
10139 mov %1,%0
10140 mov.l %1,%0
10141 sts fpscr,%0
10142 sts.l fpscr,%0"
10143 [(set_attr "length" "0,2,2,4,2,2,2,2,2")
10144 (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,fstore")])
10145
10146 (define_peephole2
10147 [(set (reg:PSI FPSCR_REG)
10148 (mem:PSI (match_operand:SI 0 "register_operand" "")))]
10149 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
10150 [(const_int 0)]
10151 {
10152 rtx fpscr, mem, new_insn;
10153
10154 fpscr = SET_DEST (PATTERN (curr_insn));
10155 mem = SET_SRC (PATTERN (curr_insn));
10156 mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
10157
10158 new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
10159 add_reg_note (new_insn, REG_INC, operands[0]);
10160 DONE;
10161 })
10162
10163 (define_split
10164 [(set (reg:PSI FPSCR_REG)
10165 (mem:PSI (match_operand:SI 0 "register_operand" "")))]
10166 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
10167 && (flag_peephole2 ? epilogue_completed : reload_completed)"
10168 [(const_int 0)]
10169 {
10170 rtx fpscr, mem, new_insn;
10171
10172 fpscr = SET_DEST (PATTERN (curr_insn));
10173 mem = SET_SRC (PATTERN (curr_insn));
10174 mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
10175
10176 new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
10177 add_reg_note (new_insn, REG_INC, operands[0]);
10178
10179 if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
10180 emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
10181 DONE;
10182 })
10183
10184 ;; ??? This uses the fp unit, but has no type indicating that.
10185 ;; If we did that, this would either give a bogus latency or introduce
10186 ;; a bogus FIFO constraint.
10187 ;; Since this insn is currently only used for prologues/epilogues,
10188 ;; it is probably best to claim no function unit, which matches the
10189 ;; current setting.
10190 (define_insn "toggle_sz"
10191 [(set (reg:PSI FPSCR_REG)
10192 (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
10193 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10194 "fschg"
10195 [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
10196
10197 ;; There's no way we can use it today, since optimize mode switching
10198 ;; doesn't enable us to know from which mode we're switching to the
10199 ;; mode it requests, to tell whether we can use a relative mode switch
10200 ;; (like toggle_pr) or an absolute switch (like loading fpscr from
10201 ;; memory).
10202 (define_insn "toggle_pr"
10203 [(set (reg:PSI FPSCR_REG)
10204 (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
10205 "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
10206 "fpchg"
10207 [(set_attr "type" "fpscr_toggle")])
10208
10209 (define_expand "addsf3"
10210 [(set (match_operand:SF 0 "arith_reg_operand" "")
10211 (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
10212 (match_operand:SF 2 "arith_reg_operand" "")))]
10213 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10214 "
10215 {
10216 if (TARGET_SH2E)
10217 {
10218 expand_sf_binop (&gen_addsf3_i, operands);
10219 DONE;
10220 }
10221 }")
10222
10223 (define_insn "*addsf3_media"
10224 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10225 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10226 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10227 "TARGET_SHMEDIA_FPU"
10228 "fadd.s %1, %2, %0"
10229 [(set_attr "type" "fparith_media")])
10230
10231 (define_insn_and_split "unary_sf_op"
10232 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10233 (vec_select:V2SF
10234 (vec_concat:V2SF
10235 (vec_select:SF
10236 (match_dup 0)
10237 (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
10238 (match_operator:SF 2 "unary_float_operator"
10239 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10240 (parallel [(match_operand 4
10241 "const_int_operand" "n")]))]))
10242 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
10243 "TARGET_SHMEDIA_FPU"
10244 "#"
10245 "TARGET_SHMEDIA_FPU && reload_completed"
10246 [(set (match_dup 5) (match_dup 6))]
10247 "
10248 {
10249 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10250 rtx op1 = gen_rtx_REG (SFmode,
10251 (true_regnum (operands[1])
10252 + (INTVAL (operands[4]) ^ endian)));
10253
10254 operands[7] = gen_rtx_REG (SFmode,
10255 (true_regnum (operands[0])
10256 + (INTVAL (operands[3]) ^ endian)));
10257 operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
10258 }"
10259 [(set_attr "type" "fparith_media")])
10260
10261 (define_insn_and_split "binary_sf_op0"
10262 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10263 (vec_concat:V2SF
10264 (match_operator:SF 3 "binary_float_operator"
10265 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10266 (parallel [(const_int 0)]))
10267 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
10268 (parallel [(const_int 0)]))])
10269 (vec_select:SF
10270 (match_dup 0)
10271 (parallel [(const_int 1)]))))]
10272 "TARGET_SHMEDIA_FPU"
10273 "#"
10274 "&& reload_completed"
10275 [(set (match_dup 4) (match_dup 5))]
10276 "
10277 {
10278 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10279 rtx op1 = gen_rtx_REG (SFmode,
10280 true_regnum (operands[1]) + endian);
10281 rtx op2 = gen_rtx_REG (SFmode,
10282 true_regnum (operands[2]) + endian);
10283
10284 operands[4] = gen_rtx_REG (SFmode,
10285 true_regnum (operands[0]) + endian);
10286 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
10287 }"
10288 [(set_attr "type" "fparith_media")])
10289
10290 (define_insn_and_split "binary_sf_op1"
10291 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10292 (vec_concat:V2SF
10293 (vec_select:SF
10294 (match_dup 0)
10295 (parallel [(const_int 0)]))
10296 (match_operator:SF 3 "binary_float_operator"
10297 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10298 (parallel [(const_int 1)]))
10299 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
10300 (parallel [(const_int 1)]))])))]
10301 "TARGET_SHMEDIA_FPU"
10302 "#"
10303 "&& reload_completed"
10304 [(set (match_dup 4) (match_dup 5))]
10305 "
10306 {
10307 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10308 rtx op1 = gen_rtx_REG (SFmode,
10309 true_regnum (operands[1]) + (1 ^ endian));
10310 rtx op2 = gen_rtx_REG (SFmode,
10311 true_regnum (operands[2]) + (1 ^ endian));
10312
10313 operands[4] = gen_rtx_REG (SFmode,
10314 true_regnum (operands[0]) + (1 ^ endian));
10315 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
10316 }"
10317 [(set_attr "type" "fparith_media")])
10318
10319 (define_insn "addsf3_i"
10320 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10321 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10322 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10323 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10324 "TARGET_SH2E"
10325 "fadd %2,%0"
10326 [(set_attr "type" "fp")
10327 (set_attr "fp_mode" "single")])
10328
10329 (define_expand "subsf3"
10330 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10331 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10332 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
10333 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10334 "
10335 {
10336 if (TARGET_SH2E)
10337 {
10338 expand_sf_binop (&gen_subsf3_i, operands);
10339 DONE;
10340 }
10341 }")
10342
10343 (define_insn "*subsf3_media"
10344 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10345 (minus: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 "fsub.s %1, %2, %0"
10349 [(set_attr "type" "fparith_media")])
10350
10351 (define_insn "subsf3_i"
10352 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10353 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
10354 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10355 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10356 "TARGET_SH2E"
10357 "fsub %2,%0"
10358 [(set_attr "type" "fp")
10359 (set_attr "fp_mode" "single")])
10360
10361 (define_expand "mulsf3"
10362 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10363 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10364 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
10365 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10366 "")
10367
10368 (define_insn "*mulsf3_media"
10369 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10370 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10371 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10372 "TARGET_SHMEDIA_FPU"
10373 "fmul.s %1, %2, %0"
10374 [(set_attr "type" "fparith_media")])
10375
10376 ;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
10377 ;; register in feeding fp instructions. Thus, in order to generate fmac,
10378 ;; we start out with a mulsf pattern that does not depend on fpscr.
10379 ;; This is split after combine to introduce the dependency, in order to
10380 ;; get mode switching and scheduling right.
10381 (define_insn_and_split "mulsf3_ie"
10382 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10383 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10384 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10385 "TARGET_SH2E"
10386 "fmul %2,%0"
10387 "TARGET_SH4 || TARGET_SH2A_SINGLE"
10388 [(const_int 0)]
10389 "
10390 {
10391 emit_insn (gen_mulsf3_i4 (operands[0], operands[1], operands[2],
10392 get_fpscr_rtx ()));
10393 DONE;
10394 }"
10395 [(set_attr "type" "fp")])
10396
10397 (define_insn "mulsf3_i4"
10398 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10399 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10400 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10401 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10402 "TARGET_SH2E"
10403 "fmul %2,%0"
10404 [(set_attr "type" "fp")
10405 (set_attr "fp_mode" "single")])
10406
10407 (define_insn "mac_media"
10408 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10409 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10410 (match_operand:SF 2 "fp_arith_reg_operand" "f"))
10411 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
10412 "TARGET_SHMEDIA_FPU && TARGET_FMAC"
10413 "fmac.s %1, %2, %0"
10414 [(set_attr "type" "fparith_media")])
10415
10416 (define_insn "*macsf3"
10417 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10418 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
10419 (match_operand:SF 2 "fp_arith_reg_operand" "f"))
10420 (match_operand:SF 3 "arith_reg_operand" "0")))
10421 (use (match_operand:PSI 4 "fpscr_operand" "c"))]
10422 "TARGET_SH2E && TARGET_FMAC"
10423 "fmac fr0,%2,%0"
10424 [(set_attr "type" "fp")
10425 (set_attr "fp_mode" "single")])
10426
10427 (define_expand "divsf3"
10428 [(set (match_operand:SF 0 "arith_reg_operand" "")
10429 (div:SF (match_operand:SF 1 "arith_reg_operand" "")
10430 (match_operand:SF 2 "arith_reg_operand" "")))]
10431 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10432 "
10433 {
10434 if (TARGET_SH2E)
10435 {
10436 expand_sf_binop (&gen_divsf3_i, operands);
10437 DONE;
10438 }
10439 }")
10440
10441 (define_insn "*divsf3_media"
10442 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10443 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10444 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10445 "TARGET_SHMEDIA_FPU"
10446 "fdiv.s %1, %2, %0"
10447 [(set_attr "type" "fdiv_media")])
10448
10449 (define_insn "divsf3_i"
10450 [(set (match_operand:SF 0 "arith_reg_dest" "=f")
10451 (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
10452 (match_operand:SF 2 "arith_reg_operand" "f")))
10453 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10454 "TARGET_SH2E"
10455 "fdiv %2,%0"
10456 [(set_attr "type" "fdiv")
10457 (set_attr "fp_mode" "single")])
10458
10459 (define_insn "floatdisf2"
10460 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10461 (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10462 "TARGET_SHMEDIA_FPU"
10463 "float.qs %1, %0"
10464 [(set_attr "type" "fpconv_media")])
10465
10466 (define_expand "floatsisf2"
10467 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10468 (float:SF (match_operand:SI 1 "fpul_operand" "")))]
10469 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10470 "
10471 {
10472 if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10473 {
10474 emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10475 DONE;
10476 }
10477 }")
10478
10479 (define_insn "*floatsisf2_media"
10480 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10481 (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10482 "TARGET_SHMEDIA_FPU"
10483 "float.ls %1, %0"
10484 [(set_attr "type" "fpconv_media")])
10485
10486 (define_insn "floatsisf2_i4"
10487 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10488 (float:SF (match_operand:SI 1 "fpul_operand" "y")))
10489 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10490 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10491 "float %1,%0"
10492 [(set_attr "type" "fp")
10493 (set_attr "fp_mode" "single")])
10494
10495 (define_insn "*floatsisf2_ie"
10496 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10497 (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
10498 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10499 "float %1,%0"
10500 [(set_attr "type" "fp")])
10501
10502 (define_insn "fix_truncsfdi2"
10503 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10504 (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10505 "TARGET_SHMEDIA_FPU"
10506 "ftrc.sq %1, %0"
10507 [(set_attr "type" "fpconv_media")])
10508
10509 (define_expand "fix_truncsfsi2"
10510 [(set (match_operand:SI 0 "fpul_operand" "=y")
10511 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10512 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10513 "
10514 {
10515 if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10516 {
10517 emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10518 DONE;
10519 }
10520 }")
10521
10522 (define_insn "*fix_truncsfsi2_media"
10523 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10524 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10525 "TARGET_SHMEDIA_FPU"
10526 "ftrc.sl %1, %0"
10527 [(set_attr "type" "fpconv_media")])
10528
10529 (define_insn "fix_truncsfsi2_i4"
10530 [(set (match_operand:SI 0 "fpul_operand" "=y")
10531 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10532 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10533 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10534 "ftrc %1,%0"
10535 [(set_attr "type" "ftrc_s")
10536 (set_attr "fp_mode" "single")])
10537
10538 ;; ??? This pattern is used nowhere. fix_truncsfsi2 always expands to
10539 ;; fix_truncsfsi2_i4.
10540 ;; (define_insn "fix_truncsfsi2_i4_2"
10541 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10542 ;; (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10543 ;; (use (reg:PSI FPSCR_REG))
10544 ;; (clobber (reg:SI FPUL_REG))]
10545 ;; "TARGET_SH4"
10546 ;; "#"
10547 ;; [(set_attr "length" "4")
10548 ;; (set_attr "fp_mode" "single")])
10549
10550 ;;(define_split
10551 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10552 ;; (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10553 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
10554 ;; (clobber (reg:SI FPUL_REG))]
10555 ;; "TARGET_SH4"
10556 ;; [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10557 ;; (use (match_dup 2))])
10558 ;; (set (match_dup 0) (reg:SI FPUL_REG))])
10559
10560 (define_insn "*fixsfsi"
10561 [(set (match_operand:SI 0 "fpul_operand" "=y")
10562 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10563 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10564 "ftrc %1,%0"
10565 [(set_attr "type" "fp")])
10566
10567 (define_insn "cmpgtsf_t"
10568 [(set (reg:SI T_REG)
10569 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10570 (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10571 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10572 "fcmp/gt %1,%0"
10573 [(set_attr "type" "fp_cmp")
10574 (set_attr "fp_mode" "single")])
10575
10576 (define_insn "cmpeqsf_t"
10577 [(set (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_SH4 || TARGET_SH2A_SINGLE)"
10581 "fcmp/eq %1,%0"
10582 [(set_attr "type" "fp_cmp")
10583 (set_attr "fp_mode" "single")])
10584
10585 (define_insn "ieee_ccmpeqsf_t"
10586 [(set (reg:SI T_REG)
10587 (ior:SI (reg:SI T_REG)
10588 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10589 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
10590 "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10591 "* return output_ieee_ccmpeq (insn, operands);"
10592 [(set_attr "length" "4")])
10593
10594
10595 (define_insn "cmpgtsf_t_i4"
10596 [(set (reg:SI T_REG)
10597 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10598 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10599 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10600 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10601 "fcmp/gt %1,%0"
10602 [(set_attr "type" "fp_cmp")
10603 (set_attr "fp_mode" "single")])
10604
10605 (define_insn "cmpeqsf_t_i4"
10606 [(set (reg:SI T_REG)
10607 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10608 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10609 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10610 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10611 "fcmp/eq %1,%0"
10612 [(set_attr "type" "fp_cmp")
10613 (set_attr "fp_mode" "single")])
10614
10615 (define_insn "*ieee_ccmpeqsf_t_4"
10616 [(set (reg:SI T_REG)
10617 (ior:SI (reg:SI T_REG)
10618 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10619 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
10620 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10621 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10622 "* return output_ieee_ccmpeq (insn, operands);"
10623 [(set_attr "length" "4")
10624 (set_attr "fp_mode" "single")])
10625
10626 (define_insn "cmpeqsf_media"
10627 [(set (match_operand:SI 0 "register_operand" "=r")
10628 (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10629 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10630 "TARGET_SHMEDIA_FPU"
10631 "fcmpeq.s %1, %2, %0"
10632 [(set_attr "type" "fcmp_media")])
10633
10634 (define_insn "cmpgtsf_media"
10635 [(set (match_operand:SI 0 "register_operand" "=r")
10636 (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10637 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10638 "TARGET_SHMEDIA_FPU"
10639 "fcmpgt.s %1, %2, %0"
10640 [(set_attr "type" "fcmp_media")])
10641
10642 (define_insn "cmpgesf_media"
10643 [(set (match_operand:SI 0 "register_operand" "=r")
10644 (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10645 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10646 "TARGET_SHMEDIA_FPU"
10647 "fcmpge.s %1, %2, %0"
10648 [(set_attr "type" "fcmp_media")])
10649
10650 (define_insn "cmpunsf_media"
10651 [(set (match_operand:SI 0 "register_operand" "=r")
10652 (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10653 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10654 "TARGET_SHMEDIA_FPU"
10655 "fcmpun.s %1, %2, %0"
10656 [(set_attr "type" "fcmp_media")])
10657
10658 (define_expand "cbranchsf4"
10659 [(set (pc)
10660 (if_then_else (match_operator 0 "sh_float_comparison_operator"
10661 [(match_operand:SF 1 "arith_operand" "")
10662 (match_operand:SF 2 "arith_operand" "")])
10663 (match_operand 3 "" "")
10664 (pc)))]
10665 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10666 "
10667 {
10668 if (TARGET_SHMEDIA)
10669 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
10670 operands[3]));
10671 else
10672 sh_emit_compare_and_branch (operands, SFmode);
10673 DONE;
10674 }")
10675
10676 (define_expand "negsf2"
10677 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10678 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10679 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10680 "
10681 {
10682 if (TARGET_SH2E)
10683 {
10684 expand_sf_unop (&gen_negsf2_i, operands);
10685 DONE;
10686 }
10687 }")
10688
10689 (define_insn "*negsf2_media"
10690 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10691 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10692 "TARGET_SHMEDIA_FPU"
10693 "fneg.s %1, %0"
10694 [(set_attr "type" "fmove_media")])
10695
10696 (define_insn "negsf2_i"
10697 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10698 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10699 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10700 "TARGET_SH2E"
10701 "fneg %0"
10702 [(set_attr "type" "fmove")
10703 (set_attr "fp_mode" "single")])
10704
10705 (define_expand "sqrtsf2"
10706 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10707 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10708 "TARGET_SH3E || TARGET_SHMEDIA_FPU"
10709 "
10710 {
10711 if (TARGET_SH3E)
10712 {
10713 expand_sf_unop (&gen_sqrtsf2_i, operands);
10714 DONE;
10715 }
10716 }")
10717
10718 (define_insn "*sqrtsf2_media"
10719 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10720 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10721 "TARGET_SHMEDIA_FPU"
10722 "fsqrt.s %1, %0"
10723 [(set_attr "type" "fdiv_media")])
10724
10725 (define_insn "sqrtsf2_i"
10726 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10727 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10728 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10729 "TARGET_SH3E"
10730 "fsqrt %0"
10731 [(set_attr "type" "fdiv")
10732 (set_attr "fp_mode" "single")])
10733
10734 (define_insn "rsqrtsf2"
10735 [(set (match_operand:SF 0 "register_operand" "=f")
10736 (div:SF (match_operand:SF 1 "immediate_operand" "i")
10737 (sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
10738 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10739 "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10740 && operands[1] == CONST1_RTX (SFmode)"
10741 "fsrra %0"
10742 [(set_attr "type" "fsrra")
10743 (set_attr "fp_mode" "single")])
10744
10745 (define_insn "fsca"
10746 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10747 (vec_concat:V2SF
10748 (unspec:SF [(mult:SF
10749 (float:SF (match_operand:SI 1 "fpul_operand" "y"))
10750 (match_operand:SF 2 "immediate_operand" "i"))
10751 ] UNSPEC_FSINA)
10752 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
10753 ] UNSPEC_FCOSA)))
10754 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10755 "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10756 && operands[2] == sh_fsca_int2sf ()"
10757 "fsca fpul,%d0"
10758 [(set_attr "type" "fsca")
10759 (set_attr "fp_mode" "single")])
10760
10761 (define_expand "sinsf2"
10762 [(set (match_operand:SF 0 "nonimmediate_operand" "")
10763 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10764 UNSPEC_FSINA))]
10765 "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10766 "
10767 {
10768 rtx scaled = gen_reg_rtx (SFmode);
10769 rtx truncated = gen_reg_rtx (SImode);
10770 rtx fsca = gen_reg_rtx (V2SFmode);
10771 rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10772
10773 emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10774 emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10775 emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10776 get_fpscr_rtx ()));
10777 emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 0));
10778 DONE;
10779 }")
10780
10781 (define_expand "cossf2"
10782 [(set (match_operand:SF 0 "nonimmediate_operand" "")
10783 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10784 UNSPEC_FCOSA))]
10785 "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10786 "
10787 {
10788 rtx scaled = gen_reg_rtx (SFmode);
10789 rtx truncated = gen_reg_rtx (SImode);
10790 rtx fsca = gen_reg_rtx (V2SFmode);
10791 rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10792
10793 emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10794 emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10795 emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10796 get_fpscr_rtx ()));
10797 emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
10798 DONE;
10799 }")
10800
10801 (define_expand "sindf2"
10802 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10803 (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10804 UNSPEC_FSINA))]
10805 "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10806 "
10807 {
10808 rtx scaled = gen_reg_rtx (DFmode);
10809 rtx truncated = gen_reg_rtx (SImode);
10810 rtx fsca = gen_reg_rtx (V2SFmode);
10811 rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10812 rtx sfresult = gen_reg_rtx (SFmode);
10813
10814 emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10815 emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10816 emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10817 get_fpscr_rtx ()));
10818 emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 0));
10819 emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10820 DONE;
10821 }")
10822
10823 (define_expand "cosdf2"
10824 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10825 (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10826 UNSPEC_FCOSA))]
10827 "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10828 "
10829 {
10830 rtx scaled = gen_reg_rtx (DFmode);
10831 rtx truncated = gen_reg_rtx (SImode);
10832 rtx fsca = gen_reg_rtx (V2SFmode);
10833 rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10834 rtx sfresult = gen_reg_rtx (SFmode);
10835
10836 emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10837 emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10838 emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10839 get_fpscr_rtx ()));
10840 emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 4));
10841 emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10842 DONE;
10843 }")
10844
10845 (define_expand "abssf2"
10846 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10847 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10848 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10849 "
10850 {
10851 if (TARGET_SH2E)
10852 {
10853 expand_sf_unop (&gen_abssf2_i, operands);
10854 DONE;
10855 }
10856 }")
10857
10858 (define_insn "*abssf2_media"
10859 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10860 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10861 "TARGET_SHMEDIA_FPU"
10862 "fabs.s %1, %0"
10863 [(set_attr "type" "fmove_media")])
10864
10865 (define_insn "abssf2_i"
10866 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10867 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10868 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10869 "TARGET_SH2E"
10870 "fabs %0"
10871 [(set_attr "type" "fmove")
10872 (set_attr "fp_mode" "single")])
10873
10874 (define_expand "adddf3"
10875 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10876 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10877 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10878 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10879 "
10880 {
10881 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10882 {
10883 expand_df_binop (&gen_adddf3_i, operands);
10884 DONE;
10885 }
10886 }")
10887
10888 (define_insn "*adddf3_media"
10889 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10890 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10891 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10892 "TARGET_SHMEDIA_FPU"
10893 "fadd.d %1, %2, %0"
10894 [(set_attr "type" "dfparith_media")])
10895
10896 (define_insn "adddf3_i"
10897 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10898 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10899 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10900 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10901 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10902 "fadd %2,%0"
10903 [(set_attr "type" "dfp_arith")
10904 (set_attr "fp_mode" "double")])
10905
10906 (define_expand "subdf3"
10907 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10908 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10909 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10910 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10911 "
10912 {
10913 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10914 {
10915 expand_df_binop (&gen_subdf3_i, operands);
10916 DONE;
10917 }
10918 }")
10919
10920 (define_insn "*subdf3_media"
10921 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10922 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10923 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10924 "TARGET_SHMEDIA_FPU"
10925 "fsub.d %1, %2, %0"
10926 [(set_attr "type" "dfparith_media")])
10927
10928 (define_insn "subdf3_i"
10929 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10930 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10931 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10932 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10933 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10934 "fsub %2,%0"
10935 [(set_attr "type" "dfp_arith")
10936 (set_attr "fp_mode" "double")])
10937
10938 (define_expand "muldf3"
10939 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10940 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10941 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10942 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10943 "
10944 {
10945 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10946 {
10947 expand_df_binop (&gen_muldf3_i, operands);
10948 DONE;
10949 }
10950 }")
10951
10952 (define_insn "*muldf3_media"
10953 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10954 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10955 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10956 "TARGET_SHMEDIA_FPU"
10957 "fmul.d %1, %2, %0"
10958 [(set_attr "type" "dfmul_media")])
10959
10960 (define_insn "muldf3_i"
10961 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10962 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10963 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10964 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10965 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10966 "fmul %2,%0"
10967 [(set_attr "type" "dfp_mul")
10968 (set_attr "fp_mode" "double")])
10969
10970 (define_expand "divdf3"
10971 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10972 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10973 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10974 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10975 "
10976 {
10977 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10978 {
10979 expand_df_binop (&gen_divdf3_i, operands);
10980 DONE;
10981 }
10982 }")
10983
10984 (define_insn "*divdf3_media"
10985 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10986 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10987 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10988 "TARGET_SHMEDIA_FPU"
10989 "fdiv.d %1, %2, %0"
10990 [(set_attr "type" "dfdiv_media")])
10991
10992 (define_insn "divdf3_i"
10993 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10994 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10995 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10996 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10997 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10998 "fdiv %2,%0"
10999 [(set_attr "type" "dfdiv")
11000 (set_attr "fp_mode" "double")])
11001
11002 (define_insn "floatdidf2"
11003 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11004 (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
11005 "TARGET_SHMEDIA_FPU"
11006 "float.qd %1, %0"
11007 [(set_attr "type" "dfpconv_media")])
11008
11009 (define_expand "floatsidf2"
11010 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
11011 (float:DF (match_operand:SI 1 "fpul_operand" "")))]
11012 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11013 "
11014 {
11015 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11016 {
11017 emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
11018 get_fpscr_rtx ()));
11019 DONE;
11020 }
11021 }")
11022
11023 (define_insn "*floatsidf2_media"
11024 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11025 (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
11026 "TARGET_SHMEDIA_FPU"
11027 "float.ld %1, %0"
11028 [(set_attr "type" "dfpconv_media")])
11029
11030 (define_insn "floatsidf2_i"
11031 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11032 (float:DF (match_operand:SI 1 "fpul_operand" "y")))
11033 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11034 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11035 "float %1,%0"
11036 [(set_attr "type" "dfp_conv")
11037 (set_attr "fp_mode" "double")])
11038
11039 (define_insn "fix_truncdfdi2"
11040 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
11041 (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11042 "TARGET_SHMEDIA_FPU"
11043 "ftrc.dq %1, %0"
11044 [(set_attr "type" "dfpconv_media")])
11045
11046 (define_expand "fix_truncdfsi2"
11047 [(set (match_operand:SI 0 "fpul_operand" "")
11048 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
11049 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11050 "
11051 {
11052 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11053 {
11054 emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
11055 get_fpscr_rtx ()));
11056 DONE;
11057 }
11058 }")
11059
11060 (define_insn "*fix_truncdfsi2_media"
11061 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
11062 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11063 "TARGET_SHMEDIA_FPU"
11064 "ftrc.dl %1, %0"
11065 [(set_attr "type" "dfpconv_media")])
11066
11067 (define_insn "fix_truncdfsi2_i"
11068 [(set (match_operand:SI 0 "fpul_operand" "=y")
11069 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
11070 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11071 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11072 "ftrc %1,%0"
11073 [(set_attr "type" "dfp_conv")
11074 (set_attr "dfp_comp" "no")
11075 (set_attr "fp_mode" "double")])
11076
11077 ;; ??? This pattern is used nowhere. fix_truncdfsi2 always expands to
11078 ;; fix_truncdfsi2_i.
11079 ;; (define_insn "fix_truncdfsi2_i4"
11080 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11081 ;; (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
11082 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
11083 ;; (clobber (reg:SI FPUL_REG))]
11084 ;; "TARGET_SH4"
11085 ;; "#"
11086 ;; [(set_attr "length" "4")
11087 ;; (set_attr "fp_mode" "double")])
11088 ;;
11089 ;; (define_split
11090 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11091 ;; (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
11092 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
11093 ;; (clobber (reg:SI FPUL_REG))]
11094 ;; "TARGET_SH4"
11095 ;; [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
11096 ;; (use (match_dup 2))])
11097 ;; (set (match_dup 0) (reg:SI FPUL_REG))])
11098
11099 (define_insn "cmpgtdf_t"
11100 [(set (reg:SI T_REG)
11101 (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
11102 (match_operand:DF 1 "arith_reg_operand" "f")))
11103 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11104 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11105 "fcmp/gt %1,%0"
11106 [(set_attr "type" "dfp_cmp")
11107 (set_attr "fp_mode" "double")])
11108
11109 (define_insn "cmpeqdf_t"
11110 [(set (reg:SI T_REG)
11111 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
11112 (match_operand:DF 1 "arith_reg_operand" "f")))
11113 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11114 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11115 "fcmp/eq %1,%0"
11116 [(set_attr "type" "dfp_cmp")
11117 (set_attr "fp_mode" "double")])
11118
11119 (define_insn "*ieee_ccmpeqdf_t"
11120 [(set (reg:SI T_REG)
11121 (ior:SI (reg:SI T_REG)
11122 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
11123 (match_operand:DF 1 "arith_reg_operand" "f"))))
11124 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11125 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11126 "* return output_ieee_ccmpeq (insn, operands);"
11127 [(set_attr "length" "4")
11128 (set_attr "fp_mode" "double")])
11129
11130 (define_insn "cmpeqdf_media"
11131 [(set (match_operand:SI 0 "register_operand" "=r")
11132 (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
11133 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11134 "TARGET_SHMEDIA_FPU"
11135 "fcmpeq.d %1,%2,%0"
11136 [(set_attr "type" "fcmp_media")])
11137
11138 (define_insn "cmpgtdf_media"
11139 [(set (match_operand:SI 0 "register_operand" "=r")
11140 (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
11141 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11142 "TARGET_SHMEDIA_FPU"
11143 "fcmpgt.d %1,%2,%0"
11144 [(set_attr "type" "fcmp_media")])
11145
11146 (define_insn "cmpgedf_media"
11147 [(set (match_operand:SI 0 "register_operand" "=r")
11148 (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
11149 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11150 "TARGET_SHMEDIA_FPU"
11151 "fcmpge.d %1,%2,%0"
11152 [(set_attr "type" "fcmp_media")])
11153
11154 (define_insn "cmpundf_media"
11155 [(set (match_operand:SI 0 "register_operand" "=r")
11156 (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
11157 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11158 "TARGET_SHMEDIA_FPU"
11159 "fcmpun.d %1,%2,%0"
11160 [(set_attr "type" "fcmp_media")])
11161
11162 (define_expand "cbranchdf4"
11163 [(set (pc)
11164 (if_then_else (match_operator 0 "sh_float_comparison_operator"
11165 [(match_operand:DF 1 "arith_operand" "")
11166 (match_operand:DF 2 "arith_operand" "")])
11167 (match_operand 3 "" "")
11168 (pc)))]
11169 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11170 "
11171 {
11172 if (TARGET_SHMEDIA)
11173 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
11174 operands[3]));
11175 else
11176 sh_emit_compare_and_branch (operands, DFmode);
11177 DONE;
11178 }")
11179
11180
11181 (define_expand "negdf2"
11182 [(set (match_operand:DF 0 "arith_reg_operand" "")
11183 (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
11184 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11185 "
11186 {
11187 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11188 {
11189 expand_df_unop (&gen_negdf2_i, operands);
11190 DONE;
11191 }
11192 }")
11193
11194 (define_insn "*negdf2_media"
11195 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11196 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11197 "TARGET_SHMEDIA_FPU"
11198 "fneg.d %1, %0"
11199 [(set_attr "type" "fmove_media")])
11200
11201 (define_insn "negdf2_i"
11202 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11203 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11204 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11205 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11206 "fneg %0"
11207 [(set_attr "type" "fmove")
11208 (set_attr "fp_mode" "double")])
11209
11210 (define_expand "sqrtdf2"
11211 [(set (match_operand:DF 0 "arith_reg_operand" "")
11212 (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
11213 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11214 "
11215 {
11216 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11217 {
11218 expand_df_unop (&gen_sqrtdf2_i, operands);
11219 DONE;
11220 }
11221 }")
11222
11223 (define_insn "*sqrtdf2_media"
11224 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11225 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11226 "TARGET_SHMEDIA_FPU"
11227 "fsqrt.d %1, %0"
11228 [(set_attr "type" "dfdiv_media")])
11229
11230 (define_insn "sqrtdf2_i"
11231 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11232 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11233 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11234 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11235 "fsqrt %0"
11236 [(set_attr "type" "dfdiv")
11237 (set_attr "fp_mode" "double")])
11238
11239 (define_expand "absdf2"
11240 [(set (match_operand:DF 0 "arith_reg_operand" "")
11241 (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
11242 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11243 "
11244 {
11245 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11246 {
11247 expand_df_unop (&gen_absdf2_i, operands);
11248 DONE;
11249 }
11250 }")
11251
11252 (define_insn "*absdf2_media"
11253 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11254 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11255 "TARGET_SHMEDIA_FPU"
11256 "fabs.d %1, %0"
11257 [(set_attr "type" "fmove_media")])
11258
11259 (define_insn "absdf2_i"
11260 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11261 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11262 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11263 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11264 "fabs %0"
11265 [(set_attr "type" "fmove")
11266 (set_attr "fp_mode" "double")])
11267
11268 (define_expand "extendsfdf2"
11269 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
11270 (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
11271 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11272 "
11273 {
11274 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11275 {
11276 emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
11277 get_fpscr_rtx ()));
11278 DONE;
11279 }
11280 }")
11281
11282 (define_insn "*extendsfdf2_media"
11283 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11284 (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
11285 "TARGET_SHMEDIA_FPU"
11286 "fcnv.sd %1, %0"
11287 [(set_attr "type" "dfpconv_media")])
11288
11289 (define_insn "extendsfdf2_i4"
11290 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11291 (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
11292 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11293 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11294 "fcnvsd %1,%0"
11295 [(set_attr "type" "fp")
11296 (set_attr "fp_mode" "double")])
11297
11298 (define_expand "truncdfsf2"
11299 [(set (match_operand:SF 0 "fpul_operand" "")
11300 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
11301 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11302 "
11303 {
11304 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11305 {
11306 emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
11307 get_fpscr_rtx ()));
11308 DONE;
11309 }
11310 }")
11311
11312 (define_insn "*truncdfsf2_media"
11313 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11314 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11315 "TARGET_SHMEDIA_FPU"
11316 "fcnv.ds %1, %0"
11317 [(set_attr "type" "dfpconv_media")])
11318
11319 (define_insn "truncdfsf2_i4"
11320 [(set (match_operand:SF 0 "fpul_operand" "=y")
11321 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
11322 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11323 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11324 "fcnvds %1,%0"
11325 [(set_attr "type" "fp")
11326 (set_attr "fp_mode" "double")])
11327 \f
11328 ;; Bit field extract patterns. These give better code for packed bitfields,
11329 ;; because they allow auto-increment addresses to be generated.
11330
11331 (define_expand "insv"
11332 [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
11333 (match_operand:SI 1 "immediate_operand" "")
11334 (match_operand:SI 2 "immediate_operand" ""))
11335 (match_operand:SI 3 "general_operand" ""))]
11336 "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
11337 "
11338 {
11339 rtx addr_target, orig_address, shift_reg, qi_val;
11340 HOST_WIDE_INT bitsize, size, v = 0;
11341 rtx x = operands[3];
11342
11343 if (TARGET_SH2A && TARGET_BITOPS
11344 && (satisfies_constraint_Sbw (operands[0])
11345 || satisfies_constraint_Sbv (operands[0]))
11346 && satisfies_constraint_M (operands[1])
11347 && satisfies_constraint_K03 (operands[2]))
11348 {
11349 if (satisfies_constraint_N (operands[3]))
11350 {
11351 emit_insn (gen_bclr_m2a (operands[0], operands[2]));
11352 DONE;
11353 }
11354 else if (satisfies_constraint_M (operands[3]))
11355 {
11356 emit_insn (gen_bset_m2a (operands[0], operands[2]));
11357 DONE;
11358 }
11359 else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
11360 && satisfies_constraint_M (operands[1]))
11361 {
11362 emit_insn (gen_bst_m2a (operands[0], operands[2]));
11363 DONE;
11364 }
11365 else if (REG_P (operands[3])
11366 && satisfies_constraint_M (operands[1]))
11367 {
11368 emit_insn (gen_bld_reg (operands[3], const0_rtx));
11369 emit_insn (gen_bst_m2a (operands[0], operands[2]));
11370 DONE;
11371 }
11372 }
11373 /* ??? expmed doesn't care for non-register predicates. */
11374 if (! memory_operand (operands[0], VOIDmode)
11375 || ! immediate_operand (operands[1], VOIDmode)
11376 || ! immediate_operand (operands[2], VOIDmode)
11377 || ! general_operand (x, VOIDmode))
11378 FAIL;
11379 /* If this isn't a 16 / 24 / 32 bit field, or if
11380 it doesn't start on a byte boundary, then fail. */
11381 bitsize = INTVAL (operands[1]);
11382 if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
11383 || (INTVAL (operands[2]) % 8) != 0)
11384 FAIL;
11385
11386 size = bitsize / 8;
11387 orig_address = XEXP (operands[0], 0);
11388 shift_reg = gen_reg_rtx (SImode);
11389 if (CONST_INT_P (x))
11390 {
11391 v = INTVAL (x);
11392 qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
11393 }
11394 else
11395 {
11396 emit_insn (gen_movsi (shift_reg, operands[3]));
11397 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11398 }
11399 addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1));
11400
11401 operands[0] = replace_equiv_address (operands[0], addr_target);
11402 emit_insn (gen_movqi (operands[0], qi_val));
11403
11404 while (size -= 1)
11405 {
11406 if (CONST_INT_P (x))
11407 qi_val
11408 = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
11409 else
11410 {
11411 emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
11412 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11413 }
11414 emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
11415 emit_insn (gen_movqi (operands[0], qi_val));
11416 }
11417
11418 DONE;
11419 }")
11420
11421 (define_insn "movua"
11422 [(set (match_operand:SI 0 "register_operand" "=z")
11423 (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
11424 UNSPEC_MOVUA))]
11425 "TARGET_SH4A_ARCH"
11426 "movua.l %1,%0"
11427 [(set_attr "type" "movua")])
11428
11429 ;; We shouldn't need this, but cse replaces increments with references
11430 ;; to other regs before flow has a chance to create post_inc
11431 ;; addressing modes, and only postreload's cse_move2add brings the
11432 ;; increments back to a usable form.
11433 (define_peephole2
11434 [(set (match_operand:SI 0 "register_operand" "")
11435 (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
11436 (const_int 32) (const_int 0)))
11437 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11438 "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
11439 [(set (match_operand:SI 0 "register_operand" "")
11440 (sign_extract:SI (mem:SI (post_inc:SI
11441 (match_operand:SI 1 "register_operand" "")))
11442 (const_int 32) (const_int 0)))]
11443 "")
11444
11445 (define_expand "extv"
11446 [(set (match_operand:SI 0 "register_operand" "")
11447 (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11448 (match_operand 2 "const_int_operand" "")
11449 (match_operand 3 "const_int_operand" "")))]
11450 "TARGET_SH4A_ARCH || TARGET_SH2A"
11451 {
11452 if (TARGET_SH2A && TARGET_BITOPS
11453 && (satisfies_constraint_Sbw (operands[1])
11454 || satisfies_constraint_Sbv (operands[1]))
11455 && satisfies_constraint_M (operands[2])
11456 && satisfies_constraint_K03 (operands[3]))
11457 {
11458 emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
11459 if (REGNO (operands[0]) != T_REG)
11460 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
11461 DONE;
11462 }
11463 if (TARGET_SH4A_ARCH
11464 && INTVAL (operands[2]) == 32
11465 && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11466 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
11467 {
11468 rtx src = adjust_address (operands[1], BLKmode, 0);
11469 set_mem_size (src, 4);
11470 emit_insn (gen_movua (operands[0], src));
11471 DONE;
11472 }
11473
11474 FAIL;
11475 })
11476
11477 (define_expand "extzv"
11478 [(set (match_operand:SI 0 "register_operand" "")
11479 (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11480 (match_operand 2 "const_int_operand" "")
11481 (match_operand 3 "const_int_operand" "")))]
11482 "TARGET_SH4A_ARCH || TARGET_SH2A"
11483 {
11484 if (TARGET_SH2A && TARGET_BITOPS
11485 && (satisfies_constraint_Sbw (operands[1])
11486 || satisfies_constraint_Sbv (operands[1]))
11487 && satisfies_constraint_M (operands[2])
11488 && satisfies_constraint_K03 (operands[3]))
11489 {
11490 emit_insn (gen_bld_m2a (operands[1], operands[3]));
11491 if (REGNO (operands[0]) != T_REG)
11492 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
11493 DONE;
11494 }
11495 if (TARGET_SH4A_ARCH
11496 && INTVAL (operands[2]) == 32
11497 && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11498 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
11499 {
11500 rtx src = adjust_address (operands[1], BLKmode, 0);
11501 set_mem_size (src, 4);
11502 emit_insn (gen_movua (operands[0], src));
11503 DONE;
11504 }
11505
11506 FAIL;
11507 })
11508
11509 ;; SH2A instructions for bitwise operations.
11510
11511 ;; Clear a bit in a memory location.
11512 (define_insn "bclr_m2a"
11513 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11514 (and:QI
11515 (not:QI (ashift:QI (const_int 1)
11516 (match_operand:QI 1 "const_int_operand" "K03,K03")))
11517 (match_dup 0)))]
11518 "TARGET_SH2A && TARGET_BITOPS"
11519 "@
11520 bclr.b\\t%1,%0
11521 bclr.b\\t%1,@(0,%t0)"
11522 [(set_attr "length" "4,4")])
11523
11524 (define_insn "bclrmem_m2a"
11525 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11526 (and:QI (match_dup 0)
11527 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
11528 "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
11529 "@
11530 bclr.b\\t%W1,%0
11531 bclr.b\\t%W1,@(0,%t0)"
11532 [(set_attr "length" "4,4")])
11533
11534 ;; Set a bit in a memory location.
11535 (define_insn "bset_m2a"
11536 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11537 (ior:QI
11538 (ashift:QI (const_int 1)
11539 (match_operand:QI 1 "const_int_operand" "K03,K03"))
11540 (match_dup 0)))]
11541 "TARGET_SH2A && TARGET_BITOPS"
11542 "@
11543 bset.b\\t%1,%0
11544 bset.b\\t%1,@(0,%t0)"
11545 [(set_attr "length" "4,4")])
11546
11547 (define_insn "bsetmem_m2a"
11548 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11549 (ior:QI (match_dup 0)
11550 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
11551 "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
11552 "@
11553 bset.b\\t%V1,%0
11554 bset.b\\t%V1,@(0,%t0)"
11555 [(set_attr "length" "4,4")])
11556
11557 ;;; Transfer the contents of the T bit to a specified bit of memory.
11558 (define_insn "bst_m2a"
11559 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
11560 (if_then_else (eq (reg:SI T_REG) (const_int 0))
11561 (and:QI
11562 (not:QI (ashift:QI (const_int 1)
11563 (match_operand:QI 1 "const_int_operand" "K03,K03")))
11564 (match_dup 0))
11565 (ior:QI
11566 (ashift:QI (const_int 1) (match_dup 1))
11567 (match_dup 0))))]
11568 "TARGET_SH2A && TARGET_BITOPS"
11569 "@
11570 bst.b\\t%1,%0
11571 bst.b\\t%1,@(0,%t0)"
11572 [(set_attr "length" "4")])
11573
11574 ;; Store a specified bit of memory in the T bit.
11575 (define_insn "bld_m2a"
11576 [(set (reg:SI T_REG)
11577 (zero_extract:SI
11578 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
11579 (const_int 1)
11580 (match_operand 1 "const_int_operand" "K03,K03")))]
11581 "TARGET_SH2A && TARGET_BITOPS"
11582 "@
11583 bld.b\\t%1,%0
11584 bld.b\\t%1,@(0,%t0)"
11585 [(set_attr "length" "4,4")])
11586
11587 ;; Store a specified bit of memory in the T bit.
11588 (define_insn "bldsign_m2a"
11589 [(set (reg:SI T_REG)
11590 (sign_extract:SI
11591 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11592 (const_int 1)
11593 (match_operand 1 "const_int_operand" "K03,K03")))]
11594 "TARGET_SH2A && TARGET_BITOPS"
11595 "@
11596 bld.b\\t%1,%0
11597 bld.b\\t%1,@(0,%t0)"
11598 [(set_attr "length" "4,4")])
11599
11600 ;; Store a specified bit of the LSB 8 bits of a register in the T bit.
11601 (define_insn "bld_reg"
11602 [(set (reg:SI T_REG)
11603 (zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
11604 (const_int 1)
11605 (match_operand 1 "const_int_operand" "K03")))]
11606 "TARGET_SH2A"
11607 "bld\\t%1,%0")
11608
11609 (define_insn "*bld_regqi"
11610 [(set (reg:SI T_REG)
11611 (zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
11612 (const_int 1)
11613 (match_operand 1 "const_int_operand" "K03")))]
11614 "TARGET_SH2A"
11615 "bld\\t%1,%0")
11616
11617 ;; Take logical and of a specified bit of memory with the T bit and
11618 ;; store its result in the T bit.
11619 (define_insn "band_m2a"
11620 [(set (reg:SI T_REG)
11621 (and:SI (reg:SI T_REG)
11622 (zero_extract:SI
11623 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11624 (const_int 1)
11625 (match_operand 1 "const_int_operand" "K03,K03"))))]
11626 "TARGET_SH2A && TARGET_BITOPS"
11627 "@
11628 band.b\\t%1,%0
11629 band.b\\t%1,@(0,%t0)"
11630 [(set_attr "length" "4,4")])
11631
11632 (define_insn "bandreg_m2a"
11633 [(set (match_operand:SI 0 "register_operand" "=r,r")
11634 (and:SI (zero_extract:SI
11635 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11636 (const_int 1)
11637 (match_operand 2 "const_int_operand" "K03,K03"))
11638 (match_operand:SI 3 "register_operand" "r,r")))]
11639 "TARGET_SH2A && TARGET_BITOPS"
11640 "@
11641 band.b\\t%2,%1\;movt\\t%0
11642 band.b\\t%2,@(0,%t1)\;movt\\t%0"
11643 [(set_attr "length" "6,6")])
11644
11645 ;; Take logical or of a specified bit of memory with the T bit and
11646 ;; store its result in the T bit.
11647 (define_insn "bor_m2a"
11648 [(set (reg:SI T_REG)
11649 (ior:SI (reg:SI T_REG)
11650 (zero_extract:SI
11651 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11652 (const_int 1)
11653 (match_operand 1 "const_int_operand" "K03,K03"))))]
11654 "TARGET_SH2A && TARGET_BITOPS"
11655 "@
11656 bor.b\\t%1,%0
11657 bor.b\\t%1,@(0,%t0)"
11658 [(set_attr "length" "4,4")])
11659
11660 (define_insn "borreg_m2a"
11661 [(set (match_operand:SI 0 "register_operand" "=r,r")
11662 (ior:SI (zero_extract:SI
11663 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11664 (const_int 1)
11665 (match_operand 2 "const_int_operand" "K03,K03"))
11666 (match_operand:SI 3 "register_operand" "=r,r")))]
11667 "TARGET_SH2A && TARGET_BITOPS"
11668 "@
11669 bor.b\\t%2,%1\;movt\\t%0
11670 bor.b\\t%2,@(0,%t1)\;movt\\t%0"
11671 [(set_attr "length" "6,6")])
11672
11673 ;; Take exclusive or of a specified bit of memory with the T bit and
11674 ;; store its result in the T bit.
11675 (define_insn "bxor_m2a"
11676 [(set (reg:SI T_REG)
11677 (xor:SI (reg:SI T_REG)
11678 (zero_extract:SI
11679 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11680 (const_int 1)
11681 (match_operand 1 "const_int_operand" "K03,K03"))))]
11682 "TARGET_SH2A && TARGET_BITOPS"
11683 "@
11684 bxor.b\\t%1,%0
11685 bxor.b\\t%1,@(0,%t0)"
11686 [(set_attr "length" "4,4")])
11687
11688 (define_insn "bxorreg_m2a"
11689 [(set (match_operand:SI 0 "register_operand" "=r,r")
11690 (xor:SI (zero_extract:SI
11691 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11692 (const_int 1)
11693 (match_operand 2 "const_int_operand" "K03,K03"))
11694 (match_operand:SI 3 "register_operand" "=r,r")))]
11695 "TARGET_SH2A && TARGET_BITOPS"
11696 "@
11697 bxor.b\\t%2,%1\;movt\\t%0
11698 bxor.b\\t%2,@(0,%t1)\;movt\\t%0"
11699 [(set_attr "length" "6,6")])
11700
11701 \f
11702 ;; -------------------------------------------------------------------------
11703 ;; Peepholes
11704 ;; -------------------------------------------------------------------------
11705 ;; This matches cases where the bit in a memory location is set.
11706 (define_peephole2
11707 [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
11708 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
11709 (set (match_dup 0)
11710 (ior:SI (match_dup 0)
11711 (match_operand:SI 2 "const_int_operand" "Pso,Pso")))
11712 (set (match_dup 1)
11713 (match_operand 3 "arith_reg_operand" "r,r"))]
11714 "TARGET_SH2A && TARGET_BITOPS
11715 && satisfies_constraint_Pso (operands[2])
11716 && REGNO (operands[0]) == REGNO (operands[3])"
11717 [(set (match_dup 1)
11718 (ior:QI (match_dup 1)
11719 (match_dup 2)))]
11720 "")
11721
11722 ;; This matches cases where the bit in a memory location is cleared.
11723 (define_peephole2
11724 [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
11725 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
11726 (set (match_dup 0)
11727 (and:SI (match_dup 0)
11728 (match_operand:SI 2 "const_int_operand" "Psz,Psz")))
11729 (set (match_dup 1)
11730 (match_operand 3 "arith_reg_operand" "r,r"))]
11731 "TARGET_SH2A && TARGET_BITOPS
11732 && satisfies_constraint_Psz (operands[2])
11733 && REGNO (operands[0]) == REGNO (operands[3])"
11734 [(set (match_dup 1)
11735 (and:QI (match_dup 1)
11736 (match_dup 2)))]
11737 "")
11738
11739 ;; This matches cases where a stack pointer increment at the start of the
11740 ;; epilogue combines with a stack slot read loading the return value.
11741
11742 (define_peephole
11743 [(set (match_operand:SI 0 "arith_reg_operand" "")
11744 (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
11745 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11746 "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
11747 "mov.l @%1+,%0")
11748
11749 ;; See the comment on the dt combiner pattern above.
11750
11751 (define_peephole
11752 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11753 (plus:SI (match_dup 0)
11754 (const_int -1)))
11755 (set (reg:SI T_REG)
11756 (eq:SI (match_dup 0)
11757 (const_int 0)))]
11758 "TARGET_SH2"
11759 "dt %0")
11760
11761 ;; The following peepholes fold load sequences for which reload was not
11762 ;; able to generate a displacement addressing move insn.
11763 ;; This can happen when reload has to transform a move insn
11764 ;; without displacement into one with displacement. Or when reload can't
11765 ;; fit a displacement into the insn's constraints. In the latter case, the
11766 ;; load destination reg remains at r0, which reload compensates by inserting
11767 ;; another mov insn.
11768
11769 ;; Fold sequence:
11770 ;; mov #54,r0
11771 ;; mov.b @(r0,r15),r0
11772 ;; mov r0,r3
11773 ;; into:
11774 ;; mov.b @(54,r15),r3
11775 ;;
11776 (define_peephole2
11777 [(set (match_operand:SI 0 "arith_reg_dest" "")
11778 (match_operand:SI 1 "const_int_operand" ""))
11779 (set (match_operand:SI 2 "arith_reg_dest" "")
11780 (sign_extend:SI
11781 (mem:QI (plus:SI (match_dup 0)
11782 (match_operand:SI 3 "arith_reg_operand" "")))))
11783 (set (match_operand:QI 4 "arith_reg_dest" "")
11784 (match_operand:QI 5 "arith_reg_operand" ""))]
11785 "TARGET_SH2A
11786 && CONST_OK_FOR_K12 (INTVAL (operands[1]))
11787 && REGNO (operands[2]) == REGNO (operands[5])
11788 && peep2_reg_dead_p (3, operands[5])"
11789 [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))]
11790 "")
11791
11792 ;; Fold sequence:
11793 ;; mov #54,r0
11794 ;; mov.b @(r0,r15),r1
11795 ;; into:
11796 ;; mov.b @(54,r15),r1
11797 ;;
11798 (define_peephole2
11799 [(set (match_operand:SI 0 "arith_reg_dest" "")
11800 (match_operand:SI 1 "const_int_operand" ""))
11801 (set (match_operand:SI 2 "arith_reg_dest" "")
11802 (sign_extend:SI
11803 (mem:QI (plus:SI (match_dup 0)
11804 (match_operand:SI 3 "arith_reg_operand" "")))))]
11805 "TARGET_SH2A
11806 && CONST_OK_FOR_K12 (INTVAL (operands[1]))
11807 && (peep2_reg_dead_p (2, operands[0])
11808 || REGNO (operands[0]) == REGNO (operands[2]))"
11809 [(set (match_dup 2)
11810 (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))]
11811 "")
11812
11813 ;; Fold sequence:
11814 ;; mov.b @(r0,r15),r0
11815 ;; mov r0,r3
11816 ;; into:
11817 ;; mov.b @(r0,r15),r3
11818 ;;
11819 (define_peephole2
11820 [(set (match_operand:SI 0 "arith_reg_dest" "")
11821 (sign_extend:SI
11822 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
11823 (match_operand:SI 2 "arith_reg_operand" "")))))
11824 (set (match_operand:QI 3 "arith_reg_dest" "")
11825 (match_operand:QI 4 "arith_reg_operand" ""))]
11826 "TARGET_SH1
11827 && REGNO (operands[0]) == REGNO (operands[4])
11828 && peep2_reg_dead_p (2, operands[0])"
11829 [(set (match_dup 3)
11830 (mem:QI (plus:SI (match_dup 1) (match_dup 2))))]
11831 "")
11832
11833 ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
11834 ;; to `mov #k,r0; mov.l @(r0,r15),rn'. These sequences are generated by
11835 ;; reload when the constant is too large for a reg+offset address.
11836
11837 ;; ??? We would get much better code if this was done in reload. This would
11838 ;; require modifying find_reloads_address to recognize that if the constant
11839 ;; is out-of-range for an immediate add, then we get better code by reloading
11840 ;; the constant into a register than by reloading the sum into a register,
11841 ;; since the former is one instruction shorter if the address does not need
11842 ;; to be offsettable. Unfortunately this does not work, because there is
11843 ;; only one register, r0, that can be used as an index register. This register
11844 ;; is also the function return value register. So, if we try to force reload
11845 ;; to use double-reg addresses, then we end up with some instructions that
11846 ;; need to use r0 twice. The only way to fix this is to change the calling
11847 ;; convention so that r0 is not used to return values.
11848
11849 (define_peephole
11850 [(set (match_operand:SI 0 "register_operand" "=r")
11851 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11852 (set (mem:SI (match_dup 0))
11853 (match_operand:SI 2 "general_movsrc_operand" ""))]
11854 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11855 "mov.l %2,@(%0,%1)")
11856
11857 (define_peephole
11858 [(set (match_operand:SI 0 "register_operand" "=r")
11859 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11860 (set (match_operand:SI 2 "general_movdst_operand" "")
11861 (mem:SI (match_dup 0)))]
11862 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11863 "mov.l @(%0,%1),%2")
11864
11865 (define_peephole
11866 [(set (match_operand:SI 0 "register_operand" "=r")
11867 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11868 (set (mem:HI (match_dup 0))
11869 (match_operand:HI 2 "general_movsrc_operand" ""))]
11870 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11871 "mov.w %2,@(%0,%1)")
11872
11873 (define_peephole
11874 [(set (match_operand:SI 0 "register_operand" "=r")
11875 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11876 (set (match_operand:HI 2 "general_movdst_operand" "")
11877 (mem:HI (match_dup 0)))]
11878 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11879 "mov.w @(%0,%1),%2")
11880
11881 (define_peephole
11882 [(set (match_operand:SI 0 "register_operand" "=r")
11883 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11884 (set (mem:QI (match_dup 0))
11885 (match_operand:QI 2 "general_movsrc_operand" ""))]
11886 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11887 "mov.b %2,@(%0,%1)")
11888
11889 (define_peephole
11890 [(set (match_operand:SI 0 "register_operand" "=r")
11891 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11892 (set (match_operand:QI 2 "general_movdst_operand" "")
11893 (mem:QI (match_dup 0)))]
11894 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11895 "mov.b @(%0,%1),%2")
11896
11897 (define_peephole
11898 [(set (match_operand:SI 0 "register_operand" "=r")
11899 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11900 (set (mem:SF (match_dup 0))
11901 (match_operand:SF 2 "general_movsrc_operand" ""))]
11902 "TARGET_SH1 && REGNO (operands[0]) == 0
11903 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
11904 || (GET_CODE (operands[2]) == SUBREG
11905 && REGNO (SUBREG_REG (operands[2])) < 16))
11906 && reg_unused_after (operands[0], insn)"
11907 "mov.l %2,@(%0,%1)")
11908
11909 (define_peephole
11910 [(set (match_operand:SI 0 "register_operand" "=r")
11911 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11912 (set (match_operand:SF 2 "general_movdst_operand" "")
11913
11914 (mem:SF (match_dup 0)))]
11915 "TARGET_SH1 && REGNO (operands[0]) == 0
11916 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
11917 || (GET_CODE (operands[2]) == SUBREG
11918 && REGNO (SUBREG_REG (operands[2])) < 16))
11919 && reg_unused_after (operands[0], insn)"
11920 "mov.l @(%0,%1),%2")
11921
11922 (define_peephole
11923 [(set (match_operand:SI 0 "register_operand" "=r")
11924 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11925 (set (mem:SF (match_dup 0))
11926 (match_operand:SF 2 "general_movsrc_operand" ""))]
11927 "TARGET_SH2E && REGNO (operands[0]) == 0
11928 && ((REG_P (operands[2])
11929 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11930 || (GET_CODE (operands[2]) == SUBREG
11931 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11932 && reg_unused_after (operands[0], insn)"
11933 "fmov{.s|} %2,@(%0,%1)")
11934
11935 (define_peephole
11936 [(set (match_operand:SI 0 "register_operand" "=r")
11937 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11938 (set (match_operand:SF 2 "general_movdst_operand" "")
11939
11940 (mem:SF (match_dup 0)))]
11941 "TARGET_SH2E && REGNO (operands[0]) == 0
11942 && ((REG_P (operands[2])
11943 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11944 || (GET_CODE (operands[2]) == SUBREG
11945 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11946 && reg_unused_after (operands[0], insn)"
11947 "fmov{.s|} @(%0,%1),%2")
11948
11949 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF). */
11950 (define_insn "sp_switch_1"
11951 [(const_int 1) (match_operand:SI 0 "symbol_ref_operand" "s")]
11952 "TARGET_SH1"
11953 "*
11954 {
11955 output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", operands);
11956 output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", operands);
11957 return \"mov r0,r15\";
11958 }"
11959 [(set_attr "length" "10")])
11960
11961 ;; Switch back to the original stack for interrupt functions with the
11962 ;; sp_switch attribute. */
11963 (define_insn "sp_switch_2"
11964 [(const_int 2)]
11965 "TARGET_SH1"
11966 "mov.l @r15+,r15\;mov.l @r15+,r0"
11967 [(set_attr "length" "4")])
11968
11969 ;; Integer vector moves
11970
11971 (define_expand "movv8qi"
11972 [(set (match_operand:V8QI 0 "general_movdst_operand" "")
11973 (match_operand:V8QI 1 "general_movsrc_operand" ""))]
11974 "TARGET_SHMEDIA"
11975 "{ if (prepare_move_operands (operands, V8QImode)) DONE; }")
11976
11977 (define_insn "movv8qi_i"
11978 [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
11979 (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11980 "TARGET_SHMEDIA
11981 && (register_operand (operands[0], V8QImode)
11982 || sh_register_operand (operands[1], V8QImode))"
11983 "@
11984 add %1, r63, %0
11985 movi %1, %0
11986 #
11987 ld%M1.q %m1, %0
11988 st%M0.q %m0, %N1"
11989 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
11990 (set_attr "length" "4,4,16,4,4")])
11991
11992 (define_split
11993 [(set (match_operand:V8QI 0 "arith_reg_dest" "")
11994 (subreg:V8QI (const_int 0) 0))]
11995 "TARGET_SHMEDIA"
11996 [(set (match_dup 0)
11997 (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
11998 (const_int 0) (const_int 0) (const_int 0)
11999 (const_int 0) (const_int 0)]))])
12000
12001 (define_split
12002 [(set (match_operand 0 "arith_reg_dest" "")
12003 (match_operand 1 "sh_rep_vec" ""))]
12004 "TARGET_SHMEDIA && reload_completed
12005 && GET_MODE (operands[0]) == GET_MODE (operands[1])
12006 && sh_vector_mode_supported_p (GET_MODE (operands[0]))
12007 && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
12008 && (XVECEXP (operands[1], 0, 0) != const0_rtx
12009 || XVECEXP (operands[1], 0, 1) != const0_rtx)
12010 && (XVECEXP (operands[1], 0, 0) != constm1_rtx
12011 || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
12012 [(set (match_dup 0) (match_dup 1))
12013 (match_dup 2)]
12014 "
12015 {
12016 int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
12017 rtx elt1 = XVECEXP (operands[1], 0, 1);
12018
12019 if (unit_size > 2)
12020 operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
12021 else
12022 {
12023 if (unit_size < 2)
12024 operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
12025 operands[2] = gen_mperm_w0 (operands[0], operands[0]);
12026 }
12027 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
12028 operands[1] = XVECEXP (operands[1], 0, 0);
12029 if (unit_size < 2)
12030 {
12031 if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
12032 operands[1]
12033 = GEN_INT (TARGET_LITTLE_ENDIAN
12034 ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
12035 : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
12036 else
12037 {
12038 operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
12039 operands[1]
12040 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
12041 }
12042 }
12043 }")
12044
12045 (define_split
12046 [(set (match_operand 0 "arith_reg_dest" "")
12047 (match_operand 1 "sh_const_vec" ""))]
12048 "TARGET_SHMEDIA && reload_completed
12049 && GET_MODE (operands[0]) == GET_MODE (operands[1])
12050 && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
12051 [(set (match_dup 0) (match_dup 1))]
12052 "
12053 {
12054 rtx v = operands[1];
12055 enum machine_mode new_mode
12056 = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
12057
12058 operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
12059 operands[1]
12060 = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
12061 }")
12062
12063 (define_expand "movv2hi"
12064 [(set (match_operand:V2HI 0 "general_movdst_operand" "")
12065 (match_operand:V2HI 1 "general_movsrc_operand" ""))]
12066 "TARGET_SHMEDIA"
12067 "{ if (prepare_move_operands (operands, V2HImode)) DONE; }")
12068
12069 (define_insn "movv2hi_i"
12070 [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
12071 (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
12072 "TARGET_SHMEDIA
12073 && (register_operand (operands[0], V2HImode)
12074 || sh_register_operand (operands[1], V2HImode))"
12075 "@
12076 add.l %1, r63, %0
12077 movi %1, %0
12078 #
12079 ld%M1.l %m1, %0
12080 st%M0.l %m0, %N1"
12081 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
12082 (set_attr "length" "4,4,16,4,4")
12083 (set (attr "highpart")
12084 (cond [(match_test "sh_contains_memref_p (insn)")
12085 (const_string "user")]
12086 (const_string "ignore")))])
12087
12088 (define_expand "movv4hi"
12089 [(set (match_operand:V4HI 0 "general_movdst_operand" "")
12090 (match_operand:V4HI 1 "general_movsrc_operand" ""))]
12091 "TARGET_SHMEDIA"
12092 "{ if (prepare_move_operands (operands, V4HImode)) DONE; }")
12093
12094 (define_insn "movv4hi_i"
12095 [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
12096 (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
12097 "TARGET_SHMEDIA
12098 && (register_operand (operands[0], V4HImode)
12099 || sh_register_operand (operands[1], V4HImode))"
12100 "@
12101 add %1, r63, %0
12102 movi %1, %0
12103 #
12104 ld%M1.q %m1, %0
12105 st%M0.q %m0, %N1"
12106 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
12107 (set_attr "length" "4,4,16,4,4")
12108 (set_attr "highpart" "depend")])
12109
12110 (define_expand "movv2si"
12111 [(set (match_operand:V2SI 0 "general_movdst_operand" "")
12112 (match_operand:V2SI 1 "general_movsrc_operand" ""))]
12113 "TARGET_SHMEDIA"
12114 "{ if (prepare_move_operands (operands, V2SImode)) DONE; }")
12115
12116 (define_insn "movv2si_i"
12117 [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
12118 (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
12119 "TARGET_SHMEDIA
12120 && (register_operand (operands[0], V2SImode)
12121 || sh_register_operand (operands[1], V2SImode))"
12122 "@
12123 add %1, r63, %0
12124 #
12125 #
12126 ld%M1.q %m1, %0
12127 st%M0.q %m0, %N1"
12128 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
12129 (set_attr "length" "4,4,16,4,4")
12130 (set_attr "highpart" "depend")])
12131
12132 ;; Multimedia Intrinsics
12133
12134 (define_insn "absv2si2"
12135 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12136 (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
12137 "TARGET_SHMEDIA"
12138 "mabs.l %1, %0"
12139 [(set_attr "type" "mcmp_media")
12140 (set_attr "highpart" "depend")])
12141
12142 (define_insn "absv4hi2"
12143 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12144 (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
12145 "TARGET_SHMEDIA"
12146 "mabs.w %1, %0"
12147 [(set_attr "type" "mcmp_media")
12148 (set_attr "highpart" "depend")])
12149
12150 (define_insn "addv2si3"
12151 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12152 (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
12153 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12154 "TARGET_SHMEDIA"
12155 "madd.l %1, %2, %0"
12156 [(set_attr "type" "arith_media")
12157 (set_attr "highpart" "depend")])
12158
12159 (define_insn "addv4hi3"
12160 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12161 (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
12162 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12163 "TARGET_SHMEDIA"
12164 "madd.w %1, %2, %0"
12165 [(set_attr "type" "arith_media")
12166 (set_attr "highpart" "depend")])
12167
12168 (define_insn_and_split "addv2hi3"
12169 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
12170 (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
12171 (match_operand:V2HI 2 "extend_reg_operand" "r")))]
12172 "TARGET_SHMEDIA"
12173 "#"
12174 "TARGET_SHMEDIA"
12175 [(const_int 0)]
12176 "
12177 {
12178 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
12179 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
12180 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
12181 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
12182 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
12183
12184 emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
12185 emit_insn (gen_truncdisi2 (si_dst, di_dst));
12186 DONE;
12187 }"
12188 [(set_attr "highpart" "must_split")])
12189
12190 (define_insn "ssaddv2si3"
12191 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12192 (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
12193 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12194 "TARGET_SHMEDIA"
12195 "madds.l %1, %2, %0"
12196 [(set_attr "type" "mcmp_media")
12197 (set_attr "highpart" "depend")])
12198
12199 (define_insn "usaddv8qi3"
12200 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12201 (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
12202 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
12203 "TARGET_SHMEDIA"
12204 "madds.ub %1, %2, %0"
12205 [(set_attr "type" "mcmp_media")
12206 (set_attr "highpart" "depend")])
12207
12208 (define_insn "ssaddv4hi3"
12209 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12210 (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
12211 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12212 "TARGET_SHMEDIA"
12213 "madds.w %1, %2, %0"
12214 [(set_attr "type" "mcmp_media")
12215 (set_attr "highpart" "depend")])
12216
12217 (define_insn "negcmpeqv8qi"
12218 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12219 (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
12220 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
12221 "TARGET_SHMEDIA"
12222 "mcmpeq.b %N1, %N2, %0"
12223 [(set_attr "type" "mcmp_media")
12224 (set_attr "highpart" "depend")])
12225
12226 (define_insn "negcmpeqv2si"
12227 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12228 (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
12229 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
12230 "TARGET_SHMEDIA"
12231 "mcmpeq.l %N1, %N2, %0"
12232 [(set_attr "type" "mcmp_media")
12233 (set_attr "highpart" "depend")])
12234
12235 (define_insn "negcmpeqv4hi"
12236 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12237 (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
12238 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
12239 "TARGET_SHMEDIA"
12240 "mcmpeq.w %N1, %N2, %0"
12241 [(set_attr "type" "mcmp_media")
12242 (set_attr "highpart" "depend")])
12243
12244 (define_insn "negcmpgtuv8qi"
12245 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12246 (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
12247 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
12248 "TARGET_SHMEDIA"
12249 "mcmpgt.ub %N1, %N2, %0"
12250 [(set_attr "type" "mcmp_media")
12251 (set_attr "highpart" "depend")])
12252
12253 (define_insn "negcmpgtv2si"
12254 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12255 (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
12256 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
12257 "TARGET_SHMEDIA"
12258 "mcmpgt.l %N1, %N2, %0"
12259 [(set_attr "type" "mcmp_media")
12260 (set_attr "highpart" "depend")])
12261
12262 (define_insn "negcmpgtv4hi"
12263 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12264 (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
12265 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
12266 "TARGET_SHMEDIA"
12267 "mcmpgt.w %N1, %N2, %0"
12268 [(set_attr "type" "mcmp_media")
12269 (set_attr "highpart" "depend")])
12270
12271 (define_insn "mcmv"
12272 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12273 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12274 (match_operand:DI 2 "arith_reg_operand" "r"))
12275 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
12276 (not:DI (match_dup 2)))))]
12277 "TARGET_SHMEDIA"
12278 "mcmv %N1, %2, %0"
12279 [(set_attr "type" "arith_media")
12280 (set_attr "highpart" "depend")])
12281
12282 (define_insn "mcnvs_lw"
12283 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12284 (vec_concat:V4HI
12285 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
12286 (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
12287 "TARGET_SHMEDIA"
12288 "mcnvs.lw %N1, %N2, %0"
12289 [(set_attr "type" "mcmp_media")])
12290
12291 (define_insn "mcnvs_wb"
12292 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12293 (vec_concat:V8QI
12294 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
12295 (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
12296 "TARGET_SHMEDIA"
12297 "mcnvs.wb %N1, %N2, %0"
12298 [(set_attr "type" "mcmp_media")])
12299
12300 (define_insn "mcnvs_wub"
12301 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12302 (vec_concat:V8QI
12303 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
12304 (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
12305 "TARGET_SHMEDIA"
12306 "mcnvs.wub %N1, %N2, %0"
12307 [(set_attr "type" "mcmp_media")])
12308
12309 (define_insn "mextr_rl"
12310 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12311 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12312 (match_operand:HI 3 "mextr_bit_offset" "i"))
12313 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12314 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
12315 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
12316 "*
12317 {
12318 static char templ[21];
12319
12320 sprintf (templ, \"mextr%d\\t%%N1, %%N2, %%0\",
12321 (int) INTVAL (operands[3]) >> 3);
12322 return templ;
12323 }"
12324 [(set_attr "type" "arith_media")])
12325
12326 (define_insn "*mextr_lr"
12327 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12328 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12329 (match_operand:HI 3 "mextr_bit_offset" "i"))
12330 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12331 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
12332 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
12333 "*
12334 {
12335 static char templ[21];
12336
12337 sprintf (templ, \"mextr%d\\t%%N2, %%N1, %%0\",
12338 (int) INTVAL (operands[4]) >> 3);
12339 return templ;
12340 }"
12341 [(set_attr "type" "arith_media")])
12342
12343 ; mextrN can be modelled with vec_select / vec_concat, but the selection
12344 ; vector then varies depending on endianness.
12345 (define_expand "mextr1"
12346 [(match_operand:DI 0 "arith_reg_dest" "")
12347 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12348 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12349 "TARGET_SHMEDIA"
12350 "
12351 {
12352 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12353 GEN_INT (1 * 8), GEN_INT (7 * 8)));
12354 DONE;
12355 }")
12356
12357 (define_expand "mextr2"
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 {
12364 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12365 GEN_INT (2 * 8), GEN_INT (6 * 8)));
12366 DONE;
12367 }")
12368
12369 (define_expand "mextr3"
12370 [(match_operand:DI 0 "arith_reg_dest" "")
12371 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12372 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12373 "TARGET_SHMEDIA"
12374 "
12375 {
12376 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12377 GEN_INT (3 * 8), GEN_INT (5 * 8)));
12378 DONE;
12379 }")
12380
12381 (define_expand "mextr4"
12382 [(match_operand:DI 0 "arith_reg_dest" "")
12383 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12384 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12385 "TARGET_SHMEDIA"
12386 "
12387 {
12388 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12389 GEN_INT (4 * 8), GEN_INT (4 * 8)));
12390 DONE;
12391 }")
12392
12393 (define_expand "mextr5"
12394 [(match_operand:DI 0 "arith_reg_dest" "")
12395 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12396 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12397 "TARGET_SHMEDIA"
12398 "
12399 {
12400 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12401 GEN_INT (5 * 8), GEN_INT (3 * 8)));
12402 DONE;
12403 }")
12404
12405 (define_expand "mextr6"
12406 [(match_operand:DI 0 "arith_reg_dest" "")
12407 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12408 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12409 "TARGET_SHMEDIA"
12410 "
12411 {
12412 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12413 GEN_INT (6 * 8), GEN_INT (2 * 8)));
12414 DONE;
12415 }")
12416
12417 (define_expand "mextr7"
12418 [(match_operand:DI 0 "arith_reg_dest" "")
12419 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12420 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12421 "TARGET_SHMEDIA"
12422 "
12423 {
12424 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12425 GEN_INT (7 * 8), GEN_INT (1 * 8)));
12426 DONE;
12427 }")
12428
12429 (define_expand "mmacfx_wl"
12430 [(match_operand:V2SI 0 "arith_reg_dest" "")
12431 (match_operand:V2HI 1 "extend_reg_operand" "")
12432 (match_operand:V2HI 2 "extend_reg_operand" "")
12433 (match_operand:V2SI 3 "arith_reg_operand" "")]
12434 "TARGET_SHMEDIA"
12435 "
12436 {
12437 emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
12438 operands[1], operands[2]));
12439 DONE;
12440 }")
12441
12442 ;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
12443 ;; is depend
12444 (define_insn "mmacfx_wl_i"
12445 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12446 (ss_plus:V2SI
12447 (match_operand:V2SI 1 "arith_reg_operand" "0")
12448 (ss_truncate:V2SI
12449 (ashift:V2DI
12450 (sign_extend:V2DI
12451 (mult:V2SI
12452 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
12453 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
12454 (const_int 1)))))]
12455 "TARGET_SHMEDIA"
12456 "mmacfx.wl %2, %3, %0"
12457 [(set_attr "type" "mac_media")
12458 (set_attr "highpart" "depend")])
12459
12460 (define_expand "mmacnfx_wl"
12461 [(match_operand:V2SI 0 "arith_reg_dest" "")
12462 (match_operand:V2HI 1 "extend_reg_operand" "")
12463 (match_operand:V2HI 2 "extend_reg_operand" "")
12464 (match_operand:V2SI 3 "arith_reg_operand" "")]
12465 "TARGET_SHMEDIA"
12466 "
12467 {
12468 emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
12469 operands[1], operands[2]));
12470 DONE;
12471 }")
12472
12473 (define_insn "mmacnfx_wl_i"
12474 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12475 (ss_minus:V2SI
12476 (match_operand:V2SI 1 "arith_reg_operand" "0")
12477 (ss_truncate:V2SI
12478 (ashift:V2DI
12479 (sign_extend:V2DI
12480 (mult:V2SI
12481 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
12482 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
12483 (const_int 1)))))]
12484 "TARGET_SHMEDIA"
12485 "mmacnfx.wl %2, %3, %0"
12486 [(set_attr "type" "mac_media")
12487 (set_attr "highpart" "depend")])
12488
12489 (define_insn "mulv2si3"
12490 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12491 (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12492 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12493 "TARGET_SHMEDIA"
12494 "mmul.l %1, %2, %0"
12495 [(set_attr "type" "d2mpy_media")
12496 (set_attr "highpart" "depend")])
12497
12498 (define_insn "mulv4hi3"
12499 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12500 (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12501 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12502 "TARGET_SHMEDIA"
12503 "mmul.w %1, %2, %0"
12504 [(set_attr "type" "dmpy_media")
12505 (set_attr "highpart" "depend")])
12506
12507 (define_insn "mmulfx_l"
12508 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12509 (ss_truncate:V2SI
12510 (ashiftrt:V2DI
12511 (mult:V2DI
12512 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12513 (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
12514 (const_int 31))))]
12515 "TARGET_SHMEDIA"
12516 "mmulfx.l %1, %2, %0"
12517 [(set_attr "type" "d2mpy_media")
12518 (set_attr "highpart" "depend")])
12519
12520 (define_insn "mmulfx_w"
12521 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12522 (ss_truncate:V4HI
12523 (ashiftrt:V4SI
12524 (mult:V4SI
12525 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12526 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12527 (const_int 15))))]
12528 "TARGET_SHMEDIA"
12529 "mmulfx.w %1, %2, %0"
12530 [(set_attr "type" "dmpy_media")
12531 (set_attr "highpart" "depend")])
12532
12533 (define_insn "mmulfxrp_w"
12534 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12535 (ss_truncate:V4HI
12536 (ashiftrt:V4SI
12537 (plus:V4SI
12538 (mult:V4SI
12539 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12540 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12541 (const_int 16384))
12542 (const_int 15))))]
12543 "TARGET_SHMEDIA"
12544 "mmulfxrp.w %1, %2, %0"
12545 [(set_attr "type" "dmpy_media")
12546 (set_attr "highpart" "depend")])
12547
12548
12549 (define_expand "mmulhi_wl"
12550 [(match_operand:V2SI 0 "arith_reg_dest" "")
12551 (match_operand:V4HI 1 "arith_reg_operand" "")
12552 (match_operand:V4HI 2 "arith_reg_operand" "")]
12553 "TARGET_SHMEDIA"
12554 "
12555 {
12556 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
12557 (operands[0], operands[1], operands[2]));
12558 DONE;
12559 }")
12560
12561 (define_expand "mmullo_wl"
12562 [(match_operand:V2SI 0 "arith_reg_dest" "")
12563 (match_operand:V4HI 1 "arith_reg_operand" "")
12564 (match_operand:V4HI 2 "arith_reg_operand" "")]
12565 "TARGET_SHMEDIA"
12566 "
12567 {
12568 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
12569 (operands[0], operands[1], operands[2]));
12570 DONE;
12571 }")
12572
12573 (define_insn "mmul23_wl"
12574 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12575 (vec_select:V2SI
12576 (mult:V4SI
12577 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12578 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12579 (parallel [(const_int 2) (const_int 3)])))]
12580 "TARGET_SHMEDIA"
12581 "* return (TARGET_LITTLE_ENDIAN
12582 ? \"mmulhi.wl %1, %2, %0\"
12583 : \"mmullo.wl %1, %2, %0\");"
12584 [(set_attr "type" "dmpy_media")
12585 (set (attr "highpart")
12586 (cond [(eq_attr "endian" "big") (const_string "ignore")]
12587 (const_string "user")))])
12588
12589 (define_insn "mmul01_wl"
12590 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12591 (vec_select:V2SI
12592 (mult:V4SI
12593 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12594 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12595 (parallel [(const_int 0) (const_int 1)])))]
12596 "TARGET_SHMEDIA"
12597 "* return (TARGET_LITTLE_ENDIAN
12598 ? \"mmullo.wl %1, %2, %0\"
12599 : \"mmulhi.wl %1, %2, %0\");"
12600 [(set_attr "type" "dmpy_media")
12601 (set (attr "highpart")
12602 (cond [(eq_attr "endian" "little") (const_string "ignore")]
12603 (const_string "user")))])
12604
12605
12606 (define_expand "mmulsum_wq"
12607 [(match_operand:DI 0 "arith_reg_dest" "")
12608 (match_operand:V4HI 1 "arith_reg_operand" "")
12609 (match_operand:V4HI 2 "arith_reg_operand" "")
12610 (match_operand:DI 3 "arith_reg_operand" "")]
12611 "TARGET_SHMEDIA"
12612 "
12613 {
12614 emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
12615 operands[1], operands[2]));
12616 DONE;
12617 }")
12618
12619 (define_insn "mmulsum_wq_i"
12620 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12621 (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
12622 (plus:DI
12623 (plus:DI
12624 (vec_select:DI
12625 (mult:V4DI
12626 (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
12627 (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
12628 (parallel [(const_int 0)]))
12629 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12630 (sign_extend:V4DI (match_dup 3)))
12631 (parallel [(const_int 1)])))
12632 (plus:DI
12633 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12634 (sign_extend:V4DI (match_dup 3)))
12635 (parallel [(const_int 2)]))
12636 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12637 (sign_extend:V4DI (match_dup 3)))
12638 (parallel [(const_int 3)]))))))]
12639 "TARGET_SHMEDIA"
12640 "mmulsum.wq %2, %3, %0"
12641 [(set_attr "type" "mac_media")])
12642
12643 (define_expand "mperm_w"
12644 [(match_operand:V4HI 0 "arith_reg_dest" "=r")
12645 (match_operand:V4HI 1 "arith_reg_operand" "r")
12646 (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
12647 "TARGET_SHMEDIA"
12648 "
12649 {
12650 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
12651 (operands[0], operands[1], operands[2]));
12652 DONE;
12653 }")
12654
12655 ; This use of vec_select isn't exactly correct according to rtl.texi
12656 ; (because not constant), but it seems a straightforward extension.
12657 (define_insn "mperm_w_little"
12658 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12659 (vec_select:V4HI
12660 (match_operand:V4HI 1 "arith_reg_operand" "r")
12661 (parallel
12662 [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
12663 (const_int 2) (const_int 0))
12664 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
12665 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
12666 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
12667 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
12668 "mperm.w %1, %N2, %0"
12669 [(set_attr "type" "arith_media")])
12670
12671 (define_insn "mperm_w_big"
12672 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12673 (vec_select:V4HI
12674 (match_operand:V4HI 1 "arith_reg_operand" "r")
12675 (parallel
12676 [(zero_extract:QI (not:QI (match_operand:QI 2
12677 "extend_reg_or_0_operand" "rZ"))
12678 (const_int 2) (const_int 0))
12679 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
12680 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
12681 (zero_extract:QI (not:QI (match_dup 2))
12682 (const_int 2) (const_int 6))])))]
12683 "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
12684 "mperm.w %1, %N2, %0"
12685 [(set_attr "type" "arith_media")])
12686
12687 (define_insn "mperm_w0"
12688 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12689 (vec_duplicate:V4HI (truncate:HI (match_operand 1
12690 "trunc_hi_operand" "r"))))]
12691 "TARGET_SHMEDIA"
12692 "mperm.w %1, r63, %0"
12693 [(set_attr "type" "arith_media")
12694 (set_attr "highpart" "ignore")])
12695
12696 (define_expand "msad_ubq"
12697 [(match_operand:DI 0 "arith_reg_dest" "")
12698 (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
12699 (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
12700 (match_operand:DI 3 "arith_reg_operand" "")]
12701 "TARGET_SHMEDIA"
12702 "
12703 {
12704 emit_insn (gen_msad_ubq_i (operands[0], operands[3],
12705 operands[1], operands[2]));
12706 DONE;
12707 }")
12708
12709 (define_insn "msad_ubq_i"
12710 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12711 (plus:DI
12712 (plus:DI
12713 (plus:DI
12714 (plus:DI
12715 (match_operand:DI 1 "arith_reg_operand" "0")
12716 (abs:DI (vec_select:DI
12717 (minus:V8DI
12718 (zero_extend:V8DI
12719 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12720 (zero_extend:V8DI
12721 (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
12722 (parallel [(const_int 0)]))))
12723 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12724 (zero_extend:V8DI (match_dup 3)))
12725 (parallel [(const_int 1)]))))
12726 (plus:DI
12727 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12728 (zero_extend:V8DI (match_dup 3)))
12729 (parallel [(const_int 2)])))
12730 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12731 (zero_extend:V8DI (match_dup 3)))
12732 (parallel [(const_int 3)])))))
12733 (plus:DI
12734 (plus:DI
12735 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12736 (zero_extend:V8DI (match_dup 3)))
12737 (parallel [(const_int 4)])))
12738 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12739 (zero_extend:V8DI (match_dup 3)))
12740 (parallel [(const_int 5)]))))
12741 (plus:DI
12742 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12743 (zero_extend:V8DI (match_dup 3)))
12744 (parallel [(const_int 6)])))
12745 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12746 (zero_extend:V8DI (match_dup 3)))
12747 (parallel [(const_int 7)])))))))]
12748 "TARGET_SHMEDIA"
12749 "msad.ubq %N2, %N3, %0"
12750 [(set_attr "type" "mac_media")])
12751
12752 (define_insn "mshalds_l"
12753 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12754 (ss_truncate:V2SI
12755 (ashift:V2DI
12756 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12757 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12758 (const_int 31)))))]
12759 "TARGET_SHMEDIA"
12760 "mshalds.l %1, %2, %0"
12761 [(set_attr "type" "mcmp_media")
12762 (set_attr "highpart" "depend")])
12763
12764 (define_insn "mshalds_w"
12765 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12766 (ss_truncate:V4HI
12767 (ashift:V4SI
12768 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12769 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12770 (const_int 15)))))]
12771 "TARGET_SHMEDIA"
12772 "mshalds.w %1, %2, %0"
12773 [(set_attr "type" "mcmp_media")
12774 (set_attr "highpart" "depend")])
12775
12776 (define_insn "ashrv2si3"
12777 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12778 (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12779 (match_operand:DI 2 "arith_reg_operand" "r")))]
12780 "TARGET_SHMEDIA"
12781 "mshard.l %1, %2, %0"
12782 [(set_attr "type" "arith_media")
12783 (set_attr "highpart" "depend")])
12784
12785 (define_insn "ashrv4hi3"
12786 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12787 (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12788 (match_operand:DI 2 "arith_reg_operand" "r")))]
12789 "TARGET_SHMEDIA"
12790 "mshard.w %1, %2, %0"
12791 [(set_attr "type" "arith_media")
12792 (set_attr "highpart" "depend")])
12793
12794 (define_insn "mshards_q"
12795 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
12796 (ss_truncate:HI
12797 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
12798 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
12799 "TARGET_SHMEDIA"
12800 "mshards.q %1, %N2, %0"
12801 [(set_attr "type" "mcmp_media")])
12802
12803 (define_expand "mshfhi_b"
12804 [(match_operand:V8QI 0 "arith_reg_dest" "")
12805 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12806 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12807 "TARGET_SHMEDIA"
12808 "
12809 {
12810 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
12811 (operands[0], operands[1], operands[2]));
12812 DONE;
12813 }")
12814
12815 (define_expand "mshflo_b"
12816 [(match_operand:V8QI 0 "arith_reg_dest" "")
12817 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12818 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12819 "TARGET_SHMEDIA"
12820 "
12821 {
12822 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
12823 (operands[0], operands[1], operands[2]));
12824 DONE;
12825 }")
12826
12827 (define_insn "mshf4_b"
12828 [(set
12829 (match_operand:V8QI 0 "arith_reg_dest" "=r")
12830 (vec_select:V8QI
12831 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12832 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12833 (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
12834 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
12835 "TARGET_SHMEDIA"
12836 "* return (TARGET_LITTLE_ENDIAN
12837 ? \"mshfhi.b %N1, %N2, %0\"
12838 : \"mshflo.b %N1, %N2, %0\");"
12839 [(set_attr "type" "arith_media")
12840 (set (attr "highpart")
12841 (cond [(eq_attr "endian" "big") (const_string "ignore")]
12842 (const_string "user")))])
12843
12844 (define_insn "mshf0_b"
12845 [(set
12846 (match_operand:V8QI 0 "arith_reg_dest" "=r")
12847 (vec_select:V8QI
12848 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12849 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12850 (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
12851 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
12852 "TARGET_SHMEDIA"
12853 "* return (TARGET_LITTLE_ENDIAN
12854 ? \"mshflo.b %N1, %N2, %0\"
12855 : \"mshfhi.b %N1, %N2, %0\");"
12856 [(set_attr "type" "arith_media")
12857 (set (attr "highpart")
12858 (cond [(eq_attr "endian" "little") (const_string "ignore")]
12859 (const_string "user")))])
12860
12861 (define_expand "mshfhi_l"
12862 [(match_operand:V2SI 0 "arith_reg_dest" "")
12863 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12864 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12865 "TARGET_SHMEDIA"
12866 "
12867 {
12868 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
12869 (operands[0], operands[1], operands[2]));
12870 DONE;
12871 }")
12872
12873 (define_expand "mshflo_l"
12874 [(match_operand:V2SI 0 "arith_reg_dest" "")
12875 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12876 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12877 "TARGET_SHMEDIA"
12878 "
12879 {
12880 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
12881 (operands[0], operands[1], operands[2]));
12882 DONE;
12883 }")
12884
12885 (define_insn "mshf4_l"
12886 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12887 (vec_select:V2SI
12888 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12889 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12890 (parallel [(const_int 1) (const_int 3)])))]
12891 "TARGET_SHMEDIA"
12892 "* return (TARGET_LITTLE_ENDIAN
12893 ? \"mshfhi.l %N1, %N2, %0\"
12894 : \"mshflo.l %N1, %N2, %0\");"
12895 [(set_attr "type" "arith_media")
12896 (set (attr "highpart")
12897 (cond [(eq_attr "endian" "big") (const_string "ignore")]
12898 (const_string "user")))])
12899
12900 (define_insn "mshf0_l"
12901 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12902 (vec_select:V2SI
12903 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12904 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12905 (parallel [(const_int 0) (const_int 2)])))]
12906 "TARGET_SHMEDIA"
12907 "* return (TARGET_LITTLE_ENDIAN
12908 ? \"mshflo.l %N1, %N2, %0\"
12909 : \"mshfhi.l %N1, %N2, %0\");"
12910 [(set_attr "type" "arith_media")
12911 (set (attr "highpart")
12912 (cond [(eq_attr "endian" "little") (const_string "ignore")]
12913 (const_string "user")))])
12914
12915 (define_expand "mshfhi_w"
12916 [(match_operand:V4HI 0 "arith_reg_dest" "")
12917 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12918 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12919 "TARGET_SHMEDIA"
12920 "
12921 {
12922 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
12923 (operands[0], operands[1], operands[2]));
12924 DONE;
12925 }")
12926
12927 (define_expand "mshflo_w"
12928 [(match_operand:V4HI 0 "arith_reg_dest" "")
12929 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12930 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12931 "TARGET_SHMEDIA"
12932 "
12933 {
12934 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
12935 (operands[0], operands[1], operands[2]));
12936 DONE;
12937 }")
12938
12939 (define_insn "mshf4_w"
12940 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12941 (vec_select:V4HI
12942 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12943 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12944 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
12945 "TARGET_SHMEDIA"
12946 "* return (TARGET_LITTLE_ENDIAN
12947 ? \"mshfhi.w %N1, %N2, %0\"
12948 : \"mshflo.w %N1, %N2, %0\");"
12949 [(set_attr "type" "arith_media")
12950 (set (attr "highpart")
12951 (cond [(eq_attr "endian" "big") (const_string "ignore")]
12952 (const_string "user")))])
12953
12954 (define_insn "mshf0_w"
12955 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12956 (vec_select:V4HI
12957 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12958 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12959 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
12960 "TARGET_SHMEDIA"
12961 "* return (TARGET_LITTLE_ENDIAN
12962 ? \"mshflo.w %N1, %N2, %0\"
12963 : \"mshfhi.w %N1, %N2, %0\");"
12964 [(set_attr "type" "arith_media")
12965 (set (attr "highpart")
12966 (cond [(eq_attr "endian" "little") (const_string "ignore")]
12967 (const_string "user")))])
12968
12969 (define_insn "mshflo_w_x"
12970 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12971 (vec_select:V4HI
12972 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
12973 (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
12974 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
12975 "TARGET_SHMEDIA"
12976 "mshflo.w %N1, %N2, %0"
12977 [(set_attr "type" "arith_media")
12978 (set_attr "highpart" "ignore")])
12979
12980 ;; These are useful to expand ANDs and as combiner patterns.
12981 (define_insn_and_split "mshfhi_l_di"
12982 [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
12983 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
12984 (const_int 32))
12985 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
12986 (const_int -4294967296))))]
12987 "TARGET_SHMEDIA"
12988 "@
12989 mshfhi.l %N1, %N2, %0
12990 #"
12991 "TARGET_SHMEDIA && reload_completed
12992 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12993 [(set (match_dup 3) (match_dup 4))
12994 (set (match_dup 5) (match_dup 6))]
12995 "
12996 {
12997 operands[3] = gen_lowpart (SImode, operands[0]);
12998 operands[4] = gen_highpart (SImode, operands[1]);
12999 operands[5] = gen_highpart (SImode, operands[0]);
13000 operands[6] = gen_highpart (SImode, operands[2]);
13001 }"
13002 [(set_attr "type" "arith_media")])
13003
13004 (define_insn "*mshfhi_l_di_rev"
13005 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13006 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13007 (const_int -4294967296))
13008 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
13009 (const_int 32))))]
13010 "TARGET_SHMEDIA"
13011 "mshfhi.l %N2, %N1, %0"
13012 [(set_attr "type" "arith_media")])
13013
13014 (define_split
13015 [(set (match_operand:DI 0 "arith_reg_dest" "")
13016 (ior:DI (zero_extend:DI (match_operand:SI 1
13017 "extend_reg_or_0_operand" ""))
13018 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
13019 (const_int -4294967296))))
13020 (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
13021 "TARGET_SHMEDIA"
13022 [(const_int 0)]
13023 "
13024 {
13025 emit_insn (gen_ashldi3_media (operands[3],
13026 simplify_gen_subreg (DImode, operands[1],
13027 SImode, 0),
13028 GEN_INT (32)));
13029 emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
13030 DONE;
13031 }")
13032
13033 (define_insn "mshflo_l_di"
13034 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13035 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13036 (const_int 4294967295))
13037 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
13038 (const_int 32))))]
13039
13040 "TARGET_SHMEDIA"
13041 "mshflo.l %N1, %N2, %0"
13042 [(set_attr "type" "arith_media")
13043 (set_attr "highpart" "ignore")])
13044
13045 (define_insn "*mshflo_l_di_rev"
13046 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13047 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13048 (const_int 32))
13049 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
13050 (const_int 4294967295))))]
13051
13052 "TARGET_SHMEDIA"
13053 "mshflo.l %N2, %N1, %0"
13054 [(set_attr "type" "arith_media")
13055 (set_attr "highpart" "ignore")])
13056
13057 ;; Combiner pattern for trampoline initialization.
13058 (define_insn_and_split "*double_shori"
13059 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13060 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
13061 (const_int 32))
13062 (match_operand:DI 2 "const_int_operand" "n")))]
13063 "TARGET_SHMEDIA
13064 && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
13065 "#"
13066 "rtx_equal_p (operands[0], operands[1])"
13067 [(const_int 0)]
13068 "
13069 {
13070 HOST_WIDE_INT v = INTVAL (operands[2]);
13071
13072 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
13073 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
13074 DONE;
13075 }"
13076 [(set_attr "highpart" "ignore")])
13077
13078
13079 (define_insn "*mshflo_l_di_x"
13080 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13081 (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
13082 "rZ"))
13083 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
13084 (const_int 32))))]
13085
13086 "TARGET_SHMEDIA"
13087 "mshflo.l %N1, %N2, %0"
13088 [(set_attr "type" "arith_media")
13089 (set_attr "highpart" "ignore")])
13090
13091 (define_insn_and_split "concat_v2sf"
13092 [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
13093 ;; (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
13094 (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
13095 (match_operand:SF 2 "register_operand" "rZ,f,f")))]
13096
13097 "TARGET_SHMEDIA"
13098 "@
13099 mshflo.l %N1, %N2, %0
13100 #
13101 #"
13102 "TARGET_SHMEDIA && reload_completed
13103 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
13104 [(set (match_dup 3) (match_dup 1))
13105 (set (match_dup 4) (match_dup 2))]
13106 "
13107 {
13108 operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
13109 operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
13110 }"
13111 [(set_attr "type" "arith_media")
13112 (set_attr "highpart" "ignore")])
13113
13114 (define_insn "*mshflo_l_di_x_rev"
13115 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13116 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13117 (const_int 32))
13118 (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
13119
13120 "TARGET_SHMEDIA"
13121 "mshflo.l %N2, %N1, %0"
13122 [(set_attr "type" "arith_media")
13123 (set_attr "highpart" "ignore")])
13124
13125 (define_insn "ashlv2si3"
13126 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13127 (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
13128 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
13129 "TARGET_SHMEDIA"
13130 "mshlld.l %1, %2, %0"
13131 [(set_attr "type" "arith_media")
13132 (set_attr "highpart" "depend")])
13133
13134 (define_split
13135 [(set (match_operand 0 "any_register_operand" "")
13136 (match_operator 3 "shift_operator"
13137 [(match_operand 1 "any_register_operand" "")
13138 (match_operand 2 "shift_count_reg_operand" "")]))]
13139 "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
13140 [(set (match_dup 0) (match_dup 3))]
13141 "
13142 {
13143 rtx count = operands[2];
13144 enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
13145
13146 while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
13147 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
13148 || GET_CODE (count) == TRUNCATE)
13149 count = XEXP (count, 0);
13150 inner_mode = GET_MODE (count);
13151 count = simplify_gen_subreg (outer_mode, count, inner_mode,
13152 subreg_lowpart_offset (outer_mode, inner_mode));
13153 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
13154 operands[1], count);
13155 }")
13156
13157 (define_insn "ashlv4hi3"
13158 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13159 (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
13160 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
13161 "TARGET_SHMEDIA"
13162 "mshlld.w %1, %2, %0"
13163 [(set_attr "type" "arith_media")
13164 (set_attr "highpart" "depend")])
13165
13166 (define_insn "lshrv2si3"
13167 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13168 (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
13169 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
13170 "TARGET_SHMEDIA"
13171 "mshlrd.l %1, %2, %0"
13172 [(set_attr "type" "arith_media")
13173 (set_attr "highpart" "depend")])
13174
13175 (define_insn "lshrv4hi3"
13176 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13177 (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
13178 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
13179 "TARGET_SHMEDIA"
13180 "mshlrd.w %1, %2, %0"
13181 [(set_attr "type" "arith_media")
13182 (set_attr "highpart" "depend")])
13183
13184 (define_insn "subv2si3"
13185 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13186 (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
13187 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
13188 "TARGET_SHMEDIA"
13189 "msub.l %N1, %2, %0"
13190 [(set_attr "type" "arith_media")
13191 (set_attr "highpart" "depend")])
13192
13193 (define_insn "subv4hi3"
13194 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13195 (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
13196 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
13197 "TARGET_SHMEDIA"
13198 "msub.w %N1, %2, %0"
13199 [(set_attr "type" "arith_media")
13200 (set_attr "highpart" "depend")])
13201
13202 (define_insn_and_split "subv2hi3"
13203 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
13204 (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
13205 (match_operand:V2HI 2 "arith_reg_operand" "r")))]
13206 "TARGET_SHMEDIA"
13207 "#"
13208 "TARGET_SHMEDIA"
13209 [(const_int 0)]
13210 "
13211 {
13212 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
13213 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
13214 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
13215 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
13216 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
13217
13218 emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
13219 emit_insn (gen_truncdisi2 (si_dst, di_dst));
13220 DONE;
13221 }"
13222 [(set_attr "highpart" "must_split")])
13223
13224 (define_insn "sssubv2si3"
13225 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13226 (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
13227 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
13228 "TARGET_SHMEDIA"
13229 "msubs.l %N1, %2, %0"
13230 [(set_attr "type" "mcmp_media")
13231 (set_attr "highpart" "depend")])
13232
13233 (define_insn "ussubv8qi3"
13234 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13235 (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
13236 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
13237 "TARGET_SHMEDIA"
13238 "msubs.ub %N1, %2, %0"
13239 [(set_attr "type" "mcmp_media")
13240 (set_attr "highpart" "depend")])
13241
13242 (define_insn "sssubv4hi3"
13243 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13244 (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
13245 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
13246 "TARGET_SHMEDIA"
13247 "msubs.w %N1, %2, %0"
13248 [(set_attr "type" "mcmp_media")
13249 (set_attr "highpart" "depend")])
13250
13251 ;; Floating Point Intrinsics
13252
13253 (define_insn "fcosa_s"
13254 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13255 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
13256 UNSPEC_FCOSA))]
13257 "TARGET_SHMEDIA"
13258 "fcosa.s %1, %0"
13259 [(set_attr "type" "atrans_media")])
13260
13261 (define_insn "fsina_s"
13262 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13263 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
13264 UNSPEC_FSINA))]
13265 "TARGET_SHMEDIA"
13266 "fsina.s %1, %0"
13267 [(set_attr "type" "atrans_media")])
13268
13269 (define_insn "fipr"
13270 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13271 (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
13272 "fp_arith_reg_operand" "f")
13273 (match_operand:V4SF 2
13274 "fp_arith_reg_operand" "f"))
13275 (parallel [(const_int 0)]))
13276 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
13277 (parallel [(const_int 1)])))
13278 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
13279 (parallel [(const_int 2)]))
13280 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
13281 (parallel [(const_int 3)])))))]
13282 "TARGET_SHMEDIA"
13283 "fipr.s %1, %2, %0"
13284 [(set_attr "type" "fparith_media")])
13285
13286 (define_insn "fsrra_s"
13287 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13288 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
13289 UNSPEC_FSRRA))]
13290 "TARGET_SHMEDIA"
13291 "fsrra.s %1, %0"
13292 [(set_attr "type" "atrans_media")])
13293
13294 (define_insn "ftrv"
13295 [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
13296 (plus:V4SF
13297 (plus:V4SF
13298 (mult:V4SF
13299 (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
13300 (parallel [(const_int 0) (const_int 5)
13301 (const_int 10) (const_int 15)]))
13302 (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
13303 (mult:V4SF
13304 (vec_select:V4SF (match_dup 1)
13305 (parallel [(const_int 4) (const_int 9)
13306 (const_int 14) (const_int 3)]))
13307 (vec_select:V4SF (match_dup 2)
13308 (parallel [(const_int 1) (const_int 2)
13309 (const_int 3) (const_int 0)]))))
13310 (plus:V4SF
13311 (mult:V4SF
13312 (vec_select:V4SF (match_dup 1)
13313 (parallel [(const_int 8) (const_int 13)
13314 (const_int 2) (const_int 7)]))
13315 (vec_select:V4SF (match_dup 2)
13316 (parallel [(const_int 2) (const_int 3)
13317 (const_int 0) (const_int 1)])))
13318 (mult:V4SF
13319 (vec_select:V4SF (match_dup 1)
13320 (parallel [(const_int 12) (const_int 1)
13321 (const_int 6) (const_int 11)]))
13322 (vec_select:V4SF (match_dup 2)
13323 (parallel [(const_int 3) (const_int 0)
13324 (const_int 1) (const_int 2)]))))))]
13325 "TARGET_SHMEDIA"
13326 "ftrv.s %1, %2, %0"
13327 [(set_attr "type" "fparith_media")])
13328
13329 (define_insn "ldhi_l"
13330 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13331 (zero_extract:SI
13332 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
13333 (const_int 3))
13334 (const_int -3)))
13335 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
13336 (const_int 0)))]
13337 "TARGET_SHMEDIA32"
13338 "ldhi.l %U1, %0"
13339 [(set_attr "type" "load_media")])
13340
13341 (define_insn "ldhi_q"
13342 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13343 (zero_extract:DI
13344 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
13345 (const_int 7))
13346 (const_int -7)))
13347 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
13348 (const_int 0)))]
13349 "TARGET_SHMEDIA32"
13350 "ldhi.q %U1, %0"
13351 [(set_attr "type" "load_media")])
13352
13353 (define_insn_and_split "*ldhi_q_comb0"
13354 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13355 (zero_extract:DI
13356 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
13357 "register_operand" "r")
13358 (match_operand:SI 2
13359 "ua_offset" "I06"))
13360 (const_int 7))
13361 (const_int -7)))
13362 (plus:SI (and:SI (match_dup 1) (const_int 7))
13363 (const_int 1))
13364 (const_int 0)))]
13365 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
13366 "#"
13367 ""
13368 [(pc)]
13369 "emit_insn (gen_ldhi_q (operands[0],
13370 gen_rtx_PLUS (SImode, operands[1], operands[2])));
13371 DONE;")
13372
13373
13374 (define_insn_and_split "*ldhi_q_comb1"
13375 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13376 (zero_extract:DI
13377 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
13378 "register_operand" "r")
13379 (match_operand:SI 2
13380 "ua_offset" "I06"))
13381 (const_int 7))
13382 (const_int -7)))
13383 (plus:SI (and:SI (plus:SI (match_dup 1) (match_operand:SI 3
13384 "ua_offset" "I06"))
13385 (const_int 7))
13386 (const_int 1))
13387 (const_int 0)))]
13388 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
13389 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
13390 "#"
13391 ""
13392 [(pc)]
13393 "emit_insn (gen_ldhi_q (operands[0],
13394 gen_rtx_PLUS (SImode, operands[1], operands[2])));
13395 DONE;")
13396
13397
13398 (define_insn "ldlo_l"
13399 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13400 (zero_extract:SI
13401 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
13402 (const_int -4)))
13403 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
13404 (and:SI (match_dup 1) (const_int 3))))]
13405 "TARGET_SHMEDIA32"
13406 "ldlo.l %U1, %0"
13407 [(set_attr "type" "load_media")])
13408
13409 (define_insn "ldlo_q"
13410 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13411 (zero_extract:DI
13412 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
13413 (const_int -8)))
13414 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
13415 (and:SI (match_dup 1) (const_int 7))))]
13416 "TARGET_SHMEDIA32"
13417 "ldlo.q %U1, %0"
13418 [(set_attr "type" "load_media")])
13419
13420 (define_insn_and_split "*ldlo_q_comb0"
13421 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13422 (zero_extract:DI
13423 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
13424 (match_operand:SI 2 "ua_offset" "I06"))
13425 (const_int -8)))
13426 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
13427 (and:SI (match_dup 1) (const_int 7))))]
13428 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
13429 "#"
13430 ""
13431 [(pc)]
13432 "emit_insn (gen_ldlo_q (operands[0],
13433 gen_rtx_PLUS (SImode, operands[1], operands[2])));
13434 DONE;")
13435
13436 (define_insn_and_split "*ldlo_q_comb1"
13437 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13438 (zero_extract:DI
13439 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
13440 (match_operand:SI 2 "ua_offset" "I06"))
13441 (const_int -8)))
13442 (minus:SI (const_int 8)
13443 (and:SI (plus:SI (match_dup 1)
13444 (match_operand:SI 3 "ua_offset" "I06"))
13445 (const_int 7)))
13446 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
13447 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
13448 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
13449 "#"
13450 ""
13451 [(pc)]
13452 "emit_insn (gen_ldlo_q (operands[0],
13453 gen_rtx_PLUS (SImode, operands[1], operands[2])));
13454 DONE;")
13455
13456 (define_insn "sthi_l"
13457 [(set (zero_extract:SI
13458 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
13459 (const_int 3))
13460 (const_int -3)))
13461 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
13462 (const_int 0))
13463 (match_operand:SI 1 "arith_reg_operand" "r"))]
13464 "TARGET_SHMEDIA32"
13465 "sthi.l %U0, %1"
13466 [(set_attr "type" "ustore_media")])
13467
13468 ;; All unaligned stores are considered to be 'narrow' because they typically
13469 ;; operate on less that a quadword, and when they operate on a full quadword,
13470 ;; the vanilla store high / store low sequence will cause a stall if not
13471 ;; scheduled apart.
13472 (define_insn "sthi_q"
13473 [(set (zero_extract:DI
13474 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
13475 (const_int 7))
13476 (const_int -7)))
13477 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
13478 (const_int 0))
13479 (match_operand:DI 1 "arith_reg_operand" "r"))]
13480 "TARGET_SHMEDIA32"
13481 "sthi.q %U0, %1"
13482 [(set_attr "type" "ustore_media")])
13483
13484 (define_insn_and_split "*sthi_q_comb0"
13485 [(set (zero_extract:DI
13486 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
13487 "register_operand" "r")
13488 (match_operand:SI 1 "ua_offset"
13489 "I06"))
13490 (const_int 7))
13491 (const_int -7)))
13492 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
13493 (const_int 0))
13494 (match_operand:DI 2 "arith_reg_operand" "r"))]
13495 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
13496 "#"
13497 ""
13498 [(pc)]
13499 "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13500 operands[2]));
13501 DONE;")
13502
13503 (define_insn_and_split "*sthi_q_comb1"
13504 [(set (zero_extract:DI
13505 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
13506 "register_operand" "r")
13507 (match_operand:SI 1 "ua_offset"
13508 "I06"))
13509 (const_int 7))
13510 (const_int -7)))
13511 (plus:SI (and:SI (plus:SI (match_dup 0)
13512 (match_operand:SI 2 "ua_offset" "I06"))
13513 (const_int 7))
13514 (const_int 1))
13515 (const_int 0))
13516 (match_operand:DI 3 "arith_reg_operand" "r"))]
13517 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
13518 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
13519 "#"
13520 ""
13521 [(pc)]
13522 "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13523 operands[3]));
13524 DONE;")
13525
13526 ;; This is highpart user because the address is used as full 64 bit.
13527 (define_insn "stlo_l"
13528 [(set (zero_extract:SI
13529 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
13530 (const_int -4)))
13531 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
13532 (and:SI (match_dup 0) (const_int 3)))
13533 (match_operand:SI 1 "arith_reg_operand" "r"))]
13534 "TARGET_SHMEDIA32"
13535 "stlo.l %U0, %1"
13536 [(set_attr "type" "ustore_media")])
13537
13538 (define_insn "stlo_q"
13539 [(set (zero_extract:DI
13540 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
13541 (const_int -8)))
13542 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
13543 (and:SI (match_dup 0) (const_int 7)))
13544 (match_operand:DI 1 "arith_reg_operand" "r"))]
13545 "TARGET_SHMEDIA32"
13546 "stlo.q %U0, %1"
13547 [(set_attr "type" "ustore_media")])
13548
13549 (define_insn_and_split "*stlo_q_comb0"
13550 [(set (zero_extract:DI
13551 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
13552 (match_operand:SI 1 "ua_offset" "I06"))
13553 (const_int -8)))
13554 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
13555 (and:SI (match_dup 0) (const_int 7)))
13556 (match_operand:DI 2 "arith_reg_operand" "r"))]
13557 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
13558 "#"
13559 ""
13560 [(pc)]
13561 "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13562 operands[2]));
13563 DONE;")
13564
13565 (define_insn_and_split "*stlo_q_comb1"
13566 [(set (zero_extract:DI
13567 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
13568 (match_operand:SI 1 "ua_offset" "I06"))
13569 (const_int -8)))
13570 (minus:SI (const_int 8) (and:SI (plus:SI (match_dup 0)
13571 (match_operand:SI 2
13572 "ua_offset" "I06"))
13573 (const_int 7)))
13574 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
13575 (match_operand:DI 3 "arith_reg_operand" "r"))]
13576 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
13577 "#"
13578 ""
13579 [(pc)]
13580 "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13581 operands[3]));
13582 DONE;")
13583
13584 (define_insn "ldhi_l64"
13585 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13586 (zero_extract:SI
13587 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13588 (const_int 3))
13589 (const_int -3)))
13590 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
13591 (const_int 0)))]
13592 "TARGET_SHMEDIA64"
13593 "ldhi.l %U1, %0"
13594 [(set_attr "type" "load_media")])
13595
13596 (define_insn "ldhi_q64"
13597 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13598 (zero_extract:DI
13599 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13600 (const_int 7))
13601 (const_int -7)))
13602 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
13603 (const_int 0)))]
13604 "TARGET_SHMEDIA64"
13605 "ldhi.q %U1, %0"
13606 [(set_attr "type" "load_media")])
13607
13608 (define_insn "ldlo_l64"
13609 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13610 (zero_extract:SI
13611 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13612 (const_int -4)))
13613 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
13614 (and:DI (match_dup 1) (const_int 3))))]
13615 "TARGET_SHMEDIA64"
13616 "ldlo.l %U1, %0"
13617 [(set_attr "type" "load_media")])
13618
13619 (define_insn "ldlo_q64"
13620 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13621 (zero_extract:DI
13622 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13623 (const_int -8)))
13624 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
13625 (and:DI (match_dup 1) (const_int 7))))]
13626 "TARGET_SHMEDIA64"
13627 "ldlo.q %U1, %0"
13628 [(set_attr "type" "load_media")])
13629
13630 (define_insn "sthi_l64"
13631 [(set (zero_extract:SI
13632 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13633 (const_int 3))
13634 (const_int -3)))
13635 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
13636 (const_int 0))
13637 (match_operand:SI 1 "arith_reg_operand" "r"))]
13638 "TARGET_SHMEDIA64"
13639 "sthi.l %U0, %1"
13640 [(set_attr "type" "ustore_media")])
13641
13642 (define_insn "sthi_q64"
13643 [(set (zero_extract:DI
13644 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13645 (const_int 7))
13646 (const_int -7)))
13647 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
13648 (const_int 0))
13649 (match_operand:DI 1 "arith_reg_operand" "r"))]
13650 "TARGET_SHMEDIA64"
13651 "sthi.q %U0, %1"
13652 [(set_attr "type" "ustore_media")])
13653
13654 (define_insn "stlo_l64"
13655 [(set (zero_extract:SI
13656 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13657 (const_int -4)))
13658 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
13659 (and:DI (match_dup 0) (const_int 3)))
13660 (match_operand:SI 1 "arith_reg_operand" "r"))]
13661 "TARGET_SHMEDIA64"
13662 "stlo.l %U0, %1"
13663 [(set_attr "type" "ustore_media")])
13664
13665 (define_insn "stlo_q64"
13666 [(set (zero_extract:DI
13667 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13668 (const_int -8)))
13669 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
13670 (and:DI (match_dup 0) (const_int 7)))
13671 (match_operand:DI 1 "arith_reg_operand" "r"))]
13672 "TARGET_SHMEDIA64"
13673 "stlo.q %U0, %1"
13674 [(set_attr "type" "ustore_media")])
13675
13676 (define_insn "nsb"
13677 [(set (match_operand:QI 0 "arith_reg_dest" "=r")
13678 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13679 UNSPEC_NSB))]
13680 "TARGET_SHMEDIA"
13681 "nsb %1, %0"
13682 [(set_attr "type" "arith_media")])
13683
13684 (define_insn "nsbsi"
13685 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13686 (zero_extend:SI
13687 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13688 UNSPEC_NSB)))]
13689 "TARGET_SHMEDIA"
13690 "nsb %1, %0"
13691 [(set_attr "type" "arith_media")])
13692
13693 (define_insn "nsbdi"
13694 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13695 (zero_extend:DI
13696 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13697 UNSPEC_NSB)))]
13698 "TARGET_SHMEDIA"
13699 "nsb %1, %0"
13700 [(set_attr "type" "arith_media")])
13701
13702 (define_expand "ffsdi2"
13703 [(set (match_operand:DI 0 "arith_reg_dest" "")
13704 (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
13705 "TARGET_SHMEDIA"
13706 "
13707 {
13708 rtx scratch = gen_reg_rtx (DImode);
13709 rtx last;
13710
13711 emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
13712 emit_insn (gen_xordi3 (scratch, operands[1], scratch));
13713 emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
13714 emit_insn (gen_nsbdi (scratch, scratch));
13715 emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
13716 emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
13717 last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
13718 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
13719
13720 DONE;
13721 }")
13722
13723 (define_expand "ffssi2"
13724 [(set (match_operand:SI 0 "arith_reg_dest" "")
13725 (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
13726 "TARGET_SHMEDIA"
13727 "
13728 {
13729 rtx scratch = gen_reg_rtx (SImode);
13730 rtx discratch = gen_reg_rtx (DImode);
13731 rtx last;
13732
13733 emit_insn (gen_adddi3 (discratch,
13734 simplify_gen_subreg (DImode, operands[1], SImode, 0),
13735 constm1_rtx));
13736 emit_insn (gen_andcdi3 (discratch,
13737 simplify_gen_subreg (DImode, operands[1], SImode, 0),
13738 discratch));
13739 emit_insn (gen_nsbsi (scratch, discratch));
13740 last = emit_insn (gen_subsi3 (operands[0],
13741 force_reg (SImode, GEN_INT (63)), scratch));
13742 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
13743
13744 DONE;
13745 }")
13746
13747 (define_insn "byterev"
13748 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13749 (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
13750 (parallel [(const_int 7) (const_int 6) (const_int 5)
13751 (const_int 4) (const_int 3) (const_int 2)
13752 (const_int 1) (const_int 0)])))]
13753 "TARGET_SHMEDIA"
13754 "byterev %1, %0"
13755 [(set_attr "type" "arith_media")])
13756
13757 (define_insn "*prefetch_media"
13758 [(prefetch (match_operand:QI 0 "address_operand" "p")
13759 (match_operand:SI 1 "const_int_operand" "n")
13760 (match_operand:SI 2 "const_int_operand" "n"))]
13761 "TARGET_SHMEDIA"
13762 "*
13763 {
13764 operands[0] = gen_rtx_MEM (QImode, operands[0]);
13765 output_asm_insn (\"ld%M0.b %m0,r63\", operands);
13766 return \"\";
13767 }"
13768 [(set_attr "type" "other")])
13769
13770 (define_insn "*prefetch_i4"
13771 [(prefetch (match_operand:SI 0 "register_operand" "r")
13772 (match_operand:SI 1 "const_int_operand" "n")
13773 (match_operand:SI 2 "const_int_operand" "n"))]
13774 "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && !TARGET_VXWORKS_RTP"
13775 "*
13776 {
13777 return \"pref @%0\";
13778 }"
13779 [(set_attr "type" "other")])
13780
13781 ;; In user mode, the "pref" instruction will raise a RADDERR exception
13782 ;; for accesses to [0x80000000,0xffffffff]. This makes it an unsuitable
13783 ;; implementation of __builtin_prefetch for VxWorks RTPs.
13784 (define_expand "prefetch"
13785 [(prefetch (match_operand 0 "address_operand" "p")
13786 (match_operand:SI 1 "const_int_operand" "n")
13787 (match_operand:SI 2 "const_int_operand" "n"))]
13788 "TARGET_SH2A || ((TARGET_HARD_SH4 || TARGET_SH5)
13789 && (TARGET_SHMEDIA || !TARGET_VXWORKS_RTP))"
13790 "
13791 {
13792 if (GET_MODE (operands[0]) != Pmode
13793 || !CONST_INT_P (operands[1])
13794 || !CONST_INT_P (operands[2]))
13795 FAIL;
13796 if (! TARGET_SHMEDIA)
13797 operands[0] = force_reg (Pmode, operands[0]);
13798 }")
13799
13800 (define_insn "prefetch_m2a"
13801 [(prefetch (match_operand:SI 0 "register_operand" "r")
13802 (match_operand:SI 1 "const_int_operand" "n")
13803 (match_operand:SI 2 "const_int_operand" "n"))]
13804 "TARGET_SH2A"
13805 "pref\\t@%0"
13806 [(set_attr "type" "other")])
13807
13808 (define_insn "alloco_i"
13809 [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
13810 (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
13811 "TARGET_SHMEDIA32"
13812 "*
13813 {
13814 rtx xops[2];
13815
13816 if (GET_CODE (operands[0]) == PLUS)
13817 {
13818 xops[0] = XEXP (operands[0], 0);
13819 xops[1] = XEXP (operands[0], 1);
13820 }
13821 else
13822 {
13823 xops[0] = operands[0];
13824 xops[1] = const0_rtx;
13825 }
13826 output_asm_insn (\"alloco %0, %1\", xops);
13827 return \"\";
13828 }"
13829 [(set_attr "type" "other")])
13830
13831 (define_split
13832 [(set (match_operand 0 "any_register_operand" "")
13833 (match_operand 1 "" ""))]
13834 "TARGET_SHMEDIA && reload_completed"
13835 [(set (match_dup 0) (match_dup 1))]
13836 "
13837 {
13838 int n_changes = 0;
13839
13840 for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
13841 if (!n_changes)
13842 FAIL;
13843 }")
13844
13845 ; Stack Protector Patterns
13846
13847 (define_expand "stack_protect_set"
13848 [(set (match_operand 0 "memory_operand" "")
13849 (match_operand 1 "memory_operand" ""))]
13850 ""
13851 {
13852 if (TARGET_SHMEDIA)
13853 {
13854 if (TARGET_SHMEDIA64)
13855 emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
13856 else
13857 emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
13858 }
13859 else
13860 emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
13861
13862 DONE;
13863 })
13864
13865 (define_insn "stack_protect_set_si"
13866 [(set (match_operand:SI 0 "memory_operand" "=m")
13867 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13868 (set (match_scratch:SI 2 "=&r") (const_int 0))]
13869 "!TARGET_SHMEDIA"
13870 "mov.l\t%1, %2\;mov.l\t%2, %0\;mov\t#0, %2"
13871 [(set_attr "type" "other")
13872 (set_attr "length" "6")])
13873
13874 (define_insn "stack_protect_set_si_media"
13875 [(set (match_operand:SI 0 "memory_operand" "=m")
13876 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13877 (set (match_scratch:SI 2 "=&r") (const_int 0))]
13878 "TARGET_SHMEDIA"
13879 "ld%M1.l\t%m1, %2\;st%M0.l\t%m0, %2\;movi\t0, %2"
13880 [(set_attr "type" "other")
13881 (set_attr "length" "12")])
13882
13883 (define_insn "stack_protect_set_di_media"
13884 [(set (match_operand:DI 0 "memory_operand" "=m")
13885 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13886 (set (match_scratch:DI 2 "=&r") (const_int 0))]
13887 "TARGET_SHMEDIA64"
13888 "ld%M1.q\t%m1, %2\;st%M0.q\t%m0, %2\;movi\t0, %2"
13889 [(set_attr "type" "other")
13890 (set_attr "length" "12")])
13891
13892 (define_expand "stack_protect_test"
13893 [(match_operand 0 "memory_operand" "")
13894 (match_operand 1 "memory_operand" "")
13895 (match_operand 2 "" "")]
13896 ""
13897 {
13898 if (TARGET_SHMEDIA)
13899 {
13900 rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
13901 rtx test;
13902
13903 test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
13904 if (TARGET_SHMEDIA64)
13905 {
13906 emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
13907 operands[1]));
13908 emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
13909 }
13910 else
13911 {
13912 emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
13913 operands[1]));
13914 emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
13915 }
13916 }
13917 else
13918 {
13919 emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
13920 emit_jump_insn (gen_branch_true (operands[2]));
13921 }
13922
13923 DONE;
13924 })
13925
13926 (define_insn "stack_protect_test_si"
13927 [(set (reg:SI T_REG)
13928 (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
13929 (match_operand:SI 1 "memory_operand" "m")]
13930 UNSPEC_SP_TEST))
13931 (set (match_scratch:SI 2 "=&r") (const_int 0))
13932 (set (match_scratch:SI 3 "=&r") (const_int 0))]
13933 "!TARGET_SHMEDIA"
13934 "mov.l\t%0, %2\;mov.l\t%1, %3\;cmp/eq\t%2, %3\;mov\t#0, %2\;mov\t#0, %3"
13935 [(set_attr "type" "other")
13936 (set_attr "length" "10")])
13937
13938 (define_insn "stack_protect_test_si_media"
13939 [(set (match_operand:SI 0 "register_operand" "=&r")
13940 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
13941 (match_operand:SI 2 "memory_operand" "m")]
13942 UNSPEC_SP_TEST))
13943 (set (match_scratch:SI 3 "=&r") (const_int 0))]
13944 "TARGET_SHMEDIA"
13945 "ld%M1.l\t%m1, %0\;ld%M2.l\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13946 [(set_attr "type" "other")
13947 (set_attr "length" "16")])
13948
13949 (define_insn "stack_protect_test_di_media"
13950 [(set (match_operand:DI 0 "register_operand" "=&r")
13951 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
13952 (match_operand:DI 2 "memory_operand" "m")]
13953 UNSPEC_SP_TEST))
13954 (set (match_scratch:DI 3 "=&r") (const_int 0))]
13955 "TARGET_SHMEDIA64"
13956 "ld%M1.q\t%m1, %0\;ld%M2.q\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13957 [(set_attr "type" "other")
13958 (set_attr "length" "16")])
13959
13960 (include "sync.md")