re PR target/49880 (SuperH: ICE when -m4 is used with -mdiv=call-div1)
[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
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 [(ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
350 (const_string "no")
351 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
352 (const_string "yes")
353 (ne (symbol_ref "NEXT_INSN (PREV_INSN (insn)) != insn") (const_int 0))
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 (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
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 (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
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 [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
383 (const_string "no")
384 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
385 (const_int 20660))
386 (const_string "yes")
387 (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
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 [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
396 (const_string "no")
397 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
398 (const_int 20658))
399 (const_string "yes")
400 (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
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 (ne (symbol_ref ("flag_pic")) (const_int 0))
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 (ne (symbol_ref "prev_nonnote_insn (insn)")
436 (const_int 0))
437 (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
438 (symbol_ref "INSN"))
439 (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
440 (symbol_ref "code_for_indirect_jump_scratch"))))
441 (cond [(eq_attr "braf_branch_p" "yes")
442 (const_int 6)
443 (eq (symbol_ref "flag_pic") (const_int 0))
444 (const_int 10)
445 (ne (symbol_ref "TARGET_SH2") (const_int 0))
446 (const_int 10)] (const_int 18))
447 (eq_attr "braf_branch_p" "yes")
448 (const_int 10)
449 ;; ??? using pc is not computed transitively.
450 (ne (match_dup 0) (match_dup 0))
451 (const_int 12)
452 (ne (symbol_ref ("flag_pic")) (const_int 0))
453 (const_int 22)
454 ] (const_int 14))
455 (eq_attr "type" "pt_media")
456 (if_then_else (ne (symbol_ref "TARGET_SHMEDIA64") (const_int 0))
457 (const_int 20) (const_int 12))
458 (and (eq_attr "type" "jump_media")
459 (ne (symbol_ref "TARGET_SH5_CUT2_WORKAROUND") (const_int 0)))
460 (const_int 8)
461 ] (if_then_else (ne (symbol_ref "TARGET_SHMEDIA") (const_int 0))
462 (const_int 4)
463 (const_int 2))))
464
465 ;; DFA descriptions for the pipelines
466
467 (include "sh1.md")
468 (include "shmedia.md")
469 (include "sh4.md")
470
471 (include "predicates.md")
472 (include "constraints.md")
473
474 ;; Definitions for filling delay slots
475
476 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
477
478 (define_attr "banked" "yes,no"
479 (cond [(eq (symbol_ref "sh_loads_bankedreg_p (insn)")
480 (const_int 1))
481 (const_string "yes")]
482 (const_string "no")))
483
484 ;; ??? This should be (nil) instead of (const_int 0)
485 (define_attr "hit_stack" "yes,no"
486 (cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)")
487 (const_int 0))
488 (const_string "no")]
489 (const_string "yes")))
490
491 (define_attr "interrupt_function" "no,yes"
492 (const (symbol_ref "current_function_interrupt")))
493
494 (define_attr "in_delay_slot" "yes,no"
495 (cond [(eq_attr "type" "cbranch") (const_string "no")
496 (eq_attr "type" "pcload,pcload_si") (const_string "no")
497 (eq_attr "needs_delay_slot" "yes") (const_string "no")
498 (eq_attr "length" "2") (const_string "yes")
499 ] (const_string "no")))
500
501 (define_attr "cond_delay_slot" "yes,no"
502 (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
503 ] (const_string "no")))
504
505 (define_attr "is_sfunc" ""
506 (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
507
508 (define_attr "is_mac_media" ""
509 (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
510
511 (define_attr "branch_zero" "yes,no"
512 (cond [(eq_attr "type" "!cbranch") (const_string "no")
513 (ne (symbol_ref "(next_active_insn (insn)\
514 == (prev_active_insn\
515 (XEXP (SET_SRC (PATTERN (insn)), 1))))\
516 && get_attr_length (next_active_insn (insn)) == 2")
517 (const_int 0))
518 (const_string "yes")]
519 (const_string "no")))
520
521 ;; SH4 Double-precision computation with double-precision result -
522 ;; the two halves are ready at different times.
523 (define_attr "dfp_comp" "yes,no"
524 (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
525 (const_string "no")))
526
527 ;; Insns for which the latency of a preceding fp insn is decreased by one.
528 (define_attr "late_fp_use" "yes,no" (const_string "no"))
529 ;; And feeding insns for which this relevant.
530 (define_attr "any_fp_comp" "yes,no"
531 (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
532 (const_string "yes")]
533 (const_string "no")))
534
535 (define_attr "any_int_load" "yes,no"
536 (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
537 (const_string "yes")]
538 (const_string "no")))
539
540 (define_attr "highpart" "user, ignore, extend, depend, must_split"
541 (const_string "user"))
542
543 (define_delay
544 (eq_attr "needs_delay_slot" "yes")
545 [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
546
547 ;; On the SH and SH2, the rte instruction reads the return pc from the stack,
548 ;; and thus we can't put a pop instruction in its delay slot.
549 ;; ??? On the SH3, the rte instruction does not use the stack, so a pop
550 ;; instruction can go in the delay slot.
551
552 ;; Since a normal return (rts) implicitly uses the PR register,
553 ;; we can't allow PR register loads in an rts delay slot.
554
555 (define_delay
556 (eq_attr "type" "return")
557 [(and (eq_attr "in_delay_slot" "yes")
558 (ior (and (eq_attr "interrupt_function" "no")
559 (eq_attr "type" "!pload,prset"))
560 (and (eq_attr "interrupt_function" "yes")
561 (ior
562 (eq (symbol_ref "TARGET_SH3") (const_int 0))
563 (eq_attr "hit_stack" "no")
564 (eq_attr "banked" "no"))))) (nil) (nil)])
565
566 ;; Since a call implicitly uses the PR register, we can't allow
567 ;; a PR register store in a jsr delay slot.
568
569 (define_delay
570 (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
571 [(and (eq_attr "in_delay_slot" "yes")
572 (eq_attr "type" "!pstore,prget")) (nil) (nil)])
573
574 ;; Say that we have annulled true branches, since this gives smaller and
575 ;; faster code when branches are predicted as not taken.
576
577 ;; ??? The non-annulled condition should really be "in_delay_slot",
578 ;; but insns that can be filled in non-annulled get priority over insns
579 ;; that can only be filled in anulled.
580
581 (define_delay
582 (and (eq_attr "type" "cbranch")
583 (ne (symbol_ref "TARGET_SH2") (const_int 0)))
584 ;; SH2e has a hardware bug that pretty much prohibits the use of
585 ;; annuled delay slots.
586 [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
587 (not (eq_attr "cpu" "sh2e"))) (nil)])
588 \f
589 ;; -------------------------------------------------------------------------
590 ;; SImode signed integer comparisons
591 ;; -------------------------------------------------------------------------
592
593 (define_insn ""
594 [(set (reg:SI T_REG)
595 (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
596 (match_operand:SI 1 "logical_operand" "K08,r"))
597 (const_int 0)))]
598 "TARGET_SH1"
599 "tst %1,%0"
600 [(set_attr "type" "mt_group")])
601
602 ;; ??? Perhaps should only accept reg/constant if the register is reg 0.
603 ;; That would still allow reload to create cmpi instructions, but would
604 ;; perhaps allow forcing the constant into a register when that is better.
605 ;; Probably should use r0 for mem/imm compares, but force constant into a
606 ;; register for pseudo/imm compares.
607
608 (define_insn "cmpeqsi_t"
609 [(set (reg:SI T_REG)
610 (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
611 (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
612 "TARGET_SH1"
613 "@
614 tst %0,%0
615 cmp/eq %1,%0
616 cmp/eq %1,%0"
617 [(set_attr "type" "mt_group")])
618
619 (define_insn "cmpgtsi_t"
620 [(set (reg:SI T_REG)
621 (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
622 (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
623 "TARGET_SH1"
624 "@
625 cmp/gt %1,%0
626 cmp/pl %0"
627 [(set_attr "type" "mt_group")])
628
629 (define_insn "cmpgesi_t"
630 [(set (reg:SI T_REG)
631 (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
632 (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
633 "TARGET_SH1"
634 "@
635 cmp/ge %1,%0
636 cmp/pz %0"
637 [(set_attr "type" "mt_group")])
638
639 ;; -------------------------------------------------------------------------
640 ;; SImode compare and branch
641 ;; -------------------------------------------------------------------------
642
643 (define_expand "cbranchsi4"
644 [(set (pc)
645 (if_then_else (match_operator 0 "comparison_operator"
646 [(match_operand:SI 1 "arith_operand" "")
647 (match_operand:SI 2 "arith_operand" "")])
648 (label_ref (match_operand 3 "" ""))
649 (pc)))
650 (clobber (reg:SI T_REG))]
651 ""
652 "if (TARGET_SHMEDIA)
653 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
654 operands[2], operands[3]));
655 else if (TARGET_CBRANCHDI4)
656 expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
657 else
658 sh_emit_compare_and_branch (operands, SImode);
659 DONE;")
660
661 ;; -------------------------------------------------------------------------
662 ;; SImode unsigned integer comparisons
663 ;; -------------------------------------------------------------------------
664
665 (define_insn_and_split "cmpgeusi_t"
666 [(set (reg:SI T_REG)
667 (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
668 (match_operand:SI 1 "arith_reg_or_0_operand" "rN")))]
669 "TARGET_SH1"
670 "cmp/hs %1,%0"
671 "&& operands[1] == CONST0_RTX (SImode)"
672 [(pc)]
673 "
674 {
675 emit_insn (gen_sett ());
676 DONE;
677 }"
678 [(set_attr "type" "mt_group")])
679
680 (define_insn "cmpgtusi_t"
681 [(set (reg:SI T_REG)
682 (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
683 (match_operand:SI 1 "arith_reg_operand" "r")))]
684 "TARGET_SH1"
685 "cmp/hi %1,%0"
686 [(set_attr "type" "mt_group")])
687
688 \f
689 ;; -------------------------------------------------------------------------
690 ;; DImode compare and branch
691 ;; -------------------------------------------------------------------------
692
693
694 ;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
695 ;; Therefore, we aim to have a set of three branches that go straight to the
696 ;; destination, i.e. only one of them is taken at any one time.
697 ;; This mechanism should also be slightly better for the sh4-200.
698
699 (define_expand "cbranchdi4"
700 [(set (pc)
701 (if_then_else (match_operator 0 "comparison_operator"
702 [(match_operand:DI 1 "arith_operand" "")
703 (match_operand:DI 2 "arith_operand" "")])
704 (label_ref (match_operand 3 "" ""))
705 (pc)))
706 (clobber (match_dup 4))
707 (clobber (reg:SI T_REG))]
708 "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
709 "
710 {
711 enum rtx_code comparison;
712
713 if (TARGET_SHMEDIA)
714 {
715 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
716 operands[2], operands[3]));
717 DONE;
718 }
719
720 else if (!TARGET_CBRANCHDI4)
721 {
722 sh_emit_compare_and_branch (operands, DImode);
723 DONE;
724 }
725
726 else
727 {
728 if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
729 DONE;
730
731 comparison = prepare_cbranch_operands (operands, DImode,
732 LAST_AND_UNUSED_RTX_CODE);
733 if (comparison != GET_CODE (operands[0]))
734 operands[0]
735 = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
736 operands[4] = gen_rtx_SCRATCH (SImode);
737 }
738 }")
739
740 (define_insn_and_split "cbranchdi4_i"
741 [(set (pc)
742 (if_then_else (match_operator 0 "comparison_operator"
743 [(match_operand:DI 1 "arith_operand" "r,r")
744 (match_operand:DI 2 "arith_operand" "rN,I08")])
745 (label_ref (match_operand 3 "" ""))
746 (pc)))
747 (clobber (match_scratch:SI 4 "=X,&r"))
748 (clobber (reg:SI T_REG))]
749 "TARGET_CBRANCHDI4"
750 "#"
751 "&& reload_completed"
752 [(pc)]
753 "
754 {
755 if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
756 FAIL;
757 DONE;
758 }")
759
760 ;; -------------------------------------------------------------------------
761 ;; DImode signed integer comparisons
762 ;; -------------------------------------------------------------------------
763
764 (define_insn ""
765 [(set (reg:SI T_REG)
766 (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
767 (match_operand:DI 1 "arith_operand" "r"))
768 (const_int 0)))]
769 "TARGET_SH1"
770 "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",
771 insn, operands);"
772 [(set_attr "length" "6")
773 (set_attr "type" "arith3b")])
774
775 (define_insn "cmpeqdi_t"
776 [(set (reg:SI T_REG)
777 (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
778 (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
779 "TARGET_SH1"
780 "@
781 tst %S0,%S0\;bf %,Ldi%=\;tst %R0,%R0\\n%,Ldi%=:
782 cmp/eq %S1,%S0\;bf %,Ldi%=\;cmp/eq %R1,%R0\\n%,Ldi%=:"
783 [(set_attr "length" "6")
784 (set_attr "type" "arith3b")])
785
786 (define_split
787 [(set (reg:SI T_REG)
788 (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
789 (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
790 ;; If we applied this split when not optimizing, it would only be
791 ;; applied during the machine-dependent reorg, when no new basic blocks
792 ;; may be created.
793 "TARGET_SH1 && reload_completed && optimize"
794 [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
795 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
796 (label_ref (match_dup 6))
797 (pc)))
798 (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
799 (match_dup 6)]
800 "
801 {
802 operands[2]
803 = gen_rtx_REG (SImode,
804 true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
805 operands[3]
806 = (operands[1] == const0_rtx
807 ? const0_rtx
808 : gen_rtx_REG (SImode,
809 true_regnum (operands[1])
810 + (TARGET_LITTLE_ENDIAN ? 1 : 0)));
811 operands[4] = gen_lowpart (SImode, operands[0]);
812 operands[5] = gen_lowpart (SImode, operands[1]);
813 operands[6] = gen_label_rtx ();
814 }")
815
816 (define_insn "cmpgtdi_t"
817 [(set (reg:SI T_REG)
818 (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
819 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
820 "TARGET_SH2"
821 "@
822 cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:
823 tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"
824 [(set_attr "length" "8")
825 (set_attr "type" "arith3")])
826
827 (define_insn "cmpgedi_t"
828 [(set (reg:SI T_REG)
829 (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
830 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
831 "TARGET_SH2"
832 "@
833 cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:
834 cmp/pz\\t%S0"
835 [(set_attr "length" "8,2")
836 (set_attr "type" "arith3,mt_group")])
837 \f
838 ;; -------------------------------------------------------------------------
839 ;; DImode unsigned integer comparisons
840 ;; -------------------------------------------------------------------------
841
842 (define_insn "cmpgeudi_t"
843 [(set (reg:SI T_REG)
844 (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
845 (match_operand:DI 1 "arith_reg_operand" "r")))]
846 "TARGET_SH2"
847 "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"
848 [(set_attr "length" "8")
849 (set_attr "type" "arith3")])
850
851 (define_insn "cmpgtudi_t"
852 [(set (reg:SI T_REG)
853 (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
854 (match_operand:DI 1 "arith_reg_operand" "r")))]
855 "TARGET_SH2"
856 "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"
857 [(set_attr "length" "8")
858 (set_attr "type" "arith3")])
859
860 (define_insn "cmpeqsi_media"
861 [(set (match_operand:SI 0 "register_operand" "=r")
862 (eq:SI (match_operand:SI 1 "logical_operand" "%r")
863 (match_operand:SI 2 "cmp_operand" "Nr")))]
864 "TARGET_SHMEDIA"
865 "cmpeq %1, %N2, %0"
866 [(set_attr "type" "cmp_media")])
867
868 (define_insn "cmpeqdi_media"
869 [(set (match_operand:SI 0 "register_operand" "=r")
870 (eq:SI (match_operand:DI 1 "register_operand" "%r")
871 (match_operand:DI 2 "cmp_operand" "Nr")))]
872 "TARGET_SHMEDIA"
873 "cmpeq %1, %N2, %0"
874 [(set_attr "type" "cmp_media")])
875
876 (define_insn "cmpgtsi_media"
877 [(set (match_operand:SI 0 "register_operand" "=r")
878 (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
879 (match_operand:SI 2 "cmp_operand" "rN")))]
880 "TARGET_SHMEDIA"
881 "cmpgt %N1, %N2, %0"
882 [(set_attr "type" "cmp_media")])
883
884 (define_insn "cmpgtdi_media"
885 [(set (match_operand:SI 0 "register_operand" "=r")
886 (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
887 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
888 "TARGET_SHMEDIA"
889 "cmpgt %N1, %N2, %0"
890 [(set_attr "type" "cmp_media")])
891
892 (define_insn "cmpgtusi_media"
893 [(set (match_operand:SI 0 "register_operand" "=r")
894 (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
895 (match_operand:SI 2 "cmp_operand" "rN")))]
896 "TARGET_SHMEDIA"
897 "cmpgtu %N1, %N2, %0"
898 [(set_attr "type" "cmp_media")])
899
900 (define_insn "cmpgtudi_media"
901 [(set (match_operand:SI 0 "register_operand" "=r")
902 (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
903 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
904 "TARGET_SHMEDIA"
905 "cmpgtu %N1, %N2, %0"
906 [(set_attr "type" "cmp_media")])
907
908 ; These two patterns are for combine.
909 (define_insn "*cmpne0sisi_media"
910 [(set (match_operand:SI 0 "register_operand" "=r")
911 (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
912 "TARGET_SHMEDIA"
913 "cmpgtu %1,r63,%0"
914 [(set_attr "type" "cmp_media")])
915
916 ;; -------------------------------------------------------------------------
917 ;; Conditional move instructions
918 ;; -------------------------------------------------------------------------
919
920 ;; The insn names may seem reversed, but note that cmveq performs the move
921 ;; if op1 == 0, and cmvne does it if op1 != 0.
922
923 (define_insn "movdicc_false"
924 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
925 (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
926 (const_int 0))
927 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
928 (match_operand:DI 3 "arith_reg_operand" "0")))]
929 "TARGET_SHMEDIA"
930 "cmveq %1, %N2, %0"
931 [(set_attr "type" "arith_media")])
932
933 (define_insn "movdicc_true"
934 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
935 (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
936 (const_int 0))
937 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
938 (match_operand:DI 3 "arith_reg_operand" "0")))]
939 "TARGET_SHMEDIA"
940 "cmvne %1, %N2, %0"
941 [(set_attr "type" "arith_media")])
942
943 (define_peephole2
944 [(set (match_operand:DI 0 "arith_reg_dest" "")
945 (if_then_else:DI (match_operator 3 "equality_comparison_operator"
946 [(match_operand:DI 1 "arith_reg_operand" "")
947 (const_int 0)])
948 (match_operand:DI 2 "arith_reg_dest" "")
949 (match_dup 0)))
950 (set (match_dup 2) (match_dup 0))]
951 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
952 [(set (match_dup 2)
953 (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
954 "
955 {
956 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
957 VOIDmode, operands[1], CONST0_RTX (DImode));
958 }")
959
960 (define_peephole2
961 [(set (match_operand:DI 0 "general_movdst_operand" "")
962 (match_operand:DI 1 "arith_reg_or_0_operand" ""))
963 (set (match_operand:DI 2 "arith_reg_dest" "")
964 (if_then_else:DI (match_operator 4 "equality_comparison_operator"
965 [(match_operand:DI 3 "arith_reg_operand" "")
966 (const_int 0)])
967 (match_dup 0)
968 (match_dup 2)))]
969 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
970 [(set (match_dup 2)
971 (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
972 "")
973
974 (define_expand "movdicc"
975 [(set (match_operand:DI 0 "register_operand" "")
976 (if_then_else:DI (match_operand 1 "comparison_operator" "")
977 (match_operand:DI 2 "register_operand" "")
978 (match_operand:DI 3 "register_operand" "")))]
979 "TARGET_SHMEDIA"
980 "
981 {
982 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
983 && GET_MODE (XEXP (operands[1], 0)) == DImode
984 && XEXP (operands[1], 1) == const0_rtx)
985 ;
986 else
987 {
988 if (!can_create_pseudo_p ())
989 FAIL;
990
991 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
992 GET_CODE (operands[1]),
993 XEXP (operands[1], 0),
994 XEXP (operands[1], 1));
995 if (!operands[1])
996 FAIL;
997 }
998 }")
999
1000 ;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1001 ;; SImode to DImode.
1002 (define_insn "movsicc_false"
1003 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1004 (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1005 (const_int 0))
1006 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1007 (match_operand:SI 3 "arith_reg_operand" "0")))]
1008 "TARGET_SHMEDIA"
1009 "cmveq %1, %N2, %0"
1010 [(set_attr "type" "arith_media")])
1011
1012 (define_insn "movsicc_true"
1013 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1014 (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1015 (const_int 0))
1016 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1017 (match_operand:SI 3 "arith_reg_operand" "0")))]
1018 "TARGET_SHMEDIA"
1019 "cmvne %1, %N2, %0"
1020 [(set_attr "type" "arith_media")])
1021
1022 (define_peephole2
1023 [(set (match_operand:SI 0 "arith_reg_dest" "")
1024 (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1025 [(match_operand:SI 1 "arith_reg_operand" "")
1026 (const_int 0)])
1027 (match_operand:SI 2 "arith_reg_dest" "")
1028 (match_dup 0)))
1029 (set (match_dup 2) (match_dup 0))]
1030 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1031 [(set (match_dup 2)
1032 (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1033 "
1034 {
1035 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1036 VOIDmode, operands[1], CONST0_RTX (SImode));
1037 }")
1038
1039 (define_peephole2
1040 [(set (match_operand:SI 0 "general_movdst_operand" "")
1041 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1042 (set (match_operand:SI 2 "arith_reg_dest" "")
1043 (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1044 [(match_operand:SI 3 "arith_reg_operand" "")
1045 (const_int 0)])
1046 (match_dup 0)
1047 (match_dup 2)))]
1048 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1049 && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1050 [(set (match_dup 2)
1051 (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1052 "
1053 {
1054 replace_rtx (operands[4], operands[0], operands[1]);
1055 }")
1056
1057 (define_peephole2
1058 [(set (match_operand 0 "any_register_operand" "")
1059 (match_operand 1 "any_register_operand" ""))
1060 (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1061 (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1062 "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1063 <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1064 && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1065 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1066 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1067 && ! reg_overlap_mentioned_p (operands[0], operands[3])
1068 && ! reg_overlap_mentioned_p (operands[2], operands[0])
1069 && ! reg_overlap_mentioned_p (operands[0], operands[1])
1070 && (REGNO_REG_CLASS (REGNO (operands[0]))
1071 == REGNO_REG_CLASS (REGNO (operands[2])))
1072 && (REGNO_REG_CLASS (REGNO (operands[1]))
1073 == REGNO_REG_CLASS (REGNO (operands[0])))"
1074 [(set (match_dup 0) (match_dup 3))
1075 (set (match_dup 4) (match_dup 5))]
1076 "
1077 {
1078 rtx set1, set2, insn2;
1079 rtx replacements[4];
1080
1081 /* We want to replace occurrences of operands[0] with operands[1] and
1082 operands[2] with operands[0] in operands[4]/operands[5].
1083 Doing just two replace_rtx calls naively would result in the second
1084 replacement undoing all that the first did if operands[1] and operands[2]
1085 are identical, so we must do this simultaneously. */
1086 replacements[0] = operands[0];
1087 replacements[1] = operands[1];
1088 replacements[2] = operands[2];
1089 replacements[3] = operands[0];
1090 if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1091 || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1092 || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1093 FAIL;
1094
1095 operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1096 replace_n_hard_rtx (operands[4], replacements, 2, 1);
1097 operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1098 /* The operands array is aliased to recog_data.operand, which gets
1099 clobbered by extract_insn, so finish with it now. */
1100 set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1101 set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1102 /* ??? The last insn might be a jump insn, but the generic peephole2 code
1103 always uses emit_insn. */
1104 /* Check that we don't violate matching constraints or earlyclobbers. */
1105 extract_insn (emit_insn (set1));
1106 if (! constrain_operands (1))
1107 goto failure;
1108 insn2 = emit (set2);
1109 if (GET_CODE (insn2) == BARRIER)
1110 goto failure;
1111 extract_insn (insn2);
1112 if (! constrain_operands (1))
1113 {
1114 rtx tmp;
1115 failure:
1116 tmp = replacements[0];
1117 replacements[0] = replacements[1];
1118 replacements[1] = tmp;
1119 tmp = replacements[2];
1120 replacements[2] = replacements[3];
1121 replacements[3] = tmp;
1122 replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1123 replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1124 replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1125 FAIL;
1126 }
1127 DONE;
1128 }")
1129
1130 ;; The register allocator is rather clumsy in handling multi-way conditional
1131 ;; moves, so allow the combiner to make them, and we split them up after
1132 ;; reload. */
1133 (define_insn_and_split "*movsicc_umin"
1134 [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1135 (umin:SI (if_then_else:SI
1136 (eq (match_operand:SI 1 "arith_reg_operand" "r")
1137 (const_int 0))
1138 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1139 (match_operand:SI 3 "register_operand" "0"))
1140 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1141 (clobber (match_scratch:SI 5 "=&r"))]
1142 "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1143 "#"
1144 "TARGET_SHMEDIA && reload_completed"
1145 [(pc)]
1146 "
1147 {
1148 emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1149 operands[3]));
1150 emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1151 emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1152 operands[0]));
1153 DONE;
1154 }")
1155
1156 (define_insn "*movsicc_t_false"
1157 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1158 (if_then_else (eq (reg:SI T_REG) (const_int 0))
1159 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1160 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1161 "TARGET_PRETEND_CMOVE
1162 && (arith_reg_operand (operands[1], SImode)
1163 || (immediate_operand (operands[1], SImode)
1164 && satisfies_constraint_I08 (operands[1])))"
1165 "bt 0f\;mov %1,%0\\n0:"
1166 [(set_attr "type" "mt_group,arith") ;; poor approximation
1167 (set_attr "length" "4")])
1168
1169 (define_insn "*movsicc_t_true"
1170 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1171 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1172 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1173 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1174 "TARGET_PRETEND_CMOVE
1175 && (arith_reg_operand (operands[1], SImode)
1176 || (immediate_operand (operands[1], SImode)
1177 && satisfies_constraint_I08 (operands[1])))"
1178 "bf 0f\;mov %1,%0\\n0:"
1179 [(set_attr "type" "mt_group,arith") ;; poor approximation
1180 (set_attr "length" "4")])
1181
1182 (define_expand "movsicc"
1183 [(set (match_operand:SI 0 "arith_reg_dest" "")
1184 (if_then_else:SI (match_operand 1 "comparison_operator" "")
1185 (match_operand:SI 2 "arith_reg_or_0_operand" "")
1186 (match_operand:SI 3 "arith_reg_operand" "")))]
1187 "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1188 "
1189 {
1190 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1191 && GET_MODE (XEXP (operands[1], 0)) == SImode
1192 && (TARGET_SHMEDIA
1193 || (REG_P (XEXP (operands[1], 0))
1194 && REGNO (XEXP (operands[1], 0)) == T_REG))
1195 && XEXP (operands[1], 1) == const0_rtx)
1196 ;
1197
1198 else if (TARGET_PRETEND_CMOVE)
1199 {
1200 enum rtx_code code = GET_CODE (operands[1]);
1201 enum rtx_code new_code = code;
1202 rtx op0 = XEXP (operands[1], 0);
1203 rtx op1 = XEXP (operands[1], 1);
1204
1205 if (! currently_expanding_to_rtl)
1206 FAIL;
1207 switch (code)
1208 {
1209 case LT: case LE: case LEU: case LTU:
1210 if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1211 break;
1212 case NE:
1213 new_code = reverse_condition (code);
1214 break;
1215 case EQ: case GT: case GE: case GEU: case GTU:
1216 break;
1217 default:
1218 FAIL;
1219 }
1220 sh_emit_scc_to_t (new_code, op0, op1);
1221 operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1222 gen_rtx_REG (SImode, T_REG), const0_rtx);
1223 }
1224 else
1225 {
1226 if (!can_create_pseudo_p ())
1227 FAIL;
1228
1229 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1230 GET_CODE (operands[1]),
1231 XEXP (operands[1], 0),
1232 XEXP (operands[1], 1));
1233 if (!operands[1])
1234 FAIL;
1235 }
1236 }")
1237
1238 (define_expand "movqicc"
1239 [(set (match_operand:QI 0 "register_operand" "")
1240 (if_then_else:QI (match_operand 1 "comparison_operator" "")
1241 (match_operand:QI 2 "register_operand" "")
1242 (match_operand:QI 3 "register_operand" "")))]
1243 "TARGET_SHMEDIA"
1244 "
1245 {
1246 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1247 operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1248 operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1249 emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1250 DONE;
1251 }")
1252 \f
1253 ;; -------------------------------------------------------------------------
1254 ;; Addition instructions
1255 ;; -------------------------------------------------------------------------
1256
1257 (define_expand "adddi3"
1258 [(set (match_operand:DI 0 "arith_reg_operand" "")
1259 (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1260 (match_operand:DI 2 "arith_operand" "")))]
1261 ""
1262 "
1263 {
1264 if (TARGET_SH1)
1265 {
1266 if (!can_create_pseudo_p () && ! arith_reg_operand (operands[2], DImode))
1267 FAIL;
1268 operands[2] = force_reg (DImode, operands[2]);
1269 emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1270 DONE;
1271 }
1272 }")
1273
1274 (define_insn "*adddi3_media"
1275 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1276 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1277 (match_operand:DI 2 "arith_operand" "r,I10")))]
1278 "TARGET_SHMEDIA"
1279 "@
1280 add %1, %2, %0
1281 addi %1, %2, %0"
1282 [(set_attr "type" "arith_media")])
1283
1284 (define_insn "*adddisi3_media"
1285 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1286 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1287 (match_operand:DI 2 "arith_operand" "r,I10")))]
1288 "TARGET_SHMEDIA"
1289 "@
1290 add.l %1, %2, %0
1291 addi.l %1, %2, %0"
1292 [(set_attr "type" "arith_media")
1293 (set_attr "highpart" "ignore")])
1294
1295 (define_insn "adddi3z_media"
1296 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1297 (zero_extend:DI
1298 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1299 (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1300 "TARGET_SHMEDIA"
1301 "addz.l %1, %N2, %0"
1302 [(set_attr "type" "arith_media")
1303 (set_attr "highpart" "ignore")])
1304
1305 (define_insn "adddi3_compact"
1306 [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1307 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1308 (match_operand:DI 2 "arith_reg_operand" "r")))
1309 (clobber (reg:SI T_REG))]
1310 "TARGET_SH1"
1311 "#"
1312 [(set_attr "length" "6")])
1313
1314 (define_split
1315 [(set (match_operand:DI 0 "arith_reg_dest" "")
1316 (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1317 (match_operand:DI 2 "arith_reg_operand" "")))
1318 (clobber (reg:SI T_REG))]
1319 "TARGET_SH1 && reload_completed"
1320 [(const_int 0)]
1321 "
1322 {
1323 rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1324 high0 = gen_rtx_REG (SImode,
1325 true_regnum (operands[0])
1326 + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1327 high2 = gen_rtx_REG (SImode,
1328 true_regnum (operands[2])
1329 + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1330 emit_insn (gen_clrt ());
1331 emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
1332 emit_insn (gen_addc1 (high0, high0, high2));
1333 DONE;
1334 }")
1335
1336 (define_insn "addc"
1337 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1338 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1339 (match_operand:SI 2 "arith_reg_operand" "r"))
1340 (reg:SI T_REG)))
1341 (set (reg:SI T_REG)
1342 (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1343 "TARGET_SH1"
1344 "addc %2,%0"
1345 [(set_attr "type" "arith")])
1346
1347 (define_insn "addc1"
1348 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1349 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1350 (match_operand:SI 2 "arith_reg_operand" "r"))
1351 (reg:SI T_REG)))
1352 (clobber (reg:SI T_REG))]
1353 "TARGET_SH1"
1354 "addc %2,%0"
1355 [(set_attr "type" "arith")])
1356
1357 (define_expand "addsi3"
1358 [(set (match_operand:SI 0 "arith_reg_operand" "")
1359 (plus:SI (match_operand:SI 1 "arith_operand" "")
1360 (match_operand:SI 2 "arith_operand" "")))]
1361 ""
1362 "
1363 {
1364 if (TARGET_SHMEDIA)
1365 operands[1] = force_reg (SImode, operands[1]);
1366 }")
1367
1368 (define_insn "addsi3_media"
1369 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1370 (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1371 (match_operand:SI 2 "arith_operand" "r,I10")))]
1372 "TARGET_SHMEDIA"
1373 "@
1374 add.l %1, %2, %0
1375 addi.l %1, %2, %0"
1376 [(set_attr "type" "arith_media")
1377 (set_attr "highpart" "ignore")])
1378
1379 (define_insn "addsidi3_media"
1380 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1381 (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
1382 "%r,r")
1383 (match_operand:SI 2 "arith_operand"
1384 "r,I10"))))]
1385 "TARGET_SHMEDIA"
1386 "@
1387 add.l %1, %2, %0
1388 addi.l %1, %2, %0"
1389 [(set_attr "type" "arith_media")
1390 (set_attr "highpart" "ignore")])
1391
1392 (define_insn "*addsi3_compact"
1393 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1394 (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1395 (match_operand:SI 2 "arith_operand" "rI08")))]
1396 "TARGET_SH1"
1397 "add %2,%0"
1398 [(set_attr "type" "arith")])
1399
1400 ;; -------------------------------------------------------------------------
1401 ;; Subtraction instructions
1402 ;; -------------------------------------------------------------------------
1403
1404 (define_expand "subdi3"
1405 [(set (match_operand:DI 0 "arith_reg_operand" "")
1406 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1407 (match_operand:DI 2 "arith_reg_operand" "")))]
1408 ""
1409 "
1410 {
1411 if (TARGET_SH1)
1412 {
1413 operands[1] = force_reg (DImode, operands[1]);
1414 emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1415 DONE;
1416 }
1417 }")
1418
1419 (define_insn "*subdi3_media"
1420 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1421 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1422 (match_operand:DI 2 "arith_reg_operand" "r")))]
1423 "TARGET_SHMEDIA"
1424 "sub %N1, %2, %0"
1425 [(set_attr "type" "arith_media")])
1426
1427 (define_insn "subdisi3_media"
1428 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
1429 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1430 (match_operand:DI 2 "arith_reg_operand" "r")))]
1431 "TARGET_SHMEDIA"
1432 "sub.l %N1, %2, %0"
1433 [(set_attr "type" "arith_media")
1434 (set_attr "highpart" "ignore")])
1435
1436 (define_insn "subdi3_compact"
1437 [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1438 (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1439 (match_operand:DI 2 "arith_reg_operand" "r")))
1440 (clobber (reg:SI T_REG))]
1441 "TARGET_SH1"
1442 "#"
1443 [(set_attr "length" "6")])
1444
1445 (define_split
1446 [(set (match_operand:DI 0 "arith_reg_dest" "")
1447 (minus:DI (match_operand:DI 1 "arith_reg_operand" "")
1448 (match_operand:DI 2 "arith_reg_operand" "")))
1449 (clobber (reg:SI T_REG))]
1450 "TARGET_SH1 && reload_completed"
1451 [(const_int 0)]
1452 "
1453 {
1454 rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1455 high0 = gen_rtx_REG (SImode,
1456 true_regnum (operands[0])
1457 + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1458 high2 = gen_rtx_REG (SImode,
1459 true_regnum (operands[2])
1460 + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1461 emit_insn (gen_clrt ());
1462 emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1463 emit_insn (gen_subc1 (high0, high0, high2));
1464 DONE;
1465 }")
1466
1467 (define_insn "subc"
1468 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1469 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1470 (match_operand:SI 2 "arith_reg_operand" "r"))
1471 (reg:SI T_REG)))
1472 (set (reg:SI T_REG)
1473 (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1474 (reg:SI T_REG))
1475 (match_dup 1)))]
1476 "TARGET_SH1"
1477 "subc %2,%0"
1478 [(set_attr "type" "arith")])
1479
1480 (define_insn "subc1"
1481 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1482 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1483 (match_operand:SI 2 "arith_reg_operand" "r"))
1484 (reg:SI T_REG)))
1485 (clobber (reg:SI T_REG))]
1486 "TARGET_SH1"
1487 "subc %2,%0"
1488 [(set_attr "type" "arith")])
1489
1490 ;; life_analysis thinks rn is live before subc rn,rn, so make a special
1491 ;; pattern for this case. This helps multimedia applications that compute
1492 ;; the sum of absolute differences.
1493 (define_insn "mov_neg_si_t"
1494 [(set (match_operand:SI 0 "arith_reg_dest" "=r") (neg:SI (reg:SI T_REG)))]
1495 "TARGET_SH1"
1496 "subc %0,%0"
1497 [(set_attr "type" "arith")])
1498
1499 (define_insn "*subsi3_internal"
1500 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1501 (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1502 (match_operand:SI 2 "arith_reg_operand" "r")))]
1503 "TARGET_SH1"
1504 "sub %2,%0"
1505 [(set_attr "type" "arith")])
1506
1507 (define_insn_and_split "*subsi3_media"
1508 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1509 (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
1510 (match_operand:SI 2 "extend_reg_operand" "r")))]
1511 "TARGET_SHMEDIA
1512 && (operands[1] != constm1_rtx
1513 || (GET_CODE (operands[2]) != TRUNCATE
1514 && GET_CODE (operands[2]) != SUBREG))"
1515 "sub.l %N1, %2, %0"
1516 "operands[1] == constm1_rtx"
1517 [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
1518 ""
1519 [(set_attr "type" "arith_media")
1520 (set_attr "highpart" "ignore")])
1521
1522 (define_split
1523 [(set (match_operand:SI 0 "arith_reg_dest" "")
1524 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1525 "general_extend_operand"
1526 "") 0)) 0)))]
1527 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
1528 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1529 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1530 "")
1531
1532 (define_split
1533 [(set (match_operand:SI 0 "arith_reg_dest" "")
1534 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1535 "general_extend_operand"
1536 "") 0)) 3)))]
1537 "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
1538 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1539 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1540 "")
1541 ;; Convert `constant - reg' to `neg rX; add rX, #const' since this
1542 ;; will sometimes save one instruction. Otherwise we might get
1543 ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
1544 ;; are the same.
1545
1546 (define_expand "subsi3"
1547 [(set (match_operand:SI 0 "arith_reg_operand" "")
1548 (minus:SI (match_operand:SI 1 "arith_operand" "")
1549 (match_operand:SI 2 "arith_reg_operand" "")))]
1550 ""
1551 "
1552 {
1553 if (TARGET_SH1 && CONST_INT_P (operands[1]))
1554 {
1555 emit_insn (gen_negsi2 (operands[0], operands[2]));
1556 emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
1557 DONE;
1558 }
1559 if (TARGET_SHMEDIA)
1560 {
1561 if (!can_create_pseudo_p ()
1562 && ! arith_reg_or_0_operand (operands[1], SImode))
1563 FAIL;
1564 if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
1565 operands[1] = force_reg (SImode, operands[1]);
1566 }
1567 }")
1568 \f
1569 ;; -------------------------------------------------------------------------
1570 ;; Division instructions
1571 ;; -------------------------------------------------------------------------
1572
1573 ;; We take advantage of the library routines which don't clobber as many
1574 ;; registers as a normal function call would.
1575
1576 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
1577 ;; also has an effect on the register that holds the address of the sfunc.
1578 ;; To make this work, we have an extra dummy insn that shows the use
1579 ;; of this register for reorg.
1580
1581 (define_insn "use_sfunc_addr"
1582 [(set (reg:SI PR_REG)
1583 (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
1584 "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
1585 ""
1586 [(set_attr "length" "0")])
1587
1588 (define_insn "udivsi3_sh2a"
1589 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1590 (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
1591 (match_operand:SI 2 "arith_reg_operand" "z")))]
1592 "TARGET_SH2A"
1593 "divu %2,%1"
1594 [(set_attr "type" "arith")
1595 (set_attr "in_delay_slot" "no")])
1596
1597 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
1598 ;; hard register 0. If we used hard register 0, then the next instruction
1599 ;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg
1600 ;; gets allocated to a stack slot that needs its address reloaded, then
1601 ;; there is nothing to prevent reload from using r0 to reload the address.
1602 ;; This reload would clobber the value in r0 we are trying to store.
1603 ;; If we let reload allocate r0, then this problem can never happen.
1604
1605 (define_insn "udivsi3_i1"
1606 [(set (match_operand:SI 0 "register_operand" "=z")
1607 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1608 (clobber (reg:SI T_REG))
1609 (clobber (reg:SI PR_REG))
1610 (clobber (reg:SI R4_REG))
1611 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1612 "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
1613 "jsr @%1%#"
1614 [(set_attr "type" "sfunc")
1615 (set_attr "needs_delay_slot" "yes")])
1616
1617 ; Since shmedia-nofpu code could be linked against shcompact code, and
1618 ; the udivsi3 libcall has the same name, we must consider all registers
1619 ; clobbered that are in the union of the registers clobbered by the
1620 ; shmedia and the shcompact implementation. Note, if the shcompact
1621 ; implementation actually used shcompact code, we'd need to clobber
1622 ; also r23 and fr23.
1623 (define_insn "udivsi3_i1_media"
1624 [(set (match_operand:SI 0 "register_operand" "=z")
1625 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1626 (clobber (reg:SI T_MEDIA_REG))
1627 (clobber (reg:SI PR_MEDIA_REG))
1628 (clobber (reg:SI R20_REG))
1629 (clobber (reg:SI R21_REG))
1630 (clobber (reg:SI R22_REG))
1631 (clobber (reg:DI TR0_REG))
1632 (clobber (reg:DI TR1_REG))
1633 (clobber (reg:DI TR2_REG))
1634 (use (match_operand 1 "target_reg_operand" "b"))]
1635 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1636 "blink %1, r18"
1637 [(set_attr "type" "sfunc")
1638 (set_attr "needs_delay_slot" "yes")])
1639
1640 (define_expand "udivsi3_i4_media"
1641 [(set (match_dup 3)
1642 (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
1643 (set (match_dup 4)
1644 (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1645 (set (match_dup 5) (float:DF (match_dup 3)))
1646 (set (match_dup 6) (float:DF (match_dup 4)))
1647 (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
1648 (set (match_dup 8) (fix:DI (match_dup 7)))
1649 (set (match_operand:SI 0 "register_operand" "")
1650 (truncate:SI (match_dup 8)))]
1651 "TARGET_SHMEDIA_FPU"
1652 "
1653 {
1654 operands[3] = gen_reg_rtx (DImode);
1655 operands[4] = gen_reg_rtx (DImode);
1656 operands[5] = gen_reg_rtx (DFmode);
1657 operands[6] = gen_reg_rtx (DFmode);
1658 operands[7] = gen_reg_rtx (DFmode);
1659 operands[8] = gen_reg_rtx (DImode);
1660 }")
1661
1662 (define_insn "udivsi3_i4"
1663 [(set (match_operand:SI 0 "register_operand" "=y")
1664 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1665 (clobber (reg:SI T_REG))
1666 (clobber (reg:SI PR_REG))
1667 (clobber (reg:DF DR0_REG))
1668 (clobber (reg:DF DR2_REG))
1669 (clobber (reg:DF DR4_REG))
1670 (clobber (reg:SI R0_REG))
1671 (clobber (reg:SI R1_REG))
1672 (clobber (reg:SI R4_REG))
1673 (clobber (reg:SI R5_REG))
1674 (use (reg:PSI FPSCR_REG))
1675 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1676 "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1677 "jsr @%1%#"
1678 [(set_attr "type" "sfunc")
1679 (set_attr "fp_mode" "double")
1680 (set_attr "needs_delay_slot" "yes")])
1681
1682 (define_insn "udivsi3_i4_single"
1683 [(set (match_operand:SI 0 "register_operand" "=y")
1684 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1685 (clobber (reg:SI T_REG))
1686 (clobber (reg:SI PR_REG))
1687 (clobber (reg:DF DR0_REG))
1688 (clobber (reg:DF DR2_REG))
1689 (clobber (reg:DF DR4_REG))
1690 (clobber (reg:SI R0_REG))
1691 (clobber (reg:SI R1_REG))
1692 (clobber (reg:SI R4_REG))
1693 (clobber (reg:SI R5_REG))
1694 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1695 "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1696 "jsr @%1%#"
1697 [(set_attr "type" "sfunc")
1698 (set_attr "needs_delay_slot" "yes")])
1699
1700 (define_insn "udivsi3_i4_int"
1701 [(set (match_operand:SI 0 "register_operand" "=z")
1702 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1703 (clobber (reg:SI T_REG))
1704 (clobber (reg:SI R1_REG))
1705 (clobber (reg:SI PR_REG))
1706 (clobber (reg:SI MACH_REG))
1707 (clobber (reg:SI MACL_REG))
1708 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1709 "TARGET_SH1"
1710 "jsr @%1%#"
1711 [(set_attr "type" "sfunc")
1712 (set_attr "needs_delay_slot" "yes")])
1713
1714
1715 (define_expand "udivsi3"
1716 [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
1717 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1718 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1719 (parallel [(set (match_operand:SI 0 "register_operand" "")
1720 (udiv:SI (reg:SI R4_REG)
1721 (reg:SI R5_REG)))
1722 (clobber (reg:SI T_REG))
1723 (clobber (reg:SI PR_REG))
1724 (clobber (reg:SI R4_REG))
1725 (use (match_dup 3))])]
1726 ""
1727 "
1728 {
1729 rtx last;
1730
1731 operands[3] = gen_reg_rtx (Pmode);
1732 /* Emit the move of the address to a pseudo outside of the libcall. */
1733 if (TARGET_DIVIDE_CALL_TABLE)
1734 {
1735 /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
1736 that causes problems when the divide code is supposed to come from a
1737 separate library. Division by zero is undefined, so dividing 1 can be
1738 implemented by comparing with the divisor. */
1739 if (operands[1] == const1_rtx && currently_expanding_to_rtl)
1740 {
1741 rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
1742 emit_insn (gen_cstoresi4 (operands[0], test,
1743 operands[1], operands[2]));
1744 DONE;
1745 }
1746 else if (operands[2] == const0_rtx)
1747 {
1748 emit_move_insn (operands[0], operands[2]);
1749 DONE;
1750 }
1751 function_symbol (operands[3], \"__udivsi3_i4i\", SFUNC_GOT);
1752 last = gen_udivsi3_i4_int (operands[0], operands[3]);
1753 }
1754 else if (TARGET_DIVIDE_CALL_FP)
1755 {
1756 function_symbol (operands[3], \"__udivsi3_i4\", SFUNC_STATIC);
1757 if (TARGET_FPU_SINGLE)
1758 last = gen_udivsi3_i4_single (operands[0], operands[3]);
1759 else
1760 last = gen_udivsi3_i4 (operands[0], operands[3]);
1761 }
1762 else if (TARGET_SHMEDIA_FPU)
1763 {
1764 operands[1] = force_reg (SImode, operands[1]);
1765 operands[2] = force_reg (SImode, operands[2]);
1766 emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
1767 DONE;
1768 }
1769 else if (TARGET_SH2A)
1770 {
1771 operands[1] = force_reg (SImode, operands[1]);
1772 operands[2] = force_reg (SImode, operands[2]);
1773 emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
1774 DONE;
1775 }
1776 else if (TARGET_SH5)
1777 {
1778 function_symbol (operands[3],
1779 TARGET_FPU_ANY ? \"__udivsi3_i4\" : \"__udivsi3\",
1780 SFUNC_STATIC);
1781
1782 if (TARGET_SHMEDIA)
1783 last = gen_udivsi3_i1_media (operands[0], operands[3]);
1784 else if (TARGET_FPU_ANY)
1785 last = gen_udivsi3_i4_single (operands[0], operands[3]);
1786 else
1787 last = gen_udivsi3_i1 (operands[0], operands[3]);
1788 }
1789 else
1790 {
1791 function_symbol (operands[3], \"__udivsi3\", SFUNC_STATIC);
1792 last = gen_udivsi3_i1 (operands[0], operands[3]);
1793 }
1794 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1795 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1796 emit_insn (last);
1797 DONE;
1798 }")
1799
1800 (define_insn "divsi3_sh2a"
1801 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1802 (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
1803 (match_operand:SI 2 "arith_reg_operand" "z")))]
1804 "TARGET_SH2A"
1805 "divs %2,%1"
1806 [(set_attr "type" "arith")
1807 (set_attr "in_delay_slot" "no")])
1808
1809 (define_insn "divsi3_i1"
1810 [(set (match_operand:SI 0 "register_operand" "=z")
1811 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1812 (clobber (reg:SI T_REG))
1813 (clobber (reg:SI PR_REG))
1814 (clobber (reg:SI R1_REG))
1815 (clobber (reg:SI R2_REG))
1816 (clobber (reg:SI R3_REG))
1817 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1818 "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
1819 "jsr @%1%#"
1820 [(set_attr "type" "sfunc")
1821 (set_attr "needs_delay_slot" "yes")])
1822
1823 (define_insn "divsi3_i1_media"
1824 [(set (match_operand:SI 0 "register_operand" "=z")
1825 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1826 (clobber (reg:SI T_MEDIA_REG))
1827 (clobber (reg:SI PR_MEDIA_REG))
1828 (clobber (reg:SI R1_REG))
1829 (clobber (reg:SI R20_REG))
1830 (clobber (reg:SI R21_REG))
1831 (clobber (reg:SI TR0_REG))
1832 (use (match_operand 1 "target_reg_operand" "b"))]
1833 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1834 "blink %1, r18"
1835 [(set_attr "type" "sfunc")])
1836
1837 (define_insn "divsi3_media_2"
1838 [(set (match_operand:SI 0 "register_operand" "=z")
1839 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1840 (clobber (reg:SI T_MEDIA_REG))
1841 (clobber (reg:SI PR_MEDIA_REG))
1842 (clobber (reg:SI R1_REG))
1843 (clobber (reg:SI R21_REG))
1844 (clobber (reg:SI TR0_REG))
1845 (use (reg:SI R20_REG))
1846 (use (match_operand 1 "target_reg_operand" "b"))]
1847 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1848 "blink %1, r18"
1849 [(set_attr "type" "sfunc")])
1850
1851 ;; This pattern acts as a placeholder for -mdiv=inv:call to carry
1852 ;; hard reg clobbers and data dependencies that we need when we want
1853 ;; to rematerialize the division into a call.
1854 (define_insn_and_split "divsi_inv_call"
1855 [(set (match_operand:SI 0 "register_operand" "=r")
1856 (div:SI (match_operand:SI 1 "register_operand" "r")
1857 (match_operand:SI 2 "register_operand" "r")))
1858 (clobber (reg:SI R4_REG))
1859 (clobber (reg:SI R5_REG))
1860 (clobber (reg:SI T_MEDIA_REG))
1861 (clobber (reg:SI PR_MEDIA_REG))
1862 (clobber (reg:SI R1_REG))
1863 (clobber (reg:SI R21_REG))
1864 (clobber (reg:SI TR0_REG))
1865 (clobber (reg:SI R20_REG))
1866 (use (match_operand:SI 3 "register_operand" "r"))]
1867 "TARGET_SHMEDIA"
1868 "#"
1869 "&& (high_life_started || reload_completed)"
1870 [(set (match_dup 0) (match_dup 3))]
1871 ""
1872 [(set_attr "highpart" "must_split")])
1873
1874 ;; This is the combiner pattern for -mdiv=inv:call .
1875 (define_insn_and_split "*divsi_inv_call_combine"
1876 [(set (match_operand:SI 0 "register_operand" "=z")
1877 (div:SI (match_operand:SI 1 "register_operand" "r")
1878 (match_operand:SI 2 "register_operand" "r")))
1879 (clobber (reg:SI R4_REG))
1880 (clobber (reg:SI R5_REG))
1881 (clobber (reg:SI T_MEDIA_REG))
1882 (clobber (reg:SI PR_MEDIA_REG))
1883 (clobber (reg:SI R1_REG))
1884 (clobber (reg:SI R21_REG))
1885 (clobber (reg:SI TR0_REG))
1886 (clobber (reg:SI R20_REG))
1887 (use (unspec:SI [(match_dup 1)
1888 (match_operand:SI 3 "" "")
1889 (unspec:SI [(match_operand:SI 4 "" "")
1890 (match_dup 3)
1891 (match_operand:DI 5 "" "")]
1892 UNSPEC_DIV_INV_M2)
1893 (match_operand:DI 6 "" "")
1894 (const_int 0)
1895 (const_int 0)]
1896 UNSPEC_DIV_INV_M3))]
1897 "TARGET_SHMEDIA"
1898 "#"
1899 "&& (high_life_started || reload_completed)"
1900 [(pc)]
1901 "
1902 {
1903 const char *name = sh_divsi3_libfunc;
1904 enum sh_function_kind kind = SFUNC_GOT;
1905 rtx sym;
1906
1907 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
1908 emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
1909 while (TARGET_DIVIDE_INV_CALL2)
1910 {
1911 rtx x = operands[3];
1912
1913 if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
1914 break;
1915 x = XVECEXP (x, 0, 0);
1916 name = \"__sdivsi3_2\";
1917 kind = SFUNC_STATIC;
1918 emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
1919 break;
1920 }
1921 sym = function_symbol (NULL, name, kind);
1922 emit_insn (gen_divsi3_media_2 (operands[0], sym));
1923 DONE;
1924 }"
1925 [(set_attr "highpart" "must_split")])
1926
1927 (define_expand "divsi3_i4_media"
1928 [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
1929 (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
1930 (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
1931 (set (match_operand:SI 0 "register_operand" "=r")
1932 (fix:SI (match_dup 5)))]
1933 "TARGET_SHMEDIA_FPU"
1934 "
1935 {
1936 operands[3] = gen_reg_rtx (DFmode);
1937 operands[4] = gen_reg_rtx (DFmode);
1938 operands[5] = gen_reg_rtx (DFmode);
1939 }")
1940
1941 (define_insn "divsi3_i4"
1942 [(set (match_operand:SI 0 "register_operand" "=y")
1943 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1944 (clobber (reg:SI PR_REG))
1945 (clobber (reg:DF DR0_REG))
1946 (clobber (reg:DF DR2_REG))
1947 (use (reg:PSI FPSCR_REG))
1948 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1949 "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1950 "jsr @%1%#"
1951 [(set_attr "type" "sfunc")
1952 (set_attr "fp_mode" "double")
1953 (set_attr "needs_delay_slot" "yes")])
1954
1955 (define_insn "divsi3_i4_single"
1956 [(set (match_operand:SI 0 "register_operand" "=y")
1957 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1958 (clobber (reg:SI PR_REG))
1959 (clobber (reg:DF DR0_REG))
1960 (clobber (reg:DF DR2_REG))
1961 (clobber (reg:SI R2_REG))
1962 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1963 "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1964 "jsr @%1%#"
1965 [(set_attr "type" "sfunc")
1966 (set_attr "needs_delay_slot" "yes")])
1967
1968 (define_insn "divsi3_i4_int"
1969 [(set (match_operand:SI 0 "register_operand" "=z")
1970 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1971 (clobber (reg:SI T_REG))
1972 (clobber (reg:SI PR_REG))
1973 (clobber (reg:SI R1_REG))
1974 (clobber (reg:SI MACH_REG))
1975 (clobber (reg:SI MACL_REG))
1976 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1977 "TARGET_SH1"
1978 "jsr @%1%#"
1979 [(set_attr "type" "sfunc")
1980 (set_attr "needs_delay_slot" "yes")])
1981
1982 (define_expand "divsi3"
1983 [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
1984 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1985 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1986 (parallel [(set (match_operand:SI 0 "register_operand" "")
1987 (div:SI (reg:SI R4_REG)
1988 (reg:SI R5_REG)))
1989 (clobber (reg:SI T_REG))
1990 (clobber (reg:SI PR_REG))
1991 (clobber (reg:SI R1_REG))
1992 (clobber (reg:SI R2_REG))
1993 (clobber (reg:SI R3_REG))
1994 (use (match_dup 3))])]
1995 ""
1996 "
1997 {
1998 rtx last;
1999
2000 operands[3] = gen_reg_rtx (Pmode);
2001 /* Emit the move of the address to a pseudo outside of the libcall. */
2002 if (TARGET_DIVIDE_CALL_TABLE)
2003 {
2004 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2005 last = gen_divsi3_i4_int (operands[0], operands[3]);
2006 }
2007 else if (TARGET_DIVIDE_CALL_FP)
2008 {
2009 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2010 if (TARGET_FPU_SINGLE)
2011 last = gen_divsi3_i4_single (operands[0], operands[3]);
2012 else
2013 last = gen_divsi3_i4 (operands[0], operands[3]);
2014 }
2015 else if (TARGET_SH2A)
2016 {
2017 operands[1] = force_reg (SImode, operands[1]);
2018 operands[2] = force_reg (SImode, operands[2]);
2019 emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2020 DONE;
2021 }
2022 else if (TARGET_DIVIDE_INV)
2023 {
2024 rtx dividend = operands[1];
2025 rtx divisor = operands[2];
2026 rtx tab_base;
2027 rtx nsb_res = gen_reg_rtx (DImode);
2028 rtx norm64 = gen_reg_rtx (DImode);
2029 rtx tab_ix = gen_reg_rtx (DImode);
2030 rtx norm32 = gen_reg_rtx (SImode);
2031 rtx i92 = force_reg (DImode, GEN_INT (92));
2032 rtx scratch0a = gen_reg_rtx (DImode);
2033 rtx scratch0b = gen_reg_rtx (DImode);
2034 rtx inv0 = gen_reg_rtx (SImode);
2035 rtx scratch1a = gen_reg_rtx (DImode);
2036 rtx scratch1b = gen_reg_rtx (DImode);
2037 rtx shift = gen_reg_rtx (DImode);
2038 rtx i2p27, i43;
2039 rtx inv1 = gen_reg_rtx (SImode);
2040 rtx scratch2a = gen_reg_rtx (DImode);
2041 rtx scratch2b = gen_reg_rtx (SImode);
2042 rtx inv2 = gen_reg_rtx (SImode);
2043 rtx scratch3a = gen_reg_rtx (DImode);
2044 rtx scratch3b = gen_reg_rtx (DImode);
2045 rtx scratch3c = gen_reg_rtx (DImode);
2046 rtx scratch3d = gen_reg_rtx (SImode);
2047 rtx scratch3e = gen_reg_rtx (DImode);
2048 rtx result = gen_reg_rtx (SImode);
2049
2050 if (! arith_reg_or_0_operand (dividend, SImode))
2051 dividend = force_reg (SImode, dividend);
2052 if (! arith_reg_operand (divisor, SImode))
2053 divisor = force_reg (SImode, divisor);
2054 if (flag_pic && Pmode != DImode)
2055 {
2056 tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2057 tab_base = gen_datalabel_ref (tab_base);
2058 tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2059 }
2060 else
2061 {
2062 tab_base = gen_rtx_SYMBOL_REF (DImode, \"__div_table\");
2063 tab_base = gen_datalabel_ref (tab_base);
2064 tab_base = force_reg (DImode, tab_base);
2065 }
2066 if (TARGET_DIVIDE_INV20U)
2067 i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2068 else
2069 i2p27 = GEN_INT (0);
2070 if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2071 i43 = force_reg (DImode, GEN_INT (43));
2072 else
2073 i43 = GEN_INT (0);
2074 emit_insn (gen_nsbdi (nsb_res,
2075 simplify_gen_subreg (DImode, divisor, SImode, 0)));
2076 emit_insn (gen_ashldi3_media (norm64,
2077 gen_rtx_SUBREG (DImode, divisor, 0),
2078 nsb_res));
2079 emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2080 emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2081 emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2082 inv0, scratch0a, scratch0b,
2083 scratch1a, scratch1b));
2084 emit_insn (gen_subdi3 (shift, i92, nsb_res));
2085 emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2086 scratch2a));
2087 emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2088 i2p27, i43,
2089 scratch3a, scratch3b, scratch3c,
2090 scratch2a, scratch2b, scratch3d, scratch3e));
2091 if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2092 emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2093 else if (TARGET_DIVIDE_INV_FP)
2094 emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2095 gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2096 gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2097 gen_reg_rtx (DFmode)));
2098 else
2099 emit_move_insn (operands[0], result);
2100 DONE;
2101 }
2102 else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2103 {
2104 operands[1] = force_reg (SImode, operands[1]);
2105 operands[2] = force_reg (SImode, operands[2]);
2106 emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2107 DONE;
2108 }
2109 else if (TARGET_SH5)
2110 {
2111 if (TARGET_DIVIDE_CALL2)
2112 {
2113 rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2114 tab_base = gen_datalabel_ref (tab_base);
2115 emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2116 }
2117 if (TARGET_FPU_ANY && TARGET_SH1)
2118 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2119 else if (TARGET_DIVIDE_CALL2)
2120 function_symbol (operands[3], \"__sdivsi3_2\", SFUNC_STATIC);
2121 else
2122 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2123
2124 if (TARGET_SHMEDIA)
2125 last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2126 (operands[0], operands[3]));
2127 else if (TARGET_FPU_ANY)
2128 last = gen_divsi3_i4_single (operands[0], operands[3]);
2129 else
2130 last = gen_divsi3_i1 (operands[0], operands[3]);
2131 }
2132 else
2133 {
2134 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2135 last = gen_divsi3_i1 (operands[0], operands[3]);
2136 }
2137 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2138 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2139 emit_insn (last);
2140 DONE;
2141 }")
2142
2143 ;; operands: scratch, tab_base, tab_ix
2144 ;; These are unspecs because we could generate an indexed addressing mode
2145 ;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2146 ;; confuse reload. See PR27117.
2147
2148 (define_insn "divsi_inv_qitable"
2149 [(set (match_operand:DI 0 "register_operand" "=r")
2150 (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2151 (match_operand:DI 2 "register_operand" "r")]
2152 UNSPEC_DIV_INV_TABLE)))]
2153 "TARGET_SHMEDIA"
2154 "@
2155 ldx.ub %1, %2, %0"
2156 [(set_attr "type" "load_media")
2157 (set_attr "highpart" "user")])
2158
2159 ;; operands: scratch, tab_base, tab_ix
2160 (define_insn "divsi_inv_hitable"
2161 [(set (match_operand:DI 0 "register_operand" "=r")
2162 (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2163 (match_operand:DI 2 "register_operand" "r")]
2164 UNSPEC_DIV_INV_TABLE)))]
2165 "TARGET_SHMEDIA"
2166 "@
2167 ldx.w %1, %2, %0"
2168 [(set_attr "type" "load_media")
2169 (set_attr "highpart" "user")])
2170
2171 ;; operands: inv0, tab_base, tab_ix, norm32
2172 ;; scratch equiv in sdivsi3_2: r19, r21
2173 (define_expand "divsi_inv_m0"
2174 [(set (match_operand:SI 0 "register_operand" "=r")
2175 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2176 (match_operand:DI 2 "register_operand" "r")
2177 (match_operand:SI 3 "register_operand" "r")]
2178 UNSPEC_DIV_INV_M0))
2179 (clobber (match_operand:DI 4 "register_operand" "=r"))
2180 (clobber (match_operand:DI 5 "register_operand" "=r"))]
2181 "TARGET_SHMEDIA"
2182 "
2183 {
2184 /*
2185 tab_base: r20
2186 tab_ix: r21
2187 norm32: r25
2188 ldx.ub r20, r21, r19 // u0.8
2189 shlli r21, 1, r21
2190 muls.l r25, r19, r19 // s2.38
2191 ldx.w r20, r21, r21 // s2.14
2192 shari r19, 24, r19 // truncate to s2.14
2193 sub r21, r19, r19 // some 11 bit inverse in s1.14
2194 */
2195
2196 rtx inv0 = operands[0];
2197 rtx tab_base = operands[1];
2198 rtx tab_ix = operands[2];
2199 rtx norm32 = operands[3];
2200 rtx scratch0 = operands[4];
2201 rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2202 rtx scratch1 = operands[5];
2203
2204 emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2205 emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2206 emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2207 emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2208 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2209 emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2210 DONE;
2211 }")
2212
2213 ;; operands: inv1, tab_base, tab_ix, norm32
2214 (define_insn_and_split "divsi_inv_m1"
2215 [(set (match_operand:SI 0 "register_operand" "=r")
2216 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2217 (match_operand:DI 2 "register_operand" "r")
2218 (match_operand:SI 3 "register_operand" "r")]
2219 UNSPEC_DIV_INV_M1))
2220 (clobber (match_operand:SI 4 "register_operand" "=r"))
2221 (clobber (match_operand:DI 5 "register_operand" "=r"))
2222 (clobber (match_operand:DI 6 "register_operand" "=r"))
2223 (clobber (match_operand:DI 7 "register_operand" "=r"))
2224 (clobber (match_operand:DI 8 "register_operand" "=r"))]
2225 "TARGET_SHMEDIA"
2226 "#"
2227 "&& !can_create_pseudo_p ()"
2228 [(pc)]
2229 "
2230 {
2231 /* inv0: r19
2232 muls.l r19, r19, r18 // u0.28
2233 muls.l r25, r18, r18 // s2.58
2234 shlli r19, 45, r0 // multiply by two and convert to s2.58
2235 sub r0, r18, r18
2236 shari r18, 28, r18 // some 18 bit inverse in s1.30
2237 */
2238
2239 rtx inv1 = operands[0];
2240 rtx tab_base = operands[1];
2241 rtx tab_ix = operands[2];
2242 rtx norm32 = operands[3];
2243 rtx inv0 = operands[4];
2244 rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2245 rtx scratch0a = operands[5];
2246 rtx scratch0b = operands[6];
2247 rtx scratch0 = operands[7];
2248 rtx scratch1 = operands[8];
2249 rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2250
2251 emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2252 scratch0a, scratch0b));
2253 emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2254 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2255 emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2256 emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2257 emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2258 DONE;
2259 }")
2260
2261 ;; operands: inv2, norm32, inv1, i92
2262 (define_insn_and_split "divsi_inv_m2"
2263 [(set (match_operand:SI 0 "register_operand" "=r")
2264 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2265 (match_operand:SI 2 "register_operand" "r")
2266 (match_operand:DI 3 "register_operand" "r")]
2267 UNSPEC_DIV_INV_M2))
2268 (clobber (match_operand:DI 4 "register_operand" "=r"))]
2269 "TARGET_SHMEDIA"
2270 "#"
2271 "&& !can_create_pseudo_p ()"
2272 [(pc)]
2273 "
2274 {
2275 /*
2276 muls.l r18, r25, r0 // s2.60
2277 shari r0, 16, r0 // s-16.44
2278 sub
2279 muls.l r0, r18, r19 // s-16.74
2280 shari r19, 30, r19 // s-16.44
2281 */
2282 rtx inv2 = operands[0];
2283 rtx norm32 = operands[1];
2284 rtx inv1 = operands[2];
2285 rtx i92 = operands[3];
2286 rtx scratch0 = operands[4];
2287 rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2288
2289 emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2290 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2291 emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2292 emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2293 emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2294 DONE;
2295 }")
2296
2297 (define_insn_and_split "divsi_inv_m3"
2298 [(set (match_operand:SI 0 "register_operand" "=r")
2299 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2300 (match_operand:SI 2 "register_operand" "r")
2301 (match_operand:SI 3 "register_operand" "r")
2302 (match_operand:DI 4 "register_operand" "r")
2303 (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
2304 (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
2305 UNSPEC_DIV_INV_M3))
2306 (clobber (match_operand:DI 7 "register_operand" "=r"))
2307 (clobber (match_operand:DI 8 "register_operand" "=r"))
2308 (clobber (match_operand:DI 9 "register_operand" "=r"))
2309 (clobber (match_operand:DI 10 "register_operand" "=r"))
2310 (clobber (match_operand:SI 11 "register_operand" "=r"))
2311 (clobber (match_operand:SI 12 "register_operand" "=r"))
2312 (clobber (match_operand:DI 13 "register_operand" "=r"))]
2313 "TARGET_SHMEDIA"
2314 "#"
2315 "&& !can_create_pseudo_p ()"
2316 [(pc)]
2317 "
2318 {
2319 /*
2320 r0: result r1: shift r4: dividend r18: inv1 r19: inv2
2321 r0: scratch0 r19: scratch1 r21: scratch2
2322
2323 muls.l r18, r4, r25 // s32.30
2324 muls.l r19, r4, r19 // s15.30
2325 shari r25, 63, r21
2326 shari r19, 14, r19 // s18.-14
2327 sub r25, r19, r0
2328 shard r0, r1, r0
2329 sub r0, r21, r0
2330 */
2331
2332 rtx result = operands[0];
2333 rtx dividend = operands[1];
2334 rtx inv1 = operands[2];
2335 rtx inv2 = operands[3];
2336 rtx shift = operands[4];
2337 rtx scratch0 = operands[7];
2338 rtx scratch1 = operands[8];
2339 rtx scratch2 = operands[9];
2340
2341 if (satisfies_constraint_N (dividend))
2342 {
2343 emit_move_insn (result, dividend);
2344 DONE;
2345 }
2346
2347 emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
2348 emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
2349 emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
2350 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
2351 emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
2352 emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
2353 emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
2354 DONE;
2355 }")
2356
2357 ;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
2358 ;; inv1: tab_base, tab_ix, norm32
2359 ;; inv2: norm32, inv1, i92
2360 (define_insn_and_split "divsi_inv_m1_3"
2361 [(set (match_operand:SI 0 "register_operand" "=r")
2362 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2363 (unspec:SI [(match_operand:DI 2 "register_operand" "r")
2364 (match_operand:DI 3 "register_operand" "r")
2365 (match_operand:SI 4 "register_operand" "r")]
2366 UNSPEC_DIV_INV_M1)
2367 (unspec:SI [(match_dup 4)
2368 (unspec:SI [(match_dup 2)
2369 (match_dup 3)
2370 (match_dup 4)] UNSPEC_DIV_INV_M1)
2371 (match_operand:SI 5 "" "")]
2372 UNSPEC_DIV_INV_M2)
2373 (match_operand:DI 6 "register_operand" "r")
2374 (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
2375 (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
2376 UNSPEC_DIV_INV_M3))
2377 (clobber (match_operand:DI 9 "register_operand" "=r"))
2378 (clobber (match_operand:DI 10 "register_operand" "=r"))
2379 (clobber (match_operand:DI 11 "register_operand" "=r"))
2380 (clobber (match_operand:DI 12 "register_operand" "=r"))
2381 (clobber (match_operand:SI 13 "register_operand" "=r"))
2382 (clobber (match_operand:SI 14 "register_operand" "=r"))
2383 (clobber (match_operand:DI 15 "register_operand" "=r"))]
2384 "TARGET_SHMEDIA
2385 && (TARGET_DIVIDE_INV_MINLAT
2386 || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2387 "#"
2388 "&& !can_create_pseudo_p ()"
2389 [(pc)]
2390 "
2391 {
2392 rtx result = operands[0];
2393 rtx dividend = operands[1];
2394 rtx tab_base = operands[2];
2395 rtx tab_ix = operands[3];
2396 rtx norm32 = operands[4];
2397 /* rtx i92 = operands[5]; */
2398 rtx shift = operands[6];
2399 rtx i2p27 = operands[7];
2400 rtx i43 = operands[8];
2401 rtx scratch0 = operands[9];
2402 rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2403 rtx scratch1 = operands[10];
2404 rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2405 rtx scratch2 = operands[11];
2406 rtx scratch3 = operands[12];
2407 rtx scratch4 = operands[13];
2408 rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
2409 rtx scratch5 = operands[14];
2410 rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
2411 rtx scratch6 = operands[15];
2412
2413 emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
2414 scratch0, scratch1));
2415 /* inv0 == scratch4 */
2416 if (! TARGET_DIVIDE_INV20U)
2417 {
2418 emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
2419 i2p27 = scratch0;
2420 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
2421 }
2422 else
2423 {
2424 emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
2425 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2426 }
2427 emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
2428 emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
2429 emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
2430 /* inv1 == scratch4 */
2431
2432 if (TARGET_DIVIDE_INV_MINLAT)
2433 {
2434 emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
2435 emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
2436 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
2437 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
2438 emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
2439 emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
2440 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
2441 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
2442 emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
2443 emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
2444 emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
2445 }
2446 else
2447 {
2448 rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
2449 /* Use separate scratch regs for nsb and sign to allow scheduling. */
2450 emit_insn (gen_nsbdi (scratch6,
2451 simplify_gen_subreg (DImode, dividend, SImode, 0)));
2452 emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
2453 emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
2454 emit_insn (gen_divsi_inv20 (scratch2,
2455 norm32, scratch4, dividend,
2456 scratch6, scratch3, i43,
2457 /* scratch0 may be shared with i2p27. */
2458 scratch0, scratch1, scratch5,
2459 label, label, i2p27));
2460 }
2461 emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
2462 emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
2463 DONE;
2464 }")
2465
2466 (define_insn "divsi_inv20"
2467 [(set (match_operand:DI 0 "register_operand" "=&r")
2468 (unspec:DI [(match_operand:SI 1 "register_operand" "r")
2469 (match_operand:SI 2 "register_operand" "r")
2470 (match_operand:SI 3 "register_operand" "r")
2471 (match_operand:DI 4 "register_operand" "r")
2472 (match_operand:DI 5 "register_operand" "r")
2473 (match_operand:DI 6 "register_operand" "r")
2474 (match_operand:DI 12 "register_operand" "r")
2475 (match_operand 10 "target_operand" "b")
2476 (match_operand 11 "immediate_operand" "i")]
2477 UNSPEC_DIV_INV20))
2478 (clobber (match_operand:DI 7 "register_operand" "=&r"))
2479 (clobber (match_operand:DI 8 "register_operand" "=&r"))
2480 (clobber (match_operand:SI 9 "register_operand" "=r"))]
2481 "TARGET_SHMEDIA
2482 && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2483 "*
2484 {
2485 /* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
2486 %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
2487 %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
2488 %10 label (tr), %11 label (imm)
2489
2490 muls.l inv1, norm32, scratch0 // s2.60
2491 muls.l inv1, dividend, result // s32.30
2492 xor i2p27, result_sign, round_scratch
2493 bge/u dividend_nsb, i43, tr.. (label)
2494 shari scratch0, 16, scratch0 // s-16.44
2495 muls.l sratch0_si, inv1, scratch0 // s-16.74
2496 sub result, round_scratch, result
2497 shari dividend, 14, scratch1 // s19.-14
2498 shari scratch0, 30, scratch0 // s-16.44
2499 muls.l scratch0, scratch1, round_scratch // s15.30
2500 label:
2501 sub result, round_scratch, result */
2502
2503 int likely = TARGET_DIVIDE_INV20L;
2504
2505 if (! likely) output_asm_insn (\"muls.l\t%2, %1 , %8\", operands);
2506 output_asm_insn (\"muls.l\t%2, %3, %0\;xor\t%12, %5, %7\", operands);
2507 output_asm_insn (likely
2508 ? \"bge/l\t%4, %6, %10\;muls.l\t%2, %1 , %8\"
2509 : \"bge/u\t%4, %6, %10\", operands);
2510 output_asm_insn (\"shari\t%8, 16, %8\;muls.l\t%8, %2, %8\", operands);
2511 if (! likely) output_asm_insn (\"sub\t%0, %7, %0\", operands);
2512 output_asm_insn (\"shari\t%3, 14, %9\;shari\t%8, 30, %8\", operands);
2513 return (likely
2514 ? \"muls.l\t%8, %9, %8\;sub\t%0, %8, %0\n%11:\tadd\t%0, %7, %0\"
2515 : \"muls.l\t%8, %9, %7\n%11:\tsub\t%0, %7, %0\");
2516 }")
2517
2518 (define_insn_and_split "divsi_inv_fp"
2519 [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
2520 (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
2521 (match_operand:SI 2 "register_operand" "rf")))
2522 (use (match_operand:SI 3 "general_movsrc_operand" "r"))
2523 (clobber (match_operand:SI 4 "register_operand" "=r"))
2524 (clobber (match_operand:SI 5 "register_operand" "=r"))
2525 (clobber (match_operand:DF 6 "register_operand" "=r"))
2526 (clobber (match_operand:DF 7 "register_operand" "=r"))
2527 (clobber (match_operand:DF 8 "register_operand" "=r"))]
2528 "TARGET_SHMEDIA_FPU"
2529 "#"
2530 "&& (high_life_started || reload_completed)"
2531 [(set (match_dup 0) (match_dup 3))]
2532 ""
2533 [(set_attr "highpart" "must_split")])
2534
2535 ;; If a matching group of divide-by-inverse instructions is in the same
2536 ;; basic block after gcse & loop optimizations, we want to transform them
2537 ;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
2538 (define_insn_and_split "*divsi_inv_fp_combine"
2539 [(set (match_operand:SI 0 "register_operand" "=f")
2540 (div:SI (match_operand:SI 1 "register_operand" "f")
2541 (match_operand:SI 2 "register_operand" "f")))
2542 (use (unspec:SI [(match_dup 1)
2543 (match_operand:SI 3 "" "")
2544 (unspec:SI [(match_operand:SI 4 "" "")
2545 (match_dup 3)
2546 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
2547 (match_operand:DI 6 "" "")
2548 (const_int 0)
2549 (const_int 0)] UNSPEC_DIV_INV_M3))
2550 (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
2551 (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
2552 (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
2553 (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
2554 (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
2555 "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
2556 "#"
2557 "&& 1"
2558 [(set (match_dup 9) (float:DF (match_dup 1)))
2559 (set (match_dup 10) (float:DF (match_dup 2)))
2560 (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
2561 (set (match_dup 8)
2562 (fix:SI (match_dup 11)))
2563 (set (match_dup 0) (match_dup 8))]
2564 "
2565 {
2566 if (! fp_arith_reg_operand (operands[1], SImode))
2567 {
2568 emit_move_insn (operands[7], operands[1]);
2569 operands[1] = operands[7];
2570 }
2571 if (! fp_arith_reg_operand (operands[2], SImode))
2572 {
2573 emit_move_insn (operands[8], operands[2]);
2574 operands[2] = operands[8];
2575 }
2576 }"
2577 [(set_attr "highpart" "must_split")])
2578 \f
2579 ;; -------------------------------------------------------------------------
2580 ;; Multiplication instructions
2581 ;; -------------------------------------------------------------------------
2582
2583 (define_insn "umulhisi3_i"
2584 [(set (reg:SI MACL_REG)
2585 (mult:SI (zero_extend:SI
2586 (match_operand:HI 0 "arith_reg_operand" "r"))
2587 (zero_extend:SI
2588 (match_operand:HI 1 "arith_reg_operand" "r"))))]
2589 "TARGET_SH1"
2590 "mulu.w %1,%0"
2591 [(set_attr "type" "smpy")])
2592
2593 (define_insn "mulhisi3_i"
2594 [(set (reg:SI MACL_REG)
2595 (mult:SI (sign_extend:SI
2596 (match_operand:HI 0 "arith_reg_operand" "r"))
2597 (sign_extend:SI
2598 (match_operand:HI 1 "arith_reg_operand" "r"))))]
2599 "TARGET_SH1"
2600 "muls.w %1,%0"
2601 [(set_attr "type" "smpy")])
2602
2603 (define_expand "mulhisi3"
2604 [(set (reg:SI MACL_REG)
2605 (mult:SI (sign_extend:SI
2606 (match_operand:HI 1 "arith_reg_operand" ""))
2607 (sign_extend:SI
2608 (match_operand:HI 2 "arith_reg_operand" ""))))
2609 (set (match_operand:SI 0 "arith_reg_operand" "")
2610 (reg:SI MACL_REG))]
2611 "TARGET_SH1"
2612 "
2613 {
2614 rtx insn, macl;
2615
2616 macl = gen_rtx_REG (SImode, MACL_REG);
2617 start_sequence ();
2618 emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
2619 insn = get_insns ();
2620 end_sequence ();
2621 /* expand_binop can't find a suitable code in umul_widen_optab to
2622 make a REG_EQUAL note from, so make one here.
2623 See also smulsi3_highpart.
2624 ??? Alternatively, we could put this at the calling site of expand_binop,
2625 i.e. expand_expr. */
2626 /* Use emit_libcall_block for loop invariant code motion and to make
2627 a REG_EQUAL note. */
2628 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
2629
2630 DONE;
2631 }")
2632
2633 (define_expand "umulhisi3"
2634 [(set (reg:SI MACL_REG)
2635 (mult:SI (zero_extend:SI
2636 (match_operand:HI 1 "arith_reg_operand" ""))
2637 (zero_extend:SI
2638 (match_operand:HI 2 "arith_reg_operand" ""))))
2639 (set (match_operand:SI 0 "arith_reg_operand" "")
2640 (reg:SI MACL_REG))]
2641 "TARGET_SH1"
2642 "
2643 {
2644 rtx insn, macl;
2645
2646 macl = gen_rtx_REG (SImode, MACL_REG);
2647 start_sequence ();
2648 emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
2649 insn = get_insns ();
2650 end_sequence ();
2651 /* expand_binop can't find a suitable code in umul_widen_optab to
2652 make a REG_EQUAL note from, so make one here.
2653 See also smulsi3_highpart.
2654 ??? Alternatively, we could put this at the calling site of expand_binop,
2655 i.e. expand_expr. */
2656 /* Use emit_libcall_block for loop invariant code motion and to make
2657 a REG_EQUAL note. */
2658 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
2659
2660 DONE;
2661 }")
2662
2663 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
2664 ;; a call to a routine which clobbers known registers.
2665
2666 (define_insn ""
2667 [(set (match_operand:SI 1 "register_operand" "=z")
2668 (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2669 (clobber (reg:SI MACL_REG))
2670 (clobber (reg:SI T_REG))
2671 (clobber (reg:SI PR_REG))
2672 (clobber (reg:SI R3_REG))
2673 (clobber (reg:SI R2_REG))
2674 (clobber (reg:SI R1_REG))
2675 (use (match_operand:SI 0 "arith_reg_operand" "r"))]
2676 "TARGET_SH1"
2677 "jsr @%0%#"
2678 [(set_attr "type" "sfunc")
2679 (set_attr "needs_delay_slot" "yes")])
2680
2681 (define_expand "mulsi3_call"
2682 [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2683 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2684 (parallel[(set (match_operand:SI 0 "register_operand" "")
2685 (mult:SI (reg:SI R4_REG)
2686 (reg:SI R5_REG)))
2687 (clobber (reg:SI MACL_REG))
2688 (clobber (reg:SI T_REG))
2689 (clobber (reg:SI PR_REG))
2690 (clobber (reg:SI R3_REG))
2691 (clobber (reg:SI R2_REG))
2692 (clobber (reg:SI R1_REG))
2693 (use (match_operand:SI 3 "register_operand" ""))])]
2694 "TARGET_SH1"
2695 "")
2696
2697 (define_insn "mul_r"
2698 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2699 (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
2700 (match_operand:SI 2 "arith_reg_operand" "z")))]
2701 "TARGET_SH2A"
2702 "mulr %2,%0"
2703 [(set_attr "type" "dmpy")])
2704
2705 (define_insn "mul_l"
2706 [(set (reg:SI MACL_REG)
2707 (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
2708 (match_operand:SI 1 "arith_reg_operand" "r")))]
2709 "TARGET_SH2"
2710 "mul.l %1,%0"
2711 [(set_attr "type" "dmpy")])
2712
2713 (define_expand "mulsi3"
2714 [(set (reg:SI MACL_REG)
2715 (mult:SI (match_operand:SI 1 "arith_reg_operand" "")
2716 (match_operand:SI 2 "arith_reg_operand" "")))
2717 (set (match_operand:SI 0 "arith_reg_operand" "")
2718 (reg:SI MACL_REG))]
2719 "TARGET_SH1"
2720 "
2721 {
2722 if (!TARGET_SH2)
2723 {
2724 /* The address must be set outside the libcall,
2725 since it goes into a pseudo. */
2726 rtx sym = function_symbol (NULL, \"__mulsi3\", SFUNC_STATIC);
2727 rtx addr = force_reg (SImode, sym);
2728 rtx insns = gen_mulsi3_call (operands[0], operands[1],
2729 operands[2], addr);
2730 emit_insn (insns);
2731 }
2732 else
2733 {
2734 rtx macl = gen_rtx_REG (SImode, MACL_REG);
2735
2736 emit_insn (gen_mul_l (operands[1], operands[2]));
2737 /* consec_sets_giv can only recognize the first insn that sets a
2738 giv as the giv insn. So we must tag this also with a REG_EQUAL
2739 note. */
2740 emit_insn (gen_movsi_i ((operands[0]), macl));
2741 }
2742 DONE;
2743 }")
2744
2745 (define_insn "mulsidi3_i"
2746 [(set (reg:SI MACH_REG)
2747 (truncate:SI
2748 (lshiftrt:DI
2749 (mult:DI
2750 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2751 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2752 (const_int 32))))
2753 (set (reg:SI MACL_REG)
2754 (mult:SI (match_dup 0)
2755 (match_dup 1)))]
2756 "TARGET_SH2"
2757 "dmuls.l %1,%0"
2758 [(set_attr "type" "dmpy")])
2759
2760 (define_expand "mulsidi3"
2761 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2762 (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2763 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2764 "TARGET_SH2 || TARGET_SHMEDIA"
2765 "
2766 {
2767 if (TARGET_SH2)
2768 {
2769 emit_insn (gen_mulsidi3_compact (operands[0], operands[1],
2770 operands[2]));
2771 DONE;
2772 }
2773 }")
2774
2775 (define_insn "mulsidi3_media"
2776 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2777 (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2778 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2779 "TARGET_SHMEDIA"
2780 "muls.l %1, %2, %0"
2781 [(set_attr "type" "dmpy_media")
2782 (set_attr "highpart" "ignore")])
2783
2784 (define_insn "mulsidi3_compact"
2785 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2786 (mult:DI
2787 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2788 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2789 (clobber (reg:SI MACH_REG))
2790 (clobber (reg:SI MACL_REG))]
2791 "TARGET_SH2"
2792 "#")
2793
2794 (define_split
2795 [(set (match_operand:DI 0 "arith_reg_dest" "")
2796 (mult:DI
2797 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2798 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2799 (clobber (reg:SI MACH_REG))
2800 (clobber (reg:SI MACL_REG))]
2801 "TARGET_SH2"
2802 [(const_int 0)]
2803 "
2804 {
2805 rtx low_dst = gen_lowpart (SImode, operands[0]);
2806 rtx high_dst = gen_highpart (SImode, operands[0]);
2807
2808 emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
2809
2810 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
2811 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
2812 /* We need something to tag the possible REG_EQUAL notes on to. */
2813 emit_move_insn (operands[0], operands[0]);
2814 DONE;
2815 }")
2816
2817 (define_insn "umulsidi3_i"
2818 [(set (reg:SI MACH_REG)
2819 (truncate:SI
2820 (lshiftrt:DI
2821 (mult:DI
2822 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2823 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2824 (const_int 32))))
2825 (set (reg:SI MACL_REG)
2826 (mult:SI (match_dup 0)
2827 (match_dup 1)))]
2828 "TARGET_SH2"
2829 "dmulu.l %1,%0"
2830 [(set_attr "type" "dmpy")])
2831
2832 (define_expand "umulsidi3"
2833 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2834 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2835 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2836 "TARGET_SH2 || TARGET_SHMEDIA"
2837 "
2838 {
2839 if (TARGET_SH2)
2840 {
2841 emit_insn (gen_umulsidi3_compact (operands[0], operands[1],
2842 operands[2]));
2843 DONE;
2844 }
2845 }")
2846
2847 (define_insn "umulsidi3_media"
2848 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2849 (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2850 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2851 "TARGET_SHMEDIA"
2852 "mulu.l %1, %2, %0"
2853 [(set_attr "type" "dmpy_media")
2854 (set_attr "highpart" "ignore")])
2855
2856 (define_insn "umulsidi3_compact"
2857 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2858 (mult:DI
2859 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2860 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2861 (clobber (reg:SI MACH_REG))
2862 (clobber (reg:SI MACL_REG))]
2863 "TARGET_SH2"
2864 "#")
2865
2866 (define_split
2867 [(set (match_operand:DI 0 "arith_reg_dest" "")
2868 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2869 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2870 (clobber (reg:SI MACH_REG))
2871 (clobber (reg:SI MACL_REG))]
2872 "TARGET_SH2"
2873 [(const_int 0)]
2874 "
2875 {
2876 rtx low_dst = gen_lowpart (SImode, operands[0]);
2877 rtx high_dst = gen_highpart (SImode, operands[0]);
2878
2879 emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
2880
2881 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
2882 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
2883 /* We need something to tag the possible REG_EQUAL notes on to. */
2884 emit_move_insn (operands[0], operands[0]);
2885 DONE;
2886 }")
2887
2888 (define_insn "smulsi3_highpart_i"
2889 [(set (reg:SI MACH_REG)
2890 (truncate:SI
2891 (lshiftrt:DI
2892 (mult:DI
2893 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2894 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2895 (const_int 32))))
2896 (clobber (reg:SI MACL_REG))]
2897 "TARGET_SH2"
2898 "dmuls.l %1,%0"
2899 [(set_attr "type" "dmpy")])
2900
2901 (define_expand "smulsi3_highpart"
2902 [(parallel
2903 [(set (reg:SI MACH_REG)
2904 (truncate:SI
2905 (lshiftrt:DI
2906 (mult:DI
2907 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2908 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
2909 (const_int 32))))
2910 (clobber (reg:SI MACL_REG))])
2911 (set (match_operand:SI 0 "arith_reg_operand" "")
2912 (reg:SI MACH_REG))]
2913 "TARGET_SH2"
2914 "
2915 {
2916 rtx insn, mach;
2917
2918 mach = gen_rtx_REG (SImode, MACH_REG);
2919 start_sequence ();
2920 emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
2921 insn = get_insns ();
2922 end_sequence ();
2923 /* expand_binop can't find a suitable code in mul_highpart_optab to
2924 make a REG_EQUAL note from, so make one here.
2925 See also {,u}mulhisi.
2926 ??? Alternatively, we could put this at the calling site of expand_binop,
2927 i.e. expand_mult_highpart. */
2928 /* Use emit_libcall_block for loop invariant code motion and to make
2929 a REG_EQUAL note. */
2930 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
2931
2932 DONE;
2933 }")
2934
2935 (define_insn "umulsi3_highpart_i"
2936 [(set (reg:SI MACH_REG)
2937 (truncate:SI
2938 (lshiftrt:DI
2939 (mult:DI
2940 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2941 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2942 (const_int 32))))
2943 (clobber (reg:SI MACL_REG))]
2944 "TARGET_SH2"
2945 "dmulu.l %1,%0"
2946 [(set_attr "type" "dmpy")])
2947
2948 (define_expand "umulsi3_highpart"
2949 [(parallel
2950 [(set (reg:SI MACH_REG)
2951 (truncate:SI
2952 (lshiftrt:DI
2953 (mult:DI
2954 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2955 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
2956 (const_int 32))))
2957 (clobber (reg:SI MACL_REG))])
2958 (set (match_operand:SI 0 "arith_reg_operand" "")
2959 (reg:SI MACH_REG))]
2960 "TARGET_SH2"
2961 "
2962 {
2963 rtx insn, mach;
2964
2965 mach = gen_rtx_REG (SImode, MACH_REG);
2966 start_sequence ();
2967 emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
2968 insn = get_insns ();
2969 end_sequence ();
2970 /* Use emit_libcall_block for loop invariant code motion and to make
2971 a REG_EQUAL note. */
2972 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
2973
2974 DONE;
2975 }")
2976
2977 (define_insn_and_split "muldi3"
2978 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2979 (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
2980 (match_operand:DI 2 "arith_reg_operand" "r")))
2981 (clobber (match_scratch:DI 3 "=&r"))
2982 (clobber (match_scratch:DI 4 "=r"))]
2983 "TARGET_SHMEDIA"
2984 "#"
2985 "reload_completed"
2986 [(const_int 0)]
2987 "
2988 {
2989 rtx op3_v2si, op2_v2si;
2990
2991 op3_v2si = operands[3];
2992 if (GET_CODE (op3_v2si) == SIGN_EXTEND)
2993 {
2994 op3_v2si = XEXP (op3_v2si, 0);
2995 op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
2996 }
2997 op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
2998 op2_v2si = operands[2];
2999 if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3000 {
3001 op2_v2si = XEXP (op2_v2si, 0);
3002 op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3003 }
3004 op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3005 emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3006 emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3007 emit_insn (gen_umulsidi3_media (operands[4],
3008 sh_gen_truncate (SImode, operands[1], 0),
3009 sh_gen_truncate (SImode, operands[2], 0)));
3010 emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3011 emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3012 emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3013 emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3014 DONE;
3015 }")
3016
3017 \f
3018 ;; -------------------------------------------------------------------------
3019 ;; Logical operations
3020 ;; -------------------------------------------------------------------------
3021
3022 (define_insn "*andsi3_compact"
3023 [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3024 (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3025 (match_operand:SI 2 "logical_operand" "r,K08")))]
3026 "TARGET_SH1"
3027 "and %2,%0"
3028 [(set_attr "type" "arith")])
3029
3030 (define_insn "*andsi3_media"
3031 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3032 (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3033 (match_operand:SI 2 "logical_operand" "r,I10")))]
3034 "TARGET_SHMEDIA"
3035 "@
3036 and %1, %2, %0
3037 andi %1, %2, %0"
3038 [(set_attr "type" "arith_media")])
3039
3040 (define_insn "*andsi3_bclr"
3041 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3042 (and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3043 (match_operand:SI 2 "const_int_operand" "Psz")))]
3044 "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
3045 "bclr\\t%W2,%0"
3046 [(set_attr "type" "arith")])
3047
3048 ;; If the constant is 255, then emit an extu.b instruction instead of an
3049 ;; and, since that will give better code.
3050
3051 (define_expand "andsi3"
3052 [(set (match_operand:SI 0 "arith_reg_operand" "")
3053 (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3054 (match_operand:SI 2 "logical_operand" "")))]
3055 ""
3056 "
3057 {
3058 if (TARGET_SH1
3059 && CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 255)
3060 {
3061 emit_insn (gen_zero_extendqisi2 (operands[0],
3062 gen_lowpart (QImode, operands[1])));
3063 DONE;
3064 }
3065 }")
3066
3067 (define_insn_and_split "anddi3"
3068 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3069 (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3070 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
3071 "TARGET_SHMEDIA"
3072 "@
3073 and %1, %2, %0
3074 andi %1, %2, %0
3075 #"
3076 "reload_completed
3077 && ! logical_operand (operands[2], DImode)"
3078 [(const_int 0)]
3079 "
3080 {
3081 if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3082 emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3083 else
3084 emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3085 DONE;
3086 }"
3087 [(set_attr "type" "arith_media")])
3088
3089 (define_insn "andcsi3"
3090 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3091 (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3092 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3093 "TARGET_SHMEDIA"
3094 "andc %1,%2,%0"
3095 [(set_attr "type" "arith_media")])
3096
3097 (define_insn "andcdi3"
3098 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3099 (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3100 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3101 "TARGET_SHMEDIA"
3102 "andc %1,%2,%0"
3103 [(set_attr "type" "arith_media")])
3104
3105 (define_expand "iorsi3"
3106 [(set (match_operand:SI 0 "arith_reg_operand" "")
3107 (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3108 (match_operand:SI 2 "logical_operand" "")))]
3109 ""
3110 "")
3111
3112 (define_insn "*iorsi3_compact"
3113 [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3114 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3115 (match_operand:SI 2 "logical_operand" "r,K08")))]
3116 "TARGET_SH1
3117 && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
3118 "or %2,%0"
3119 [(set_attr "type" "arith")])
3120
3121 (define_insn "*iorsi3_media"
3122 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3123 (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3124 (match_operand:SI 2 "logical_operand" "r,I10")))]
3125 "TARGET_SHMEDIA"
3126 "@
3127 or %1, %2, %0
3128 ori %1, %2, %0"
3129 [(set_attr "type" "arith_media")])
3130
3131 (define_insn "*iorsi3_bset"
3132 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3133 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3134 (match_operand:SI 2 "const_int_operand" "Pso")))]
3135 "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
3136 "bset\\t%V2,%0"
3137 [(set_attr "type" "arith")])
3138
3139 (define_insn "iordi3"
3140 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3141 (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3142 (match_operand:DI 2 "logical_operand" "r,I10")))]
3143 "TARGET_SHMEDIA"
3144 "@
3145 or %1, %2, %0
3146 ori %1, %2, %0"
3147 [(set_attr "type" "arith_media")])
3148
3149 (define_insn_and_split "*logical_sidi3"
3150 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3151 (sign_extend:DI (match_operator:SI 3 "logical_operator"
3152 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3153 (match_operand:SI 2 "logical_operand" "r,I10")])))]
3154 "TARGET_SHMEDIA"
3155 "#"
3156 "&& reload_completed"
3157 [(set (match_dup 0) (match_dup 3))]
3158 "
3159 {
3160 operands[3]
3161 = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3162 simplify_gen_subreg (DImode, operands[1], SImode, 0),
3163 simplify_gen_subreg (DImode, operands[2], SImode, 0));
3164 }")
3165
3166 (define_insn_and_split "*logical_sidisi3"
3167 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3168 (truncate:SI (sign_extend:DI
3169 (match_operator:SI 3 "logical_operator"
3170 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3171 (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3172 "TARGET_SHMEDIA"
3173 "#"
3174 "&& 1"
3175 [(set (match_dup 0) (match_dup 3))])
3176
3177 (define_insn_and_split "*logical_sidi3_2"
3178 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3179 (sign_extend:DI (truncate:SI (sign_extend:DI
3180 (match_operator:SI 3 "logical_operator"
3181 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3182 (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3183 "TARGET_SHMEDIA"
3184 "#"
3185 "&& 1"
3186 [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3187
3188 (define_expand "xorsi3"
3189 [(set (match_operand:SI 0 "arith_reg_operand" "")
3190 (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3191 (match_operand:SI 2 "xor_operand" "")))]
3192 ""
3193 "")
3194
3195 (define_insn "*xorsi3_compact"
3196 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3197 (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3198 (match_operand:SI 2 "logical_operand" "K08,r")))]
3199 "TARGET_SH1"
3200 "xor %2,%0"
3201 [(set_attr "type" "arith")])
3202
3203 (define_insn "*xorsi3_media"
3204 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3205 (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3206 (match_operand:SI 2 "xor_operand" "r,I06")))]
3207 "TARGET_SHMEDIA"
3208 "@
3209 xor %1, %2, %0
3210 xori %1, %2, %0"
3211 [(set_attr "type" "arith_media")])
3212
3213 ;; Store the complements of the T bit in a register.
3214 (define_insn "xorsi3_movrt"
3215 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3216 (xor:SI (reg:SI T_REG)
3217 (const_int 1)))]
3218 "TARGET_SH2A"
3219 "movrt\\t%0"
3220 [(set_attr "type" "arith")])
3221
3222 (define_insn "xordi3"
3223 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3224 (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3225 (match_operand:DI 2 "xor_operand" "r,I06")))]
3226 "TARGET_SHMEDIA"
3227 "@
3228 xor %1, %2, %0
3229 xori %1, %2, %0"
3230 [(set_attr "type" "arith_media")])
3231
3232 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3233 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
3234 (define_split
3235 [(set (match_operand:DI 0 "arith_reg_dest" "")
3236 (sign_extend:DI (match_operator 4 "binary_logical_operator"
3237 [(match_operand 1 "any_register_operand" "")
3238 (match_operand 2 "any_register_operand" "")])))]
3239 "TARGET_SHMEDIA"
3240 [(set (match_dup 5) (match_dup 4))
3241 (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3242 "
3243 {
3244 enum machine_mode inmode = GET_MODE (operands[1]);
3245 int offset = 0;
3246
3247 if (GET_CODE (operands[0]) == SUBREG)
3248 {
3249 offset = SUBREG_BYTE (operands[0]);
3250 operands[0] = SUBREG_REG (operands[0]);
3251 }
3252 gcc_assert (REG_P (operands[0]));
3253 if (! TARGET_LITTLE_ENDIAN)
3254 offset += 8 - GET_MODE_SIZE (inmode);
3255 operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3256 }")
3257 \f
3258 ;; -------------------------------------------------------------------------
3259 ;; Shifts and rotates
3260 ;; -------------------------------------------------------------------------
3261
3262 (define_expand "rotldi3"
3263 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3264 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3265 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3266 "TARGET_SHMEDIA"
3267 "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3268
3269 (define_insn "rotldi3_mextr"
3270 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3271 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3272 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3273 "TARGET_SHMEDIA"
3274 "*
3275 {
3276 static char templ[16];
3277
3278 sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\",
3279 8 - (int) (INTVAL (operands[2]) >> 3));
3280 return templ;
3281 }"
3282 [(set_attr "type" "arith_media")])
3283
3284 (define_expand "rotrdi3"
3285 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3286 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3287 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3288 "TARGET_SHMEDIA"
3289 "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3290
3291 (define_insn "rotrdi3_mextr"
3292 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3293 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3294 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3295 "TARGET_SHMEDIA"
3296 "*
3297 {
3298 static char templ[16];
3299
3300 sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\", (int) INTVAL (operands[2]) >> 3);
3301 return templ;
3302 }"
3303 [(set_attr "type" "arith_media")])
3304
3305 (define_split
3306 [(set (match_operand:DI 0 "arith_reg_dest" "")
3307 (ior:DI (zero_extend:DI (mem:QI (match_operand 1
3308 "ua_address_operand" "")))
3309 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
3310 (const_int 8))))
3311 (clobber (match_operand:DI 3 "register_operand" ""))]
3312 "TARGET_SHMEDIA"
3313 [(match_dup 4) (match_dup 5)]
3314 "
3315 {
3316 operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
3317 (operands[3], operands[1]));
3318 operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
3319 GEN_INT (56), GEN_INT (8));
3320 }")
3321
3322 (define_insn "rotlsi3_1"
3323 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3324 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3325 (const_int 1)))
3326 (set (reg:SI T_REG)
3327 (lshiftrt:SI (match_dup 1) (const_int 31)))]
3328 "TARGET_SH1"
3329 "rotl %0"
3330 [(set_attr "type" "arith")])
3331
3332 (define_insn "rotlsi3_31"
3333 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3334 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3335 (const_int 31)))
3336 (clobber (reg:SI T_REG))]
3337 "TARGET_SH1"
3338 "rotr %0"
3339 [(set_attr "type" "arith")])
3340
3341 (define_insn "rotlsi3_16"
3342 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3343 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
3344 (const_int 16)))]
3345 "TARGET_SH1"
3346 "swap.w %1,%0"
3347 [(set_attr "type" "arith")])
3348
3349 (define_expand "rotlsi3"
3350 [(set (match_operand:SI 0 "arith_reg_dest" "")
3351 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
3352 (match_operand:SI 2 "immediate_operand" "")))]
3353 "TARGET_SH1"
3354 "
3355 {
3356 static const char rot_tab[] = {
3357 000, 000, 000, 000, 000, 000, 010, 001,
3358 001, 001, 011, 013, 003, 003, 003, 003,
3359 003, 003, 003, 003, 003, 013, 012, 002,
3360 002, 002, 010, 000, 000, 000, 000, 000,
3361 };
3362
3363 int count, choice;
3364
3365 if (!CONST_INT_P (operands[2]))
3366 FAIL;
3367 count = INTVAL (operands[2]);
3368 choice = rot_tab[count];
3369 if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
3370 FAIL;
3371 choice &= 7;
3372 switch (choice)
3373 {
3374 case 0:
3375 emit_move_insn (operands[0], operands[1]);
3376 count -= (count & 16) * 2;
3377 break;
3378 case 3:
3379 emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
3380 count -= 16;
3381 break;
3382 case 1:
3383 case 2:
3384 {
3385 rtx parts[2];
3386 parts[0] = gen_reg_rtx (SImode);
3387 parts[1] = gen_reg_rtx (SImode);
3388 emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
3389 emit_move_insn (parts[choice-1], operands[1]);
3390 emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
3391 emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
3392 emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
3393 count = (count & ~16) - 8;
3394 }
3395 }
3396
3397 for (; count > 0; count--)
3398 emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
3399 for (; count < 0; count++)
3400 emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
3401
3402 DONE;
3403 }")
3404
3405 (define_insn "*rotlhi3_8"
3406 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3407 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
3408 (const_int 8)))]
3409 "TARGET_SH1"
3410 "swap.b %1,%0"
3411 [(set_attr "type" "arith")])
3412
3413 (define_expand "rotlhi3"
3414 [(set (match_operand:HI 0 "arith_reg_operand" "")
3415 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "")
3416 (match_operand:HI 2 "immediate_operand" "")))]
3417 "TARGET_SH1"
3418 "
3419 {
3420 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 8)
3421 FAIL;
3422 }")
3423
3424 ;;
3425 ;; shift left
3426
3427 (define_insn "ashlsi3_sh2a"
3428 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3429 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3430 (match_operand:SI 2 "arith_reg_operand" "r")))]
3431 "TARGET_SH2A"
3432 "shad %2,%0"
3433 [(set_attr "type" "arith")
3434 (set_attr "length" "4")])
3435
3436 ;; This pattern is used by init_expmed for computing the costs of shift
3437 ;; insns.
3438
3439 (define_insn_and_split "ashlsi3_std"
3440 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,r,r")
3441 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
3442 (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
3443 (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
3444 "TARGET_SH3
3445 || (TARGET_SH1 && satisfies_constraint_P27 (operands[2]))"
3446 "@
3447 shld %2,%0
3448 add %0,%0
3449 shll%O2 %0
3450 #"
3451 "TARGET_SH3
3452 && reload_completed
3453 && CONST_INT_P (operands[2])
3454 && ! satisfies_constraint_P27 (operands[2])"
3455 [(set (match_dup 3) (match_dup 2))
3456 (parallel
3457 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
3458 (clobber (match_dup 4))])]
3459 "operands[4] = gen_rtx_SCRATCH (SImode);"
3460 [(set_attr "length" "*,*,*,4")
3461 (set_attr "type" "dyn_shift,arith,arith,arith")])
3462
3463 (define_insn "ashlhi3_k"
3464 [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
3465 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
3466 (match_operand:HI 2 "const_int_operand" "M,P27")))]
3467 "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
3468 "@
3469 add %0,%0
3470 shll%O2 %0"
3471 [(set_attr "type" "arith")])
3472
3473 (define_insn "ashlsi3_n"
3474 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3475 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3476 (match_operand:SI 2 "const_int_operand" "n")))
3477 (clobber (reg:SI T_REG))]
3478 "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3479 "#"
3480 [(set (attr "length")
3481 (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3482 (const_string "2")
3483 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3484 (const_string "4")
3485 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3486 (const_string "6")]
3487 (const_string "8")))
3488 (set_attr "type" "arith")])
3489
3490 (define_split
3491 [(set (match_operand:SI 0 "arith_reg_dest" "")
3492 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3493 (match_operand:SI 2 "const_int_operand" "")))
3494 (clobber (reg:SI T_REG))]
3495 "TARGET_SH1 && reload_completed"
3496 [(use (reg:SI R0_REG))]
3497 "
3498 {
3499 gen_shifty_op (ASHIFT, operands);
3500 DONE;
3501 }")
3502
3503 (define_insn "ashlsi3_media"
3504 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3505 (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3506 (match_operand:SI 2 "shift_count_operand" "r,n")))]
3507 "TARGET_SHMEDIA"
3508 "@
3509 shlld.l %1, %2, %0
3510 shlli.l %1, %2, %0"
3511 [(set_attr "type" "arith_media")
3512 (set_attr "highpart" "ignore")])
3513
3514 (define_expand "ashlsi3"
3515 [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3516 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3517 (match_operand:SI 2 "nonmemory_operand" "")))
3518 (clobber (reg:SI T_REG))])]
3519 ""
3520 "
3521 {
3522 if (TARGET_SHMEDIA)
3523 {
3524 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
3525 DONE;
3526 }
3527 if (CONST_INT_P (operands[2])
3528 && sh_dynamicalize_shift_p (operands[2]))
3529 operands[2] = force_reg (SImode, operands[2]);
3530 if (TARGET_SH3)
3531 {
3532 emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
3533 DONE;
3534 }
3535 if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3536 FAIL;
3537 }")
3538
3539 (define_insn "*ashlhi3_n"
3540 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3541 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
3542 (match_operand:HI 2 "const_int_operand" "n")))
3543 (clobber (reg:SI T_REG))]
3544 "TARGET_SH1"
3545 "#"
3546 [(set (attr "length")
3547 (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3548 (const_string "2")
3549 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3550 (const_string "4")]
3551 (const_string "6")))
3552 (set_attr "type" "arith")])
3553
3554 (define_expand "ashlhi3"
3555 [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
3556 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3557 (match_operand:SI 2 "nonmemory_operand" "")))
3558 (clobber (reg:SI T_REG))])]
3559 "TARGET_SH1"
3560 "
3561 {
3562 if (!CONST_INT_P (operands[2]))
3563 FAIL;
3564 /* It may be possible to call gen_ashlhi3 directly with more generic
3565 operands. Make sure operands[1] is a HImode register here. */
3566 if (!arith_reg_operand (operands[1], HImode))
3567 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3568 }")
3569
3570 (define_split
3571 [(set (match_operand:HI 0 "arith_reg_dest" "")
3572 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3573 (match_operand:HI 2 "const_int_operand" "")))
3574 (clobber (reg:SI T_REG))]
3575 "TARGET_SH1 && reload_completed"
3576 [(use (reg:SI R0_REG))]
3577 "
3578 {
3579 gen_shifty_hi_op (ASHIFT, operands);
3580 DONE;
3581 }")
3582
3583 ;
3584 ; arithmetic shift right
3585 ;
3586
3587 (define_insn "ashrsi3_sh2a"
3588 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3589 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3590 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3591 "TARGET_SH2A"
3592 "shad %2,%0"
3593 [(set_attr "type" "dyn_shift")
3594 (set_attr "length" "4")])
3595
3596 (define_insn "ashrsi3_k"
3597 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3598 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3599 (match_operand:SI 2 "const_int_operand" "M")))
3600 (clobber (reg:SI T_REG))]
3601 "TARGET_SH1 && INTVAL (operands[2]) == 1"
3602 "shar %0"
3603 [(set_attr "type" "arith")])
3604
3605 ;; We can't do HImode right shifts correctly unless we start out with an
3606 ;; explicit zero / sign extension; doing that would result in worse overall
3607 ;; code, so just let the machine independent code widen the mode.
3608 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
3609
3610
3611 ;; ??? This should be a define expand.
3612
3613 (define_insn "ashrsi2_16"
3614 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3615 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
3616 (const_int 16)))]
3617 "TARGET_SH1"
3618 "#"
3619 [(set_attr "length" "4")])
3620
3621 (define_split
3622 [(set (match_operand:SI 0 "arith_reg_dest" "")
3623 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3624 (const_int 16)))]
3625 "TARGET_SH1"
3626 [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
3627 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3628 "operands[2] = gen_lowpart (HImode, operands[0]);")
3629
3630 ;; ??? This should be a define expand.
3631
3632 (define_insn "ashrsi2_31"
3633 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3634 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3635 (const_int 31)))
3636 (clobber (reg:SI T_REG))]
3637 "TARGET_SH1"
3638 "#"
3639 [(set_attr "length" "4")])
3640
3641 (define_split
3642 [(set (match_operand:SI 0 "arith_reg_dest" "")
3643 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3644 (const_int 31)))
3645 (clobber (reg:SI T_REG))]
3646 "TARGET_SH1"
3647 [(const_int 0)]
3648 "
3649 {
3650 emit_insn (gen_ashlsi_c (operands[0], operands[1]));
3651 emit_insn (gen_mov_neg_si_t (copy_rtx (operands[0])));
3652 DONE;
3653 }")
3654
3655 (define_peephole2
3656 [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
3657 (set (reg:SI T_REG)
3658 (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
3659 "TARGET_SH1
3660 && peep2_reg_dead_p (2, operands[0])
3661 && peep2_reg_dead_p (2, operands[1])"
3662 [(const_int 0)]
3663 "
3664 {
3665 emit_insn (gen_ashlsi_c (operands[1], operands[1]));
3666 DONE;
3667 }")
3668
3669 (define_insn "ashlsi_c"
3670 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3671 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
3672 (set (reg:SI T_REG)
3673 (lt:SI (match_dup 1) (const_int 0)))]
3674 "TARGET_SH1"
3675 "shll %0"
3676 [(set_attr "type" "arith")])
3677
3678 (define_insn "*ashlsi_c_void"
3679 [(set (reg:SI T_REG)
3680 (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
3681 (clobber (match_scratch:SI 1 "=0"))]
3682 "TARGET_SH1 && cse_not_expected"
3683 "shll %0"
3684 [(set_attr "type" "arith")])
3685
3686 (define_insn "ashrsi3_d"
3687 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3688 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3689 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3690 "TARGET_SH3"
3691 "shad %2,%0"
3692 [(set_attr "type" "dyn_shift")])
3693
3694 (define_insn "ashrsi3_n"
3695 [(set (reg:SI R4_REG)
3696 (ashiftrt:SI (reg:SI R4_REG)
3697 (match_operand:SI 0 "const_int_operand" "i")))
3698 (clobber (reg:SI T_REG))
3699 (clobber (reg:SI PR_REG))
3700 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
3701 "TARGET_SH1"
3702 "jsr @%1%#"
3703 [(set_attr "type" "sfunc")
3704 (set_attr "needs_delay_slot" "yes")])
3705
3706 (define_insn "ashrsi3_media"
3707 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3708 (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3709 (match_operand:SI 2 "shift_count_operand" "r,n")))]
3710 "TARGET_SHMEDIA"
3711 "@
3712 shard.l %1, %2, %0
3713 shari.l %1, %2, %0"
3714 [(set_attr "type" "arith_media")
3715 (set_attr "highpart" "ignore")])
3716
3717 (define_expand "ashrsi3"
3718 [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3719 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3720 (match_operand:SI 2 "nonmemory_operand" "")))
3721 (clobber (reg:SI T_REG))])]
3722 ""
3723 "
3724 {
3725 if (TARGET_SHMEDIA)
3726 {
3727 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
3728 DONE;
3729 }
3730 if (expand_ashiftrt (operands))
3731 DONE;
3732 else
3733 FAIL;
3734 }")
3735
3736 ;; logical shift right
3737
3738 (define_insn "lshrsi3_sh2a"
3739 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3740 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3741 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3742 "TARGET_SH2A"
3743 "shld %2,%0"
3744 [(set_attr "type" "dyn_shift")
3745 (set_attr "length" "4")])
3746
3747 (define_insn "lshrsi3_d"
3748 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3749 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3750 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3751 "TARGET_SH3"
3752 "shld %2,%0"
3753 [(set_attr "type" "dyn_shift")])
3754
3755 ;; Only the single bit shift clobbers the T bit.
3756
3757 (define_insn "lshrsi3_m"
3758 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3759 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3760 (match_operand:SI 2 "const_int_operand" "M")))
3761 (clobber (reg:SI T_REG))]
3762 "TARGET_SH1 && satisfies_constraint_M (operands[2])"
3763 "shlr %0"
3764 [(set_attr "type" "arith")])
3765
3766 (define_insn "lshrsi3_k"
3767 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3768 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3769 (match_operand:SI 2 "const_int_operand" "P27")))]
3770 "TARGET_SH1 && satisfies_constraint_P27 (operands[2])
3771 && ! satisfies_constraint_M (operands[2])"
3772 "shlr%O2 %0"
3773 [(set_attr "type" "arith")])
3774
3775 (define_insn "lshrsi3_n"
3776 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3777 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3778 (match_operand:SI 2 "const_int_operand" "n")))
3779 (clobber (reg:SI T_REG))]
3780 "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3781 "#"
3782 [(set (attr "length")
3783 (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3784 (const_string "2")
3785 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3786 (const_string "4")
3787 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3788 (const_string "6")]
3789 (const_string "8")))
3790 (set_attr "type" "arith")])
3791
3792 (define_split
3793 [(set (match_operand:SI 0 "arith_reg_dest" "")
3794 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3795 (match_operand:SI 2 "const_int_operand" "")))
3796 (clobber (reg:SI T_REG))]
3797 "TARGET_SH1 && reload_completed"
3798 [(use (reg:SI R0_REG))]
3799 "
3800 {
3801 gen_shifty_op (LSHIFTRT, operands);
3802 DONE;
3803 }")
3804
3805 (define_insn "lshrsi3_media"
3806 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3807 (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3808 (match_operand:SI 2 "shift_count_operand" "r,n")))]
3809 "TARGET_SHMEDIA"
3810 "@
3811 shlrd.l %1, %2, %0
3812 shlri.l %1, %2, %0"
3813 [(set_attr "type" "arith_media")
3814 (set_attr "highpart" "ignore")])
3815
3816 (define_expand "lshrsi3"
3817 [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
3818 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3819 (match_operand:SI 2 "nonmemory_operand" "")))
3820 (clobber (reg:SI T_REG))])]
3821 ""
3822 "
3823 {
3824 if (TARGET_SHMEDIA)
3825 {
3826 emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
3827 DONE;
3828 }
3829 if (CONST_INT_P (operands[2])
3830 && sh_dynamicalize_shift_p (operands[2]))
3831 operands[2] = force_reg (SImode, operands[2]);
3832 if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
3833 {
3834 rtx count = copy_to_mode_reg (SImode, operands[2]);
3835 emit_insn (gen_negsi2 (count, count));
3836 emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
3837 DONE;
3838 }
3839 if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3840 FAIL;
3841 }")
3842
3843 ;; ??? This should be a define expand.
3844
3845 (define_insn "ashldi3_k"
3846 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3847 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
3848 (const_int 1)))
3849 (clobber (reg:SI T_REG))]
3850 "TARGET_SH1"
3851 "shll %R0\;rotcl %S0"
3852 [(set_attr "length" "4")
3853 (set_attr "type" "arith")])
3854
3855 ;; Expander for DImode shift left with SImode operations.
3856
3857 (define_expand "ashldi3_std"
3858 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3859 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
3860 (match_operand:DI 2 "const_int_operand" "n")))]
3861 "TARGET_SH1 && INTVAL (operands[2]) < 32"
3862 "
3863 {
3864 int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
3865 int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
3866 rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
3867 rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
3868 rtx dst = gen_reg_rtx (DImode);
3869 rtx low_dst = operand_subword (dst, low_word, 1, DImode);
3870 rtx high_dst = operand_subword (dst, high_word, 1, DImode);
3871 rtx tmp0, tmp1;
3872
3873 tmp0 = gen_reg_rtx (SImode);
3874 tmp1 = gen_reg_rtx (SImode);
3875 emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
3876 emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));
3877 emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));
3878 emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
3879 emit_move_insn (operands[0], dst);
3880 DONE;
3881 }")
3882
3883 (define_insn "ashldi3_media"
3884 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3885 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3886 (match_operand:DI 2 "shift_count_operand" "r,n")))]
3887 "TARGET_SHMEDIA"
3888 "@
3889 shlld %1, %2, %0
3890 shlli %1, %2, %0"
3891 [(set_attr "type" "arith_media")])
3892
3893 (define_insn "*ashldisi3_media"
3894 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
3895 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
3896 (match_operand:DI 2 "const_int_operand" "n")))]
3897 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
3898 "shlli.l %1, %2, %0"
3899 [(set_attr "type" "arith_media")
3900 (set_attr "highpart" "ignore")])
3901
3902 (define_expand "ashldi3"
3903 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
3904 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
3905 (match_operand:DI 2 "immediate_operand" "")))
3906 (clobber (reg:SI T_REG))])]
3907 ""
3908 "
3909 {
3910 if (TARGET_SHMEDIA)
3911 {
3912 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
3913 DONE;
3914 }
3915 if (CONST_INT_P (operands[2])
3916 && INTVAL (operands[2]) == 1)
3917 {
3918 emit_insn (gen_ashldi3_k (operands[0], operands[1]));
3919 DONE;
3920 }
3921 else if (CONST_INT_P (operands[2])
3922 && INTVAL (operands[2]) < 32)
3923 {
3924 emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
3925 DONE;
3926 }
3927 else
3928 FAIL;
3929 }")
3930
3931 ;; ??? This should be a define expand.
3932
3933 (define_insn "lshrdi3_k"
3934 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3935 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
3936 (const_int 1)))
3937 (clobber (reg:SI T_REG))]
3938 "TARGET_SH1"
3939 "shlr %S0\;rotcr %R0"
3940 [(set_attr "length" "4")
3941 (set_attr "type" "arith")])
3942
3943 (define_insn "lshrdi3_media"
3944 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
3945 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3946 (match_operand:DI 2 "shift_count_operand" "r,n")))]
3947 "TARGET_SHMEDIA
3948 && (arith_reg_dest (operands[0], DImode)
3949 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
3950 "@
3951 shlrd %1, %2, %0
3952 shlri %1, %2, %0"
3953 [(set_attr "type" "arith_media")])
3954
3955 (define_insn "*lshrdisi3_media"
3956 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
3957 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
3958 (match_operand:DI 2 "const_int_operand" "n")))]
3959 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
3960 "shlri.l %1, %2, %0"
3961 [(set_attr "type" "arith_media")
3962 (set_attr "highpart" "ignore")])
3963
3964 (define_expand "lshrdi3"
3965 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
3966 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
3967 (match_operand:DI 2 "immediate_operand" "")))
3968 (clobber (reg:SI T_REG))])]
3969 ""
3970 "
3971 {
3972 if (TARGET_SHMEDIA)
3973 {
3974 emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
3975 DONE;
3976 }
3977 if (!CONST_INT_P (operands[2])
3978 || INTVAL (operands[2]) != 1)
3979 FAIL;
3980 }")
3981
3982 ;; ??? This should be a define expand.
3983
3984 (define_insn "ashrdi3_k"
3985 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3986 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
3987 (const_int 1)))
3988 (clobber (reg:SI T_REG))]
3989 "TARGET_SH1"
3990 "shar %S0\;rotcr %R0"
3991 [(set_attr "length" "4")
3992 (set_attr "type" "arith")])
3993
3994 (define_insn "ashrdi3_media"
3995 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
3996 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3997 (match_operand:DI 2 "shift_count_operand" "r,n")))]
3998 "TARGET_SHMEDIA
3999 && (arith_reg_dest (operands[0], DImode)
4000 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
4001 "@
4002 shard %1, %2, %0
4003 shari %1, %2, %0"
4004 [(set_attr "type" "arith_media")])
4005
4006 (define_insn "*ashrdisi3_media"
4007 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4008 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4009 (match_operand:DI 2 "const_int_operand" "n")))]
4010 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4011 "shari.l %1, %2, %0"
4012 [(set_attr "type" "arith_media")
4013 (set_attr "highpart" "ignore")])
4014
4015 (define_insn "ashrdisi3_media_high"
4016 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4017 (truncate:SI
4018 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4019 (match_operand:DI 2 "const_int_operand" "n"))))]
4020 "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
4021 "shari %1, %2, %0"
4022 [(set_attr "type" "arith_media")])
4023
4024 (define_insn "ashrdisi3_media_opaque"
4025 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4026 (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
4027 (match_operand:DI 2 "const_int_operand" "n")]
4028 UNSPEC_ASHIFTRT))]
4029 "TARGET_SHMEDIA"
4030 "shari %1, %2, %0"
4031 [(set_attr "type" "arith_media")])
4032
4033 (define_expand "ashrdi3"
4034 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4035 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4036 (match_operand:DI 2 "immediate_operand" "")))
4037 (clobber (reg:SI T_REG))])]
4038 ""
4039 "
4040 {
4041 if (TARGET_SHMEDIA)
4042 {
4043 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4044 DONE;
4045 }
4046 if (!CONST_INT_P (operands[2])
4047 || INTVAL (operands[2]) != 1)
4048 FAIL;
4049 }")
4050
4051 ;; combined left/right shift
4052
4053 (define_split
4054 [(set (match_operand:SI 0 "register_operand" "")
4055 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4056 (match_operand:SI 2 "const_int_operand" ""))
4057 (match_operand:SI 3 "const_int_operand" "")))]
4058 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4059 [(use (reg:SI R0_REG))]
4060 "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4061 DONE;")
4062
4063 (define_split
4064 [(set (match_operand:SI 0 "register_operand" "")
4065 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4066 (match_operand:SI 2 "const_int_operand" ""))
4067 (match_operand:SI 3 "const_int_operand" "")))
4068 (clobber (reg:SI T_REG))]
4069 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4070 [(use (reg:SI R0_REG))]
4071 "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4072 DONE;")
4073
4074 (define_insn ""
4075 [(set (match_operand:SI 0 "register_operand" "=r")
4076 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4077 (match_operand:SI 2 "const_int_operand" "n"))
4078 (match_operand:SI 3 "const_int_operand" "n")))
4079 (clobber (reg:SI T_REG))]
4080 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
4081 "#"
4082 [(set (attr "length")
4083 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4084 (const_string "4")
4085 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4086 (const_string "6")
4087 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4088 (const_string "8")
4089 (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
4090 (const_string "10")
4091 (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
4092 (const_string "12")
4093 (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
4094 (const_string "14")
4095 (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
4096 (const_string "16")]
4097 (const_string "18")))
4098 (set_attr "type" "arith")])
4099
4100 (define_insn ""
4101 [(set (match_operand:SI 0 "register_operand" "=z")
4102 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4103 (match_operand:SI 2 "const_int_operand" "n"))
4104 (match_operand:SI 3 "const_int_operand" "n")))
4105 (clobber (reg:SI T_REG))]
4106 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
4107 "#"
4108 [(set (attr "length")
4109 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4110 (const_string "4")
4111 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4112 (const_string "6")
4113 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4114 (const_string "8")]
4115 (const_string "10")))
4116 (set_attr "type" "arith")])
4117
4118 ;; shift left / and combination with a scratch register: The combine pass
4119 ;; does not accept the individual instructions, even though they are
4120 ;; cheap. But it needs a precise description so that it is usable after
4121 ;; reload.
4122 (define_insn "and_shl_scratch"
4123 [(set (match_operand:SI 0 "register_operand" "=r,&r")
4124 (lshiftrt:SI
4125 (ashift:SI
4126 (and:SI
4127 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
4128 (match_operand:SI 2 "const_int_operand" "N,n"))
4129 (match_operand:SI 3 "" "0,r"))
4130 (match_operand:SI 4 "const_int_operand" "n,n"))
4131 (match_operand:SI 5 "const_int_operand" "n,n")))
4132 (clobber (reg:SI T_REG))]
4133 "TARGET_SH1"
4134 "#"
4135 [(set (attr "length")
4136 (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
4137 (const_string "4")
4138 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
4139 (const_string "6")
4140 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
4141 (const_string "8")
4142 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
4143 (const_string "10")]
4144 (const_string "12")))
4145 (set_attr "type" "arith")])
4146
4147 (define_split
4148 [(set (match_operand:SI 0 "register_operand" "")
4149 (lshiftrt:SI
4150 (ashift:SI
4151 (and:SI
4152 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
4153 (match_operand:SI 2 "const_int_operand" ""))
4154 (match_operand:SI 3 "register_operand" ""))
4155 (match_operand:SI 4 "const_int_operand" ""))
4156 (match_operand:SI 5 "const_int_operand" "")))
4157 (clobber (reg:SI T_REG))]
4158 "TARGET_SH1"
4159 [(use (reg:SI R0_REG))]
4160 "
4161 {
4162 rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
4163
4164 if (INTVAL (operands[2]))
4165 {
4166 gen_shifty_op (LSHIFTRT, operands);
4167 }
4168 emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
4169 operands[2] = operands[4];
4170 gen_shifty_op (ASHIFT, operands);
4171 if (INTVAL (operands[5]))
4172 {
4173 operands[2] = operands[5];
4174 gen_shifty_op (LSHIFTRT, operands);
4175 }
4176 DONE;
4177 }")
4178
4179 ;; signed left/right shift combination.
4180 (define_split
4181 [(set (match_operand:SI 0 "register_operand" "")
4182 (sign_extract:SI
4183 (ashift:SI (match_operand:SI 1 "register_operand" "")
4184 (match_operand:SI 2 "const_int_operand" ""))
4185 (match_operand:SI 3 "const_int_operand" "")
4186 (const_int 0)))
4187 (clobber (reg:SI T_REG))]
4188 "TARGET_SH1"
4189 [(use (reg:SI R0_REG))]
4190 "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL;
4191 DONE;")
4192
4193 (define_insn "shl_sext_ext"
4194 [(set (match_operand:SI 0 "register_operand" "=r")
4195 (sign_extract:SI
4196 (ashift:SI (match_operand:SI 1 "register_operand" "0")
4197 (match_operand:SI 2 "const_int_operand" "n"))
4198 (match_operand:SI 3 "const_int_operand" "n")
4199 (const_int 0)))
4200 (clobber (reg:SI T_REG))]
4201 "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
4202 "#"
4203 [(set (attr "length")
4204 (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1))
4205 (const_string "2")
4206 (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
4207 (const_string "4")
4208 (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4209 (const_string "6")
4210 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4211 (const_string "8")
4212 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4213 (const_string "10")
4214 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4215 (const_string "12")
4216 (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
4217 (const_string "14")
4218 (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
4219 (const_string "16")]
4220 (const_string "18")))
4221 (set_attr "type" "arith")])
4222
4223 (define_insn "shl_sext_sub"
4224 [(set (match_operand:SI 0 "register_operand" "=z")
4225 (sign_extract:SI
4226 (ashift:SI (match_operand:SI 1 "register_operand" "0")
4227 (match_operand:SI 2 "const_int_operand" "n"))
4228 (match_operand:SI 3 "const_int_operand" "n")
4229 (const_int 0)))
4230 (clobber (reg:SI T_REG))]
4231 "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
4232 "#"
4233 [(set (attr "length")
4234 (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4235 (const_string "6")
4236 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4237 (const_string "8")
4238 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4239 (const_string "10")
4240 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4241 (const_string "12")]
4242 (const_string "14")))
4243 (set_attr "type" "arith")])
4244
4245 ;; These patterns are found in expansions of DImode shifts by 16, and
4246 ;; allow the xtrct instruction to be generated from C source.
4247
4248 (define_insn "xtrct_left"
4249 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4250 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
4251 (const_int 16))
4252 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
4253 (const_int 16))))]
4254 "TARGET_SH1"
4255 "xtrct %1,%0"
4256 [(set_attr "type" "arith")])
4257
4258 (define_insn "xtrct_right"
4259 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4260 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4261 (const_int 16))
4262 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
4263 (const_int 16))))]
4264 "TARGET_SH1"
4265 "xtrct %2,%0"
4266 [(set_attr "type" "arith")])
4267
4268 ;; -------------------------------------------------------------------------
4269 ;; Unary arithmetic
4270 ;; -------------------------------------------------------------------------
4271
4272 (define_insn "negc"
4273 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4274 (neg:SI (plus:SI (reg:SI T_REG)
4275 (match_operand:SI 1 "arith_reg_operand" "r"))))
4276 (set (reg:SI T_REG)
4277 (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
4278 (const_int 0)))]
4279 "TARGET_SH1"
4280 "negc %1,%0"
4281 [(set_attr "type" "arith")])
4282
4283 (define_insn "*negdi_media"
4284 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4285 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
4286 "TARGET_SHMEDIA"
4287 "sub r63, %1, %0"
4288 [(set_attr "type" "arith_media")])
4289
4290 (define_expand "negdi2"
4291 [(set (match_operand:DI 0 "arith_reg_operand" "")
4292 (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))]
4293 ""
4294 "
4295 {
4296 if (TARGET_SH1)
4297 {
4298 int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
4299 int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
4300
4301 rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
4302 rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
4303
4304 rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
4305 rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
4306
4307 emit_insn (gen_clrt ());
4308 emit_insn (gen_negc (low_dst, low_src));
4309 emit_insn (gen_negc (high_dst, high_src));
4310 DONE;
4311 }
4312 }")
4313
4314 (define_insn "negsi2"
4315 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4316 (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4317 "TARGET_SH1"
4318 "neg %1,%0"
4319 [(set_attr "type" "arith")])
4320
4321 (define_insn "one_cmplsi2"
4322 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4323 (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4324 "TARGET_SH1"
4325 "not %1,%0"
4326 [(set_attr "type" "arith")])
4327
4328 (define_expand "one_cmpldi2"
4329 [(set (match_operand:DI 0 "arith_reg_dest" "")
4330 (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
4331 (const_int -1)))]
4332 "TARGET_SHMEDIA" "")
4333
4334 /* The SH4 202 can do zero-offset branches without pipeline stalls.
4335 This can be used as some kind of conditional execution, which is useful
4336 for abs. */
4337 (define_split
4338 [(set (match_operand:SI 0 "arith_reg_dest" "")
4339 (plus:SI (xor:SI (neg:SI (reg:SI T_REG))
4340 (match_operand:SI 1 "arith_reg_operand" ""))
4341 (reg:SI T_REG)))]
4342 "TARGET_HARD_SH4"
4343 [(const_int 0)]
4344 "emit_insn (gen_movsi_i (operands[0], operands[1]));
4345 emit_insn (gen_cneg (operands[0], operands[0], operands[0]));
4346 DONE;")
4347
4348 (define_insn "cneg"
4349 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4350 (if_then_else:SI (eq:SI (reg:SI T_REG) (const_int 0))
4351 (match_operand:SI 1 "arith_reg_operand" "0")
4352 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4353 "TARGET_HARD_SH4"
4354 "bf 0f\;neg %2,%0\\n0:"
4355 [(set_attr "type" "arith") ;; poor approximation
4356 (set_attr "length" "4")])
4357
4358 \f
4359 ;; -------------------------------------------------------------------------
4360 ;; Zero extension instructions
4361 ;; -------------------------------------------------------------------------
4362
4363 (define_insn "zero_extendsidi2"
4364 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4365 (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
4366 "TARGET_SHMEDIA"
4367 "addz.l %1, r63, %0"
4368 [(set_attr "type" "arith_media")
4369 (set_attr "highpart" "extend")])
4370
4371 (define_insn "zero_extendhidi2"
4372 [(set (match_operand:DI 0 "register_operand" "=r,r")
4373 (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4374 "TARGET_SHMEDIA"
4375 "@
4376 #
4377 ld%M1.uw %m1, %0"
4378 [(set_attr "type" "*,load_media")
4379 (set (attr "highpart")
4380 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4381 (const_string "user")]
4382 (const_string "ignore")))])
4383
4384 (define_split
4385 [(set (match_operand:DI 0 "register_operand" "")
4386 (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4387 "TARGET_SHMEDIA && reload_completed"
4388 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4389 (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
4390 "
4391 {
4392 if (GET_CODE (operands[1]) == TRUNCATE)
4393 operands[1] = XEXP (operands[1], 0);
4394 }")
4395
4396 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
4397 ;; reload the entire truncate expression.
4398 (define_insn_and_split "*loaddi_trunc"
4399 [(set (match_operand 0 "any_register_operand" "=r")
4400 (truncate (match_operand:DI 1 "memory_operand" "m")))]
4401 "TARGET_SHMEDIA && reload_completed"
4402 "#"
4403 "TARGET_SHMEDIA && reload_completed"
4404 [(set (match_dup 0) (match_dup 1))]
4405 "operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));")
4406
4407 (define_insn "zero_extendqidi2"
4408 [(set (match_operand:DI 0 "register_operand" "=r,r")
4409 (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4410 "TARGET_SHMEDIA"
4411 "@
4412 andi %1, 255, %0
4413 ld%M1.ub %m1, %0"
4414 [(set_attr "type" "arith_media,load_media")
4415 (set (attr "highpart")
4416 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4417 (const_string "user")]
4418 (const_string "ignore")))])
4419
4420 (define_expand "zero_extendhisi2"
4421 [(set (match_operand:SI 0 "arith_reg_operand" "")
4422 (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "")))]
4423 ""
4424 "
4425 {
4426 if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], HImode))
4427 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4428 }")
4429
4430 (define_insn "*zero_extendhisi2_compact"
4431 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4432 (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))]
4433 "TARGET_SH1"
4434 "extu.w %1,%0"
4435 [(set_attr "type" "arith")])
4436
4437 (define_insn "*zero_extendhisi2_media"
4438 [(set (match_operand:SI 0 "register_operand" "=r,r")
4439 (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4440 "TARGET_SHMEDIA"
4441 "@
4442 #
4443 ld%M1.uw %m1, %0"
4444 [(set_attr "type" "arith_media,load_media")
4445 (set (attr "highpart")
4446 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4447 (const_string "user")]
4448 (const_string "ignore")))])
4449
4450 (define_split
4451 [(set (match_operand:SI 0 "register_operand" "")
4452 (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4453 "TARGET_SHMEDIA && reload_completed"
4454 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4455 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4456 "
4457 {
4458 rtx op1 = operands[1];
4459
4460 if (GET_CODE (op1) == TRUNCATE)
4461 op1 = XEXP (op1, 0);
4462 operands[2]
4463 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4464 subreg_lowpart_offset (SImode, GET_MODE (op1)));
4465 }")
4466
4467 (define_expand "zero_extendqisi2"
4468 [(set (match_operand:SI 0 "arith_reg_operand" "")
4469 (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
4470 ""
4471 "
4472 {
4473 if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], QImode))
4474 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4475 }")
4476
4477 (define_insn "*zero_extendqisi2_compact"
4478 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4479 (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))]
4480 "TARGET_SH1"
4481 "extu.b %1,%0"
4482 [(set_attr "type" "arith")])
4483
4484 (define_insn "*zero_extendqisi2_media"
4485 [(set (match_operand:SI 0 "register_operand" "=r,r")
4486 (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4487 "TARGET_SHMEDIA"
4488 "@
4489 andi %1, 255, %0
4490 ld%M1.ub %m1, %0"
4491 [(set_attr "type" "arith_media,load_media")
4492 (set (attr "highpart")
4493 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4494 (const_string "user")]
4495 (const_string "ignore")))])
4496
4497 (define_insn "zero_extendqihi2"
4498 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4499 (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
4500 "TARGET_SH1"
4501 "extu.b %1,%0"
4502 [(set_attr "type" "arith")])
4503
4504 ;; -------------------------------------------------------------------------
4505 ;; Sign extension instructions
4506 ;; -------------------------------------------------------------------------
4507
4508 ;; ??? This should be a define expand.
4509 ;; ??? Or perhaps it should be dropped?
4510
4511 ;; convert_move generates good code for SH[1-4].
4512 (define_insn "extendsidi2"
4513 [(set (match_operand:DI 0 "register_operand" "=r,r,r")
4514 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
4515 "TARGET_SHMEDIA"
4516 "@
4517 add.l %1, r63, %0
4518 ld%M1.l %m1, %0
4519 fmov.sl %1, %0"
4520 [(set_attr "type" "arith_media,load_media,fpconv_media")
4521 (set (attr "highpart")
4522 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4523 (const_string "user")]
4524 (const_string "extend")))])
4525
4526 (define_insn "extendhidi2"
4527 [(set (match_operand:DI 0 "register_operand" "=r,r")
4528 (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4529 "TARGET_SHMEDIA"
4530 "@
4531 #
4532 ld%M1.w %m1, %0"
4533 [(set_attr "type" "*,load_media")
4534 (set (attr "highpart")
4535 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4536 (const_string "user")]
4537 (const_string "ignore")))])
4538
4539 (define_split
4540 [(set (match_operand:DI 0 "register_operand" "")
4541 (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4542 "TARGET_SHMEDIA && reload_completed"
4543 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4544 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
4545 "
4546 {
4547 if (GET_CODE (operands[1]) == TRUNCATE)
4548 operands[1] = XEXP (operands[1], 0);
4549 }")
4550
4551 (define_insn "extendqidi2"
4552 [(set (match_operand:DI 0 "register_operand" "=r,r")
4553 (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4554 "TARGET_SHMEDIA"
4555 "@
4556 #
4557 ld%M1.b %m1, %0"
4558 [(set_attr "type" "*,load_media")
4559 (set (attr "highpart")
4560 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4561 (const_string "user")]
4562 (const_string "ignore")))])
4563
4564 (define_split
4565 [(set (match_operand:DI 0 "register_operand" "")
4566 (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
4567 "TARGET_SHMEDIA && reload_completed"
4568 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
4569 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
4570 "
4571 {
4572 if (GET_CODE (operands[1]) == TRUNCATE)
4573 operands[1] = XEXP (operands[1], 0);
4574 }")
4575
4576 (define_expand "extendhisi2"
4577 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4578 (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4579 ""
4580 "")
4581
4582 (define_insn "*extendhisi2_compact"
4583 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4584 (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))]
4585 "TARGET_SH1"
4586 "@
4587 exts.w %1,%0
4588 mov.w %1,%0"
4589 [(set_attr "type" "arith,load")])
4590
4591 (define_insn "*extendhisi2_media"
4592 [(set (match_operand:SI 0 "register_operand" "=r,r")
4593 (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4594 "TARGET_SHMEDIA"
4595 "@
4596 #
4597 ld%M1.w %m1, %0"
4598 [(set_attr "type" "arith_media,load_media")
4599 (set (attr "highpart")
4600 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4601 (const_string "user")]
4602 (const_string "ignore")))])
4603
4604 (define_split
4605 [(set (match_operand:SI 0 "register_operand" "")
4606 (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4607 "TARGET_SHMEDIA && reload_completed"
4608 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4609 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4610 "
4611 {
4612 rtx op1 = operands[1];
4613 if (GET_CODE (op1) == TRUNCATE)
4614 op1 = XEXP (op1, 0);
4615 operands[2]
4616 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4617 subreg_lowpart_offset (SImode, GET_MODE (op1)));
4618 }")
4619
4620 (define_expand "extendqisi2"
4621 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4622 (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4623 ""
4624 "")
4625
4626 (define_insn "*extendqisi2_compact"
4627 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4628 (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
4629 "TARGET_SH1"
4630 "@
4631 exts.b %1,%0
4632 mov.b %1,%0"
4633 [(set_attr "type" "arith,load")
4634 (set_attr_alternative "length"
4635 [(const_int 2)
4636 (if_then_else
4637 (ne (symbol_ref "TARGET_SH2A") (const_int 0))
4638 (const_int 4) (const_int 2))])])
4639
4640 (define_insn "*extendqisi2_media"
4641 [(set (match_operand:SI 0 "register_operand" "=r,r")
4642 (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4643 "TARGET_SHMEDIA"
4644 "@
4645 #
4646 ld%M1.b %m1, %0"
4647 [(set_attr "type" "arith_media,load_media")
4648 (set (attr "highpart")
4649 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4650 (const_string "user")]
4651 (const_string "ignore")))])
4652
4653 (define_split
4654 [(set (match_operand:SI 0 "register_operand" "")
4655 (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
4656 "TARGET_SHMEDIA && reload_completed"
4657 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4658 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4659 "
4660 {
4661 rtx op1 = operands[1];
4662 if (GET_CODE (op1) == TRUNCATE)
4663 op1 = XEXP (op1, 0);
4664 operands[2]
4665 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4666 subreg_lowpart_offset (SImode, GET_MODE (op1)));
4667 }")
4668
4669 (define_insn "extendqihi2"
4670 [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4671 (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
4672 "TARGET_SH1"
4673 "@
4674 exts.b %1,%0
4675 mov.b %1,%0"
4676 [(set_attr "type" "arith,load")
4677 (set_attr_alternative "length"
4678 [(const_int 2)
4679 (if_then_else
4680 (ne (symbol_ref "TARGET_SH2A") (const_int 0))
4681 (const_int 4) (const_int 2))])])
4682
4683 /* It would seem useful to combine the truncXi patterns into the movXi
4684 patterns, but unary operators are ignored when matching constraints,
4685 so we need separate patterns. */
4686 (define_insn "truncdisi2"
4687 [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
4688 (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
4689 "TARGET_SHMEDIA"
4690 "@
4691 add.l %1, r63, %0
4692 st%M0.l %m0, %1
4693 fst%M0.s %m0, %T1
4694 fmov.ls %1, %0
4695 fmov.sl %T1, %0
4696 fmov.s %T1, %0"
4697 [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")
4698 (set (attr "highpart")
4699 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4700 (const_string "user")]
4701 (const_string "extend")))])
4702
4703 (define_insn "truncdihi2"
4704 [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
4705 (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
4706 "TARGET_SHMEDIA"
4707 "@
4708 shlli\\t%1,48,%0\;shlri\\t%0,48,%0
4709 st%M0.w %m0, %1"
4710 [(set_attr "type" "arith_media,store_media")
4711 (set_attr "length" "8,4")
4712 (set (attr "highpart")
4713 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4714 (const_string "user")]
4715 (const_string "extend")))])
4716
4717 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
4718 ; Because we use zero extension, we can't provide signed QImode compares
4719 ; using a simple compare or conditional branch insn.
4720 (define_insn "truncdiqi2"
4721 [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
4722 (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
4723 "TARGET_SHMEDIA"
4724 "@
4725 andi %1, 255, %0
4726 st%M0.b %m0, %1"
4727 [(set_attr "type" "arith_media,store")
4728 (set (attr "highpart")
4729 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4730 (const_string "user")]
4731 (const_string "extend")))])
4732 ;; -------------------------------------------------------------------------
4733 ;; Move instructions
4734 ;; -------------------------------------------------------------------------
4735
4736 ;; define push and pop so it is easy for sh.c
4737 ;; We can't use push and pop on SHcompact because the stack must always
4738 ;; be 8-byte aligned.
4739
4740 (define_expand "push"
4741 [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
4742 (match_operand:SI 0 "register_operand" "r,l,x"))]
4743 "TARGET_SH1 && ! TARGET_SH5"
4744 "")
4745
4746 (define_expand "pop"
4747 [(set (match_operand:SI 0 "register_operand" "=r,l,x")
4748 (mem:SI (post_inc:SI (reg:SI SP_REG))))]
4749 "TARGET_SH1 && ! TARGET_SH5"
4750 "")
4751
4752 (define_expand "push_e"
4753 [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
4754 (match_operand:SF 0 "" ""))
4755 (use (reg:PSI FPSCR_REG))
4756 (clobber (scratch:SI))])]
4757 "TARGET_SH1 && ! TARGET_SH5"
4758 "")
4759
4760 (define_insn "push_fpul"
4761 [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
4762 "TARGET_SH2E && ! TARGET_SH5"
4763 "sts.l fpul,@-r15"
4764 [(set_attr "type" "fstore")
4765 (set_attr "late_fp_use" "yes")
4766 (set_attr "hit_stack" "yes")])
4767
4768 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
4769 ;; so use that.
4770 (define_expand "push_4"
4771 [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
4772 (match_operand:DF 0 "" ""))
4773 (use (reg:PSI FPSCR_REG))
4774 (clobber (scratch:SI))])]
4775 "TARGET_SH1 && ! TARGET_SH5"
4776 "")
4777
4778 (define_expand "pop_e"
4779 [(parallel [(set (match_operand:SF 0 "" "")
4780 (mem:SF (post_inc:SI (reg:SI SP_REG))))
4781 (use (reg:PSI FPSCR_REG))
4782 (clobber (scratch:SI))])]
4783 "TARGET_SH1 && ! TARGET_SH5"
4784 "")
4785
4786 (define_insn "pop_fpul"
4787 [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
4788 "TARGET_SH2E && ! TARGET_SH5"
4789 "lds.l @r15+,fpul"
4790 [(set_attr "type" "load")
4791 (set_attr "hit_stack" "yes")])
4792
4793 (define_expand "pop_4"
4794 [(parallel [(set (match_operand:DF 0 "" "")
4795 (mem:DF (post_inc:SI (reg:SI SP_REG))))
4796 (use (reg:PSI FPSCR_REG))
4797 (clobber (scratch:SI))])]
4798 "TARGET_SH1 && ! TARGET_SH5"
4799 "")
4800
4801 (define_expand "push_fpscr"
4802 [(const_int 0)]
4803 "TARGET_SH2E"
4804 "
4805 {
4806 rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
4807 gen_rtx_PRE_DEC (Pmode,
4808 stack_pointer_rtx)),
4809 get_fpscr_rtx ()));
4810 add_reg_note (insn, REG_INC, stack_pointer_rtx);
4811 DONE;
4812 }")
4813
4814 (define_expand "pop_fpscr"
4815 [(const_int 0)]
4816 "TARGET_SH2E"
4817 "
4818 {
4819 rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
4820 gen_frame_mem (PSImode,
4821 gen_rtx_POST_INC (Pmode,
4822 stack_pointer_rtx))));
4823 add_reg_note (insn, REG_INC, stack_pointer_rtx);
4824 DONE;
4825 }")
4826
4827 ;; These two patterns can happen as the result of optimization, when
4828 ;; comparisons get simplified to a move of zero or 1 into the T reg.
4829 ;; They don't disappear completely, because the T reg is a fixed hard reg.
4830
4831 (define_insn "clrt"
4832 [(set (reg:SI T_REG) (const_int 0))]
4833 "TARGET_SH1"
4834 "clrt")
4835
4836 (define_insn "sett"
4837 [(set (reg:SI T_REG) (const_int 1))]
4838 "TARGET_SH1"
4839 "sett")
4840
4841 ;; Define additional pop for SH1 and SH2 so it does not get
4842 ;; placed in the delay slot.
4843 (define_insn "*movsi_pop"
4844 [(set (match_operand:SI 0 "register_operand" "=r,x,l")
4845 (match_operand:SI 1 "sh_no_delay_pop_operand" ">,>,>"))]
4846 "(TARGET_SH1 || TARGET_SH2E || TARGET_SH2A)
4847 && ! TARGET_SH3"
4848 "@
4849 mov.l %1,%0
4850 lds.l %1,%0
4851 lds.l %1,%0"
4852 [(set_attr "type" "load_si,mem_mac,pload")
4853 (set_attr "length" "2,2,2")
4854 (set_attr "in_delay_slot" "no,no,no")])
4855
4856 ;; t/r must come after r/r, lest reload will try to reload stuff like
4857 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
4858 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
4859 (define_insn "movsi_i"
4860 [(set (match_operand:SI 0 "general_movdst_operand"
4861 "=r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
4862 (match_operand:SI 1 "general_movsrc_operand"
4863 "Q,r,I08,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
4864 "TARGET_SH1
4865 && ! TARGET_SH2E
4866 && ! TARGET_SH2A
4867 && (register_operand (operands[0], SImode)
4868 || register_operand (operands[1], SImode))"
4869 "@
4870 mov.l %1,%0
4871 mov %1,%0
4872 mov %1,%0
4873 cmp/pl %1
4874 mov.l %1,%0
4875 sts %1,%0
4876 sts %1,%0
4877 movt %0
4878 mov.l %1,%0
4879 sts.l %1,%0
4880 sts.l %1,%0
4881 lds %1,%0
4882 lds %1,%0
4883 lds.l %1,%0
4884 lds.l %1,%0
4885 fake %1,%0"
4886 [(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")
4887 (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
4888
4889 ;; t/r must come after r/r, lest reload will try to reload stuff like
4890 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
4891 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
4892 ;; will require a reload.
4893 ;; ??? We can't include f/f because we need the proper FPSCR setting when
4894 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
4895 (define_insn "movsi_ie"
4896 [(set (match_operand:SI 0 "general_movdst_operand"
4897 "=r,r,r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
4898 (match_operand:SI 1 "general_movsrc_operand"
4899 "Q,r,I08,I20,I28,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
4900 "(TARGET_SH2E || TARGET_SH2A)
4901 && (register_operand (operands[0], SImode)
4902 || register_operand (operands[1], SImode))"
4903 "@
4904 mov.l %1,%0
4905 mov %1,%0
4906 mov %1,%0
4907 movi20 %1,%0
4908 movi20s %1,%0
4909 cmp/pl %1
4910 mov.l %1,%0
4911 sts %1,%0
4912 sts %1,%0
4913 movt %0
4914 mov.l %1,%0
4915 sts.l %1,%0
4916 sts.l %1,%0
4917 lds %1,%0
4918 lds %1,%0
4919 lds.l %1,%0
4920 lds.l %1,%0
4921 lds.l %1,%0
4922 sts.l %1,%0
4923 fake %1,%0
4924 lds %1,%0
4925 sts %1,%0
4926 fsts fpul,%0
4927 flds %1,fpul
4928 fmov %1,%0
4929 ! move optimized away"
4930 [(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")
4931 (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
4932 (set_attr_alternative "length"
4933 [(const_int 2)
4934 (const_int 2)
4935 (const_int 2)
4936 (const_int 4)
4937 (const_int 4)
4938 (const_int 2)
4939 (if_then_else
4940 (ne (symbol_ref "TARGET_SH2A") (const_int 0))
4941 (const_int 4) (const_int 2))
4942 (const_int 2)
4943 (const_int 2)
4944 (const_int 2)
4945 (if_then_else
4946 (ne (symbol_ref "TARGET_SH2A") (const_int 0))
4947 (const_int 4) (const_int 2))
4948 (const_int 2)
4949 (const_int 2)
4950 (const_int 2)
4951 (const_int 2)
4952 (const_int 2)
4953 (const_int 2)
4954 (const_int 2)
4955 (const_int 2)
4956 (const_int 2)
4957 (const_int 2)
4958 (const_int 2)
4959 (const_int 2)
4960 (const_int 2)
4961 (const_int 2)
4962 (const_int 0)])])
4963
4964 (define_insn "movsi_i_lowpart"
4965 [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,r,m,r"))
4966 (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,t,r,i"))]
4967 "TARGET_SH1
4968 && (register_operand (operands[0], SImode)
4969 || register_operand (operands[1], SImode))"
4970 "@
4971 mov.l %1,%0
4972 mov %1,%0
4973 mov %1,%0
4974 mov.l %1,%0
4975 sts %1,%0
4976 sts %1,%0
4977 movt %0
4978 mov.l %1,%0
4979 fake %1,%0"
4980 [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,arith,store,pcload")])
4981
4982 (define_insn_and_split "load_ra"
4983 [(set (match_operand:SI 0 "general_movdst_operand" "")
4984 (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
4985 "TARGET_SH1"
4986 "#"
4987 "&& ! currently_expanding_to_rtl"
4988 [(set (match_dup 0) (match_dup 1))]
4989 "
4990 {
4991 if (TARGET_SHCOMPACT && crtl->saves_all_registers)
4992 operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
4993 }")
4994
4995 ;; The '?'s in the following constraints may not reflect the time taken
4996 ;; to perform the move. They are there to discourage the use of floating-
4997 ;; point registers for storing integer values.
4998 (define_insn "*movsi_media"
4999 [(set (match_operand:SI 0 "general_movdst_operand"
5000 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
5001 (match_operand:SI 1 "general_movsrc_operand"
5002 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5003 "TARGET_SHMEDIA_FPU
5004 && (register_operand (operands[0], SImode)
5005 || sh_register_operand (operands[1], SImode)
5006 || GET_CODE (operands[1]) == TRUNCATE)"
5007 "@
5008 add.l %1, r63, %0
5009 movi %1, %0
5010 #
5011 ld%M1.l %m1, %0
5012 st%M0.l %m0, %N1
5013 fld%M1.s %m1, %0
5014 fst%M0.s %m0, %1
5015 fmov.ls %N1, %0
5016 fmov.sl %1, %0
5017 fmov.s %1, %0
5018 ptabs %1, %0
5019 gettr %1, %0
5020 pt %1, %0"
5021 [(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")
5022 (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
5023 (set (attr "highpart")
5024 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5025 (const_string "user")]
5026 (const_string "ignore")))])
5027
5028 (define_insn "*movsi_media_nofpu"
5029 [(set (match_operand:SI 0 "general_movdst_operand"
5030 "=r,r,r,r,m,*b,r,*b")
5031 (match_operand:SI 1 "general_movsrc_operand"
5032 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
5033 "TARGET_SHMEDIA
5034 && (register_operand (operands[0], SImode)
5035 || sh_register_operand (operands[1], SImode)
5036 || GET_CODE (operands[1]) == TRUNCATE)"
5037 "@
5038 add.l %1, r63, %0
5039 movi %1, %0
5040 #
5041 ld%M1.l %m1, %0
5042 st%M0.l %m0, %N1
5043 ptabs %1, %0
5044 gettr %1, %0
5045 pt %1, %0"
5046 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5047 (set_attr "length" "4,4,8,4,4,4,4,12")
5048 (set (attr "highpart")
5049 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5050 (const_string "user")]
5051 (const_string "ignore")))])
5052
5053 (define_expand "movsi_const"
5054 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5055 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
5056 (const_int 16)] UNSPEC_EXTRACT_S16)))
5057 (set (match_dup 0)
5058 (ior:SI (ashift:SI (match_dup 0) (const_int 16))
5059 (const:SI (unspec:SI [(match_dup 1)
5060 (const_int 0)] UNSPEC_EXTRACT_U16))))]
5061 "TARGET_SHMEDIA && reload_completed
5062 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5063 "
5064 {
5065 if (GET_CODE (operands[1]) == LABEL_REF
5066 && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
5067 LABEL_NUSES (XEXP (operands[1], 0)) += 2;
5068 else if (GOTOFF_P (operands[1]))
5069 {
5070 rtx unspec = XEXP (operands[1], 0);
5071
5072 if (! UNSPEC_GOTOFF_P (unspec))
5073 {
5074 unspec = XEXP (unspec, 0);
5075 if (! UNSPEC_GOTOFF_P (unspec))
5076 abort ();
5077 }
5078 if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
5079 && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
5080 LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
5081 }
5082 }")
5083
5084 (define_expand "movsi_const_16bit"
5085 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5086 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
5087 (const_int 0)] UNSPEC_EXTRACT_S16)))]
5088 "TARGET_SHMEDIA && flag_pic && reload_completed
5089 && GET_CODE (operands[1]) == SYMBOL_REF"
5090 "")
5091
5092 (define_split
5093 [(set (match_operand:SI 0 "arith_reg_dest" "")
5094 (match_operand:SI 1 "immediate_operand" ""))]
5095 "TARGET_SHMEDIA && reload_completed
5096 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5097 [(const_int 0)]
5098 "
5099 {
5100 rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
5101
5102 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
5103
5104 DONE;
5105 }")
5106
5107 (define_split
5108 [(set (match_operand:SI 0 "register_operand" "")
5109 (match_operand:SI 1 "immediate_operand" ""))]
5110 "TARGET_SHMEDIA && reload_completed
5111 && ((CONST_INT_P (operands[1])
5112 && ! satisfies_constraint_I16 (operands[1]))
5113 || GET_CODE (operands[1]) == CONST_DOUBLE)"
5114 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5115
5116 (define_expand "movsi"
5117 [(set (match_operand:SI 0 "general_movdst_operand" "")
5118 (match_operand:SI 1 "general_movsrc_operand" ""))]
5119 ""
5120 "{ if (prepare_move_operands (operands, SImode)) DONE; }")
5121
5122 (define_expand "ic_invalidate_line"
5123 [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
5124 (match_dup 1)] UNSPEC_ICACHE)
5125 (clobber (scratch:SI))])]
5126 "TARGET_HARD_SH4 || TARGET_SH5"
5127 "
5128 {
5129 if (TARGET_SHMEDIA)
5130 {
5131 emit_insn (gen_ic_invalidate_line_media (operands[0]));
5132 DONE;
5133 }
5134 else if (TARGET_SHCOMPACT)
5135 {
5136 operands[1] = function_symbol (NULL, \"__ic_invalidate\", SFUNC_STATIC);
5137 operands[1] = force_reg (Pmode, operands[1]);
5138 emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
5139 DONE;
5140 }
5141 else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
5142 {
5143 emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
5144 DONE;
5145 }
5146 operands[0] = force_reg (Pmode, operands[0]);
5147 operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
5148 Pmode)));
5149 }")
5150
5151 ;; The address %0 is assumed to be 4-aligned at least. Thus, by ORing
5152 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
5153 ;; the requirement *1*00 for associative address writes. The alignment of
5154 ;; %0 implies that its least significant bit is cleared,
5155 ;; thus we clear the V bit of a matching entry if there is one.
5156 (define_insn "ic_invalidate_line_i"
5157 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
5158 (match_operand:SI 1 "register_operand" "r")]
5159 UNSPEC_ICACHE)
5160 (clobber (match_scratch:SI 2 "=&r"))]
5161 "TARGET_HARD_SH4"
5162 "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
5163 [(set_attr "length" "8")
5164 (set_attr "type" "cwb")])
5165
5166 (define_insn "ic_invalidate_line_sh4a"
5167 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
5168 UNSPEC_ICACHE)]
5169 "TARGET_SH4A_ARCH || TARGET_SH4_300"
5170 "ocbwb\\t@%0\;synco\;icbi\\t@%0"
5171 [(set_attr "length" "16")
5172 (set_attr "type" "cwb")])
5173
5174 ;; ??? could make arg 0 an offsettable memory operand to allow to save
5175 ;; an add in the code that calculates the address.
5176 (define_insn "ic_invalidate_line_media"
5177 [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
5178 UNSPEC_ICACHE)]
5179 "TARGET_SHMEDIA"
5180 "ocbwb %0,0\;synco\;icbi %0, 0\;synci"
5181 [(set_attr "length" "16")
5182 (set_attr "type" "invalidate_line_media")])
5183
5184 (define_insn "ic_invalidate_line_compact"
5185 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5186 (match_operand:SI 1 "register_operand" "r")]
5187 UNSPEC_ICACHE)
5188 (clobber (reg:SI PR_REG))]
5189 "TARGET_SHCOMPACT"
5190 "jsr @%1%#"
5191 [(set_attr "type" "sfunc")
5192 (set_attr "needs_delay_slot" "yes")])
5193
5194 (define_expand "initialize_trampoline"
5195 [(match_operand:SI 0 "" "")
5196 (match_operand:SI 1 "" "")
5197 (match_operand:SI 2 "" "")]
5198 "TARGET_SHCOMPACT"
5199 "
5200 {
5201 rtx sfun, tramp;
5202
5203 tramp = force_reg (Pmode, operands[0]);
5204 sfun = force_reg (Pmode, function_symbol (NULL, \"__init_trampoline\",
5205 SFUNC_STATIC));
5206 emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
5207 emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
5208
5209 emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
5210 DONE;
5211 }")
5212
5213 (define_insn "initialize_trampoline_compact"
5214 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5215 (match_operand:SI 1 "register_operand" "r")
5216 (reg:SI R2_REG) (reg:SI R3_REG)]
5217 UNSPEC_INIT_TRAMP)
5218
5219 (clobber (reg:SI PR_REG))]
5220 "TARGET_SHCOMPACT"
5221 "jsr @%1%#"
5222 [(set_attr "type" "sfunc")
5223 (set_attr "needs_delay_slot" "yes")])
5224
5225 (define_insn "movqi_i"
5226 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m,r,r,l")
5227 (match_operand:QI 1 "general_movsrc_operand" "r,i,m,r,t,l,r"))]
5228 "TARGET_SH1
5229 && (arith_reg_operand (operands[0], QImode)
5230 || arith_reg_operand (operands[1], QImode))"
5231 "@
5232 mov %1,%0
5233 mov %1,%0
5234 mov.b %1,%0
5235 mov.b %1,%0
5236 movt %0
5237 sts %1,%0
5238 lds %1,%0"
5239 [(set_attr "type" "move,movi8,load,store,arith,prget,prset")
5240 (set_attr_alternative "length"
5241 [(const_int 2)
5242 (const_int 2)
5243 (if_then_else
5244 (ne (symbol_ref "TARGET_SH2A") (const_int 0))
5245 (const_int 4) (const_int 2))
5246 (if_then_else
5247 (ne (symbol_ref "TARGET_SH2A") (const_int 0))
5248 (const_int 4) (const_int 2))
5249 (const_int 2)
5250 (const_int 2)
5251 (const_int 2)])])
5252
5253 (define_insn "*movqi_media"
5254 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
5255 (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
5256 "TARGET_SHMEDIA
5257 && (arith_reg_operand (operands[0], QImode)
5258 || extend_reg_or_0_operand (operands[1], QImode))"
5259 "@
5260 add.l %1, r63, %0
5261 movi %1, %0
5262 ld%M1.ub %m1, %0
5263 st%M0.b %m0, %N1"
5264 [(set_attr "type" "arith_media,arith_media,load_media,store_media")
5265 (set (attr "highpart")
5266 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5267 (const_string "user")]
5268 (const_string "ignore")))])
5269
5270 (define_expand "movqi"
5271 [(set (match_operand:QI 0 "general_operand" "")
5272 (match_operand:QI 1 "general_operand" ""))]
5273 ""
5274 "{ if (prepare_move_operands (operands, QImode)) DONE; }")
5275
5276 (define_expand "reload_inqi"
5277 [(set (match_operand:SI 2 "" "=&r")
5278 (match_operand:QI 1 "inqhi_operand" ""))
5279 (set (match_operand:QI 0 "arith_reg_operand" "=r")
5280 (truncate:QI (match_dup 3)))]
5281 "TARGET_SHMEDIA"
5282 "
5283 {
5284 rtx inner = XEXP (operands[1], 0);
5285 int regno = REGNO (inner);
5286
5287 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5288 operands[1] = gen_rtx_REG (SImode, regno);
5289 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5290 }")
5291
5292 /* When storing r0, we have to avoid reg+reg addressing. */
5293 (define_insn "movhi_i"
5294 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m,r,l,r")
5295 (match_operand:HI 1 "general_movsrc_operand" "Q,rI08,m,t,r,l,r,i"))]
5296 "TARGET_SH1
5297 && (arith_reg_operand (operands[0], HImode)
5298 || arith_reg_operand (operands[1], HImode))
5299 && (!MEM_P (operands[0])
5300 || GET_CODE (XEXP (operands[0], 0)) != PLUS
5301 || !REG_P (XEXP (XEXP (operands[0], 0), 1))
5302 || ! refers_to_regno_p (R0_REG, R0_REG + 1, operands[1], (rtx *)0))"
5303 "@
5304 mov.w %1,%0
5305 mov %1,%0
5306 mov.w %1,%0
5307 movt %0
5308 mov.w %1,%0
5309 sts %1,%0
5310 lds %1,%0
5311 fake %1,%0"
5312 [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
5313
5314 (define_insn "*movhi_media"
5315 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m")
5316 (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
5317 "TARGET_SHMEDIA
5318 && (arith_reg_operand (operands[0], HImode)
5319 || arith_reg_or_0_operand (operands[1], HImode))"
5320 "@
5321 add.l %1, r63, %0
5322 movi %1, %0
5323 #
5324 ld%M1.w %m1, %0
5325 st%M0.w %m0, %N1"
5326 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
5327 (set (attr "highpart")
5328 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5329 (const_string "user")]
5330 (const_string "ignore")))])
5331
5332 (define_split
5333 [(set (match_operand:HI 0 "register_operand" "")
5334 (match_operand:HI 1 "immediate_operand" ""))]
5335 "TARGET_SHMEDIA && reload_completed
5336 && ! satisfies_constraint_I16 (operands[1])"
5337 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5338
5339 (define_expand "movhi"
5340 [(set (match_operand:HI 0 "general_movdst_operand" "")
5341 (match_operand:HI 1 "general_movsrc_operand" ""))]
5342 ""
5343 "{ if (prepare_move_operands (operands, HImode)) DONE; }")
5344
5345 (define_expand "reload_inhi"
5346 [(set (match_operand:SI 2 "" "=&r")
5347 (match_operand:HI 1 "inqhi_operand" ""))
5348 (set (match_operand:HI 0 "arith_reg_operand" "=r")
5349 (truncate:HI (match_dup 3)))]
5350 "TARGET_SHMEDIA"
5351 "
5352 {
5353 rtx inner = XEXP (operands[1], 0);
5354 int regno = REGNO (inner);
5355
5356 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5357 operands[1] = gen_rtx_REG (SImode, regno);
5358 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5359 }")
5360
5361 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
5362 ;; compiled with -m2 -ml -O3 -funroll-loops
5363 (define_insn "*movdi_i"
5364 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
5365 (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
5366 "TARGET_SH1
5367 && (arith_reg_operand (operands[0], DImode)
5368 || arith_reg_operand (operands[1], DImode))"
5369 "* return output_movedouble (insn, operands, DImode);"
5370 [(set_attr "length" "4")
5371 (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
5372
5373 ;; If the output is a register and the input is memory or a register, we have
5374 ;; to be careful and see which word needs to be loaded first.
5375
5376 (define_split
5377 [(set (match_operand:DI 0 "general_movdst_operand" "")
5378 (match_operand:DI 1 "general_movsrc_operand" ""))]
5379 "TARGET_SH1 && reload_completed"
5380 [(set (match_dup 2) (match_dup 3))
5381 (set (match_dup 4) (match_dup 5))]
5382 "
5383 {
5384 int regno;
5385
5386 if ((MEM_P (operands[0])
5387 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
5388 || (MEM_P (operands[1])
5389 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
5390 FAIL;
5391
5392 switch (GET_CODE (operands[0]))
5393 {
5394 case REG:
5395 regno = REGNO (operands[0]);
5396 break;
5397 case SUBREG:
5398 regno = subreg_regno (operands[0]);
5399 break;
5400 case MEM:
5401 regno = -1;
5402 break;
5403 default:
5404 gcc_unreachable ();
5405 }
5406
5407 if (regno == -1
5408 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
5409 {
5410 operands[2] = operand_subword (operands[0], 0, 0, DImode);
5411 operands[3] = operand_subword (operands[1], 0, 0, DImode);
5412 operands[4] = operand_subword (operands[0], 1, 0, DImode);
5413 operands[5] = operand_subword (operands[1], 1, 0, DImode);
5414 }
5415 else
5416 {
5417 operands[2] = operand_subword (operands[0], 1, 0, DImode);
5418 operands[3] = operand_subword (operands[1], 1, 0, DImode);
5419 operands[4] = operand_subword (operands[0], 0, 0, DImode);
5420 operands[5] = operand_subword (operands[1], 0, 0, DImode);
5421 }
5422
5423 if (operands[2] == 0 || operands[3] == 0
5424 || operands[4] == 0 || operands[5] == 0)
5425 FAIL;
5426 }")
5427
5428 ;; The '?'s in the following constraints may not reflect the time taken
5429 ;; to perform the move. They are there to discourage the use of floating-
5430 ;; point registers for storing integer values.
5431 (define_insn "*movdi_media"
5432 [(set (match_operand:DI 0 "general_movdst_operand"
5433 "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
5434 (match_operand:DI 1 "general_movsrc_operand"
5435 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5436 "TARGET_SHMEDIA_FPU
5437 && (register_operand (operands[0], DImode)
5438 || sh_register_operand (operands[1], DImode))"
5439 "@
5440 add %1, r63, %0
5441 movi %1, %0
5442 #
5443 ld%M1.q %m1, %0
5444 st%M0.q %m0, %N1
5445 fld%M1.d %m1, %0
5446 fst%M0.d %m0, %1
5447 fmov.qd %N1, %0
5448 fmov.dq %1, %0
5449 fmov.d %1, %0
5450 ptabs %1, %0
5451 gettr %1, %0
5452 pt %1, %0"
5453 [(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")
5454 (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
5455
5456 (define_insn "*movdi_media_nofpu"
5457 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
5458 (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
5459 "TARGET_SHMEDIA
5460 && (register_operand (operands[0], DImode)
5461 || sh_register_operand (operands[1], DImode))"
5462 "@
5463 add %1, r63, %0
5464 movi %1, %0
5465 #
5466 ld%M1.q %m1, %0
5467 st%M0.q %m0, %N1
5468 ptabs %1, %0
5469 gettr %1, %0
5470 pt %1, %0"
5471 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5472 (set_attr "length" "4,4,16,4,4,4,4,*")])
5473
5474 (define_insn "*movdi_media_I16"
5475 [(set (match_operand:DI 0 "ext_dest_operand" "=r")
5476 (match_operand:DI 1 "const_int_operand" "I16"))]
5477 "TARGET_SHMEDIA && reload_completed"
5478 "movi %1, %0"
5479 [(set_attr "type" "arith_media")
5480 (set_attr "length" "4")])
5481
5482 (define_split
5483 [(set (match_operand:DI 0 "arith_reg_dest" "")
5484 (match_operand:DI 1 "immediate_operand" ""))]
5485 "TARGET_SHMEDIA && reload_completed
5486 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5487 [(set (match_dup 0) (match_dup 1))]
5488 "
5489 {
5490 rtx insn;
5491
5492 if (TARGET_SHMEDIA64)
5493 insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
5494 else
5495 insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
5496
5497 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
5498
5499 DONE;
5500 }")
5501
5502 (define_expand "movdi_const"
5503 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5504 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5505 (const_int 48)] UNSPEC_EXTRACT_S16)))
5506 (set (match_dup 0)
5507 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5508 (const:DI (unspec:DI [(match_dup 1)
5509 (const_int 32)] UNSPEC_EXTRACT_U16))))
5510 (set (match_dup 0)
5511 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5512 (const:DI (unspec:DI [(match_dup 1)
5513 (const_int 16)] UNSPEC_EXTRACT_U16))))
5514 (set (match_dup 0)
5515 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5516 (const:DI (unspec:DI [(match_dup 1)
5517 (const_int 0)] UNSPEC_EXTRACT_U16))))]
5518 "TARGET_SHMEDIA64 && reload_completed
5519 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5520 "
5521 {
5522 sh_mark_label (operands[1], 4);
5523 }")
5524
5525 (define_expand "movdi_const_32bit"
5526 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5527 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5528 (const_int 16)] UNSPEC_EXTRACT_S16)))
5529 (set (match_dup 0)
5530 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5531 (const:DI (unspec:DI [(match_dup 1)
5532 (const_int 0)] UNSPEC_EXTRACT_U16))))]
5533 "TARGET_SHMEDIA32 && reload_completed
5534 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5535 "
5536 {
5537 sh_mark_label (operands[1], 2);
5538 }")
5539
5540 (define_expand "movdi_const_16bit"
5541 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5542 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5543 (const_int 0)] UNSPEC_EXTRACT_S16)))]
5544 "TARGET_SHMEDIA && flag_pic && reload_completed
5545 && GET_CODE (operands[1]) == SYMBOL_REF"
5546 "")
5547
5548 (define_split
5549 [(set (match_operand:DI 0 "ext_dest_operand" "")
5550 (match_operand:DI 1 "immediate_operand" ""))]
5551 "TARGET_SHMEDIA && reload_completed
5552 && CONST_INT_P (operands[1])
5553 && ! satisfies_constraint_I16 (operands[1])"
5554 [(set (match_dup 0) (match_dup 2))
5555 (match_dup 1)]
5556 "
5557 {
5558 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
5559 unsigned HOST_WIDE_INT low = val;
5560 unsigned HOST_WIDE_INT high = val;
5561 unsigned HOST_WIDE_INT sign;
5562 unsigned HOST_WIDE_INT val2 = val ^ (val-1);
5563
5564 /* Zero-extend the 16 least-significant bits. */
5565 low &= 0xffff;
5566
5567 /* Arithmetic shift right the word by 16 bits. */
5568 high >>= 16;
5569 if (GET_CODE (operands[0]) == SUBREG
5570 && GET_MODE (SUBREG_REG (operands[0])) == SImode)
5571 {
5572 high &= 0xffff;
5573 high ^= 0x8000;
5574 high -= 0x8000;
5575 }
5576 else
5577 {
5578 sign = 1;
5579 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5580 high ^= sign;
5581 high -= sign;
5582 }
5583 do
5584 {
5585 /* If we can't generate the constant with a two-insn movi / shori
5586 sequence, try some other strategies. */
5587 if (! CONST_OK_FOR_I16 (high))
5588 {
5589 /* Try constant load / left shift. We know VAL != 0. */
5590 val2 = val ^ (val-1);
5591 if (val2 > 0x1ffff)
5592 {
5593 int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
5594
5595 if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
5596 || (! CONST_OK_FOR_I16 (high >> 16)
5597 && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
5598 {
5599 val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
5600 operands[1] = gen_ashldi3_media (operands[0], operands[0],
5601 GEN_INT (trailing_zeroes));
5602 break;
5603 }
5604 }
5605 /* Try constant load / right shift. */
5606 val2 = (val >> 15) + 1;
5607 if (val2 == (val2 & -val2))
5608 {
5609 int shift = 49 - exact_log2 (val2);
5610
5611 val2 = trunc_int_for_mode (val << shift, DImode);
5612 if (CONST_OK_FOR_I16 (val2))
5613 {
5614 operands[1] = gen_lshrdi3_media (operands[0], operands[0],
5615 GEN_INT (shift));
5616 break;
5617 }
5618 }
5619 /* Try mperm.w . */
5620 val2 = val & 0xffff;
5621 if ((val >> 16 & 0xffff) == val2
5622 && (val >> 32 & 0xffff) == val2
5623 && (val >> 48 & 0xffff) == val2)
5624 {
5625 val2 = (HOST_WIDE_INT) val >> 48;
5626 operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
5627 operands[1] = gen_mperm_w0 (operands[1], operands[1]);
5628 break;
5629 }
5630 /* Try movi / mshflo.l */
5631 val2 = (HOST_WIDE_INT) val >> 32;
5632 if (val2 == ((unsigned HOST_WIDE_INT)
5633 trunc_int_for_mode (val, SImode)))
5634 {
5635 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5636 operands[0]);
5637 break;
5638 }
5639 /* Try movi / mshflo.l w/ r63. */
5640 val2 = val + ((HOST_WIDE_INT) -1 << 32);
5641 if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
5642 {
5643 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5644 const0_rtx);
5645 break;
5646 }
5647 }
5648 val2 = high;
5649 operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
5650 }
5651 while (0);
5652 operands[2] = GEN_INT (val2);
5653 }")
5654
5655 (define_split
5656 [(set (match_operand:DI 0 "ext_dest_operand" "")
5657 (match_operand:DI 1 "immediate_operand" ""))]
5658 "TARGET_SHMEDIA && reload_completed
5659 && GET_CODE (operands[1]) == CONST_DOUBLE"
5660 [(set (match_dup 0) (match_dup 2))
5661 (set (match_dup 0)
5662 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
5663 "
5664 {
5665 unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
5666 unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
5667 unsigned HOST_WIDE_INT val = low;
5668 unsigned HOST_WIDE_INT sign;
5669
5670 /* Zero-extend the 16 least-significant bits. */
5671 val &= 0xffff;
5672 operands[1] = GEN_INT (val);
5673
5674 /* Arithmetic shift right the double-word by 16 bits. */
5675 low >>= 16;
5676 low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
5677 high >>= 16;
5678 sign = 1;
5679 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5680 high ^= sign;
5681 high -= sign;
5682
5683 /* This will only be true if high is a sign-extension of low, i.e.,
5684 it must be either 0 or (unsigned)-1, and be zero iff the
5685 most-significant bit of low is set. */
5686 if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
5687 operands[2] = GEN_INT (low);
5688 else
5689 operands[2] = immed_double_const (low, high, DImode);
5690 }")
5691
5692 (define_insn "shori_media"
5693 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5694 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
5695 (const_int 16))
5696 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
5697 "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
5698 "@
5699 shori %u2, %0
5700 #"
5701 [(set_attr "type" "arith_media,*")])
5702
5703 (define_insn "*shori_media_si"
5704 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5705 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5706 (const_int 16))
5707 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
5708 "TARGET_SHMEDIA"
5709 "shori %u2, %0")
5710
5711 (define_expand "movdi"
5712 [(set (match_operand:DI 0 "general_movdst_operand" "")
5713 (match_operand:DI 1 "general_movsrc_operand" ""))]
5714 ""
5715 "{ if (prepare_move_operands (operands, DImode)) DONE; }")
5716
5717 (define_insn "movdf_media"
5718 [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
5719 (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
5720 "TARGET_SHMEDIA_FPU
5721 && (register_operand (operands[0], DFmode)
5722 || sh_register_operand (operands[1], DFmode))"
5723 "@
5724 fmov.d %1, %0
5725 fmov.qd %N1, %0
5726 fmov.dq %1, %0
5727 add %1, r63, %0
5728 #
5729 fld%M1.d %m1, %0
5730 fst%M0.d %m0, %1
5731 ld%M1.q %m1, %0
5732 st%M0.q %m0, %N1"
5733 [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
5734
5735 (define_insn "movdf_media_nofpu"
5736 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
5737 (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
5738 "TARGET_SHMEDIA
5739 && (register_operand (operands[0], DFmode)
5740 || sh_register_operand (operands[1], DFmode))"
5741 "@
5742 add %1, r63, %0
5743 #
5744 ld%M1.q %m1, %0
5745 st%M0.q %m0, %N1"
5746 [(set_attr "type" "arith_media,*,load_media,store_media")])
5747
5748 (define_split
5749 [(set (match_operand:DF 0 "arith_reg_dest" "")
5750 (match_operand:DF 1 "immediate_operand" ""))]
5751 "TARGET_SHMEDIA && reload_completed"
5752 [(set (match_dup 3) (match_dup 2))]
5753 "
5754 {
5755 int endian = WORDS_BIG_ENDIAN ? 1 : 0;
5756 long values[2];
5757 REAL_VALUE_TYPE value;
5758
5759 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
5760 REAL_VALUE_TO_TARGET_DOUBLE (value, values);
5761
5762 if (HOST_BITS_PER_WIDE_INT >= 64)
5763 operands[2] = immed_double_const ((unsigned long) values[endian]
5764 | ((HOST_WIDE_INT) values[1 - endian]
5765 << 32), 0, DImode);
5766 else
5767 {
5768 gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
5769 operands[2] = immed_double_const (values[endian], values[1 - endian],
5770 DImode);
5771 }
5772
5773 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
5774 }")
5775
5776 ;; ??? This should be a define expand.
5777
5778 (define_insn "movdf_k"
5779 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
5780 (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
5781 "TARGET_SH1
5782 && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
5783 /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
5784 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
5785 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
5786 && (arith_reg_operand (operands[0], DFmode)
5787 || arith_reg_operand (operands[1], DFmode))"
5788 "* return output_movedouble (insn, operands, DFmode);"
5789 [(set_attr "length" "4")
5790 (set_attr "type" "move,pcload,load,store")])
5791
5792 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
5793 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
5794 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
5795 ;; the d/m/c/X alternative, which is split later into single-precision
5796 ;; instructions. And when not optimizing, no splits are done before fixing
5797 ;; up pcloads, so we need usable length information for that.
5798 (define_insn "movdf_i4"
5799 [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
5800 (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
5801 (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
5802 (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
5803 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
5804 && (arith_reg_operand (operands[0], DFmode)
5805 || arith_reg_operand (operands[1], DFmode))"
5806 {
5807 switch (which_alternative)
5808 {
5809 case 0:
5810 if (TARGET_FMOVD)
5811 return "fmov %1,%0";
5812 else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
5813 return "fmov %R1,%R0\n\tfmov %S1,%S0";
5814 else
5815 return "fmov %S1,%S0\n\tfmov %R1,%R0";
5816 case 3:
5817 case 4:
5818 return "fmov.d %1,%0";
5819 default:
5820 return "#";
5821 }
5822 }
5823 [(set_attr_alternative "length"
5824 [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
5825 (const_int 4)
5826 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5827 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5828 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5829 (const_int 4)
5830 (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
5831 ;; We can't use 4-byte push/pop on SHcompact, so we have to
5832 ;; increment or decrement r15 explicitly.
5833 (if_then_else
5834 (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
5835 (const_int 10) (const_int 8))
5836 (if_then_else
5837 (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
5838 (const_int 10) (const_int 8))])
5839 (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
5840 (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
5841 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
5842 (const_string "double")
5843 (const_string "none")))])
5844
5845 ;; Moving DFmode between fp/general registers through memory
5846 ;; (the top of the stack) is faster than moving through fpul even for
5847 ;; little endian. Because the type of an instruction is important for its
5848 ;; scheduling, it is beneficial to split these operations, rather than
5849 ;; emitting them in one single chunk, even if this will expose a stack
5850 ;; use that will prevent scheduling of other stack accesses beyond this
5851 ;; instruction.
5852 (define_split
5853 [(set (match_operand:DF 0 "register_operand" "")
5854 (match_operand:DF 1 "register_operand" ""))
5855 (use (match_operand:PSI 2 "fpscr_operand" ""))
5856 (clobber (match_scratch:SI 3 "=X"))]
5857 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
5858 && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
5859 [(const_int 0)]
5860 "
5861 {
5862 rtx insn, tos;
5863
5864 if (TARGET_SH5 && true_regnum (operands[1]) < 16)
5865 {
5866 emit_move_insn (stack_pointer_rtx,
5867 plus_constant (stack_pointer_rtx, -8));
5868 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
5869 }
5870 else
5871 tos = gen_tmp_stack_mem (DFmode,
5872 gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
5873 insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
5874 if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
5875 add_reg_note (insn, REG_INC, stack_pointer_rtx);
5876 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
5877 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
5878 else
5879 tos = gen_tmp_stack_mem (DFmode,
5880 gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
5881 insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
5882 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
5883 emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
5884 else
5885 add_reg_note (insn, REG_INC, stack_pointer_rtx);
5886 DONE;
5887 }")
5888
5889 ;; local-alloc sometimes allocates scratch registers even when not required,
5890 ;; so we must be prepared to handle these.
5891
5892 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
5893 (define_split
5894 [(set (match_operand:DF 0 "general_movdst_operand" "")
5895 (match_operand:DF 1 "general_movsrc_operand" ""))
5896 (use (match_operand:PSI 2 "fpscr_operand" ""))
5897 (clobber (match_scratch:SI 3 ""))]
5898 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
5899 && reload_completed
5900 && true_regnum (operands[0]) < 16
5901 && true_regnum (operands[1]) < 16"
5902 [(set (match_dup 0) (match_dup 1))]
5903 "
5904 {
5905 /* If this was a reg <-> mem operation with base + index reg addressing,
5906 we have to handle this in a special way. */
5907 rtx mem = operands[0];
5908 int store_p = 1;
5909 if (! memory_operand (mem, DFmode))
5910 {
5911 mem = operands[1];
5912 store_p = 0;
5913 }
5914 if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
5915 mem = SUBREG_REG (mem);
5916 if (MEM_P (mem))
5917 {
5918 rtx addr = XEXP (mem, 0);
5919 if (GET_CODE (addr) == PLUS
5920 && REG_P (XEXP (addr, 0))
5921 && REG_P (XEXP (addr, 1)))
5922 {
5923 int offset;
5924 rtx reg0 = gen_rtx_REG (Pmode, 0);
5925 rtx regop = operands[store_p], word0 ,word1;
5926
5927 if (GET_CODE (regop) == SUBREG)
5928 alter_subreg (&regop);
5929 if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
5930 offset = 2;
5931 else
5932 offset = 4;
5933 mem = copy_rtx (mem);
5934 PUT_MODE (mem, SImode);
5935 word0 = gen_rtx_SUBREG (SImode, regop, 0);
5936 alter_subreg (&word0);
5937 word1 = gen_rtx_SUBREG (SImode, regop, 4);
5938 alter_subreg (&word1);
5939 if (store_p || ! refers_to_regno_p (REGNO (word0),
5940 REGNO (word0) + 1, addr, 0))
5941 {
5942 emit_insn (store_p
5943 ? gen_movsi_ie (mem, word0)
5944 : gen_movsi_ie (word0, mem));
5945 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
5946 mem = copy_rtx (mem);
5947 emit_insn (store_p
5948 ? gen_movsi_ie (mem, word1)
5949 : gen_movsi_ie (word1, mem));
5950 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
5951 }
5952 else
5953 {
5954 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
5955 emit_insn (gen_movsi_ie (word1, mem));
5956 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
5957 mem = copy_rtx (mem);
5958 emit_insn (gen_movsi_ie (word0, mem));
5959 }
5960 DONE;
5961 }
5962 }
5963 }")
5964
5965 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
5966 (define_split
5967 [(set (match_operand:DF 0 "register_operand" "")
5968 (match_operand:DF 1 "memory_operand" ""))
5969 (use (match_operand:PSI 2 "fpscr_operand" ""))
5970 (clobber (reg:SI R0_REG))]
5971 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
5972 [(parallel [(set (match_dup 0) (match_dup 1))
5973 (use (match_dup 2))
5974 (clobber (scratch:SI))])]
5975 "")
5976
5977 (define_expand "reload_indf__frn"
5978 [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
5979 (match_operand:DF 1 "immediate_operand" "FQ"))
5980 (use (reg:PSI FPSCR_REG))
5981 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
5982 "TARGET_SH1"
5983 "")
5984
5985 (define_expand "reload_outdf__RnFRm"
5986 [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
5987 (match_operand:DF 1 "register_operand" "af,r"))
5988 (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
5989 "TARGET_SH1"
5990 "")
5991
5992 ;; Simplify no-op moves.
5993 (define_split
5994 [(set (match_operand:SF 0 "register_operand" "")
5995 (match_operand:SF 1 "register_operand" ""))
5996 (use (match_operand:PSI 2 "fpscr_operand" ""))
5997 (clobber (match_scratch:SI 3 ""))]
5998 "TARGET_SH2E && reload_completed
5999 && true_regnum (operands[0]) == true_regnum (operands[1])"
6000 [(set (match_dup 0) (match_dup 0))]
6001 "")
6002
6003 ;; fmovd substitute post-reload splits
6004 (define_split
6005 [(set (match_operand:DF 0 "register_operand" "")
6006 (match_operand:DF 1 "register_operand" ""))
6007 (use (match_operand:PSI 2 "fpscr_operand" ""))
6008 (clobber (match_scratch:SI 3 ""))]
6009 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
6010 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
6011 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6012 [(const_int 0)]
6013 "
6014 {
6015 int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
6016 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
6017 gen_rtx_REG (SFmode, src), operands[2]));
6018 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
6019 gen_rtx_REG (SFmode, src + 1), operands[2]));
6020 DONE;
6021 }")
6022
6023 (define_split
6024 [(set (match_operand:DF 0 "register_operand" "")
6025 (mem:DF (match_operand:SI 1 "register_operand" "")))
6026 (use (match_operand:PSI 2 "fpscr_operand" ""))
6027 (clobber (match_scratch:SI 3 ""))]
6028 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6029 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
6030 && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
6031 [(const_int 0)]
6032 "
6033 {
6034 int regno = true_regnum (operands[0]);
6035 rtx insn;
6036 rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
6037 rtx mem2
6038 = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
6039 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6040 regno + !! TARGET_LITTLE_ENDIAN),
6041 mem2, operands[2]));
6042 add_reg_note (insn, REG_INC, operands[1]);
6043 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6044 regno + ! TARGET_LITTLE_ENDIAN),
6045 change_address (mem, SFmode, NULL_RTX),
6046 operands[2]));
6047 DONE;
6048 }")
6049
6050 (define_split
6051 [(set (match_operand:DF 0 "register_operand" "")
6052 (match_operand:DF 1 "memory_operand" ""))
6053 (use (match_operand:PSI 2 "fpscr_operand" ""))
6054 (clobber (match_scratch:SI 3 ""))]
6055 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6056 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
6057 [(const_int 0)]
6058 {
6059 int regno = true_regnum (operands[0]);
6060 rtx addr, insn;
6061 rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
6062 rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
6063 rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
6064
6065 operands[1] = copy_rtx (mem2);
6066 addr = XEXP (mem2, 0);
6067
6068 switch (GET_CODE (addr))
6069 {
6070 case REG:
6071 /* This is complicated. If the register is an arithmetic register
6072 we can just fall through to the REG+DISP case below. Otherwise
6073 we have to use a combination of POST_INC and REG addressing... */
6074 if (! arith_reg_operand (operands[1], SFmode))
6075 {
6076 XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
6077 insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
6078 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6079
6080 emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6081
6082 /* If we have modified the stack pointer, the value that we have
6083 read with post-increment might be modified by an interrupt,
6084 so write it back. */
6085 if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
6086 emit_insn (gen_push_e (reg0));
6087 else
6088 emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0), GEN_INT (-4)));
6089 break;
6090 }
6091 /* Fall through. */
6092
6093 case PLUS:
6094 emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
6095 operands[1] = copy_rtx (operands[1]);
6096 XEXP (operands[1], 0) = plus_constant (addr, 4);
6097 emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6098 break;
6099
6100 case POST_INC:
6101 insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
6102 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6103
6104 insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6105 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6106 break;
6107
6108 default:
6109 debug_rtx (addr);
6110 gcc_unreachable ();
6111 }
6112
6113 DONE;
6114 })
6115
6116 (define_split
6117 [(set (match_operand:DF 0 "memory_operand" "")
6118 (match_operand:DF 1 "register_operand" ""))
6119 (use (match_operand:PSI 2 "fpscr_operand" ""))
6120 (clobber (match_scratch:SI 3 ""))]
6121 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6122 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6123 [(const_int 0)]
6124 {
6125 int regno = true_regnum (operands[1]);
6126 rtx insn, addr;
6127 rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
6128 rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
6129
6130 operands[0] = copy_rtx (operands[0]);
6131 PUT_MODE (operands[0], SFmode);
6132 addr = XEXP (operands[0], 0);
6133
6134 switch (GET_CODE (addr))
6135 {
6136 case REG:
6137 /* This is complicated. If the register is an arithmetic register
6138 we can just fall through to the REG+DISP case below. Otherwise
6139 we have to use a combination of REG and PRE_DEC addressing... */
6140 if (! arith_reg_operand (operands[0], SFmode))
6141 {
6142 emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
6143 emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
6144
6145 operands[0] = copy_rtx (operands[0]);
6146 XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
6147
6148 insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6149 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6150 break;
6151 }
6152 /* Fall through. */
6153
6154 case PLUS:
6155 /* Since REG+DISP addressing has already been decided upon by gcc
6156 we can rely upon it having chosen an arithmetic register as the
6157 register component of the address. Just emit the lower numbered
6158 register first, to the lower address, then the higher numbered
6159 register to the higher address. */
6160 emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6161
6162 operands[0] = copy_rtx (operands[0]);
6163 XEXP (operands[0], 0) = plus_constant (addr, 4);
6164
6165 emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
6166 break;
6167
6168 case PRE_DEC:
6169 /* This is easy. Output the word to go to the higher address
6170 first (ie the word in the higher numbered register) then the
6171 word to go to the lower address. */
6172
6173 insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
6174 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6175
6176 insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6177 add_reg_note (insn, REG_INC, XEXP (addr, 0));
6178 break;
6179
6180 default:
6181 /* FAIL; */
6182 debug_rtx (addr);
6183 gcc_unreachable ();
6184 }
6185
6186 DONE;
6187 })
6188
6189 ;; If the output is a register and the input is memory or a register, we have
6190 ;; to be careful and see which word needs to be loaded first.
6191
6192 (define_split
6193 [(set (match_operand:DF 0 "general_movdst_operand" "")
6194 (match_operand:DF 1 "general_movsrc_operand" ""))]
6195 "TARGET_SH1 && reload_completed"
6196 [(set (match_dup 2) (match_dup 3))
6197 (set (match_dup 4) (match_dup 5))]
6198 "
6199 {
6200 int regno;
6201
6202 if ((MEM_P (operands[0])
6203 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
6204 || (MEM_P (operands[1])
6205 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
6206 FAIL;
6207
6208 switch (GET_CODE (operands[0]))
6209 {
6210 case REG:
6211 regno = REGNO (operands[0]);
6212 break;
6213 case SUBREG:
6214 regno = subreg_regno (operands[0]);
6215 break;
6216 case MEM:
6217 regno = -1;
6218 break;
6219 default:
6220 gcc_unreachable ();
6221 }
6222
6223 if (regno == -1
6224 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
6225 {
6226 operands[2] = operand_subword (operands[0], 0, 0, DFmode);
6227 operands[3] = operand_subword (operands[1], 0, 0, DFmode);
6228 operands[4] = operand_subword (operands[0], 1, 0, DFmode);
6229 operands[5] = operand_subword (operands[1], 1, 0, DFmode);
6230 }
6231 else
6232 {
6233 operands[2] = operand_subword (operands[0], 1, 0, DFmode);
6234 operands[3] = operand_subword (operands[1], 1, 0, DFmode);
6235 operands[4] = operand_subword (operands[0], 0, 0, DFmode);
6236 operands[5] = operand_subword (operands[1], 0, 0, DFmode);
6237 }
6238
6239 if (operands[2] == 0 || operands[3] == 0
6240 || operands[4] == 0 || operands[5] == 0)
6241 FAIL;
6242 }")
6243
6244 ;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is
6245 ;; used only once, let combine add in the index again.
6246
6247 (define_split
6248 [(set (match_operand:SI 0 "register_operand" "")
6249 (match_operand:SI 1 "" ""))
6250 (clobber (match_operand 2 "register_operand" ""))]
6251 "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6252 && ALLOW_INDEXED_ADDRESS"
6253 [(use (reg:SI R0_REG))]
6254 "
6255 {
6256 rtx addr, reg, const_int;
6257
6258 if (!MEM_P (operands[1]))
6259 FAIL;
6260 addr = XEXP (operands[1], 0);
6261 if (GET_CODE (addr) != PLUS)
6262 FAIL;
6263 reg = XEXP (addr, 0);
6264 const_int = XEXP (addr, 1);
6265 if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6266 && CONST_INT_P (const_int)))
6267 FAIL;
6268 emit_move_insn (operands[2], const_int);
6269 emit_move_insn (operands[0],
6270 change_address (operands[1], VOIDmode,
6271 gen_rtx_PLUS (SImode, reg, operands[2])));
6272 DONE;
6273 }")
6274
6275 (define_split
6276 [(set (match_operand:SI 1 "" "")
6277 (match_operand:SI 0 "register_operand" ""))
6278 (clobber (match_operand 2 "register_operand" ""))]
6279 "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6280 && ALLOW_INDEXED_ADDRESS"
6281 [(use (reg:SI R0_REG))]
6282 "
6283 {
6284 rtx addr, reg, const_int;
6285
6286 if (!MEM_P (operands[1]))
6287 FAIL;
6288 addr = XEXP (operands[1], 0);
6289 if (GET_CODE (addr) != PLUS)
6290 FAIL;
6291 reg = XEXP (addr, 0);
6292 const_int = XEXP (addr, 1);
6293 if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6294 && CONST_INT_P (const_int)))
6295 FAIL;
6296 emit_move_insn (operands[2], const_int);
6297 emit_move_insn (change_address (operands[1], VOIDmode,
6298 gen_rtx_PLUS (SImode, reg, operands[2])),
6299 operands[0]);
6300 DONE;
6301 }")
6302
6303 (define_expand "movdf"
6304 [(set (match_operand:DF 0 "general_movdst_operand" "")
6305 (match_operand:DF 1 "general_movsrc_operand" ""))]
6306 ""
6307 "
6308 {
6309 if (prepare_move_operands (operands, DFmode)) DONE;
6310 if (TARGET_SHMEDIA)
6311 {
6312 if (TARGET_SHMEDIA_FPU)
6313 emit_insn (gen_movdf_media (operands[0], operands[1]));
6314 else
6315 emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
6316 DONE;
6317 }
6318 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
6319 {
6320 emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
6321 DONE;
6322 }
6323 }")
6324
6325 ;;This is incompatible with the way gcc uses subregs.
6326 ;;(define_insn "movv2sf_i"
6327 ;; [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
6328 ;; (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
6329 ;; "TARGET_SHMEDIA_FPU
6330 ;; && (fp_arith_reg_operand (operands[0], V2SFmode)
6331 ;; || fp_arith_reg_operand (operands[1], V2SFmode))"
6332 ;; "@
6333 ;; #
6334 ;; fld%M1.p %m1, %0
6335 ;; fst%M0.p %m0, %1"
6336 ;; [(set_attr "type" "*,fload_media,fstore_media")])
6337
6338 (define_insn_and_split "movv2sf_i"
6339 [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6340 (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6341 "TARGET_SHMEDIA_FPU"
6342 "#"
6343 "TARGET_SHMEDIA_FPU && reload_completed"
6344 [(set (match_dup 0) (match_dup 1))]
6345 "
6346 {
6347 operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
6348 operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
6349 }")
6350
6351 (define_expand "movv2sf"
6352 [(set (match_operand:V2SF 0 "general_movdst_operand" "")
6353 (match_operand:V2SF 1 "nonimmediate_operand" ""))]
6354 "TARGET_SHMEDIA_FPU"
6355 "
6356 {
6357 if (prepare_move_operands (operands, V2SFmode))
6358 DONE;
6359 }")
6360
6361 (define_expand "addv2sf3"
6362 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6363 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6364 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6365 "TARGET_SHMEDIA_FPU"
6366 "
6367 {
6368 sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
6369 DONE;
6370 }")
6371
6372 (define_expand "subv2sf3"
6373 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6374 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6375 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6376 "TARGET_SHMEDIA_FPU"
6377 "
6378 {
6379 sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
6380 DONE;
6381 }")
6382
6383 (define_expand "mulv2sf3"
6384 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6385 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6386 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6387 "TARGET_SHMEDIA_FPU"
6388 "
6389 {
6390 sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
6391 DONE;
6392 }")
6393
6394 (define_expand "divv2sf3"
6395 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6396 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6397 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6398 "TARGET_SHMEDIA_FPU"
6399 "
6400 {
6401 sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
6402 DONE;
6403 }")
6404
6405 (define_insn_and_split "*movv4sf_i"
6406 [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6407 (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6408 "TARGET_SHMEDIA_FPU"
6409 "#"
6410 "&& reload_completed"
6411 [(const_int 0)]
6412 "
6413 {
6414 int i;
6415
6416 for (i = 0; i < 4/2; i++)
6417 {
6418 rtx x, y;
6419
6420 if (MEM_P (operands[0]))
6421 x = adjust_address (operands[0], V2SFmode,
6422 i * GET_MODE_SIZE (V2SFmode));
6423 else
6424 x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
6425
6426 if (MEM_P (operands[1]))
6427 y = adjust_address (operands[1], V2SFmode,
6428 i * GET_MODE_SIZE (V2SFmode));
6429 else
6430 y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
6431
6432 emit_insn (gen_movv2sf_i (x, y));
6433 }
6434
6435 DONE;
6436 }"
6437 [(set_attr "length" "8")])
6438
6439 (define_expand "movv4sf"
6440 [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
6441 (match_operand:V4SF 1 "general_operand" ""))]
6442 "TARGET_SHMEDIA_FPU"
6443 "
6444 {
6445 if (prepare_move_operands (operands, V4SFmode))
6446 DONE;
6447 }")
6448
6449 (define_insn_and_split "*movv16sf_i"
6450 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6451 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6452 "TARGET_SHMEDIA_FPU"
6453 "#"
6454 "&& reload_completed"
6455 [(const_int 0)]
6456 "
6457 {
6458 int i;
6459
6460 for (i = 0; i < 16/2; i++)
6461 {
6462 rtx x,y;
6463
6464 if (MEM_P (operands[0]))
6465 x = adjust_address (operands[0], V2SFmode,
6466 i * GET_MODE_SIZE (V2SFmode));
6467 else
6468 {
6469 x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
6470 alter_subreg (&x);
6471 }
6472
6473 if (MEM_P (operands[1]))
6474 y = adjust_address (operands[1], V2SFmode,
6475 i * GET_MODE_SIZE (V2SFmode));
6476 else
6477 {
6478 y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
6479 alter_subreg (&y);
6480 }
6481
6482 emit_insn (gen_movv2sf_i (x, y));
6483 }
6484
6485 DONE;
6486 }"
6487 [(set_attr "length" "32")])
6488
6489 (define_expand "movv16sf"
6490 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6491 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6492 "TARGET_SHMEDIA_FPU"
6493 "
6494 {
6495 if (prepare_move_operands (operands, V16SFmode))
6496 DONE;
6497 }")
6498
6499 (define_insn "movsf_media"
6500 [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
6501 (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
6502 "TARGET_SHMEDIA_FPU
6503 && (register_operand (operands[0], SFmode)
6504 || sh_register_operand (operands[1], SFmode))"
6505 "@
6506 fmov.s %1, %0
6507 fmov.ls %N1, %0
6508 fmov.sl %1, %0
6509 add.l %1, r63, %0
6510 #
6511 fld%M1.s %m1, %0
6512 fst%M0.s %m0, %1
6513 ld%M1.l %m1, %0
6514 st%M0.l %m0, %N1"
6515 [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
6516 (set (attr "highpart")
6517 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
6518 (const_string "user")]
6519 (const_string "ignore")))])
6520
6521 (define_insn "movsf_media_nofpu"
6522 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
6523 (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
6524 "TARGET_SHMEDIA
6525 && (register_operand (operands[0], SFmode)
6526 || sh_register_operand (operands[1], SFmode))"
6527 "@
6528 add.l %1, r63, %0
6529 #
6530 ld%M1.l %m1, %0
6531 st%M0.l %m0, %N1"
6532 [(set_attr "type" "arith_media,*,load_media,store_media")
6533 (set (attr "highpart")
6534 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
6535 (const_string "user")]
6536 (const_string "ignore")))])
6537
6538 (define_split
6539 [(set (match_operand:SF 0 "arith_reg_dest" "")
6540 (match_operand:SF 1 "immediate_operand" ""))]
6541 "TARGET_SHMEDIA && reload_completed
6542 && ! FP_REGISTER_P (true_regnum (operands[0]))"
6543 [(set (match_dup 3) (match_dup 2))]
6544 "
6545 {
6546 long values;
6547 REAL_VALUE_TYPE value;
6548
6549 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
6550 REAL_VALUE_TO_TARGET_SINGLE (value, values);
6551 operands[2] = GEN_INT (values);
6552
6553 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6554 }")
6555
6556 (define_insn "movsf_i"
6557 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
6558 (match_operand:SF 1 "general_movsrc_operand" "r,G,FQ,mr,r,r,l"))]
6559 "TARGET_SH1
6560 && (! TARGET_SH2E
6561 /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
6562 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
6563 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
6564 && (arith_reg_operand (operands[0], SFmode)
6565 || arith_reg_operand (operands[1], SFmode))"
6566 "@
6567 mov %1,%0
6568 mov #0,%0
6569 mov.l %1,%0
6570 mov.l %1,%0
6571 mov.l %1,%0
6572 lds %1,%0
6573 sts %1,%0"
6574 [(set_attr "type" "move,move,pcload,load,store,move,move")])
6575
6576 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
6577 ;; update_flow_info would not know where to put REG_EQUAL notes
6578 ;; when the destination changes mode.
6579 (define_insn "movsf_ie"
6580 [(set (match_operand:SF 0 "general_movdst_operand"
6581 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
6582 (match_operand:SF 1 "general_movsrc_operand"
6583 "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
6584 (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"))
6585 (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
6586
6587 "TARGET_SH2E
6588 && (arith_reg_operand (operands[0], SFmode)
6589 || arith_reg_operand (operands[1], SFmode)
6590 || arith_reg_operand (operands[3], SImode)
6591 || (fpul_operand (operands[0], SFmode)
6592 && memory_operand (operands[1], SFmode)
6593 && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
6594 || (fpul_operand (operands[1], SFmode)
6595 && memory_operand (operands[0], SFmode)
6596 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
6597 "@
6598 fmov %1,%0
6599 mov %1,%0
6600 fldi0 %0
6601 fldi1 %0
6602 #
6603 fmov.s %1,%0
6604 fmov.s %1,%0
6605 mov.l %1,%0
6606 mov.l %1,%0
6607 mov.l %1,%0
6608 fsts fpul,%0
6609 flds %1,fpul
6610 lds.l %1,%0
6611 #
6612 sts %1,%0
6613 lds %1,%0
6614 sts.l %1,%0
6615 lds.l %1,%0
6616 ! move optimized away"
6617 [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
6618 (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
6619 (set_attr_alternative "length"
6620 [(const_int 2)
6621 (const_int 2)
6622 (const_int 2)
6623 (const_int 2)
6624 (const_int 4)
6625 (if_then_else
6626 (ne (symbol_ref "TARGET_SH2A") (const_int 0))
6627 (const_int 4) (const_int 2))
6628 (if_then_else
6629 (ne (symbol_ref "TARGET_SH2A") (const_int 0))
6630 (const_int 4) (const_int 2))
6631 (const_int 2)
6632 (if_then_else
6633 (ne (symbol_ref "TARGET_SH2A") (const_int 0))
6634 (const_int 4) (const_int 2))
6635 (if_then_else
6636 (ne (symbol_ref "TARGET_SH2A") (const_int 0))
6637 (const_int 4) (const_int 2))
6638 (const_int 2)
6639 (const_int 2)
6640 (const_int 2)
6641 (const_int 4)
6642 (const_int 2)
6643 (const_int 2)
6644 (const_int 2)
6645 (const_int 2)
6646 (const_int 0)])
6647 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
6648 (const_string "single")
6649 (const_string "single")))])
6650
6651 (define_split
6652 [(set (match_operand:SF 0 "register_operand" "")
6653 (match_operand:SF 1 "register_operand" ""))
6654 (use (match_operand:PSI 2 "fpscr_operand" ""))
6655 (clobber (reg:SI FPUL_REG))]
6656 "TARGET_SH1"
6657 [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
6658 (use (match_dup 2))
6659 (clobber (scratch:SI))])
6660 (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
6661 (use (match_dup 2))
6662 (clobber (scratch:SI))])]
6663 "")
6664
6665 (define_expand "movsf"
6666 [(set (match_operand:SF 0 "general_movdst_operand" "")
6667 (match_operand:SF 1 "general_movsrc_operand" ""))]
6668 ""
6669 "
6670 {
6671 if (prepare_move_operands (operands, SFmode))
6672 DONE;
6673 if (TARGET_SHMEDIA)
6674 {
6675 if (TARGET_SHMEDIA_FPU)
6676 emit_insn (gen_movsf_media (operands[0], operands[1]));
6677 else
6678 emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
6679 DONE;
6680 }
6681 if (TARGET_SH2E)
6682 {
6683 emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
6684 DONE;
6685 }
6686 }")
6687
6688 (define_insn "mov_nop"
6689 [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
6690 "TARGET_SH2E"
6691 ""
6692 [(set_attr "length" "0")
6693 (set_attr "type" "nil")])
6694
6695 (define_expand "reload_insf__frn"
6696 [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
6697 (match_operand:SF 1 "immediate_operand" "FQ"))
6698 (use (reg:PSI FPSCR_REG))
6699 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6700 "TARGET_SH1"
6701 "")
6702
6703 (define_expand "reload_insi__i_fpul"
6704 [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
6705 (match_operand:SI 1 "immediate_operand" "i"))
6706 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6707 "TARGET_SH1"
6708 "")
6709
6710 (define_expand "ptabs"
6711 [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
6712 "TARGET_SHMEDIA"
6713 "
6714 {
6715 if (!TARGET_PT_FIXED)
6716 {
6717 rtx eq = operands[1];
6718
6719 /* ??? For canonical RTL we really should remove any CONST from EQ
6720 before wrapping it in the AND, and finally wrap the EQ into a
6721 const if is constant. However, for reload we must expose the
6722 input register or symbolic constant, and we can't have
6723 different insn structures outside of the operands for different
6724 alternatives of the same pattern. */
6725 eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
6726 GEN_INT (3));
6727 operands[1]
6728 = (gen_rtx_IF_THEN_ELSE
6729 (PDImode,
6730 eq,
6731 gen_rtx_MEM (PDImode, operands[1]),
6732 gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
6733 PDImode, operands[1])));
6734 }
6735 }")
6736
6737 ;; expanded by ptabs expander.
6738 (define_insn "*extendsipdi_media"
6739 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
6740 (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
6741 "r,Csy")
6742 (const_int 3))
6743 (const_int 3))
6744 (mem:PDI (match_dup 1))
6745 (sign_extend:PDI (match_dup 1))))]
6746 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
6747 "@
6748 ptabs %1, %0
6749 pt %1, %0"
6750 [(set_attr "type" "ptabs_media,pt_media")
6751 (set_attr "length" "4,*")])
6752
6753 (define_insn "*truncdipdi_media"
6754 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
6755 (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
6756 "r,Csy")
6757 (const_int 3))
6758 (const_int 3))
6759 (mem:PDI (match_dup 1))
6760 (truncate:PDI (match_dup 1))))]
6761 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
6762 "@
6763 ptabs %1, %0
6764 pt %1, %0"
6765 [(set_attr "type" "ptabs_media,pt_media")
6766 (set_attr "length" "4,*")])
6767
6768 (define_insn "*movsi_y"
6769 [(set (match_operand:SI 0 "register_operand" "=y,y")
6770 (match_operand:SI 1 "immediate_operand" "Qi,I08"))
6771 (clobber (match_scratch:SI 2 "=&z,r"))]
6772 "TARGET_SH2E
6773 && (reload_in_progress || reload_completed)"
6774 "#"
6775 [(set_attr "length" "4")
6776 (set_attr "type" "pcload,move")])
6777
6778 (define_split
6779 [(set (match_operand:SI 0 "register_operand" "")
6780 (match_operand:SI 1 "immediate_operand" ""))
6781 (clobber (match_operand:SI 2 "register_operand" ""))]
6782 "TARGET_SH1"
6783 [(set (match_dup 2) (match_dup 1))
6784 (set (match_dup 0) (match_dup 2))]
6785 "")
6786
6787 (define_split
6788 [(set (match_operand:SI 0 "register_operand" "")
6789 (match_operand:SI 1 "memory_operand" ""))
6790 (clobber (reg:SI R0_REG))]
6791 "TARGET_SH1"
6792 [(set (match_dup 0) (match_dup 1))]
6793 "")
6794 \f
6795 ;; ------------------------------------------------------------------------
6796 ;; Define the real conditional branch instructions.
6797 ;; ------------------------------------------------------------------------
6798
6799 (define_insn "branch_true"
6800 [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
6801 (label_ref (match_operand 0 "" ""))
6802 (pc)))]
6803 "TARGET_SH1"
6804 "* return output_branch (1, insn, operands);"
6805 [(set_attr "type" "cbranch")])
6806
6807 (define_insn "branch_false"
6808 [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
6809 (label_ref (match_operand 0 "" ""))
6810 (pc)))]
6811 "TARGET_SH1"
6812 "* return output_branch (0, insn, operands);"
6813 [(set_attr "type" "cbranch")])
6814
6815 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
6816 ;; which destination is too far away.
6817 ;; The const_int_operand is distinct for each branch target; it avoids
6818 ;; unwanted matches with redundant_insn.
6819 (define_insn "block_branch_redirect"
6820 [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
6821 "TARGET_SH1"
6822 ""
6823 [(set_attr "length" "0")])
6824
6825 ;; This one has the additional purpose to record a possible scratch register
6826 ;; for the following branch.
6827 ;; ??? Unfortunately, just setting the scratch register is not good enough,
6828 ;; because the insn then might be deemed dead and deleted. And we can't
6829 ;; make the use in the jump insn explicit because that would disable
6830 ;; delay slot scheduling from the target.
6831 (define_insn "indirect_jump_scratch"
6832 [(set (match_operand:SI 0 "register_operand" "=r")
6833 (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
6834 (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
6835 "TARGET_SH1"
6836 ""
6837 [(set_attr "length" "0")])
6838
6839 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
6840 ;; being pulled into the delay slot of a condbranch that has been made to
6841 ;; jump around the unconditional jump because it was out of range.
6842 (define_insn "stuff_delay_slot"
6843 [(set (pc)
6844 (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
6845 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
6846 "TARGET_SH1"
6847 ""
6848 [(set_attr "length" "0")
6849 (set_attr "cond_delay_slot" "yes")])
6850 \f
6851 ;; Conditional branch insns
6852
6853 (define_expand "cbranchint4_media"
6854 [(set (pc)
6855 (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
6856 [(match_operand 1 "" "")
6857 (match_operand 2 "" "")])
6858 (match_operand 3 "" "")
6859 (pc)))]
6860 "TARGET_SHMEDIA"
6861 "
6862 {
6863 enum machine_mode mode = GET_MODE (operands[1]);
6864 if (mode == VOIDmode)
6865 mode = GET_MODE (operands[2]);
6866 if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
6867 {
6868 operands[1] = force_reg (mode, operands[1]);
6869 if (CONSTANT_P (operands[2])
6870 && (! satisfies_constraint_I06 (operands[2])))
6871 operands[2] = force_reg (mode, operands[2]);
6872 }
6873 else
6874 {
6875 if (operands[1] != const0_rtx)
6876 operands[1] = force_reg (mode, operands[1]);
6877 if (operands[2] != const0_rtx)
6878 operands[2] = force_reg (mode, operands[2]);
6879 }
6880 switch (GET_CODE (operands[0]))
6881 {
6882 case LEU:
6883 case LE:
6884 case LTU:
6885 case LT:
6886 operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
6887 VOIDmode, operands[2], operands[1]);
6888 operands[1] = XEXP (operands[0], 0);
6889 operands[2] = XEXP (operands[0], 1);
6890 break;
6891 default:
6892 operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
6893 VOIDmode, operands[1], operands[2]);
6894 break;
6895 }
6896 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
6897 }")
6898
6899 (define_expand "cbranchfp4_media"
6900 [(set (pc)
6901 (if_then_else (match_operator 0 "sh_float_comparison_operator"
6902 [(match_operand 1 "" "")
6903 (match_operand 2 "" "")])
6904 (match_operand 3 "" "")
6905 (pc)))]
6906 "TARGET_SHMEDIA"
6907 "
6908 {
6909 rtx tmp = gen_reg_rtx (SImode);
6910 rtx cmp;
6911 if (GET_CODE (operands[0]) == NE)
6912 cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
6913 else
6914 cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
6915 operands[1], operands[2]);
6916
6917 emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
6918
6919 if (GET_CODE (cmp) == GET_CODE (operands[0]))
6920 operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
6921 else
6922 operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
6923 operands[1] = tmp;
6924 operands[2] = const0_rtx;
6925 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
6926 }")
6927
6928 (define_insn "*beq_media_i"
6929 [(set (pc)
6930 (if_then_else (match_operator 3 "equality_comparison_operator"
6931 [(match_operand:DI 1 "arith_reg_operand" "r,r")
6932 (match_operand:DI 2 "arith_operand" "r,I06")])
6933 (match_operand 0 "target_operand" "b,b")
6934 (pc)))]
6935 "TARGET_SHMEDIA"
6936 "@
6937 b%o3%' %1, %2, %0%>
6938 b%o3i%' %1, %2, %0%>"
6939 [(set_attr "type" "cbranch_media")])
6940
6941 (define_insn "*beq_media_i32"
6942 [(set (pc)
6943 (if_then_else (match_operator 3 "equality_comparison_operator"
6944 [(match_operand:SI 1 "arith_reg_operand" "r,r")
6945 (match_operand:SI 2 "arith_operand" "r,I06")])
6946 (match_operand 0 "target_operand" "b,b")
6947 (pc)))]
6948 "TARGET_SHMEDIA"
6949 "@
6950 b%o3%' %1, %2, %0%>
6951 b%o3i%' %1, %2, %0%>"
6952 [(set_attr "type" "cbranch_media")])
6953
6954 (define_insn "*bgt_media_i"
6955 [(set (pc)
6956 (if_then_else (match_operator 3 "greater_comparison_operator"
6957 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
6958 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
6959 (match_operand 0 "target_operand" "b")
6960 (pc)))]
6961 "TARGET_SHMEDIA"
6962 "b%o3%' %N1, %N2, %0%>"
6963 [(set_attr "type" "cbranch_media")])
6964
6965 (define_insn "*bgt_media_i32"
6966 [(set (pc)
6967 (if_then_else (match_operator 3 "greater_comparison_operator"
6968 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
6969 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
6970 (match_operand 0 "target_operand" "b")
6971 (pc)))]
6972 "TARGET_SHMEDIA"
6973 "b%o3%' %N1, %N2, %0%>"
6974 [(set_attr "type" "cbranch_media")])
6975
6976 ;; These are only needed to make invert_jump() happy - otherwise, jump
6977 ;; optimization will be silently disabled.
6978 (define_insn "*blt_media_i"
6979 [(set (pc)
6980 (if_then_else (match_operator 3 "less_comparison_operator"
6981 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
6982 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
6983 (match_operand 0 "target_operand" "b")
6984 (pc)))]
6985 "TARGET_SHMEDIA"
6986 "b%o3%' %N2, %N1, %0%>"
6987 [(set_attr "type" "cbranch_media")])
6988
6989 (define_insn "*blt_media_i32"
6990 [(set (pc)
6991 (if_then_else (match_operator 3 "less_comparison_operator"
6992 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
6993 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
6994 (match_operand 0 "target_operand" "b")
6995 (pc)))]
6996 "TARGET_SHMEDIA"
6997 "b%o3%' %N2, %N1, %0%>"
6998 [(set_attr "type" "cbranch_media")])
6999
7000 ;; combiner splitter for test-and-branch on single bit in register. This
7001 ;; is endian dependent because the non-paradoxical subreg looks different
7002 ;; on big endian.
7003 (define_split
7004 [(set (pc)
7005 (if_then_else
7006 (match_operator 3 "equality_comparison_operator"
7007 [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1
7008 "extend_reg_operand" "")
7009 0)
7010 (const_int 1)
7011 (match_operand 2
7012 "const_int_operand" "")) 0)
7013 (const_int 0)])
7014 (match_operand 0 "target_operand" "")
7015 (pc)))
7016 (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
7017 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
7018 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
7019 (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
7020
7021 "
7022 {
7023 operands[5] = GEN_INT (31 - INTVAL (operands[2]));
7024 operands[6] = (GET_CODE (operands[3]) == EQ
7025 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
7026 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
7027 }")
7028
7029 ; operand 0 is the loop count pseudo register
7030 ; operand 1 is the number of loop iterations or 0 if it is unknown
7031 ; operand 2 is the maximum number of loop iterations
7032 ; operand 3 is the number of levels of enclosed loops
7033 ; operand 4 is the label to jump to at the top of the loop
7034
7035 (define_expand "doloop_end"
7036 [(parallel [(set (pc) (if_then_else
7037 (ne:SI (match_operand:SI 0 "" "")
7038 (const_int 1))
7039 (label_ref (match_operand 4 "" ""))
7040 (pc)))
7041 (set (match_dup 0)
7042 (plus:SI (match_dup 0) (const_int -1)))
7043 (clobber (reg:SI T_REG))])]
7044 "TARGET_SH2"
7045 "
7046 {
7047 if (GET_MODE (operands[0]) != SImode)
7048 FAIL;
7049 }
7050 ")
7051
7052 (define_insn_and_split "doloop_end_split"
7053 [(set (pc)
7054 (if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0")
7055 (const_int 1))
7056 (label_ref (match_operand 1 "" ""))
7057 (pc)))
7058 (set (match_operand:SI 0 "arith_reg_dest" "=r")
7059 (plus (match_dup 2) (const_int -1)))
7060 (clobber (reg:SI T_REG))]
7061 "TARGET_SH2"
7062 "#"
7063 ""
7064 [(parallel [(set (reg:SI T_REG)
7065 (eq:SI (match_dup 2) (const_int 1)))
7066 (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
7067 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
7068 (label_ref (match_dup 1))
7069 (pc)))]
7070 ""
7071 [(set_attr "type" "cbranch")])
7072
7073 \f
7074 ;; ------------------------------------------------------------------------
7075 ;; Jump and linkage insns
7076 ;; ------------------------------------------------------------------------
7077
7078 (define_insn "jump_compact"
7079 [(set (pc)
7080 (label_ref (match_operand 0 "" "")))]
7081 "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
7082 "*
7083 {
7084 /* The length is 16 if the delay slot is unfilled. */
7085 if (get_attr_length(insn) > 4)
7086 return output_far_jump(insn, operands[0]);
7087 else
7088 return \"bra %l0%#\";
7089 }"
7090 [(set_attr "type" "jump")
7091 (set_attr "needs_delay_slot" "yes")])
7092
7093 ;; ??? It would be much saner to explicitly use the scratch register
7094 ;; in the jump insn, and have indirect_jump_scratch only set it,
7095 ;; but fill_simple_delay_slots would refuse to do delay slot filling
7096 ;; from the target then, as it uses simplejump_p.
7097 ;;(define_insn "jump_compact_far"
7098 ;; [(set (pc)
7099 ;; (label_ref (match_operand 0 "" "")))
7100 ;; (use (match_operand 1 "register_operand" "r")]
7101 ;; "TARGET_SH1"
7102 ;; "* return output_far_jump(insn, operands[0], operands[1]);"
7103 ;; [(set_attr "type" "jump")
7104 ;; (set_attr "needs_delay_slot" "yes")])
7105
7106 (define_insn "jump_media"
7107 [(set (pc)
7108 (match_operand 0 "target_operand" "b"))]
7109 "TARGET_SHMEDIA"
7110 "blink %0, r63%>"
7111 [(set_attr "type" "jump_media")])
7112
7113 (define_expand "jump"
7114 [(set (pc)
7115 (label_ref (match_operand 0 "" "")))]
7116 ""
7117 "
7118 {
7119 if (TARGET_SH1)
7120 emit_jump_insn (gen_jump_compact (operands[0]));
7121 else if (TARGET_SHMEDIA)
7122 {
7123 if (reload_in_progress || reload_completed)
7124 FAIL;
7125 emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode,
7126 operands[0])));
7127 }
7128 DONE;
7129 }")
7130
7131 (define_insn "force_mode_for_call"
7132 [(use (reg:PSI FPSCR_REG))]
7133 "TARGET_SHCOMPACT"
7134 ""
7135 [(set_attr "length" "0")
7136 (set (attr "fp_mode")
7137 (if_then_else (eq_attr "fpu_single" "yes")
7138 (const_string "single") (const_string "double")))])
7139
7140 (define_insn "calli"
7141 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7142 (match_operand 1 "" ""))
7143 (use (reg:PSI FPSCR_REG))
7144 (clobber (reg:SI PR_REG))]
7145 "TARGET_SH1"
7146 "*
7147 {
7148 if (TARGET_SH2A && (dbr_sequence_length () == 0))
7149 return \"jsr/n\\t@%0\";
7150 else
7151 return \"jsr\\t@%0%#\";
7152 }"
7153
7154 [(set_attr "type" "call")
7155 (set (attr "fp_mode")
7156 (if_then_else (eq_attr "fpu_single" "yes")
7157 (const_string "single") (const_string "double")))
7158 (set_attr "needs_delay_slot" "yes")
7159 (set_attr "fp_set" "unknown")])
7160
7161 ;; This is TBR relative jump instruction for SH2A architecture.
7162 ;; Its use is enabled assigning an attribute "function_vector"
7163 ;; and the vector number to a function during its declaration.
7164
7165 (define_insn "calli_tbr_rel"
7166 [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
7167 (match_operand 1 "" ""))
7168 (use (reg:PSI FPSCR_REG))
7169 (clobber (reg:SI PR_REG))]
7170 "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
7171 "*
7172 {
7173 unsigned HOST_WIDE_INT vect_num;
7174 vect_num = sh2a_get_function_vector_number (operands[0]);
7175 operands[2] = GEN_INT (vect_num * 4);
7176
7177 return \"jsr/n\\t@@(%O2,tbr)\";
7178 }"
7179 [(set_attr "type" "call")
7180 (set (attr "fp_mode")
7181 (if_then_else (eq_attr "fpu_single" "yes")
7182 (const_string "single") (const_string "double")))
7183 (set_attr "needs_delay_slot" "no")
7184 (set_attr "fp_set" "unknown")])
7185
7186 ;; This is a pc-rel call, using bsrf, for use with PIC.
7187
7188 (define_insn "calli_pcrel"
7189 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7190 (match_operand 1 "" ""))
7191 (use (reg:PSI FPSCR_REG))
7192 (use (reg:SI PIC_REG))
7193 (use (match_operand 2 "" ""))
7194 (clobber (reg:SI PR_REG))]
7195 "TARGET_SH2"
7196 "bsrf %0\\n%O2:%#"
7197 [(set_attr "type" "call")
7198 (set (attr "fp_mode")
7199 (if_then_else (eq_attr "fpu_single" "yes")
7200 (const_string "single") (const_string "double")))
7201 (set_attr "needs_delay_slot" "yes")
7202 (set_attr "fp_set" "unknown")])
7203
7204 (define_insn_and_split "call_pcrel"
7205 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7206 (match_operand 1 "" ""))
7207 (use (reg:PSI FPSCR_REG))
7208 (use (reg:SI PIC_REG))
7209 (clobber (reg:SI PR_REG))
7210 (clobber (match_scratch:SI 2 "=r"))]
7211 "TARGET_SH2"
7212 "#"
7213 "reload_completed"
7214 [(const_int 0)]
7215 "
7216 {
7217 rtx lab = PATTERN (gen_call_site ());
7218
7219 if (SYMBOL_REF_LOCAL_P (operands[0]))
7220 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7221 else
7222 emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
7223 emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
7224 DONE;
7225 }"
7226 [(set_attr "type" "call")
7227 (set (attr "fp_mode")
7228 (if_then_else (eq_attr "fpu_single" "yes")
7229 (const_string "single") (const_string "double")))
7230 (set_attr "needs_delay_slot" "yes")
7231 (set_attr "fp_set" "unknown")])
7232
7233 (define_insn "call_compact"
7234 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7235 (match_operand 1 "" ""))
7236 (match_operand 2 "immediate_operand" "n")
7237 (use (reg:SI R0_REG))
7238 (use (reg:SI R1_REG))
7239 (use (reg:PSI FPSCR_REG))
7240 (clobber (reg:SI PR_REG))]
7241 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7242 "jsr @%0%#"
7243 [(set_attr "type" "call")
7244 (set (attr "fp_mode")
7245 (if_then_else (eq_attr "fpu_single" "yes")
7246 (const_string "single") (const_string "double")))
7247 (set_attr "needs_delay_slot" "yes")])
7248
7249 (define_insn "call_compact_rettramp"
7250 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7251 (match_operand 1 "" ""))
7252 (match_operand 2 "immediate_operand" "n")
7253 (use (reg:SI R0_REG))
7254 (use (reg:SI R1_REG))
7255 (use (reg:PSI FPSCR_REG))
7256 (clobber (reg:SI R10_REG))
7257 (clobber (reg:SI PR_REG))]
7258 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7259 "jsr @%0%#"
7260 [(set_attr "type" "call")
7261 (set (attr "fp_mode")
7262 (if_then_else (eq_attr "fpu_single" "yes")
7263 (const_string "single") (const_string "double")))
7264 (set_attr "needs_delay_slot" "yes")])
7265
7266 (define_insn "call_media"
7267 [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
7268 (match_operand 1 "" ""))
7269 (clobber (reg:DI PR_MEDIA_REG))]
7270 "TARGET_SHMEDIA"
7271 "blink %0, r18"
7272 [(set_attr "type" "jump_media")])
7273
7274 (define_insn "call_valuei"
7275 [(set (match_operand 0 "" "=rf")
7276 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7277 (match_operand 2 "" "")))
7278 (use (reg:PSI FPSCR_REG))
7279 (clobber (reg:SI PR_REG))]
7280 "TARGET_SH1"
7281 "*
7282 {
7283 if (TARGET_SH2A && (dbr_sequence_length () == 0))
7284 return \"jsr/n\\t@%1\";
7285 else
7286 return \"jsr\\t@%1%#\";
7287 }"
7288 [(set_attr "type" "call")
7289 (set (attr "fp_mode")
7290 (if_then_else (eq_attr "fpu_single" "yes")
7291 (const_string "single") (const_string "double")))
7292 (set_attr "needs_delay_slot" "yes")
7293 (set_attr "fp_set" "unknown")])
7294
7295 ;; This is TBR relative jump instruction for SH2A architecture.
7296 ;; Its use is enabled assigning an attribute "function_vector"
7297 ;; and the vector number to a function during its declaration.
7298
7299 (define_insn "call_valuei_tbr_rel"
7300 [(set (match_operand 0 "" "=rf")
7301 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7302 (match_operand 2 "" "")))
7303 (use (reg:PSI FPSCR_REG))
7304 (clobber (reg:SI PR_REG))]
7305 "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
7306 "*
7307 {
7308 unsigned HOST_WIDE_INT vect_num;
7309 vect_num = sh2a_get_function_vector_number (operands[1]);
7310 operands[3] = GEN_INT (vect_num * 4);
7311
7312 return \"jsr/n\\t@@(%O3,tbr)\";
7313 }"
7314 [(set_attr "type" "call")
7315 (set (attr "fp_mode")
7316 (if_then_else (eq_attr "fpu_single" "yes")
7317 (const_string "single") (const_string "double")))
7318 (set_attr "needs_delay_slot" "no")
7319 (set_attr "fp_set" "unknown")])
7320
7321 (define_insn "call_valuei_pcrel"
7322 [(set (match_operand 0 "" "=rf")
7323 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7324 (match_operand 2 "" "")))
7325 (use (reg:PSI FPSCR_REG))
7326 (use (reg:SI PIC_REG))
7327 (use (match_operand 3 "" ""))
7328 (clobber (reg:SI PR_REG))]
7329 "TARGET_SH2"
7330 "bsrf %1\\n%O3:%#"
7331 [(set_attr "type" "call")
7332 (set (attr "fp_mode")
7333 (if_then_else (eq_attr "fpu_single" "yes")
7334 (const_string "single") (const_string "double")))
7335 (set_attr "needs_delay_slot" "yes")
7336 (set_attr "fp_set" "unknown")])
7337
7338 (define_insn_and_split "call_value_pcrel"
7339 [(set (match_operand 0 "" "=rf")
7340 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7341 (match_operand 2 "" "")))
7342 (use (reg:PSI FPSCR_REG))
7343 (use (reg:SI PIC_REG))
7344 (clobber (reg:SI PR_REG))
7345 (clobber (match_scratch:SI 3 "=r"))]
7346 "TARGET_SH2"
7347 "#"
7348 "reload_completed"
7349 [(const_int 0)]
7350 "
7351 {
7352 rtx lab = PATTERN (gen_call_site ());
7353
7354 if (SYMBOL_REF_LOCAL_P (operands[1]))
7355 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
7356 else
7357 emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
7358 emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
7359 operands[2], copy_rtx (lab)));
7360 DONE;
7361 }"
7362 [(set_attr "type" "call")
7363 (set (attr "fp_mode")
7364 (if_then_else (eq_attr "fpu_single" "yes")
7365 (const_string "single") (const_string "double")))
7366 (set_attr "needs_delay_slot" "yes")
7367 (set_attr "fp_set" "unknown")])
7368
7369 (define_insn "call_value_compact"
7370 [(set (match_operand 0 "" "=rf")
7371 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7372 (match_operand 2 "" "")))
7373 (match_operand 3 "immediate_operand" "n")
7374 (use (reg:SI R0_REG))
7375 (use (reg:SI R1_REG))
7376 (use (reg:PSI FPSCR_REG))
7377 (clobber (reg:SI PR_REG))]
7378 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7379 "jsr @%1%#"
7380 [(set_attr "type" "call")
7381 (set (attr "fp_mode")
7382 (if_then_else (eq_attr "fpu_single" "yes")
7383 (const_string "single") (const_string "double")))
7384 (set_attr "needs_delay_slot" "yes")])
7385
7386 (define_insn "call_value_compact_rettramp"
7387 [(set (match_operand 0 "" "=rf")
7388 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7389 (match_operand 2 "" "")))
7390 (match_operand 3 "immediate_operand" "n")
7391 (use (reg:SI R0_REG))
7392 (use (reg:SI R1_REG))
7393 (use (reg:PSI FPSCR_REG))
7394 (clobber (reg:SI R10_REG))
7395 (clobber (reg:SI PR_REG))]
7396 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7397 "jsr @%1%#"
7398 [(set_attr "type" "call")
7399 (set (attr "fp_mode")
7400 (if_then_else (eq_attr "fpu_single" "yes")
7401 (const_string "single") (const_string "double")))
7402 (set_attr "needs_delay_slot" "yes")])
7403
7404 (define_insn "call_value_media"
7405 [(set (match_operand 0 "" "=rf")
7406 (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
7407 (match_operand 2 "" "")))
7408 (clobber (reg:DI PR_MEDIA_REG))]
7409 "TARGET_SHMEDIA"
7410 "blink %1, r18"
7411 [(set_attr "type" "jump_media")])
7412
7413 (define_expand "call"
7414 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7415 (match_operand 1 "" ""))
7416 (match_operand 2 "" "")
7417 (use (reg:PSI FPSCR_REG))
7418 (clobber (reg:SI PR_REG))])]
7419 ""
7420 "
7421 {
7422 if (TARGET_SHMEDIA)
7423 {
7424 operands[0] = shmedia_prepare_call_address (operands[0], 0);
7425 emit_call_insn (gen_call_media (operands[0], operands[1]));
7426 DONE;
7427 }
7428 else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
7429 {
7430 rtx cookie_rtx = operands[2];
7431 long cookie = INTVAL (cookie_rtx);
7432 rtx func = XEXP (operands[0], 0);
7433 rtx r0, r1;
7434
7435 if (flag_pic)
7436 {
7437 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7438 {
7439 rtx reg = gen_reg_rtx (Pmode);
7440
7441 emit_insn (gen_symGOTPLT2reg (reg, func));
7442 func = reg;
7443 }
7444 else
7445 func = legitimize_pic_address (func, Pmode, 0);
7446 }
7447
7448 r0 = gen_rtx_REG (SImode, R0_REG);
7449 r1 = gen_rtx_REG (SImode, R1_REG);
7450
7451 /* Since such a call function may use all call-clobbered
7452 registers, we force a mode switch earlier, so that we don't
7453 run out of registers when adjusting fpscr for the call. */
7454 emit_insn (gen_force_mode_for_call ());
7455
7456 operands[0]
7457 = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7458 SFUNC_GOT);
7459 operands[0] = force_reg (SImode, operands[0]);
7460
7461 emit_move_insn (r0, func);
7462 emit_move_insn (r1, cookie_rtx);
7463
7464 if (cookie & CALL_COOKIE_RET_TRAMP (1))
7465 emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
7466 operands[2]));
7467 else
7468 emit_call_insn (gen_call_compact (operands[0], operands[1],
7469 operands[2]));
7470
7471 DONE;
7472 }
7473 else if (TARGET_SHCOMPACT && flag_pic
7474 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7475 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7476 {
7477 rtx reg = gen_reg_rtx (Pmode);
7478
7479 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
7480 XEXP (operands[0], 0) = reg;
7481 }
7482 if (!flag_pic && TARGET_SH2A
7483 && MEM_P (operands[0])
7484 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
7485 {
7486 if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
7487 {
7488 emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
7489 operands[1]));
7490 DONE;
7491 }
7492 }
7493 if (flag_pic && TARGET_SH2
7494 && MEM_P (operands[0])
7495 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
7496 {
7497 emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
7498 DONE;
7499 }
7500 else
7501 {
7502 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
7503 operands[1] = operands[2];
7504 }
7505
7506 emit_call_insn (gen_calli (operands[0], operands[1]));
7507 DONE;
7508 }")
7509
7510 (define_insn "call_pop_compact"
7511 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7512 (match_operand 1 "" ""))
7513 (match_operand 2 "immediate_operand" "n")
7514 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7515 (match_operand 3 "immediate_operand" "n")))
7516 (use (reg:SI R0_REG))
7517 (use (reg:SI R1_REG))
7518 (use (reg:PSI FPSCR_REG))
7519 (clobber (reg:SI PR_REG))]
7520 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7521 "jsr @%0%#"
7522 [(set_attr "type" "call")
7523 (set (attr "fp_mode")
7524 (if_then_else (eq_attr "fpu_single" "yes")
7525 (const_string "single") (const_string "double")))
7526 (set_attr "needs_delay_slot" "yes")])
7527
7528 (define_insn "call_pop_compact_rettramp"
7529 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7530 (match_operand 1 "" ""))
7531 (match_operand 2 "immediate_operand" "n")
7532 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7533 (match_operand 3 "immediate_operand" "n")))
7534 (use (reg:SI R0_REG))
7535 (use (reg:SI R1_REG))
7536 (use (reg:PSI FPSCR_REG))
7537 (clobber (reg:SI R10_REG))
7538 (clobber (reg:SI PR_REG))]
7539 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7540 "jsr @%0%#"
7541 [(set_attr "type" "call")
7542 (set (attr "fp_mode")
7543 (if_then_else (eq_attr "fpu_single" "yes")
7544 (const_string "single") (const_string "double")))
7545 (set_attr "needs_delay_slot" "yes")])
7546
7547 (define_expand "call_pop"
7548 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7549 (match_operand 1 "" ""))
7550 (match_operand 2 "" "")
7551 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7552 (match_operand 3 "" "")))])]
7553 "TARGET_SHCOMPACT"
7554 "
7555 {
7556 rtx cookie_rtx;
7557 long cookie;
7558 rtx func;
7559 rtx r0, r1;
7560
7561 gcc_assert (operands[2] && INTVAL (operands[2]));
7562 cookie_rtx = operands[2];
7563 cookie = INTVAL (cookie_rtx);
7564 func = XEXP (operands[0], 0);
7565
7566 if (flag_pic)
7567 {
7568 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7569 {
7570 rtx reg = gen_reg_rtx (Pmode);
7571 emit_insn (gen_symGOTPLT2reg (reg, func));
7572 func = reg;
7573 }
7574 else
7575 func = legitimize_pic_address (func, Pmode, 0);
7576 }
7577
7578 r0 = gen_rtx_REG (SImode, R0_REG);
7579 r1 = gen_rtx_REG (SImode, R1_REG);
7580
7581 /* Since such a call function may use all call-clobbered
7582 registers, we force a mode switch earlier, so that we don't
7583 run out of registers when adjusting fpscr for the call. */
7584 emit_insn (gen_force_mode_for_call ());
7585
7586 operands[0] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7587 SFUNC_GOT);
7588 operands[0] = force_reg (SImode, operands[0]);
7589
7590 emit_move_insn (r0, func);
7591 emit_move_insn (r1, cookie_rtx);
7592
7593 if (cookie & CALL_COOKIE_RET_TRAMP (1))
7594 emit_call_insn (gen_call_pop_compact_rettramp
7595 (operands[0], operands[1], operands[2], operands[3]));
7596 else
7597 emit_call_insn (gen_call_pop_compact
7598 (operands[0], operands[1], operands[2], operands[3]));
7599
7600 DONE;
7601 }")
7602
7603 (define_expand "call_value"
7604 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
7605 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
7606 (match_operand 2 "" "")))
7607 (match_operand 3 "" "")
7608 (use (reg:PSI FPSCR_REG))
7609 (clobber (reg:SI PR_REG))])]
7610 ""
7611 "
7612 {
7613 if (TARGET_SHMEDIA)
7614 {
7615 operands[1] = shmedia_prepare_call_address (operands[1], 0);
7616 emit_call_insn (gen_call_value_media (operands[0], operands[1],
7617 operands[2]));
7618 DONE;
7619 }
7620 else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
7621 {
7622 rtx cookie_rtx = operands[3];
7623 long cookie = INTVAL (cookie_rtx);
7624 rtx func = XEXP (operands[1], 0);
7625 rtx r0, r1;
7626
7627 if (flag_pic)
7628 {
7629 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7630 {
7631 rtx reg = gen_reg_rtx (Pmode);
7632
7633 emit_insn (gen_symGOTPLT2reg (reg, func));
7634 func = reg;
7635 }
7636 else
7637 func = legitimize_pic_address (func, Pmode, 0);
7638 }
7639
7640 r0 = gen_rtx_REG (SImode, R0_REG);
7641 r1 = gen_rtx_REG (SImode, R1_REG);
7642
7643 /* Since such a call function may use all call-clobbered
7644 registers, we force a mode switch earlier, so that we don't
7645 run out of registers when adjusting fpscr for the call. */
7646 emit_insn (gen_force_mode_for_call ());
7647
7648 operands[1]
7649 = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7650 SFUNC_GOT);
7651 operands[1] = force_reg (SImode, operands[1]);
7652
7653 emit_move_insn (r0, func);
7654 emit_move_insn (r1, cookie_rtx);
7655
7656 if (cookie & CALL_COOKIE_RET_TRAMP (1))
7657 emit_call_insn (gen_call_value_compact_rettramp (operands[0],
7658 operands[1],
7659 operands[2],
7660 operands[3]));
7661 else
7662 emit_call_insn (gen_call_value_compact (operands[0], operands[1],
7663 operands[2], operands[3]));
7664
7665 DONE;
7666 }
7667 else if (TARGET_SHCOMPACT && flag_pic
7668 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7669 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
7670 {
7671 rtx reg = gen_reg_rtx (Pmode);
7672
7673 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
7674 XEXP (operands[1], 0) = reg;
7675 }
7676 if (!flag_pic && TARGET_SH2A
7677 && MEM_P (operands[1])
7678 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
7679 {
7680 if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
7681 {
7682 emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
7683 XEXP (operands[1], 0), operands[2]));
7684 DONE;
7685 }
7686 }
7687 if (flag_pic && TARGET_SH2
7688 && MEM_P (operands[1])
7689 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
7690 {
7691 emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
7692 operands[2]));
7693 DONE;
7694 }
7695 else
7696 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
7697
7698 emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
7699 DONE;
7700 }")
7701
7702 (define_insn "sibcalli"
7703 [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
7704 (match_operand 1 "" ""))
7705 (use (reg:PSI FPSCR_REG))
7706 (return)]
7707 "TARGET_SH1"
7708 "jmp @%0%#"
7709 [(set_attr "needs_delay_slot" "yes")
7710 (set (attr "fp_mode")
7711 (if_then_else (eq_attr "fpu_single" "yes")
7712 (const_string "single") (const_string "double")))
7713 (set_attr "type" "jump_ind")])
7714
7715 (define_insn "sibcalli_pcrel"
7716 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
7717 (match_operand 1 "" ""))
7718 (use (match_operand 2 "" ""))
7719 (use (reg:PSI FPSCR_REG))
7720 (return)]
7721 "TARGET_SH2"
7722 "braf %0\\n%O2:%#"
7723 [(set_attr "needs_delay_slot" "yes")
7724 (set (attr "fp_mode")
7725 (if_then_else (eq_attr "fpu_single" "yes")
7726 (const_string "single") (const_string "double")))
7727 (set_attr "type" "jump_ind")])
7728
7729 ;; This uses an unspec to describe that the symbol_ref is very close.
7730 (define_insn "sibcalli_thunk"
7731 [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
7732 UNSPEC_THUNK))
7733 (match_operand 1 "" ""))
7734 (use (reg:PSI FPSCR_REG))
7735 (return)]
7736 "TARGET_SH1"
7737 "bra %O0"
7738 [(set_attr "needs_delay_slot" "yes")
7739 (set (attr "fp_mode")
7740 (if_then_else (eq_attr "fpu_single" "yes")
7741 (const_string "single") (const_string "double")))
7742 (set_attr "type" "jump")
7743 (set_attr "length" "2")])
7744
7745 (define_insn_and_split "sibcall_pcrel"
7746 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7747 (match_operand 1 "" ""))
7748 (use (reg:PSI FPSCR_REG))
7749 (clobber (match_scratch:SI 2 "=k"))
7750 (return)]
7751 "TARGET_SH2"
7752 "#"
7753 "reload_completed"
7754 [(const_int 0)]
7755 "
7756 {
7757 rtx lab = PATTERN (gen_call_site ());
7758 rtx call_insn;
7759
7760 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7761 call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
7762 copy_rtx (lab)));
7763 SIBLING_CALL_P (call_insn) = 1;
7764 DONE;
7765 }"
7766 [(set_attr "needs_delay_slot" "yes")
7767 (set (attr "fp_mode")
7768 (if_then_else (eq_attr "fpu_single" "yes")
7769 (const_string "single") (const_string "double")))
7770 (set_attr "type" "jump_ind")])
7771
7772 (define_insn "sibcall_compact"
7773 [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
7774 (match_operand 1 "" ""))
7775 (return)
7776 (use (match_operand:SI 2 "register_operand" "z,x"))
7777 (use (reg:SI R1_REG))
7778 (use (reg:PSI FPSCR_REG))
7779 ;; We want to make sure the `x' above will only match MACH_REG
7780 ;; because sibcall_epilogue may clobber MACL_REG.
7781 (clobber (reg:SI MACL_REG))]
7782 "TARGET_SHCOMPACT"
7783 "@
7784 jmp @%0%#
7785 jmp @%0\\n sts %2, r0"
7786 [(set_attr "needs_delay_slot" "yes,no")
7787 (set_attr "length" "2,4")
7788 (set (attr "fp_mode") (const_string "single"))
7789 (set_attr "type" "jump_ind")])
7790
7791 (define_insn "sibcall_media"
7792 [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
7793 (match_operand 1 "" ""))
7794 (use (reg:SI PR_MEDIA_REG))
7795 (return)]
7796 "TARGET_SHMEDIA"
7797 "blink %0, r63"
7798 [(set_attr "type" "jump_media")])
7799
7800 (define_expand "sibcall"
7801 [(parallel
7802 [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7803 (match_operand 1 "" ""))
7804 (match_operand 2 "" "")
7805 (use (reg:PSI FPSCR_REG))
7806 (return)])]
7807 ""
7808 "
7809 {
7810 if (TARGET_SHMEDIA)
7811 {
7812 operands[0] = shmedia_prepare_call_address (operands[0], 1);
7813 emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
7814 DONE;
7815 }
7816 else if (TARGET_SHCOMPACT && operands[2]
7817 && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
7818 {
7819 rtx cookie_rtx = operands[2];
7820 long cookie = INTVAL (cookie_rtx);
7821 rtx func = XEXP (operands[0], 0);
7822 rtx mach, r1;
7823
7824 if (flag_pic)
7825 {
7826 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7827 {
7828 rtx reg = gen_reg_rtx (Pmode);
7829
7830 emit_insn (gen_symGOT2reg (reg, func));
7831 func = reg;
7832 }
7833 else
7834 func = legitimize_pic_address (func, Pmode, 0);
7835 }
7836
7837 /* FIXME: if we could tell whether all argument registers are
7838 already taken, we could decide whether to force the use of
7839 MACH_REG or to stick to R0_REG. Unfortunately, there's no
7840 simple way to tell. We could use the CALL_COOKIE, but we
7841 can't currently tell a register used for regular argument
7842 passing from one that is unused. If we leave it up to reload
7843 to decide which register to use, it seems to always choose
7844 R0_REG, which leaves no available registers in SIBCALL_REGS
7845 to hold the address of the trampoline. */
7846 mach = gen_rtx_REG (SImode, MACH_REG);
7847 r1 = gen_rtx_REG (SImode, R1_REG);
7848
7849 /* Since such a call function may use all call-clobbered
7850 registers, we force a mode switch earlier, so that we don't
7851 run out of registers when adjusting fpscr for the call. */
7852 emit_insn (gen_force_mode_for_call ());
7853
7854 operands[0]
7855 = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7856 SFUNC_GOT);
7857 operands[0] = force_reg (SImode, operands[0]);
7858
7859 /* We don't need a return trampoline, since the callee will
7860 return directly to the upper caller. */
7861 if (cookie & CALL_COOKIE_RET_TRAMP (1))
7862 {
7863 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
7864 cookie_rtx = GEN_INT (cookie);
7865 }
7866
7867 emit_move_insn (mach, func);
7868 emit_move_insn (r1, cookie_rtx);
7869
7870 emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
7871 DONE;
7872 }
7873 else if (TARGET_SHCOMPACT && flag_pic
7874 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7875 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7876 {
7877 rtx reg = gen_reg_rtx (Pmode);
7878
7879 emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
7880 XEXP (operands[0], 0) = reg;
7881 }
7882 if (flag_pic && TARGET_SH2
7883 && MEM_P (operands[0])
7884 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7885 /* The PLT needs the PIC register, but the epilogue would have
7886 to restore it, so we can only use PC-relative PIC calls for
7887 static functions. */
7888 && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7889 {
7890 emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
7891 DONE;
7892 }
7893 else
7894 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
7895
7896 emit_call_insn (gen_sibcalli (operands[0], operands[1]));
7897 DONE;
7898 }")
7899
7900 (define_insn "sibcall_valuei"
7901 [(set (match_operand 0 "" "=rf")
7902 (call (mem:SI (match_operand:SI 1 "register_operand" "k"))
7903 (match_operand 2 "" "")))
7904 (use (reg:PSI FPSCR_REG))
7905 (return)]
7906 "TARGET_SH1"
7907 "jmp @%1%#"
7908 [(set_attr "needs_delay_slot" "yes")
7909 (set (attr "fp_mode")
7910 (if_then_else (eq_attr "fpu_single" "yes")
7911 (const_string "single") (const_string "double")))
7912 (set_attr "type" "jump_ind")])
7913
7914 (define_insn "sibcall_valuei_pcrel"
7915 [(set (match_operand 0 "" "=rf")
7916 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
7917 (match_operand 2 "" "")))
7918 (use (match_operand 3 "" ""))
7919 (use (reg:PSI FPSCR_REG))
7920 (return)]
7921 "TARGET_SH2"
7922 "braf %1\\n%O3:%#"
7923 [(set_attr "needs_delay_slot" "yes")
7924 (set (attr "fp_mode")
7925 (if_then_else (eq_attr "fpu_single" "yes")
7926 (const_string "single") (const_string "double")))
7927 (set_attr "type" "jump_ind")])
7928
7929 (define_insn_and_split "sibcall_value_pcrel"
7930 [(set (match_operand 0 "" "=rf")
7931 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7932 (match_operand 2 "" "")))
7933 (use (reg:PSI FPSCR_REG))
7934 (clobber (match_scratch:SI 3 "=k"))
7935 (return)]
7936 "TARGET_SH2"
7937 "#"
7938 "reload_completed"
7939 [(const_int 0)]
7940 "
7941 {
7942 rtx lab = PATTERN (gen_call_site ());
7943 rtx call_insn;
7944
7945 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
7946 call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
7947 operands[3],
7948 operands[2],
7949 copy_rtx (lab)));
7950 SIBLING_CALL_P (call_insn) = 1;
7951 DONE;
7952 }"
7953 [(set_attr "needs_delay_slot" "yes")
7954 (set (attr "fp_mode")
7955 (if_then_else (eq_attr "fpu_single" "yes")
7956 (const_string "single") (const_string "double")))
7957 (set_attr "type" "jump_ind")])
7958
7959 (define_insn "sibcall_value_compact"
7960 [(set (match_operand 0 "" "=rf,rf")
7961 (call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
7962 (match_operand 2 "" "")))
7963 (return)
7964 (use (match_operand:SI 3 "register_operand" "z,x"))
7965 (use (reg:SI R1_REG))
7966 (use (reg:PSI FPSCR_REG))
7967 ;; We want to make sure the `x' above will only match MACH_REG
7968 ;; because sibcall_epilogue may clobber MACL_REG.
7969 (clobber (reg:SI MACL_REG))]
7970 "TARGET_SHCOMPACT"
7971 "@
7972 jmp @%1%#
7973 jmp @%1\\n sts %3, r0"
7974 [(set_attr "needs_delay_slot" "yes,no")
7975 (set_attr "length" "2,4")
7976 (set (attr "fp_mode") (const_string "single"))
7977 (set_attr "type" "jump_ind")])
7978
7979 (define_insn "sibcall_value_media"
7980 [(set (match_operand 0 "" "=rf")
7981 (call (mem:DI (match_operand 1 "target_reg_operand" "k"))
7982 (match_operand 2 "" "")))
7983 (use (reg:SI PR_MEDIA_REG))
7984 (return)]
7985 "TARGET_SHMEDIA"
7986 "blink %1, r63"
7987 [(set_attr "type" "jump_media")])
7988
7989 (define_expand "sibcall_value"
7990 [(parallel
7991 [(set (match_operand 0 "arith_reg_operand" "")
7992 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
7993 (match_operand 2 "" "")))
7994 (match_operand 3 "" "")
7995 (use (reg:PSI FPSCR_REG))
7996 (return)])]
7997 ""
7998 "
7999 {
8000 if (TARGET_SHMEDIA)
8001 {
8002 operands[1] = shmedia_prepare_call_address (operands[1], 1);
8003 emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
8004 operands[2]));
8005 DONE;
8006 }
8007 else if (TARGET_SHCOMPACT && operands[3]
8008 && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
8009 {
8010 rtx cookie_rtx = operands[3];
8011 long cookie = INTVAL (cookie_rtx);
8012 rtx func = XEXP (operands[1], 0);
8013 rtx mach, r1;
8014
8015 if (flag_pic)
8016 {
8017 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8018 {
8019 rtx reg = gen_reg_rtx (Pmode);
8020
8021 emit_insn (gen_symGOT2reg (reg, func));
8022 func = reg;
8023 }
8024 else
8025 func = legitimize_pic_address (func, Pmode, 0);
8026 }
8027
8028 /* FIXME: if we could tell whether all argument registers are
8029 already taken, we could decide whether to force the use of
8030 MACH_REG or to stick to R0_REG. Unfortunately, there's no
8031 simple way to tell. We could use the CALL_COOKIE, but we
8032 can't currently tell a register used for regular argument
8033 passing from one that is unused. If we leave it up to reload
8034 to decide which register to use, it seems to always choose
8035 R0_REG, which leaves no available registers in SIBCALL_REGS
8036 to hold the address of the trampoline. */
8037 mach = gen_rtx_REG (SImode, MACH_REG);
8038 r1 = gen_rtx_REG (SImode, R1_REG);
8039
8040 /* Since such a call function may use all call-clobbered
8041 registers, we force a mode switch earlier, so that we don't
8042 run out of registers when adjusting fpscr for the call. */
8043 emit_insn (gen_force_mode_for_call ());
8044
8045 operands[1]
8046 = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8047 SFUNC_GOT);
8048 operands[1] = force_reg (SImode, operands[1]);
8049
8050 /* We don't need a return trampoline, since the callee will
8051 return directly to the upper caller. */
8052 if (cookie & CALL_COOKIE_RET_TRAMP (1))
8053 {
8054 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
8055 cookie_rtx = GEN_INT (cookie);
8056 }
8057
8058 emit_move_insn (mach, func);
8059 emit_move_insn (r1, cookie_rtx);
8060
8061 emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
8062 operands[2], mach));
8063 DONE;
8064 }
8065 else if (TARGET_SHCOMPACT && flag_pic
8066 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8067 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
8068 {
8069 rtx reg = gen_reg_rtx (Pmode);
8070
8071 emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
8072 XEXP (operands[1], 0) = reg;
8073 }
8074 if (flag_pic && TARGET_SH2
8075 && MEM_P (operands[1])
8076 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8077 /* The PLT needs the PIC register, but the epilogue would have
8078 to restore it, so we can only use PC-relative PIC calls for
8079 static functions. */
8080 && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
8081 {
8082 emit_call_insn (gen_sibcall_value_pcrel (operands[0],
8083 XEXP (operands[1], 0),
8084 operands[2]));
8085 DONE;
8086 }
8087 else
8088 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
8089
8090 emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
8091 DONE;
8092 }")
8093
8094 (define_insn "call_value_pop_compact"
8095 [(set (match_operand 0 "" "=rf")
8096 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8097 (match_operand 2 "" "")))
8098 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8099 (match_operand 4 "immediate_operand" "n")))
8100 (match_operand 3 "immediate_operand" "n")
8101 (use (reg:SI R0_REG))
8102 (use (reg:SI R1_REG))
8103 (use (reg:PSI FPSCR_REG))
8104 (clobber (reg:SI PR_REG))]
8105 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8106 "jsr @%1%#"
8107 [(set_attr "type" "call")
8108 (set (attr "fp_mode")
8109 (if_then_else (eq_attr "fpu_single" "yes")
8110 (const_string "single") (const_string "double")))
8111 (set_attr "needs_delay_slot" "yes")])
8112
8113 (define_insn "call_value_pop_compact_rettramp"
8114 [(set (match_operand 0 "" "=rf")
8115 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8116 (match_operand 2 "" "")))
8117 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8118 (match_operand 4 "immediate_operand" "n")))
8119 (match_operand 3 "immediate_operand" "n")
8120 (use (reg:SI R0_REG))
8121 (use (reg:SI R1_REG))
8122 (use (reg:PSI FPSCR_REG))
8123 (clobber (reg:SI R10_REG))
8124 (clobber (reg:SI PR_REG))]
8125 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8126 "jsr @%1%#"
8127 [(set_attr "type" "call")
8128 (set (attr "fp_mode")
8129 (if_then_else (eq_attr "fpu_single" "yes")
8130 (const_string "single") (const_string "double")))
8131 (set_attr "needs_delay_slot" "yes")])
8132
8133 (define_expand "call_value_pop"
8134 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
8135 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
8136 (match_operand 2 "" "")))
8137 (match_operand 3 "" "")
8138 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8139 (match_operand 4 "" "")))])]
8140 "TARGET_SHCOMPACT"
8141 "
8142 {
8143 rtx cookie_rtx;
8144 long cookie;
8145 rtx func;
8146 rtx r0, r1;
8147
8148 gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
8149 cookie_rtx = operands[3];
8150 cookie = INTVAL (cookie_rtx);
8151 func = XEXP (operands[1], 0);
8152
8153 if (flag_pic)
8154 {
8155 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8156 {
8157 rtx reg = gen_reg_rtx (Pmode);
8158
8159 emit_insn (gen_symGOTPLT2reg (reg, func));
8160 func = reg;
8161 }
8162 else
8163 func = legitimize_pic_address (func, Pmode, 0);
8164 }
8165
8166 r0 = gen_rtx_REG (SImode, R0_REG);
8167 r1 = gen_rtx_REG (SImode, R1_REG);
8168
8169 /* Since such a call function may use all call-clobbered
8170 registers, we force a mode switch earlier, so that we don't
8171 run out of registers when adjusting fpscr for the call. */
8172 emit_insn (gen_force_mode_for_call ());
8173
8174 operands[1] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8175 SFUNC_GOT);
8176 operands[1] = force_reg (SImode, operands[1]);
8177
8178 emit_move_insn (r0, func);
8179 emit_move_insn (r1, cookie_rtx);
8180
8181 if (cookie & CALL_COOKIE_RET_TRAMP (1))
8182 emit_call_insn (gen_call_value_pop_compact_rettramp
8183 (operands[0], operands[1], operands[2],
8184 operands[3], operands[4]));
8185 else
8186 emit_call_insn (gen_call_value_pop_compact
8187 (operands[0], operands[1], operands[2],
8188 operands[3], operands[4]));
8189
8190 DONE;
8191 }")
8192
8193 (define_expand "sibcall_epilogue"
8194 [(return)]
8195 ""
8196 "
8197 {
8198 sh_expand_epilogue (1);
8199 if (TARGET_SHCOMPACT)
8200 {
8201 rtx insn, set;
8202
8203 /* If epilogue clobbers r0, preserve it in macl. */
8204 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
8205 if ((set = single_set (insn))
8206 && REG_P (SET_DEST (set))
8207 && REGNO (SET_DEST (set)) == R0_REG)
8208 {
8209 rtx r0 = gen_rtx_REG (SImode, R0_REG);
8210 rtx tmp = gen_rtx_REG (SImode, MACL_REG);
8211
8212 /* We can't tell at this point whether the sibcall is a
8213 sibcall_compact and, if it is, whether it uses r0 or
8214 mach as operand 2, so let the instructions that
8215 preserve r0 be optimized away if r0 turns out to be
8216 dead. */
8217 emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
8218 emit_move_insn (r0, tmp);
8219 break;
8220 }
8221 }
8222 DONE;
8223 }")
8224
8225 (define_insn "indirect_jump_compact"
8226 [(set (pc)
8227 (match_operand:SI 0 "arith_reg_operand" "r"))]
8228 "TARGET_SH1"
8229 "jmp @%0%#"
8230 [(set_attr "needs_delay_slot" "yes")
8231 (set_attr "type" "jump_ind")])
8232
8233 (define_expand "indirect_jump"
8234 [(set (pc)
8235 (match_operand 0 "register_operand" ""))]
8236 ""
8237 "
8238 {
8239 if (GET_MODE (operands[0]) != Pmode)
8240 operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
8241 }")
8242
8243 ;; The use of operand 1 / 2 helps us distinguish case table jumps
8244 ;; which can be present in structured code from indirect jumps which can not
8245 ;; be present in structured code. This allows -fprofile-arcs to work.
8246
8247 ;; For SH1 processors.
8248 (define_insn "casesi_jump_1"
8249 [(set (pc)
8250 (match_operand:SI 0 "register_operand" "r"))
8251 (use (label_ref (match_operand 1 "" "")))]
8252 "TARGET_SH1"
8253 "jmp @%0%#"
8254 [(set_attr "needs_delay_slot" "yes")
8255 (set_attr "type" "jump_ind")])
8256
8257 ;; For all later processors.
8258 (define_insn "casesi_jump_2"
8259 [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
8260 (label_ref (match_operand 1 "" ""))))
8261 (use (label_ref (match_operand 2 "" "")))]
8262 "TARGET_SH2
8263 && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
8264 "braf %0%#"
8265 [(set_attr "needs_delay_slot" "yes")
8266 (set_attr "type" "jump_ind")])
8267
8268 (define_insn "casesi_jump_media"
8269 [(set (pc) (match_operand 0 "target_reg_operand" "b"))
8270 (use (label_ref (match_operand 1 "" "")))]
8271 "TARGET_SHMEDIA"
8272 "blink %0, r63"
8273 [(set_attr "type" "jump_media")])
8274
8275 ;; Call subroutine returning any type.
8276 ;; ??? This probably doesn't work.
8277
8278 (define_expand "untyped_call"
8279 [(parallel [(call (match_operand 0 "" "")
8280 (const_int 0))
8281 (match_operand 1 "" "")
8282 (match_operand 2 "" "")])]
8283 "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
8284 "
8285 {
8286 int i;
8287
8288 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
8289
8290 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8291 {
8292 rtx set = XVECEXP (operands[2], 0, i);
8293 emit_move_insn (SET_DEST (set), SET_SRC (set));
8294 }
8295
8296 /* The optimizer does not know that the call sets the function value
8297 registers we stored in the result block. We avoid problems by
8298 claiming that all hard registers are used and clobbered at this
8299 point. */
8300 emit_insn (gen_blockage ());
8301
8302 DONE;
8303 }")
8304 \f
8305 ;; ------------------------------------------------------------------------
8306 ;; Misc insns
8307 ;; ------------------------------------------------------------------------
8308
8309 (define_insn "dect"
8310 [(set (reg:SI T_REG)
8311 (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
8312 (set (match_operand:SI 0 "arith_reg_dest" "=r")
8313 (plus:SI (match_dup 1) (const_int -1)))]
8314 "TARGET_SH2"
8315 "dt %0"
8316 [(set_attr "type" "arith")])
8317
8318 (define_insn "nop"
8319 [(const_int 0)]
8320 ""
8321 "nop")
8322
8323 ;; Load address of a label. This is only generated by the casesi expand,
8324 ;; and by machine_dependent_reorg (fixing up fp moves).
8325 ;; This must use unspec, because this only works for labels that are
8326 ;; within range,
8327
8328 (define_insn "mova"
8329 [(set (reg:SI R0_REG)
8330 (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
8331 "TARGET_SH1"
8332 "mova %O0,r0"
8333 [(set_attr "in_delay_slot" "no")
8334 (set_attr "type" "arith")])
8335
8336 ;; machine_dependent_reorg will make this a `mova'.
8337 (define_insn "mova_const"
8338 [(set (reg:SI R0_REG)
8339 (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
8340 "TARGET_SH1"
8341 "#"
8342 [(set_attr "in_delay_slot" "no")
8343 (set_attr "type" "arith")])
8344
8345 (define_expand "GOTaddr2picreg"
8346 [(set (reg:SI R0_REG)
8347 (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
8348 UNSPEC_MOVA))
8349 (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
8350 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
8351 "" "
8352 {
8353 if (TARGET_VXWORKS_RTP)
8354 {
8355 rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
8356 rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
8357 emit_insn (gen_vxworks_picreg (gott_base, gott_index));
8358 DONE;
8359 }
8360
8361 operands[0] = gen_rtx_REG (Pmode, PIC_REG);
8362 operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
8363
8364 if (TARGET_SHMEDIA)
8365 {
8366 rtx tr = gen_rtx_REG (Pmode, TR0_REG);
8367 rtx pic = operands[0];
8368 rtx lab = PATTERN (gen_call_site ());
8369 rtx insn, equiv;
8370
8371 equiv = operands[1];
8372 operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
8373 UNSPEC_PCREL_SYMOFF);
8374 operands[1] = gen_rtx_CONST (Pmode, operands[1]);
8375
8376 if (Pmode == SImode)
8377 {
8378 emit_insn (gen_movsi_const (pic, operands[1]));
8379 emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
8380 }
8381 else
8382 {
8383 emit_insn (gen_movdi_const (pic, operands[1]));
8384 emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
8385 }
8386
8387 insn = emit_move_insn (operands[0], tr);
8388
8389 set_unique_reg_note (insn, REG_EQUAL, equiv);
8390
8391 DONE;
8392 }
8393 }
8394 ")
8395
8396 ;; A helper for GOTaddr2picreg to finish up the initialization of the
8397 ;; PIC register.
8398
8399 (define_expand "vxworks_picreg"
8400 [(set (reg:SI PIC_REG)
8401 (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
8402 (set (reg:SI R0_REG)
8403 (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
8404 (set (reg:SI PIC_REG)
8405 (mem:SI (reg:SI PIC_REG)))
8406 (set (reg:SI PIC_REG)
8407 (mem:SI (plus:SI (reg:SI PIC_REG)
8408 (reg:SI R0_REG))))]
8409 "TARGET_VXWORKS_RTP")
8410
8411 (define_insn "*ptb"
8412 [(set (match_operand 0 "target_reg_operand" "=b")
8413 (const (unspec [(match_operand 1 "" "Csy")]
8414 UNSPEC_DATALABEL)))]
8415 "TARGET_SHMEDIA && flag_pic
8416 && satisfies_constraint_Csy (operands[1])"
8417 "ptb/u datalabel %1, %0"
8418 [(set_attr "type" "ptabs_media")
8419 (set_attr "length" "*")])
8420
8421 (define_insn "ptrel_si"
8422 [(set (match_operand:SI 0 "target_reg_operand" "=b")
8423 (plus:SI (match_operand:SI 1 "register_operand" "r")
8424 (pc)))
8425 (match_operand:SI 2 "" "")]
8426 "TARGET_SHMEDIA"
8427 "%O2: ptrel/u %1, %0"
8428 [(set_attr "type" "ptabs_media")])
8429
8430 (define_insn "ptrel_di"
8431 [(set (match_operand:DI 0 "target_reg_operand" "=b")
8432 (plus:DI (match_operand:DI 1 "register_operand" "r")
8433 (pc)))
8434 (match_operand:DI 2 "" "")]
8435 "TARGET_SHMEDIA"
8436 "%O2: ptrel/u %1, %0"
8437 [(set_attr "type" "ptabs_media")])
8438
8439 (define_expand "builtin_setjmp_receiver"
8440 [(match_operand 0 "" "")]
8441 "flag_pic"
8442 "
8443 {
8444 emit_insn (gen_GOTaddr2picreg ());
8445 DONE;
8446 }")
8447
8448 (define_expand "call_site"
8449 [(unspec [(match_dup 0)] UNSPEC_CALLER)]
8450 "TARGET_SH1"
8451 "
8452 {
8453 static HOST_WIDE_INT i = 0;
8454 operands[0] = GEN_INT (i);
8455 i++;
8456 }")
8457
8458 ;; op0 = op1 + r12 but hide it before reload completed. See the comment
8459 ;; in symGOT_load expand.
8460
8461 (define_insn_and_split "chk_guard_add"
8462 [(set (match_operand:SI 0 "register_operand" "=&r")
8463 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
8464 (reg:SI PIC_REG)]
8465 UNSPEC_CHKADD))]
8466 "TARGET_SH1"
8467 "#"
8468 "TARGET_SH1 && reload_completed"
8469 [(set (match_dup 0) (reg:SI PIC_REG))
8470 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8471 ""
8472 [(set_attr "type" "arith")])
8473
8474 (define_expand "sym_label2reg"
8475 [(set (match_operand:SI 0 "" "")
8476 (const:SI (unspec:SI [(match_operand:SI 1 "" "")
8477 (const (plus:SI (match_operand:SI 2 "" "")
8478 (const_int 2)))]
8479 UNSPEC_SYMOFF)))]
8480 "TARGET_SH1" "")
8481
8482 (define_expand "symGOT_load"
8483 [(set (match_dup 2) (match_operand 1 "" ""))
8484 (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
8485 (set (match_operand 0 "" "") (mem (match_dup 3)))]
8486 ""
8487 "
8488 {
8489 rtx mem;
8490
8491 operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
8492 operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
8493
8494 if (TARGET_SHMEDIA)
8495 {
8496 rtx reg = operands[2];
8497
8498 if (Pmode == DImode)
8499 {
8500 if (flag_pic > 1)
8501 emit_insn (gen_movdi_const_32bit (reg, operands[1]));
8502 else
8503 emit_insn (gen_movdi_const_16bit (reg, operands[1]));
8504 }
8505 else
8506 {
8507 if (flag_pic > 1)
8508 emit_insn (gen_movsi_const (reg, operands[1]));
8509 else
8510 emit_insn (gen_movsi_const_16bit (reg, operands[1]));
8511 }
8512 }
8513 else
8514 emit_move_insn (operands[2], operands[1]);
8515
8516 /* When stack protector inserts codes after the result is set to
8517 R0, @(rX, r12) will cause a spill failure for R0. Use a unspec
8518 insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
8519 when rX is a GOT address for the guard symbol. Ugly but doesn't
8520 matter because this is a rare situation. */
8521 if (!TARGET_SHMEDIA
8522 && flag_stack_protect
8523 && GET_CODE (operands[1]) == CONST
8524 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
8525 && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
8526 && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
8527 \"__stack_chk_guard\") == 0)
8528 emit_insn (gen_chk_guard_add (operands[3], operands[2]));
8529 else
8530 emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
8531 gen_rtx_REG (Pmode, PIC_REG)));
8532
8533 /* N.B. This is not constant for a GOTPLT relocation. */
8534 mem = gen_rtx_MEM (Pmode, operands[3]);
8535 MEM_NOTRAP_P (mem) = 1;
8536 /* ??? Should we have a special alias set for the GOT? */
8537 emit_move_insn (operands[0], mem);
8538
8539 DONE;
8540 }")
8541
8542 (define_expand "sym2GOT"
8543 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
8544 ""
8545 "")
8546
8547 (define_expand "symGOT2reg"
8548 [(match_operand 0 "" "") (match_operand 1 "" "")]
8549 ""
8550 "
8551 {
8552 rtx gotsym, insn;
8553
8554 gotsym = gen_sym2GOT (operands[1]);
8555 PUT_MODE (gotsym, Pmode);
8556 insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
8557
8558 MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
8559
8560 DONE;
8561 }")
8562
8563 (define_expand "symGOTPLT2reg"
8564 [(match_operand 0 "" "") (match_operand 1 "" "")]
8565 ""
8566 "
8567 {
8568 rtx pltsym = gen_rtx_CONST (Pmode,
8569 gen_rtx_UNSPEC (Pmode,
8570 gen_rtvec (1, operands[1]),
8571 UNSPEC_GOTPLT));
8572 emit_insn (gen_symGOT_load (operands[0], pltsym));
8573 DONE;
8574 }")
8575
8576 (define_expand "sym2GOTOFF"
8577 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
8578 ""
8579 "")
8580
8581 (define_expand "symGOTOFF2reg"
8582 [(match_operand 0 "" "") (match_operand 1 "" "")]
8583 ""
8584 "
8585 {
8586 rtx gotoffsym, insn;
8587 rtx t = (!can_create_pseudo_p ()
8588 ? operands[0]
8589 : gen_reg_rtx (GET_MODE (operands[0])));
8590
8591 gotoffsym = gen_sym2GOTOFF (operands[1]);
8592 PUT_MODE (gotoffsym, Pmode);
8593 emit_move_insn (t, gotoffsym);
8594 insn = emit_move_insn (operands[0],
8595 gen_rtx_PLUS (Pmode, t,
8596 gen_rtx_REG (Pmode, PIC_REG)));
8597
8598 set_unique_reg_note (insn, REG_EQUAL, operands[1]);
8599
8600 DONE;
8601 }")
8602
8603 (define_expand "symPLT_label2reg"
8604 [(set (match_operand:SI 0 "" "")
8605 (const:SI
8606 (unspec:SI
8607 [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
8608 (const:SI (plus:SI (match_operand:SI 2 "" "")
8609 (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
8610 ;; Even though the PIC register is not really used by the call
8611 ;; sequence in which this is expanded, the PLT code assumes the PIC
8612 ;; register is set, so we must not skip its initialization. Since
8613 ;; we only use this expand as part of calling sequences, and never
8614 ;; to take the address of a function, this is the best point to
8615 ;; insert the (use). Using the PLT to take the address of a
8616 ;; function would be wrong, not only because the PLT entry could
8617 ;; then be called from a function that doesn't initialize the PIC
8618 ;; register to the proper GOT, but also because pointers to the
8619 ;; same function might not compare equal, should they be set by
8620 ;; different shared libraries.
8621 (use (reg:SI PIC_REG))]
8622 "TARGET_SH1"
8623 "")
8624
8625 (define_expand "sym2PIC"
8626 [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
8627 ""
8628 "")
8629
8630 ;; TLS code generation.
8631 ;; ??? this should be a define_insn_and_split
8632 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
8633 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
8634 ;; for details.
8635
8636 (define_insn "tls_global_dynamic"
8637 [(set (match_operand:SI 0 "register_operand" "=&z")
8638 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8639 UNSPEC_TLSGD))
8640 (const_int 0)))
8641 (use (reg:PSI FPSCR_REG))
8642 (use (reg:SI PIC_REG))
8643 (clobber (reg:SI PR_REG))
8644 (clobber (scratch:SI))]
8645 "TARGET_SH1"
8646 "*
8647 {
8648 return \"\\
8649 mov.l\\t1f,r4\\n\\
8650 \\tmova\\t2f,r0\\n\\
8651 \\tmov.l\\t2f,r1\\n\\
8652 \\tadd\\tr0,r1\\n\\
8653 \\tjsr\\t@r1\\n\\
8654 \\tadd\\tr12,r4\\n\\
8655 \\tbra\\t3f\\n\\
8656 \\tnop\\n\\
8657 \\t.align\\t2\\n\\
8658 1:\\t.long\\t%a1@TLSGD\\n\\
8659 2:\\t.long\\t__tls_get_addr@PLT\\n\\
8660 3:\";
8661 }"
8662 [(set_attr "type" "tls_load")
8663 (set_attr "length" "26")])
8664
8665 (define_insn "tls_local_dynamic"
8666 [(set (match_operand:SI 0 "register_operand" "=&z")
8667 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8668 UNSPEC_TLSLDM))
8669 (const_int 0)))
8670 (use (reg:PSI FPSCR_REG))
8671 (use (reg:SI PIC_REG))
8672 (clobber (reg:SI PR_REG))
8673 (clobber (scratch:SI))]
8674 "TARGET_SH1"
8675 "*
8676 {
8677 return \"\\
8678 mov.l\\t1f,r4\\n\\
8679 \\tmova\\t2f,r0\\n\\
8680 \\tmov.l\\t2f,r1\\n\\
8681 \\tadd\\tr0,r1\\n\\
8682 \\tjsr\\t@r1\\n\\
8683 \\tadd\\tr12,r4\\n\\
8684 \\tbra\\t3f\\n\\
8685 \\tnop\\n\\
8686 \\t.align\\t2\\n\\
8687 1:\\t.long\\t%a1@TLSLDM\\n\\
8688 2:\\t.long\\t__tls_get_addr@PLT\\n\\
8689 3:\";
8690 }"
8691 [(set_attr "type" "tls_load")
8692 (set_attr "length" "26")])
8693
8694 (define_expand "sym2DTPOFF"
8695 [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
8696 ""
8697 "")
8698
8699 (define_expand "symDTPOFF2reg"
8700 [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
8701 ""
8702 "
8703 {
8704 rtx dtpoffsym;
8705 rtx t = (!can_create_pseudo_p ()
8706 ? operands[0]
8707 : gen_reg_rtx (GET_MODE (operands[0])));
8708
8709 dtpoffsym = gen_sym2DTPOFF (operands[1]);
8710 PUT_MODE (dtpoffsym, Pmode);
8711 emit_move_insn (t, dtpoffsym);
8712 emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
8713 DONE;
8714 }")
8715
8716 (define_expand "sym2GOTTPOFF"
8717 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
8718 ""
8719 "")
8720
8721 (define_insn "tls_initial_exec"
8722 [(set (match_operand:SI 0 "register_operand" "=&r")
8723 (unspec:SI [(match_operand:SI 1 "" "")]
8724 UNSPEC_TLSIE))
8725 (use (reg:SI GBR_REG))
8726 (use (reg:SI PIC_REG))
8727 (clobber (reg:SI R0_REG))]
8728 ""
8729 "*
8730 {
8731 return \"\\
8732 mov.l\\t1f,r0\\n\\
8733 \\tstc\\tgbr,%0\\n\\
8734 \\tmov.l\\t@(r0,r12),r0\\n\\
8735 \\tbra\\t2f\\n\\
8736 \\tadd\\tr0,%0\\n\\
8737 \\t.align\\t2\\n\\
8738 1:\\t.long\\t%a1\\n\\
8739 2:\";
8740 }"
8741 [(set_attr "type" "tls_load")
8742 (set_attr "length" "16")])
8743
8744 (define_expand "sym2TPOFF"
8745 [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
8746 ""
8747 "")
8748
8749 (define_expand "symTPOFF2reg"
8750 [(match_operand 0 "" "") (match_operand 1 "" "")]
8751 ""
8752 "
8753 {
8754 rtx tpoffsym;
8755
8756 tpoffsym = gen_sym2TPOFF (operands[1]);
8757 PUT_MODE (tpoffsym, Pmode);
8758 emit_move_insn (operands[0], tpoffsym);
8759 DONE;
8760 }")
8761
8762 (define_insn "load_gbr"
8763 [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))
8764 (use (reg:SI GBR_REG))]
8765 ""
8766 "stc gbr,%0"
8767 [(set_attr "type" "tls_load")])
8768
8769 ;; case instruction for switch statements.
8770
8771 ;; Operand 0 is index
8772 ;; operand 1 is the minimum bound
8773 ;; operand 2 is the maximum bound - minimum bound + 1
8774 ;; operand 3 is CODE_LABEL for the table;
8775 ;; operand 4 is the CODE_LABEL to go to if index out of range.
8776
8777 (define_expand "casesi"
8778 [(match_operand:SI 0 "arith_reg_operand" "")
8779 (match_operand:SI 1 "arith_reg_operand" "")
8780 (match_operand:SI 2 "arith_reg_operand" "")
8781 (match_operand 3 "" "") (match_operand 4 "" "")]
8782 ""
8783 "
8784 {
8785 rtx reg = gen_reg_rtx (SImode);
8786 rtx reg2 = gen_reg_rtx (SImode);
8787 if (TARGET_SHMEDIA)
8788 {
8789 rtx reg = gen_reg_rtx (DImode);
8790 rtx reg2 = gen_reg_rtx (DImode);
8791 rtx reg3 = gen_reg_rtx (Pmode);
8792 rtx reg4 = gen_reg_rtx (Pmode);
8793 rtx reg5 = gen_reg_rtx (Pmode);
8794 rtx load, test;
8795
8796 operands[0] = convert_modes (DImode, SImode, operands[0], 0);
8797 operands[1] = convert_modes (DImode, SImode, operands[1], 0);
8798 operands[2] = convert_modes (DImode, SImode, operands[2], 1);
8799
8800 test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
8801 emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0], operands[4]));
8802 emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
8803 test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
8804 emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
8805 emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
8806 emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
8807 (Pmode, operands[3])));
8808 /* Messy: can we subreg to clean this up? */
8809 if (Pmode == DImode)
8810 load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
8811 else
8812 load = gen_casesi_load_media (reg4,
8813 gen_rtx_SUBREG (DImode, reg3, 0),
8814 reg2, operands[3]);
8815 PUT_MODE (SET_SRC (load), Pmode);
8816 emit_insn (load);
8817 /* ??? The following add could be eliminated if we used ptrel. */
8818 emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
8819 emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
8820 emit_barrier ();
8821 DONE;
8822 }
8823 operands[1] = copy_to_mode_reg (SImode, operands[1]);
8824 operands[2] = copy_to_mode_reg (SImode, operands[2]);
8825 /* If optimizing, casesi_worker depends on the mode of the instruction
8826 before label it 'uses' - operands[3]. */
8827 emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
8828 reg));
8829 emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
8830 if (TARGET_SH2)
8831 emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
8832 else
8833 emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
8834 /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
8835 operands[3], but to lab. We will fix this up in
8836 machine_dependent_reorg. */
8837 emit_barrier ();
8838 DONE;
8839 }")
8840
8841 (define_expand "casesi_0"
8842 [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
8843 (set (match_dup 4) (minus:SI (match_dup 4)
8844 (match_operand:SI 1 "arith_operand" "")))
8845 (set (reg:SI T_REG)
8846 (gtu:SI (match_dup 4)
8847 (match_operand:SI 2 "arith_reg_operand" "")))
8848 (set (pc)
8849 (if_then_else (ne (reg:SI T_REG)
8850 (const_int 0))
8851 (label_ref (match_operand 3 "" ""))
8852 (pc)))]
8853 "TARGET_SH1"
8854 "")
8855
8856 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
8857 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
8858 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
8859
8860 (define_insn "casesi_worker_0"
8861 [(set (match_operand:SI 0 "register_operand" "=r,r")
8862 (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
8863 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8864 (clobber (match_scratch:SI 3 "=X,1"))
8865 (clobber (match_scratch:SI 4 "=&z,z"))]
8866 "TARGET_SH1"
8867 "#")
8868
8869 (define_split
8870 [(set (match_operand:SI 0 "register_operand" "")
8871 (unspec:SI [(match_operand:SI 1 "register_operand" "")
8872 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8873 (clobber (match_scratch:SI 3 ""))
8874 (clobber (match_scratch:SI 4 ""))]
8875 "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
8876 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
8877 (parallel [(set (match_dup 0)
8878 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
8879 (label_ref (match_dup 2))] UNSPEC_CASESI))
8880 (clobber (match_dup 3))])
8881 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
8882 "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
8883
8884 (define_split
8885 [(set (match_operand:SI 0 "register_operand" "")
8886 (unspec:SI [(match_operand:SI 1 "register_operand" "")
8887 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8888 (clobber (match_scratch:SI 3 ""))
8889 (clobber (match_scratch:SI 4 ""))]
8890 "TARGET_SH2 && reload_completed"
8891 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
8892 (parallel [(set (match_dup 0)
8893 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
8894 (label_ref (match_dup 2))] UNSPEC_CASESI))
8895 (clobber (match_dup 3))])]
8896 "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
8897
8898 (define_insn "casesi_worker_1"
8899 [(set (match_operand:SI 0 "register_operand" "=r,r")
8900 (unspec:SI [(reg:SI R0_REG)
8901 (match_operand:SI 1 "register_operand" "0,r")
8902 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8903 (clobber (match_scratch:SI 3 "=X,1"))]
8904 "TARGET_SH1"
8905 "*
8906 {
8907 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8908
8909 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8910
8911 switch (GET_MODE (diff_vec))
8912 {
8913 case SImode:
8914 return \"shll2 %1\;mov.l @(r0,%1),%0\";
8915 case HImode:
8916 return \"add %1,%1\;mov.w @(r0,%1),%0\";
8917 case QImode:
8918 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8919 return \"mov.b @(r0,%1),%0\;extu.b %0,%0\";
8920 return \"mov.b @(r0,%1),%0\";
8921 default:
8922 gcc_unreachable ();
8923 }
8924 }"
8925 [(set_attr "length" "4")])
8926
8927 (define_insn "casesi_worker_2"
8928 [(set (match_operand:SI 0 "register_operand" "=r,r")
8929 (unspec:SI [(reg:SI R0_REG)
8930 (match_operand:SI 1 "register_operand" "0,r")
8931 (label_ref (match_operand 2 "" ""))
8932 (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
8933 (clobber (match_operand:SI 4 "" "=X,1"))]
8934 "TARGET_SH2 && reload_completed && flag_pic"
8935 "*
8936 {
8937 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8938 const char *load;
8939
8940 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8941
8942 switch (GET_MODE (diff_vec))
8943 {
8944 case SImode:
8945 output_asm_insn (\"shll2 %1\", operands);
8946 load = \"mov.l @(r0,%1),%0\"; break;
8947 case HImode:
8948 output_asm_insn (\"add %1,%1\", operands);
8949 load = \"mov.w @(r0,%1),%0\"; break;
8950 case QImode:
8951 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8952 load = \"mov.b @(r0,%1),%0\;extu.b %0,%0\";
8953 else
8954 load = \"mov.b @(r0,%1),%0\";
8955 break;
8956 default:
8957 gcc_unreachable ();
8958 }
8959 output_asm_insn (\"add\tr0,%1\;mova\t%O3,r0\\n\", operands);
8960 return load;
8961 }"
8962 [(set_attr "length" "8")])
8963
8964 (define_insn "casesi_shift_media"
8965 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
8966 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
8967 (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
8968 UNSPEC_CASESI)))]
8969 "TARGET_SHMEDIA"
8970 "*
8971 {
8972 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8973
8974 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8975
8976 switch (GET_MODE (diff_vec))
8977 {
8978 case SImode:
8979 return \"shlli %1, 2, %0\";
8980 case HImode:
8981 return \"shlli %1, 1, %0\";
8982 case QImode:
8983 if (rtx_equal_p (operands[0], operands[1]))
8984 return \"\";
8985 return \"add %1, r63, %0\";
8986 default:
8987 gcc_unreachable ();
8988 }
8989 }"
8990 [(set_attr "type" "arith_media")])
8991
8992 (define_insn "casesi_load_media"
8993 [(set (match_operand 0 "any_arith_reg_dest" "=r")
8994 (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
8995 (match_operand:DI 2 "arith_reg_operand" "r")
8996 (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
8997 "TARGET_SHMEDIA"
8998 "*
8999 {
9000 rtx diff_vec = PATTERN (next_real_insn (operands[3]));
9001
9002 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9003
9004 switch (GET_MODE (diff_vec))
9005 {
9006 case SImode:
9007 return \"ldx.l %1, %2, %0\";
9008 case HImode:
9009 #if 0
9010 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9011 return \"ldx.uw %1, %2, %0\";
9012 #endif
9013 return \"ldx.w %1, %2, %0\";
9014 case QImode:
9015 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9016 return \"ldx.ub %1, %2, %0\";
9017 return \"ldx.b %1, %2, %0\";
9018 default:
9019 gcc_unreachable ();
9020 }
9021 }"
9022 [(set_attr "type" "load_media")])
9023
9024 (define_expand "return"
9025 [(return)]
9026 "reload_completed && ! sh_need_epilogue ()"
9027 "
9028 {
9029 if (TARGET_SHMEDIA)
9030 {
9031 emit_jump_insn (gen_return_media ());
9032 DONE;
9033 }
9034
9035 if (TARGET_SHCOMPACT
9036 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
9037 {
9038 emit_jump_insn (gen_shcompact_return_tramp ());
9039 DONE;
9040 }
9041 }")
9042
9043 (define_insn "*return_i"
9044 [(return)]
9045 "TARGET_SH1 && ! (TARGET_SHCOMPACT
9046 && (crtl->args.info.call_cookie
9047 & CALL_COOKIE_RET_TRAMP (1)))
9048 && reload_completed
9049 && lookup_attribute (\"trap_exit\",
9050 DECL_ATTRIBUTES (current_function_decl)) == NULL_TREE"
9051 "*
9052 {
9053 if (TARGET_SH2A && (dbr_sequence_length () == 0)
9054 && !current_function_interrupt)
9055 return \"rts/n\";
9056 else
9057 return \"%@ %#\";
9058 }"
9059 [(set_attr "type" "return")
9060 (set_attr "needs_delay_slot" "yes")])
9061
9062 ;; trapa has no delay slot.
9063 (define_insn "*return_trapa"
9064 [(return)]
9065 "TARGET_SH1 && !TARGET_SHCOMPACT
9066 && reload_completed"
9067 "%@"
9068 [(set_attr "type" "return")])
9069
9070 (define_expand "shcompact_return_tramp"
9071 [(return)]
9072 "TARGET_SHCOMPACT
9073 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
9074 "
9075 {
9076 rtx reg = gen_rtx_REG (Pmode, R0_REG);
9077
9078 function_symbol (reg, \"__GCC_shcompact_return_trampoline\", SFUNC_STATIC);
9079 emit_jump_insn (gen_shcompact_return_tramp_i ());
9080 DONE;
9081 }")
9082
9083 (define_insn "shcompact_return_tramp_i"
9084 [(parallel [(return) (use (reg:SI R0_REG))])]
9085 "TARGET_SHCOMPACT
9086 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
9087 "jmp @r0%#"
9088 [(set_attr "type" "jump_ind")
9089 (set_attr "needs_delay_slot" "yes")])
9090
9091 (define_insn "return_media_i"
9092 [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
9093 "TARGET_SHMEDIA && reload_completed"
9094 "blink %0, r63"
9095 [(set_attr "type" "jump_media")])
9096
9097 (define_insn "return_media_rte"
9098 [(return)]
9099 "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
9100 "rte"
9101 [(set_attr "type" "jump_media")])
9102
9103 (define_expand "return_media"
9104 [(return)]
9105 "TARGET_SHMEDIA && reload_completed"
9106 "
9107 {
9108 int tr_regno = sh_media_register_for_return ();
9109 rtx tr;
9110
9111 if (current_function_interrupt)
9112 {
9113 emit_jump_insn (gen_return_media_rte ());
9114 DONE;
9115 }
9116 if (tr_regno < 0)
9117 {
9118 rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
9119
9120 gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
9121 tr_regno = TR0_REG;
9122 tr = gen_rtx_REG (Pmode, tr_regno);
9123 emit_move_insn (tr, r18);
9124 }
9125 else
9126 tr = gen_rtx_REG (Pmode, tr_regno);
9127
9128 emit_jump_insn (gen_return_media_i (tr));
9129 DONE;
9130 }")
9131
9132 (define_insn "shcompact_preserve_incoming_args"
9133 [(set (match_operand:SI 0 "register_operand" "+r")
9134 (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
9135 "TARGET_SHCOMPACT"
9136 ""
9137 [(set_attr "length" "0")])
9138
9139 (define_insn "shcompact_incoming_args"
9140 [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
9141 (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
9142 (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
9143 (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
9144 (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
9145 (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
9146 (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
9147 (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
9148 (set (mem:BLK (reg:SI MACL_REG))
9149 (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
9150 (use (reg:SI R0_REG))
9151 (clobber (reg:SI R0_REG))
9152 (clobber (reg:SI MACL_REG))
9153 (clobber (reg:SI MACH_REG))
9154 (clobber (reg:SI PR_REG))]
9155 "TARGET_SHCOMPACT"
9156 "jsr @r0%#"
9157 [(set_attr "needs_delay_slot" "yes")])
9158
9159 (define_insn "shmedia_save_restore_regs_compact"
9160 [(set (reg:SI SP_REG)
9161 (plus:SI (reg:SI SP_REG)
9162 (match_operand:SI 0 "immediate_operand" "i")))
9163 (use (reg:SI R0_REG))
9164 (clobber (reg:SI PR_REG))]
9165 "TARGET_SHCOMPACT
9166 && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
9167 || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
9168 "jsr @r0%#"
9169 [(set_attr "needs_delay_slot" "yes")])
9170
9171 (define_expand "prologue"
9172 [(const_int 0)]
9173 ""
9174 "sh_expand_prologue (); DONE;")
9175
9176 (define_expand "epilogue"
9177 [(return)]
9178 ""
9179 "
9180 {
9181 sh_expand_epilogue (0);
9182 emit_jump_insn (gen_return ());
9183 DONE;
9184 }")
9185
9186 (define_expand "eh_return"
9187 [(use (match_operand 0 "register_operand" ""))]
9188 ""
9189 {
9190 rtx ra = operands[0];
9191
9192 if (TARGET_SHMEDIA64)
9193 emit_insn (gen_eh_set_ra_di (ra));
9194 else
9195 emit_insn (gen_eh_set_ra_si (ra));
9196
9197 DONE;
9198 })
9199
9200 ;; Clobber the return address on the stack. We can't expand this
9201 ;; until we know where it will be put in the stack frame.
9202
9203 (define_insn "eh_set_ra_si"
9204 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
9205 UNSPECV_EH_RETURN)
9206 (clobber (match_scratch:SI 1 "=&r"))]
9207 "! TARGET_SHMEDIA64"
9208 "#")
9209
9210 (define_insn "eh_set_ra_di"
9211 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
9212 UNSPECV_EH_RETURN)
9213 (clobber (match_scratch:DI 1 "=&r"))]
9214 "TARGET_SHMEDIA64"
9215 "#")
9216
9217 (define_split
9218 [(unspec_volatile [(match_operand 0 "register_operand" "")]
9219 UNSPECV_EH_RETURN)
9220 (clobber (match_scratch 1 ""))]
9221 "reload_completed"
9222 [(const_int 0)]
9223 "
9224 {
9225 sh_set_return_address (operands[0], operands[1]);
9226 DONE;
9227 }")
9228
9229 (define_insn "blockage"
9230 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
9231 ""
9232 ""
9233 [(set_attr "length" "0")])
9234 \f
9235 ;; Define movml instructions for SH2A target. Currently they are
9236 ;; used to push and pop all banked registers only.
9237
9238 (define_insn "movml_push_banked"
9239 [(set (match_operand:SI 0 "register_operand" "=r")
9240 (plus (match_dup 0) (const_int -32)))
9241 (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
9242 (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
9243 (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
9244 (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
9245 (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
9246 (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
9247 (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
9248 (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
9249 "TARGET_SH2A && REGNO (operands[0]) == 15"
9250 "movml.l\tr7,@-r15"
9251 [(set_attr "in_delay_slot" "no")])
9252
9253 (define_insn "movml_pop_banked"
9254 [(set (match_operand:SI 0 "register_operand" "=r")
9255 (plus (match_dup 0) (const_int 32)))
9256 (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
9257 (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
9258 (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
9259 (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
9260 (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
9261 (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
9262 (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
9263 (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
9264 "TARGET_SH2A && REGNO (operands[0]) == 15"
9265 "movml.l\t@r15+,r7"
9266 [(set_attr "in_delay_slot" "no")])
9267 \f
9268 ;; ------------------------------------------------------------------------
9269 ;; Scc instructions
9270 ;; ------------------------------------------------------------------------
9271
9272 (define_insn "movt"
9273 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9274 (eq:SI (reg:SI T_REG) (const_int 1)))]
9275 "TARGET_SH1"
9276 "movt %0"
9277 [(set_attr "type" "arith")])
9278
9279 (define_expand "cstore4_media"
9280 [(set (match_operand:SI 0 "register_operand" "=r")
9281 (match_operator:SI 1 "sh_float_comparison_operator"
9282 [(match_operand 2 "logical_operand" "")
9283 (match_operand 3 "cmp_operand" "")]))]
9284 "TARGET_SHMEDIA"
9285 "
9286 {
9287 enum machine_mode mode = GET_MODE (operands[2]);
9288 enum rtx_code code = GET_CODE (operands[1]);
9289 bool invert, swap;
9290 if (mode == VOIDmode)
9291 mode = GET_MODE (operands[3]);
9292 if (operands[2] == const0_rtx)
9293 {
9294 if (code == EQ || code == NE)
9295 operands[2] = operands[3], operands[3] = const0_rtx;
9296 }
9297 else
9298 operands[2] = force_reg (mode, operands[2]);
9299 if (operands[3] != const0_rtx)
9300 operands[3] = force_reg (mode, operands[3]);
9301
9302 switch (code)
9303 {
9304 case GEU:
9305 case GE:
9306 swap = invert = !FLOAT_MODE_P (mode);
9307 break;
9308
9309 case LEU:
9310 case LE:
9311 swap = FLOAT_MODE_P (mode), invert = !swap;
9312 break;
9313
9314 case LTU:
9315 case LT:
9316 swap = true, invert = false;
9317 break;
9318
9319 case GTU:
9320 case GT:
9321 case EQ:
9322 case UNORDERED:
9323 swap = invert = false;
9324 break;
9325
9326 case NE:
9327 swap = invert = true;
9328 break;
9329
9330 default:
9331 gcc_unreachable ();
9332 }
9333
9334 if (swap)
9335 {
9336 rtx tem = operands[2];
9337 operands[2] = operands[3];
9338 operands[3] = tem;
9339 code = swap_condition (code);
9340 }
9341
9342 if (invert)
9343 {
9344 rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
9345 code = reverse_condition (code);
9346 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
9347 emit_insn (gen_cstore4_media (tem, operands[1],
9348 operands[2], operands[3]));
9349 code = EQ;
9350 operands[2] = tem;
9351 operands[3] = const0_rtx;
9352 }
9353
9354 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
9355 }")
9356
9357 (define_expand "cstoresi4"
9358 [(set (match_operand:SI 0 "register_operand" "=r")
9359 (match_operator:SI 1 "comparison_operator"
9360 [(match_operand:SI 2 "cmpsi_operand" "")
9361 (match_operand:SI 3 "arith_operand" "")]))]
9362 "TARGET_SH1 || TARGET_SHMEDIA"
9363 "if (TARGET_SHMEDIA)
9364 {
9365 emit_insn (gen_cstore4_media (operands[0], operands[1],
9366 operands[2], operands[3]));
9367 DONE;
9368 }
9369
9370 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
9371 && sh_expand_t_scc (operands))
9372 DONE;
9373
9374 if (! currently_expanding_to_rtl)
9375 FAIL;
9376
9377 sh_emit_compare_and_set (operands, SImode);
9378 DONE;
9379 ")
9380
9381 (define_expand "cstoredi4"
9382 [(set (match_operand:SI 0 "register_operand" "=r")
9383 (match_operator:SI 1 "comparison_operator"
9384 [(match_operand:DI 2 "arith_operand" "")
9385 (match_operand:DI 3 "arith_operand" "")]))]
9386 "TARGET_SH2 || TARGET_SHMEDIA"
9387 "if (TARGET_SHMEDIA)
9388 {
9389 emit_insn (gen_cstore4_media (operands[0], operands[1],
9390 operands[2], operands[3]));
9391 DONE;
9392 }
9393
9394 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
9395 && sh_expand_t_scc (operands))
9396 DONE;
9397
9398 if (! currently_expanding_to_rtl)
9399 FAIL;
9400
9401 sh_emit_compare_and_set (operands, DImode);
9402 DONE;
9403 ")
9404
9405
9406
9407 ;; sne moves the complement of the T reg to DEST like this:
9408 ;; cmp/eq ...
9409 ;; mov #-1,temp
9410 ;; negc temp,dest
9411 ;; This is better than xoring compare result with 1 because it does
9412 ;; not require r0 and further, the -1 may be CSE-ed or lifted out of a
9413 ;; loop.
9414
9415 (define_expand "movnegt"
9416 [(set (match_dup 1) (const_int -1))
9417 (parallel [(set (match_operand:SI 0 "" "")
9418 (neg:SI (plus:SI (reg:SI T_REG)
9419 (match_dup 1))))
9420 (set (reg:SI T_REG)
9421 (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
9422 (const_int 0)))])]
9423 ""
9424 "
9425 {
9426 operands[1] = gen_reg_rtx (SImode);
9427 }")
9428
9429
9430 ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
9431 ;; This prevents a regression that occurred when we switched from xor to
9432 ;; mov/neg for sne.
9433
9434 (define_split
9435 [(set (match_operand:SI 0 "arith_reg_dest" "")
9436 (plus:SI (reg:SI T_REG)
9437 (const_int -1)))]
9438 "TARGET_SH1"
9439 [(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1)))
9440 (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
9441 "")
9442
9443 (define_expand "cstoresf4"
9444 [(set (match_operand:SI 0 "register_operand" "=r")
9445 (match_operator:SI 1 "sh_float_comparison_operator"
9446 [(match_operand:SF 2 "arith_operand" "")
9447 (match_operand:SF 3 "arith_operand" "")]))]
9448 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
9449 "if (TARGET_SHMEDIA)
9450 {
9451 emit_insn (gen_cstore4_media (operands[0], operands[1],
9452 operands[2], operands[3]));
9453 DONE;
9454 }
9455
9456 if (! currently_expanding_to_rtl)
9457 FAIL;
9458
9459 sh_emit_compare_and_set (operands, SFmode);
9460 DONE;
9461 ")
9462
9463 (define_expand "cstoredf4"
9464 [(set (match_operand:SI 0 "register_operand" "=r")
9465 (match_operator:SI 1 "sh_float_comparison_operator"
9466 [(match_operand:DF 2 "arith_operand" "")
9467 (match_operand:DF 3 "arith_operand" "")]))]
9468 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9469 "if (TARGET_SHMEDIA)
9470 {
9471 emit_insn (gen_cstore4_media (operands[0], operands[1],
9472 operands[2], operands[3]));
9473 DONE;
9474 }
9475
9476 if (! currently_expanding_to_rtl)
9477 FAIL;
9478
9479 sh_emit_compare_and_set (operands, DFmode);
9480 DONE;
9481 ")
9482
9483
9484 ;; -------------------------------------------------------------------------
9485 ;; Instructions to cope with inline literal tables
9486 ;; -------------------------------------------------------------------------
9487
9488 ; 2 byte integer in line
9489
9490 (define_insn "consttable_2"
9491 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9492 (match_operand 1 "" "")]
9493 UNSPECV_CONST2)]
9494 ""
9495 "*
9496 {
9497 if (operands[1] != const0_rtx)
9498 assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
9499 return \"\";
9500 }"
9501 [(set_attr "length" "2")
9502 (set_attr "in_delay_slot" "no")])
9503
9504 ; 4 byte integer in line
9505
9506 (define_insn "consttable_4"
9507 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9508 (match_operand 1 "" "")]
9509 UNSPECV_CONST4)]
9510 ""
9511 "*
9512 {
9513 if (operands[1] != const0_rtx)
9514 {
9515 assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
9516 mark_symbol_refs_as_used (operands[0]);
9517 }
9518 return \"\";
9519 }"
9520 [(set_attr "length" "4")
9521 (set_attr "in_delay_slot" "no")])
9522
9523 ; 8 byte integer in line
9524
9525 (define_insn "consttable_8"
9526 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9527 (match_operand 1 "" "")]
9528 UNSPECV_CONST8)]
9529 ""
9530 "*
9531 {
9532 if (operands[1] != const0_rtx)
9533 assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
9534 return \"\";
9535 }"
9536 [(set_attr "length" "8")
9537 (set_attr "in_delay_slot" "no")])
9538
9539 ; 4 byte floating point
9540
9541 (define_insn "consttable_sf"
9542 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
9543 (match_operand 1 "" "")]
9544 UNSPECV_CONST4)]
9545 ""
9546 "*
9547 {
9548 if (operands[1] != const0_rtx)
9549 {
9550 REAL_VALUE_TYPE d;
9551 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9552 assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
9553 }
9554 return \"\";
9555 }"
9556 [(set_attr "length" "4")
9557 (set_attr "in_delay_slot" "no")])
9558
9559 ; 8 byte floating point
9560
9561 (define_insn "consttable_df"
9562 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
9563 (match_operand 1 "" "")]
9564 UNSPECV_CONST8)]
9565 ""
9566 "*
9567 {
9568 if (operands[1] != const0_rtx)
9569 {
9570 REAL_VALUE_TYPE d;
9571 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9572 assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
9573 }
9574 return \"\";
9575 }"
9576 [(set_attr "length" "8")
9577 (set_attr "in_delay_slot" "no")])
9578
9579 ;; Alignment is needed for some constant tables; it may also be added for
9580 ;; Instructions at the start of loops, or after unconditional branches.
9581 ;; ??? We would get more accurate lengths if we did instruction
9582 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
9583 ;; here is too conservative.
9584
9585 ; align to a two byte boundary
9586
9587 (define_expand "align_2"
9588 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
9589 ""
9590 "")
9591
9592 ; align to a four byte boundary
9593 ;; align_4 and align_log are instructions for the starts of loops, or
9594 ;; after unconditional branches, which may take up extra room.
9595
9596 (define_expand "align_4"
9597 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
9598 ""
9599 "")
9600
9601 ; align to a cache line boundary
9602
9603 (define_insn "align_log"
9604 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
9605 ""
9606 ""
9607 [(set_attr "length" "0")
9608 (set_attr "in_delay_slot" "no")])
9609
9610 ; emitted at the end of the literal table, used to emit the
9611 ; 32bit branch labels if needed.
9612
9613 (define_insn "consttable_end"
9614 [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
9615 ""
9616 "* return output_jump_label_table ();"
9617 [(set_attr "in_delay_slot" "no")])
9618
9619 ; emitted at the end of the window in the literal table.
9620
9621 (define_insn "consttable_window_end"
9622 [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
9623 ""
9624 ""
9625 [(set_attr "length" "0")
9626 (set_attr "in_delay_slot" "no")])
9627
9628 ;; -------------------------------------------------------------------------
9629 ;; Misc
9630 ;; -------------------------------------------------------------------------
9631
9632 ;; String/block move insn.
9633
9634 (define_expand "movmemsi"
9635 [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
9636 (mem:BLK (match_operand:BLK 1 "" "")))
9637 (use (match_operand:SI 2 "nonmemory_operand" ""))
9638 (use (match_operand:SI 3 "immediate_operand" ""))
9639 (clobber (reg:SI PR_REG))
9640 (clobber (reg:SI R4_REG))
9641 (clobber (reg:SI R5_REG))
9642 (clobber (reg:SI R0_REG))])]
9643 "TARGET_SH1 && ! TARGET_SH5"
9644 "
9645 {
9646 if(expand_block_move (operands))
9647 DONE;
9648 else FAIL;
9649 }")
9650
9651 (define_insn "block_move_real"
9652 [(parallel [(set (mem:BLK (reg:SI R4_REG))
9653 (mem:BLK (reg:SI R5_REG)))
9654 (use (match_operand:SI 0 "arith_reg_operand" "r"))
9655 (clobber (reg:SI PR_REG))
9656 (clobber (reg:SI R0_REG))])]
9657 "TARGET_SH1 && ! TARGET_HARD_SH4"
9658 "jsr @%0%#"
9659 [(set_attr "type" "sfunc")
9660 (set_attr "needs_delay_slot" "yes")])
9661
9662 (define_insn "block_lump_real"
9663 [(parallel [(set (mem:BLK (reg:SI R4_REG))
9664 (mem:BLK (reg:SI R5_REG)))
9665 (use (match_operand:SI 0 "arith_reg_operand" "r"))
9666 (use (reg:SI R6_REG))
9667 (clobber (reg:SI PR_REG))
9668 (clobber (reg:SI T_REG))
9669 (clobber (reg:SI R4_REG))
9670 (clobber (reg:SI R5_REG))
9671 (clobber (reg:SI R6_REG))
9672 (clobber (reg:SI R0_REG))])]
9673 "TARGET_SH1 && ! TARGET_HARD_SH4"
9674 "jsr @%0%#"
9675 [(set_attr "type" "sfunc")
9676 (set_attr "needs_delay_slot" "yes")])
9677
9678 (define_insn "block_move_real_i4"
9679 [(parallel [(set (mem:BLK (reg:SI R4_REG))
9680 (mem:BLK (reg:SI R5_REG)))
9681 (use (match_operand:SI 0 "arith_reg_operand" "r"))
9682 (clobber (reg:SI PR_REG))
9683 (clobber (reg:SI R0_REG))
9684 (clobber (reg:SI R1_REG))
9685 (clobber (reg:SI R2_REG))])]
9686 "TARGET_HARD_SH4"
9687 "jsr @%0%#"
9688 [(set_attr "type" "sfunc")
9689 (set_attr "needs_delay_slot" "yes")])
9690
9691 (define_insn "block_lump_real_i4"
9692 [(parallel [(set (mem:BLK (reg:SI R4_REG))
9693 (mem:BLK (reg:SI R5_REG)))
9694 (use (match_operand:SI 0 "arith_reg_operand" "r"))
9695 (use (reg:SI R6_REG))
9696 (clobber (reg:SI PR_REG))
9697 (clobber (reg:SI T_REG))
9698 (clobber (reg:SI R4_REG))
9699 (clobber (reg:SI R5_REG))
9700 (clobber (reg:SI R6_REG))
9701 (clobber (reg:SI R0_REG))
9702 (clobber (reg:SI R1_REG))
9703 (clobber (reg:SI R2_REG))
9704 (clobber (reg:SI R3_REG))])]
9705 "TARGET_HARD_SH4"
9706 "jsr @%0%#"
9707 [(set_attr "type" "sfunc")
9708 (set_attr "needs_delay_slot" "yes")])
9709 \f
9710 ;; -------------------------------------------------------------------------
9711 ;; Floating point instructions.
9712 ;; -------------------------------------------------------------------------
9713
9714 ;; ??? All patterns should have a type attribute.
9715
9716 (define_expand "movpsi"
9717 [(set (match_operand:PSI 0 "register_operand" "")
9718 (match_operand:PSI 1 "general_movsrc_operand" ""))]
9719 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9720 "")
9721
9722 ;; The c / m alternative is a fake to guide reload to load directly into
9723 ;; fpscr, since reload doesn't know how to use post-increment.
9724 ;; TARGET_LEGITIMATE_ADDRESS_P guards about bogus addresses before reload,
9725 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
9726 ;; predicate after reload.
9727 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
9728 ;; like a mac -> gpr move.
9729 (define_insn "fpu_switch"
9730 [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
9731 (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
9732 "TARGET_SH2E
9733 && (! reload_completed
9734 || true_regnum (operands[0]) != FPSCR_REG
9735 || !MEM_P (operands[1])
9736 || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
9737 "@
9738 ! precision stays the same
9739 lds.l %1,fpscr
9740 mov.l %1,%0
9741 #
9742 lds %1,fpscr
9743 mov %1,%0
9744 mov.l %1,%0
9745 sts fpscr,%0
9746 sts.l fpscr,%0"
9747 [(set_attr "length" "0,2,2,4,2,2,2,2,2")
9748 (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,fstore")])
9749
9750 (define_peephole2
9751 [(set (reg:PSI FPSCR_REG)
9752 (mem:PSI (match_operand:SI 0 "register_operand" "")))]
9753 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
9754 [(const_int 0)]
9755 {
9756 rtx fpscr, mem, new_insn;
9757
9758 fpscr = SET_DEST (PATTERN (curr_insn));
9759 mem = SET_SRC (PATTERN (curr_insn));
9760 mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
9761
9762 new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
9763 add_reg_note (new_insn, REG_INC, operands[0]);
9764 DONE;
9765 })
9766
9767 (define_split
9768 [(set (reg:PSI FPSCR_REG)
9769 (mem:PSI (match_operand:SI 0 "register_operand" "")))]
9770 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
9771 && (flag_peephole2 ? epilogue_completed : reload_completed)"
9772 [(const_int 0)]
9773 {
9774 rtx fpscr, mem, new_insn;
9775
9776 fpscr = SET_DEST (PATTERN (curr_insn));
9777 mem = SET_SRC (PATTERN (curr_insn));
9778 mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
9779
9780 new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
9781 add_reg_note (new_insn, REG_INC, operands[0]);
9782
9783 if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
9784 emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
9785 DONE;
9786 })
9787
9788 ;; ??? This uses the fp unit, but has no type indicating that.
9789 ;; If we did that, this would either give a bogus latency or introduce
9790 ;; a bogus FIFO constraint.
9791 ;; Since this insn is currently only used for prologues/epilogues,
9792 ;; it is probably best to claim no function unit, which matches the
9793 ;; current setting.
9794 (define_insn "toggle_sz"
9795 [(set (reg:PSI FPSCR_REG)
9796 (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
9797 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9798 "fschg"
9799 [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
9800
9801 ;; There's no way we can use it today, since optimize mode switching
9802 ;; doesn't enable us to know from which mode we're switching to the
9803 ;; mode it requests, to tell whether we can use a relative mode switch
9804 ;; (like toggle_pr) or an absolute switch (like loading fpscr from
9805 ;; memory).
9806 (define_insn "toggle_pr"
9807 [(set (reg:PSI FPSCR_REG)
9808 (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
9809 "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
9810 "fpchg"
9811 [(set_attr "type" "fpscr_toggle")])
9812
9813 (define_expand "addsf3"
9814 [(set (match_operand:SF 0 "arith_reg_operand" "")
9815 (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
9816 (match_operand:SF 2 "arith_reg_operand" "")))]
9817 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
9818 "
9819 {
9820 if (TARGET_SH2E)
9821 {
9822 expand_sf_binop (&gen_addsf3_i, operands);
9823 DONE;
9824 }
9825 }")
9826
9827 (define_insn "*addsf3_media"
9828 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9829 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
9830 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
9831 "TARGET_SHMEDIA_FPU"
9832 "fadd.s %1, %2, %0"
9833 [(set_attr "type" "fparith_media")])
9834
9835 (define_insn_and_split "unary_sf_op"
9836 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
9837 (vec_select:V2SF
9838 (vec_concat:V2SF
9839 (vec_select:SF
9840 (match_dup 0)
9841 (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
9842 (match_operator:SF 2 "unary_float_operator"
9843 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
9844 (parallel [(match_operand 4
9845 "const_int_operand" "n")]))]))
9846 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
9847 "TARGET_SHMEDIA_FPU"
9848 "#"
9849 "TARGET_SHMEDIA_FPU && reload_completed"
9850 [(set (match_dup 5) (match_dup 6))]
9851 "
9852 {
9853 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
9854 rtx op1 = gen_rtx_REG (SFmode,
9855 (true_regnum (operands[1])
9856 + (INTVAL (operands[4]) ^ endian)));
9857
9858 operands[7] = gen_rtx_REG (SFmode,
9859 (true_regnum (operands[0])
9860 + (INTVAL (operands[3]) ^ endian)));
9861 operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
9862 }"
9863 [(set_attr "type" "fparith_media")])
9864
9865 (define_insn_and_split "binary_sf_op0"
9866 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
9867 (vec_concat:V2SF
9868 (match_operator:SF 3 "binary_float_operator"
9869 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
9870 (parallel [(const_int 0)]))
9871 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
9872 (parallel [(const_int 0)]))])
9873 (vec_select:SF
9874 (match_dup 0)
9875 (parallel [(const_int 1)]))))]
9876 "TARGET_SHMEDIA_FPU"
9877 "#"
9878 "&& reload_completed"
9879 [(set (match_dup 4) (match_dup 5))]
9880 "
9881 {
9882 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
9883 rtx op1 = gen_rtx_REG (SFmode,
9884 true_regnum (operands[1]) + endian);
9885 rtx op2 = gen_rtx_REG (SFmode,
9886 true_regnum (operands[2]) + endian);
9887
9888 operands[4] = gen_rtx_REG (SFmode,
9889 true_regnum (operands[0]) + endian);
9890 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
9891 }"
9892 [(set_attr "type" "fparith_media")])
9893
9894 (define_insn_and_split "binary_sf_op1"
9895 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
9896 (vec_concat:V2SF
9897 (vec_select:SF
9898 (match_dup 0)
9899 (parallel [(const_int 0)]))
9900 (match_operator:SF 3 "binary_float_operator"
9901 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
9902 (parallel [(const_int 1)]))
9903 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
9904 (parallel [(const_int 1)]))])))]
9905 "TARGET_SHMEDIA_FPU"
9906 "#"
9907 "&& reload_completed"
9908 [(set (match_dup 4) (match_dup 5))]
9909 "
9910 {
9911 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
9912 rtx op1 = gen_rtx_REG (SFmode,
9913 true_regnum (operands[1]) + (1 ^ endian));
9914 rtx op2 = gen_rtx_REG (SFmode,
9915 true_regnum (operands[2]) + (1 ^ endian));
9916
9917 operands[4] = gen_rtx_REG (SFmode,
9918 true_regnum (operands[0]) + (1 ^ endian));
9919 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
9920 }"
9921 [(set_attr "type" "fparith_media")])
9922
9923 (define_insn "addsf3_i"
9924 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9925 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
9926 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
9927 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
9928 "TARGET_SH2E"
9929 "fadd %2,%0"
9930 [(set_attr "type" "fp")
9931 (set_attr "fp_mode" "single")])
9932
9933 (define_expand "subsf3"
9934 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
9935 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
9936 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
9937 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
9938 "
9939 {
9940 if (TARGET_SH2E)
9941 {
9942 expand_sf_binop (&gen_subsf3_i, operands);
9943 DONE;
9944 }
9945 }")
9946
9947 (define_insn "*subsf3_media"
9948 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9949 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
9950 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
9951 "TARGET_SHMEDIA_FPU"
9952 "fsub.s %1, %2, %0"
9953 [(set_attr "type" "fparith_media")])
9954
9955 (define_insn "subsf3_i"
9956 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9957 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
9958 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
9959 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
9960 "TARGET_SH2E"
9961 "fsub %2,%0"
9962 [(set_attr "type" "fp")
9963 (set_attr "fp_mode" "single")])
9964
9965 (define_expand "mulsf3"
9966 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
9967 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
9968 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
9969 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
9970 "")
9971
9972 (define_insn "*mulsf3_media"
9973 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9974 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
9975 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
9976 "TARGET_SHMEDIA_FPU"
9977 "fmul.s %1, %2, %0"
9978 [(set_attr "type" "fparith_media")])
9979
9980 ;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
9981 ;; register in feeding fp instructions. Thus, in order to generate fmac,
9982 ;; we start out with a mulsf pattern that does not depend on fpscr.
9983 ;; This is split after combine to introduce the dependency, in order to
9984 ;; get mode switching and scheduling right.
9985 (define_insn_and_split "mulsf3_ie"
9986 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9987 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
9988 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
9989 "TARGET_SH2E"
9990 "fmul %2,%0"
9991 "TARGET_SH4 || TARGET_SH2A_SINGLE"
9992 [(const_int 0)]
9993 "
9994 {
9995 emit_insn (gen_mulsf3_i4 (operands[0], operands[1], operands[2],
9996 get_fpscr_rtx ()));
9997 DONE;
9998 }"
9999 [(set_attr "type" "fp")])
10000
10001 (define_insn "mulsf3_i4"
10002 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10003 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10004 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10005 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10006 "TARGET_SH2E"
10007 "fmul %2,%0"
10008 [(set_attr "type" "fp")
10009 (set_attr "fp_mode" "single")])
10010
10011 (define_insn "mac_media"
10012 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10013 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10014 (match_operand:SF 2 "fp_arith_reg_operand" "f"))
10015 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
10016 "TARGET_SHMEDIA_FPU && TARGET_FMAC"
10017 "fmac.s %1, %2, %0"
10018 [(set_attr "type" "fparith_media")])
10019
10020 (define_insn "*macsf3"
10021 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10022 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
10023 (match_operand:SF 2 "fp_arith_reg_operand" "f"))
10024 (match_operand:SF 3 "arith_reg_operand" "0")))
10025 (use (match_operand:PSI 4 "fpscr_operand" "c"))]
10026 "TARGET_SH2E && TARGET_FMAC"
10027 "fmac fr0,%2,%0"
10028 [(set_attr "type" "fp")
10029 (set_attr "fp_mode" "single")])
10030
10031 (define_expand "divsf3"
10032 [(set (match_operand:SF 0 "arith_reg_operand" "")
10033 (div:SF (match_operand:SF 1 "arith_reg_operand" "")
10034 (match_operand:SF 2 "arith_reg_operand" "")))]
10035 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10036 "
10037 {
10038 if (TARGET_SH2E)
10039 {
10040 expand_sf_binop (&gen_divsf3_i, operands);
10041 DONE;
10042 }
10043 }")
10044
10045 (define_insn "*divsf3_media"
10046 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10047 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10048 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10049 "TARGET_SHMEDIA_FPU"
10050 "fdiv.s %1, %2, %0"
10051 [(set_attr "type" "fdiv_media")])
10052
10053 (define_insn "divsf3_i"
10054 [(set (match_operand:SF 0 "arith_reg_dest" "=f")
10055 (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
10056 (match_operand:SF 2 "arith_reg_operand" "f")))
10057 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10058 "TARGET_SH2E"
10059 "fdiv %2,%0"
10060 [(set_attr "type" "fdiv")
10061 (set_attr "fp_mode" "single")])
10062
10063 (define_insn "floatdisf2"
10064 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10065 (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10066 "TARGET_SHMEDIA_FPU"
10067 "float.qs %1, %0"
10068 [(set_attr "type" "fpconv_media")])
10069
10070 (define_expand "floatsisf2"
10071 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10072 (float:SF (match_operand:SI 1 "fpul_operand" "")))]
10073 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10074 "
10075 {
10076 if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10077 {
10078 emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10079 DONE;
10080 }
10081 }")
10082
10083 (define_insn "*floatsisf2_media"
10084 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10085 (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10086 "TARGET_SHMEDIA_FPU"
10087 "float.ls %1, %0"
10088 [(set_attr "type" "fpconv_media")])
10089
10090 (define_insn "floatsisf2_i4"
10091 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10092 (float:SF (match_operand:SI 1 "fpul_operand" "y")))
10093 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10094 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10095 "float %1,%0"
10096 [(set_attr "type" "fp")
10097 (set_attr "fp_mode" "single")])
10098
10099 (define_insn "*floatsisf2_ie"
10100 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10101 (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
10102 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10103 "float %1,%0"
10104 [(set_attr "type" "fp")])
10105
10106 (define_insn "fix_truncsfdi2"
10107 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10108 (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10109 "TARGET_SHMEDIA_FPU"
10110 "ftrc.sq %1, %0"
10111 [(set_attr "type" "fpconv_media")])
10112
10113 (define_expand "fix_truncsfsi2"
10114 [(set (match_operand:SI 0 "fpul_operand" "=y")
10115 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10116 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10117 "
10118 {
10119 if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10120 {
10121 emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10122 DONE;
10123 }
10124 }")
10125
10126 (define_insn "*fix_truncsfsi2_media"
10127 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10128 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10129 "TARGET_SHMEDIA_FPU"
10130 "ftrc.sl %1, %0"
10131 [(set_attr "type" "fpconv_media")])
10132
10133 (define_insn "fix_truncsfsi2_i4"
10134 [(set (match_operand:SI 0 "fpul_operand" "=y")
10135 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10136 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10137 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10138 "ftrc %1,%0"
10139 [(set_attr "type" "ftrc_s")
10140 (set_attr "fp_mode" "single")])
10141
10142 ;; ??? This pattern is used nowhere. fix_truncsfsi2 always expands to
10143 ;; fix_truncsfsi2_i4.
10144 ;; (define_insn "fix_truncsfsi2_i4_2"
10145 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10146 ;; (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10147 ;; (use (reg:PSI FPSCR_REG))
10148 ;; (clobber (reg:SI FPUL_REG))]
10149 ;; "TARGET_SH4"
10150 ;; "#"
10151 ;; [(set_attr "length" "4")
10152 ;; (set_attr "fp_mode" "single")])
10153
10154 ;;(define_split
10155 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10156 ;; (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10157 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
10158 ;; (clobber (reg:SI FPUL_REG))]
10159 ;; "TARGET_SH4"
10160 ;; [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10161 ;; (use (match_dup 2))])
10162 ;; (set (match_dup 0) (reg:SI FPUL_REG))])
10163
10164 (define_insn "*fixsfsi"
10165 [(set (match_operand:SI 0 "fpul_operand" "=y")
10166 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10167 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10168 "ftrc %1,%0"
10169 [(set_attr "type" "fp")])
10170
10171 (define_insn "cmpgtsf_t"
10172 [(set (reg:SI T_REG)
10173 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10174 (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10175 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10176 "fcmp/gt %1,%0"
10177 [(set_attr "type" "fp_cmp")
10178 (set_attr "fp_mode" "single")])
10179
10180 (define_insn "cmpeqsf_t"
10181 [(set (reg:SI T_REG)
10182 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10183 (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10184 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10185 "fcmp/eq %1,%0"
10186 [(set_attr "type" "fp_cmp")
10187 (set_attr "fp_mode" "single")])
10188
10189 (define_insn "ieee_ccmpeqsf_t"
10190 [(set (reg:SI T_REG)
10191 (ior:SI (reg:SI T_REG)
10192 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10193 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
10194 "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10195 "* return output_ieee_ccmpeq (insn, operands);"
10196 [(set_attr "length" "4")])
10197
10198
10199 (define_insn "cmpgtsf_t_i4"
10200 [(set (reg:SI T_REG)
10201 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10202 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10203 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10204 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10205 "fcmp/gt %1,%0"
10206 [(set_attr "type" "fp_cmp")
10207 (set_attr "fp_mode" "single")])
10208
10209 (define_insn "cmpeqsf_t_i4"
10210 [(set (reg:SI T_REG)
10211 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10212 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10213 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10214 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10215 "fcmp/eq %1,%0"
10216 [(set_attr "type" "fp_cmp")
10217 (set_attr "fp_mode" "single")])
10218
10219 (define_insn "*ieee_ccmpeqsf_t_4"
10220 [(set (reg:SI T_REG)
10221 (ior:SI (reg:SI T_REG)
10222 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10223 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
10224 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10225 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10226 "* return output_ieee_ccmpeq (insn, operands);"
10227 [(set_attr "length" "4")
10228 (set_attr "fp_mode" "single")])
10229
10230 (define_insn "cmpeqsf_media"
10231 [(set (match_operand:SI 0 "register_operand" "=r")
10232 (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10233 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10234 "TARGET_SHMEDIA_FPU"
10235 "fcmpeq.s %1, %2, %0"
10236 [(set_attr "type" "fcmp_media")])
10237
10238 (define_insn "cmpgtsf_media"
10239 [(set (match_operand:SI 0 "register_operand" "=r")
10240 (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10241 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10242 "TARGET_SHMEDIA_FPU"
10243 "fcmpgt.s %1, %2, %0"
10244 [(set_attr "type" "fcmp_media")])
10245
10246 (define_insn "cmpgesf_media"
10247 [(set (match_operand:SI 0 "register_operand" "=r")
10248 (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10249 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10250 "TARGET_SHMEDIA_FPU"
10251 "fcmpge.s %1, %2, %0"
10252 [(set_attr "type" "fcmp_media")])
10253
10254 (define_insn "cmpunsf_media"
10255 [(set (match_operand:SI 0 "register_operand" "=r")
10256 (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10257 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10258 "TARGET_SHMEDIA_FPU"
10259 "fcmpun.s %1, %2, %0"
10260 [(set_attr "type" "fcmp_media")])
10261
10262 (define_expand "cbranchsf4"
10263 [(set (pc)
10264 (if_then_else (match_operator 0 "sh_float_comparison_operator"
10265 [(match_operand:SF 1 "arith_operand" "")
10266 (match_operand:SF 2 "arith_operand" "")])
10267 (match_operand 3 "" "")
10268 (pc)))]
10269 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10270 "
10271 {
10272 if (TARGET_SHMEDIA)
10273 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
10274 operands[3]));
10275 else
10276 sh_emit_compare_and_branch (operands, SFmode);
10277 DONE;
10278 }")
10279
10280 (define_expand "negsf2"
10281 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10282 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10283 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10284 "
10285 {
10286 if (TARGET_SH2E)
10287 {
10288 expand_sf_unop (&gen_negsf2_i, operands);
10289 DONE;
10290 }
10291 }")
10292
10293 (define_insn "*negsf2_media"
10294 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10295 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10296 "TARGET_SHMEDIA_FPU"
10297 "fneg.s %1, %0"
10298 [(set_attr "type" "fmove_media")])
10299
10300 (define_insn "negsf2_i"
10301 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10302 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10303 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10304 "TARGET_SH2E"
10305 "fneg %0"
10306 [(set_attr "type" "fmove")
10307 (set_attr "fp_mode" "single")])
10308
10309 (define_expand "sqrtsf2"
10310 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10311 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10312 "TARGET_SH3E || TARGET_SHMEDIA_FPU"
10313 "
10314 {
10315 if (TARGET_SH3E)
10316 {
10317 expand_sf_unop (&gen_sqrtsf2_i, operands);
10318 DONE;
10319 }
10320 }")
10321
10322 (define_insn "*sqrtsf2_media"
10323 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10324 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10325 "TARGET_SHMEDIA_FPU"
10326 "fsqrt.s %1, %0"
10327 [(set_attr "type" "fdiv_media")])
10328
10329 (define_insn "sqrtsf2_i"
10330 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10331 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10332 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10333 "TARGET_SH3E"
10334 "fsqrt %0"
10335 [(set_attr "type" "fdiv")
10336 (set_attr "fp_mode" "single")])
10337
10338 (define_insn "rsqrtsf2"
10339 [(set (match_operand:SF 0 "register_operand" "=f")
10340 (div:SF (match_operand:SF 1 "immediate_operand" "i")
10341 (sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
10342 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10343 "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10344 && operands[1] == CONST1_RTX (SFmode)"
10345 "fsrra %0"
10346 [(set_attr "type" "fsrra")
10347 (set_attr "fp_mode" "single")])
10348
10349 (define_insn "fsca"
10350 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10351 (vec_concat:V2SF
10352 (unspec:SF [(mult:SF
10353 (float:SF (match_operand:SI 1 "fpul_operand" "y"))
10354 (match_operand:SF 2 "immediate_operand" "i"))
10355 ] UNSPEC_FSINA)
10356 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
10357 ] UNSPEC_FCOSA)))
10358 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10359 "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10360 && operands[2] == sh_fsca_int2sf ()"
10361 "fsca fpul,%d0"
10362 [(set_attr "type" "fsca")
10363 (set_attr "fp_mode" "single")])
10364
10365 (define_expand "sinsf2"
10366 [(set (match_operand:SF 0 "nonimmediate_operand" "")
10367 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10368 UNSPEC_FSINA))]
10369 "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10370 "
10371 {
10372 rtx scaled = gen_reg_rtx (SFmode);
10373 rtx truncated = gen_reg_rtx (SImode);
10374 rtx fsca = gen_reg_rtx (V2SFmode);
10375 rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10376
10377 emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10378 emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10379 emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10380 get_fpscr_rtx ()));
10381 emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 0));
10382 DONE;
10383 }")
10384
10385 (define_expand "cossf2"
10386 [(set (match_operand:SF 0 "nonimmediate_operand" "")
10387 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10388 UNSPEC_FCOSA))]
10389 "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10390 "
10391 {
10392 rtx scaled = gen_reg_rtx (SFmode);
10393 rtx truncated = gen_reg_rtx (SImode);
10394 rtx fsca = gen_reg_rtx (V2SFmode);
10395 rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10396
10397 emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10398 emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10399 emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10400 get_fpscr_rtx ()));
10401 emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
10402 DONE;
10403 }")
10404
10405 (define_expand "sindf2"
10406 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10407 (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10408 UNSPEC_FSINA))]
10409 "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10410 "
10411 {
10412 rtx scaled = gen_reg_rtx (DFmode);
10413 rtx truncated = gen_reg_rtx (SImode);
10414 rtx fsca = gen_reg_rtx (V2SFmode);
10415 rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10416 rtx sfresult = gen_reg_rtx (SFmode);
10417
10418 emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10419 emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10420 emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10421 get_fpscr_rtx ()));
10422 emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 0));
10423 emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10424 DONE;
10425 }")
10426
10427 (define_expand "cosdf2"
10428 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10429 (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10430 UNSPEC_FCOSA))]
10431 "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10432 "
10433 {
10434 rtx scaled = gen_reg_rtx (DFmode);
10435 rtx truncated = gen_reg_rtx (SImode);
10436 rtx fsca = gen_reg_rtx (V2SFmode);
10437 rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10438 rtx sfresult = gen_reg_rtx (SFmode);
10439
10440 emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10441 emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10442 emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10443 get_fpscr_rtx ()));
10444 emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 4));
10445 emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10446 DONE;
10447 }")
10448
10449 (define_expand "abssf2"
10450 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10451 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10452 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10453 "
10454 {
10455 if (TARGET_SH2E)
10456 {
10457 expand_sf_unop (&gen_abssf2_i, operands);
10458 DONE;
10459 }
10460 }")
10461
10462 (define_insn "*abssf2_media"
10463 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10464 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10465 "TARGET_SHMEDIA_FPU"
10466 "fabs.s %1, %0"
10467 [(set_attr "type" "fmove_media")])
10468
10469 (define_insn "abssf2_i"
10470 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10471 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10472 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10473 "TARGET_SH2E"
10474 "fabs %0"
10475 [(set_attr "type" "fmove")
10476 (set_attr "fp_mode" "single")])
10477
10478 (define_expand "adddf3"
10479 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10480 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10481 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10482 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10483 "
10484 {
10485 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10486 {
10487 expand_df_binop (&gen_adddf3_i, operands);
10488 DONE;
10489 }
10490 }")
10491
10492 (define_insn "*adddf3_media"
10493 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10494 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10495 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10496 "TARGET_SHMEDIA_FPU"
10497 "fadd.d %1, %2, %0"
10498 [(set_attr "type" "dfparith_media")])
10499
10500 (define_insn "adddf3_i"
10501 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10502 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10503 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10504 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10505 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10506 "fadd %2,%0"
10507 [(set_attr "type" "dfp_arith")
10508 (set_attr "fp_mode" "double")])
10509
10510 (define_expand "subdf3"
10511 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10512 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10513 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10514 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10515 "
10516 {
10517 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10518 {
10519 expand_df_binop (&gen_subdf3_i, operands);
10520 DONE;
10521 }
10522 }")
10523
10524 (define_insn "*subdf3_media"
10525 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10526 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10527 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10528 "TARGET_SHMEDIA_FPU"
10529 "fsub.d %1, %2, %0"
10530 [(set_attr "type" "dfparith_media")])
10531
10532 (define_insn "subdf3_i"
10533 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10534 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10535 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10536 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10537 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10538 "fsub %2,%0"
10539 [(set_attr "type" "dfp_arith")
10540 (set_attr "fp_mode" "double")])
10541
10542 (define_expand "muldf3"
10543 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10544 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10545 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10546 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10547 "
10548 {
10549 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10550 {
10551 expand_df_binop (&gen_muldf3_i, operands);
10552 DONE;
10553 }
10554 }")
10555
10556 (define_insn "*muldf3_media"
10557 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10558 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10559 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10560 "TARGET_SHMEDIA_FPU"
10561 "fmul.d %1, %2, %0"
10562 [(set_attr "type" "dfmul_media")])
10563
10564 (define_insn "muldf3_i"
10565 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10566 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10567 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10568 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10569 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10570 "fmul %2,%0"
10571 [(set_attr "type" "dfp_mul")
10572 (set_attr "fp_mode" "double")])
10573
10574 (define_expand "divdf3"
10575 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10576 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10577 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10578 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10579 "
10580 {
10581 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10582 {
10583 expand_df_binop (&gen_divdf3_i, operands);
10584 DONE;
10585 }
10586 }")
10587
10588 (define_insn "*divdf3_media"
10589 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10590 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10591 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10592 "TARGET_SHMEDIA_FPU"
10593 "fdiv.d %1, %2, %0"
10594 [(set_attr "type" "dfdiv_media")])
10595
10596 (define_insn "divdf3_i"
10597 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10598 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10599 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10600 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10601 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10602 "fdiv %2,%0"
10603 [(set_attr "type" "dfdiv")
10604 (set_attr "fp_mode" "double")])
10605
10606 (define_insn "floatdidf2"
10607 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10608 (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10609 "TARGET_SHMEDIA_FPU"
10610 "float.qd %1, %0"
10611 [(set_attr "type" "dfpconv_media")])
10612
10613 (define_expand "floatsidf2"
10614 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10615 (float:DF (match_operand:SI 1 "fpul_operand" "")))]
10616 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10617 "
10618 {
10619 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10620 {
10621 emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
10622 get_fpscr_rtx ()));
10623 DONE;
10624 }
10625 }")
10626
10627 (define_insn "*floatsidf2_media"
10628 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10629 (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10630 "TARGET_SHMEDIA_FPU"
10631 "float.ld %1, %0"
10632 [(set_attr "type" "dfpconv_media")])
10633
10634 (define_insn "floatsidf2_i"
10635 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10636 (float:DF (match_operand:SI 1 "fpul_operand" "y")))
10637 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10638 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10639 "float %1,%0"
10640 [(set_attr "type" "dfp_conv")
10641 (set_attr "fp_mode" "double")])
10642
10643 (define_insn "fix_truncdfdi2"
10644 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10645 (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10646 "TARGET_SHMEDIA_FPU"
10647 "ftrc.dq %1, %0"
10648 [(set_attr "type" "dfpconv_media")])
10649
10650 (define_expand "fix_truncdfsi2"
10651 [(set (match_operand:SI 0 "fpul_operand" "")
10652 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
10653 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10654 "
10655 {
10656 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10657 {
10658 emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
10659 get_fpscr_rtx ()));
10660 DONE;
10661 }
10662 }")
10663
10664 (define_insn "*fix_truncdfsi2_media"
10665 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10666 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10667 "TARGET_SHMEDIA_FPU"
10668 "ftrc.dl %1, %0"
10669 [(set_attr "type" "dfpconv_media")])
10670
10671 (define_insn "fix_truncdfsi2_i"
10672 [(set (match_operand:SI 0 "fpul_operand" "=y")
10673 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
10674 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10675 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10676 "ftrc %1,%0"
10677 [(set_attr "type" "dfp_conv")
10678 (set_attr "dfp_comp" "no")
10679 (set_attr "fp_mode" "double")])
10680
10681 ;; ??? This pattern is used nowhere. fix_truncdfsi2 always expands to
10682 ;; fix_truncdfsi2_i.
10683 ;; (define_insn "fix_truncdfsi2_i4"
10684 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10685 ;; (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
10686 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
10687 ;; (clobber (reg:SI FPUL_REG))]
10688 ;; "TARGET_SH4"
10689 ;; "#"
10690 ;; [(set_attr "length" "4")
10691 ;; (set_attr "fp_mode" "double")])
10692 ;;
10693 ;; (define_split
10694 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10695 ;; (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
10696 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
10697 ;; (clobber (reg:SI FPUL_REG))]
10698 ;; "TARGET_SH4"
10699 ;; [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10700 ;; (use (match_dup 2))])
10701 ;; (set (match_dup 0) (reg:SI FPUL_REG))])
10702
10703 (define_insn "cmpgtdf_t"
10704 [(set (reg:SI T_REG)
10705 (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
10706 (match_operand:DF 1 "arith_reg_operand" "f")))
10707 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10708 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10709 "fcmp/gt %1,%0"
10710 [(set_attr "type" "dfp_cmp")
10711 (set_attr "fp_mode" "double")])
10712
10713 (define_insn "cmpeqdf_t"
10714 [(set (reg:SI T_REG)
10715 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
10716 (match_operand:DF 1 "arith_reg_operand" "f")))
10717 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10718 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10719 "fcmp/eq %1,%0"
10720 [(set_attr "type" "dfp_cmp")
10721 (set_attr "fp_mode" "double")])
10722
10723 (define_insn "*ieee_ccmpeqdf_t"
10724 [(set (reg:SI T_REG)
10725 (ior:SI (reg:SI T_REG)
10726 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
10727 (match_operand:DF 1 "arith_reg_operand" "f"))))
10728 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10729 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10730 "* return output_ieee_ccmpeq (insn, operands);"
10731 [(set_attr "length" "4")
10732 (set_attr "fp_mode" "double")])
10733
10734 (define_insn "cmpeqdf_media"
10735 [(set (match_operand:SI 0 "register_operand" "=r")
10736 (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10737 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10738 "TARGET_SHMEDIA_FPU"
10739 "fcmpeq.d %1,%2,%0"
10740 [(set_attr "type" "fcmp_media")])
10741
10742 (define_insn "cmpgtdf_media"
10743 [(set (match_operand:SI 0 "register_operand" "=r")
10744 (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10745 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10746 "TARGET_SHMEDIA_FPU"
10747 "fcmpgt.d %1,%2,%0"
10748 [(set_attr "type" "fcmp_media")])
10749
10750 (define_insn "cmpgedf_media"
10751 [(set (match_operand:SI 0 "register_operand" "=r")
10752 (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10753 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10754 "TARGET_SHMEDIA_FPU"
10755 "fcmpge.d %1,%2,%0"
10756 [(set_attr "type" "fcmp_media")])
10757
10758 (define_insn "cmpundf_media"
10759 [(set (match_operand:SI 0 "register_operand" "=r")
10760 (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10761 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10762 "TARGET_SHMEDIA_FPU"
10763 "fcmpun.d %1,%2,%0"
10764 [(set_attr "type" "fcmp_media")])
10765
10766 (define_expand "cbranchdf4"
10767 [(set (pc)
10768 (if_then_else (match_operator 0 "sh_float_comparison_operator"
10769 [(match_operand:DF 1 "arith_operand" "")
10770 (match_operand:DF 2 "arith_operand" "")])
10771 (match_operand 3 "" "")
10772 (pc)))]
10773 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10774 "
10775 {
10776 if (TARGET_SHMEDIA)
10777 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
10778 operands[3]));
10779 else
10780 sh_emit_compare_and_branch (operands, DFmode);
10781 DONE;
10782 }")
10783
10784
10785 (define_expand "negdf2"
10786 [(set (match_operand:DF 0 "arith_reg_operand" "")
10787 (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
10788 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10789 "
10790 {
10791 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10792 {
10793 expand_df_unop (&gen_negdf2_i, operands);
10794 DONE;
10795 }
10796 }")
10797
10798 (define_insn "*negdf2_media"
10799 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10800 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10801 "TARGET_SHMEDIA_FPU"
10802 "fneg.d %1, %0"
10803 [(set_attr "type" "fmove_media")])
10804
10805 (define_insn "negdf2_i"
10806 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10807 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
10808 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10809 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10810 "fneg %0"
10811 [(set_attr "type" "fmove")
10812 (set_attr "fp_mode" "double")])
10813
10814 (define_expand "sqrtdf2"
10815 [(set (match_operand:DF 0 "arith_reg_operand" "")
10816 (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
10817 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10818 "
10819 {
10820 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10821 {
10822 expand_df_unop (&gen_sqrtdf2_i, operands);
10823 DONE;
10824 }
10825 }")
10826
10827 (define_insn "*sqrtdf2_media"
10828 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10829 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10830 "TARGET_SHMEDIA_FPU"
10831 "fsqrt.d %1, %0"
10832 [(set_attr "type" "dfdiv_media")])
10833
10834 (define_insn "sqrtdf2_i"
10835 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10836 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
10837 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10838 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10839 "fsqrt %0"
10840 [(set_attr "type" "dfdiv")
10841 (set_attr "fp_mode" "double")])
10842
10843 (define_expand "absdf2"
10844 [(set (match_operand:DF 0 "arith_reg_operand" "")
10845 (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
10846 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10847 "
10848 {
10849 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10850 {
10851 expand_df_unop (&gen_absdf2_i, operands);
10852 DONE;
10853 }
10854 }")
10855
10856 (define_insn "*absdf2_media"
10857 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10858 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10859 "TARGET_SHMEDIA_FPU"
10860 "fabs.d %1, %0"
10861 [(set_attr "type" "fmove_media")])
10862
10863 (define_insn "absdf2_i"
10864 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10865 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
10866 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10867 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10868 "fabs %0"
10869 [(set_attr "type" "fmove")
10870 (set_attr "fp_mode" "double")])
10871
10872 (define_expand "extendsfdf2"
10873 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10874 (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
10875 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10876 "
10877 {
10878 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10879 {
10880 emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
10881 get_fpscr_rtx ()));
10882 DONE;
10883 }
10884 }")
10885
10886 (define_insn "*extendsfdf2_media"
10887 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10888 (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10889 "TARGET_SHMEDIA_FPU"
10890 "fcnv.sd %1, %0"
10891 [(set_attr "type" "dfpconv_media")])
10892
10893 (define_insn "extendsfdf2_i4"
10894 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10895 (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
10896 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10897 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10898 "fcnvsd %1,%0"
10899 [(set_attr "type" "fp")
10900 (set_attr "fp_mode" "double")])
10901
10902 (define_expand "truncdfsf2"
10903 [(set (match_operand:SF 0 "fpul_operand" "")
10904 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
10905 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10906 "
10907 {
10908 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10909 {
10910 emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
10911 get_fpscr_rtx ()));
10912 DONE;
10913 }
10914 }")
10915
10916 (define_insn "*truncdfsf2_media"
10917 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10918 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10919 "TARGET_SHMEDIA_FPU"
10920 "fcnv.ds %1, %0"
10921 [(set_attr "type" "dfpconv_media")])
10922
10923 (define_insn "truncdfsf2_i4"
10924 [(set (match_operand:SF 0 "fpul_operand" "=y")
10925 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
10926 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10927 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10928 "fcnvds %1,%0"
10929 [(set_attr "type" "fp")
10930 (set_attr "fp_mode" "double")])
10931 \f
10932 ;; Bit field extract patterns. These give better code for packed bitfields,
10933 ;; because they allow auto-increment addresses to be generated.
10934
10935 (define_expand "insv"
10936 [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
10937 (match_operand:SI 1 "immediate_operand" "")
10938 (match_operand:SI 2 "immediate_operand" ""))
10939 (match_operand:SI 3 "general_operand" ""))]
10940 "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
10941 "
10942 {
10943 rtx addr_target, orig_address, shift_reg, qi_val;
10944 HOST_WIDE_INT bitsize, size, v = 0;
10945 rtx x = operands[3];
10946
10947 if (TARGET_SH2A && TARGET_BITOPS
10948 && (satisfies_constraint_Sbw (operands[0])
10949 || satisfies_constraint_Sbv (operands[0]))
10950 && satisfies_constraint_M (operands[1])
10951 && satisfies_constraint_K03 (operands[2]))
10952 {
10953 if (satisfies_constraint_N (operands[3]))
10954 {
10955 emit_insn (gen_bclr_m2a (operands[0], operands[2]));
10956 DONE;
10957 }
10958 else if (satisfies_constraint_M (operands[3]))
10959 {
10960 emit_insn (gen_bset_m2a (operands[0], operands[2]));
10961 DONE;
10962 }
10963 else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
10964 && satisfies_constraint_M (operands[1]))
10965 {
10966 emit_insn (gen_bst_m2a (operands[0], operands[2]));
10967 DONE;
10968 }
10969 else if (REG_P (operands[3])
10970 && satisfies_constraint_M (operands[1]))
10971 {
10972 emit_insn (gen_bld_reg (operands[3], const0_rtx));
10973 emit_insn (gen_bst_m2a (operands[0], operands[2]));
10974 DONE;
10975 }
10976 }
10977 /* ??? expmed doesn't care for non-register predicates. */
10978 if (! memory_operand (operands[0], VOIDmode)
10979 || ! immediate_operand (operands[1], VOIDmode)
10980 || ! immediate_operand (operands[2], VOIDmode)
10981 || ! general_operand (x, VOIDmode))
10982 FAIL;
10983 /* If this isn't a 16 / 24 / 32 bit field, or if
10984 it doesn't start on a byte boundary, then fail. */
10985 bitsize = INTVAL (operands[1]);
10986 if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
10987 || (INTVAL (operands[2]) % 8) != 0)
10988 FAIL;
10989
10990 size = bitsize / 8;
10991 orig_address = XEXP (operands[0], 0);
10992 shift_reg = gen_reg_rtx (SImode);
10993 if (CONST_INT_P (x))
10994 {
10995 v = INTVAL (x);
10996 qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
10997 }
10998 else
10999 {
11000 emit_insn (gen_movsi (shift_reg, operands[3]));
11001 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11002 }
11003 addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1));
11004
11005 operands[0] = replace_equiv_address (operands[0], addr_target);
11006 emit_insn (gen_movqi (operands[0], qi_val));
11007
11008 while (size -= 1)
11009 {
11010 if (CONST_INT_P (x))
11011 qi_val
11012 = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
11013 else
11014 {
11015 emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
11016 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11017 }
11018 emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
11019 emit_insn (gen_movqi (operands[0], qi_val));
11020 }
11021
11022 DONE;
11023 }")
11024
11025 (define_insn "movua"
11026 [(set (match_operand:SI 0 "register_operand" "=z")
11027 (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
11028 UNSPEC_MOVUA))]
11029 "TARGET_SH4A_ARCH"
11030 "movua.l %1,%0"
11031 [(set_attr "type" "movua")])
11032
11033 ;; We shouldn't need this, but cse replaces increments with references
11034 ;; to other regs before flow has a chance to create post_inc
11035 ;; addressing modes, and only postreload's cse_move2add brings the
11036 ;; increments back to a usable form.
11037 (define_peephole2
11038 [(set (match_operand:SI 0 "register_operand" "")
11039 (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
11040 (const_int 32) (const_int 0)))
11041 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11042 "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
11043 [(set (match_operand:SI 0 "register_operand" "")
11044 (sign_extract:SI (mem:SI (post_inc:SI
11045 (match_operand:SI 1 "register_operand" "")))
11046 (const_int 32) (const_int 0)))]
11047 "")
11048
11049 (define_expand "extv"
11050 [(set (match_operand:SI 0 "register_operand" "")
11051 (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11052 (match_operand 2 "const_int_operand" "")
11053 (match_operand 3 "const_int_operand" "")))]
11054 "TARGET_SH4A_ARCH || TARGET_SH2A"
11055 {
11056 if (TARGET_SH2A && TARGET_BITOPS
11057 && (satisfies_constraint_Sbw (operands[1])
11058 || satisfies_constraint_Sbv (operands[1]))
11059 && satisfies_constraint_M (operands[2])
11060 && satisfies_constraint_K03 (operands[3]))
11061 {
11062 emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
11063 if (REGNO (operands[0]) != T_REG)
11064 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
11065 DONE;
11066 }
11067 if (TARGET_SH4A_ARCH
11068 && INTVAL (operands[2]) == 32
11069 && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11070 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
11071 {
11072 rtx src = adjust_address (operands[1], BLKmode, 0);
11073 set_mem_size (src, 4);
11074 emit_insn (gen_movua (operands[0], src));
11075 DONE;
11076 }
11077
11078 FAIL;
11079 })
11080
11081 (define_expand "extzv"
11082 [(set (match_operand:SI 0 "register_operand" "")
11083 (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11084 (match_operand 2 "const_int_operand" "")
11085 (match_operand 3 "const_int_operand" "")))]
11086 "TARGET_SH4A_ARCH || TARGET_SH2A"
11087 {
11088 if (TARGET_SH2A && TARGET_BITOPS
11089 && (satisfies_constraint_Sbw (operands[1])
11090 || satisfies_constraint_Sbv (operands[1]))
11091 && satisfies_constraint_M (operands[2])
11092 && satisfies_constraint_K03 (operands[3]))
11093 {
11094 emit_insn (gen_bld_m2a (operands[1], operands[3]));
11095 if (REGNO (operands[0]) != T_REG)
11096 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
11097 DONE;
11098 }
11099 if (TARGET_SH4A_ARCH
11100 && INTVAL (operands[2]) == 32
11101 && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11102 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
11103 {
11104 rtx src = adjust_address (operands[1], BLKmode, 0);
11105 set_mem_size (src, 4);
11106 emit_insn (gen_movua (operands[0], src));
11107 DONE;
11108 }
11109
11110 FAIL;
11111 })
11112
11113 ;; SH2A instructions for bitwise operations.
11114
11115 ;; Clear a bit in a memory location.
11116 (define_insn "bclr_m2a"
11117 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11118 (and:QI
11119 (not:QI (ashift:QI (const_int 1)
11120 (match_operand:QI 1 "const_int_operand" "K03,K03")))
11121 (match_dup 0)))]
11122 "TARGET_SH2A && TARGET_BITOPS"
11123 "@
11124 bclr.b\\t%1,%0
11125 bclr.b\\t%1,@(0,%t0)"
11126 [(set_attr "length" "4,4")])
11127
11128 (define_insn "bclrmem_m2a"
11129 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11130 (and:QI (match_dup 0)
11131 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
11132 "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
11133 "@
11134 bclr.b\\t%W1,%0
11135 bclr.b\\t%W1,@(0,%t0)"
11136 [(set_attr "length" "4,4")])
11137
11138 ;; Set a bit in a memory location.
11139 (define_insn "bset_m2a"
11140 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11141 (ior:QI
11142 (ashift:QI (const_int 1)
11143 (match_operand:QI 1 "const_int_operand" "K03,K03"))
11144 (match_dup 0)))]
11145 "TARGET_SH2A && TARGET_BITOPS"
11146 "@
11147 bset.b\\t%1,%0
11148 bset.b\\t%1,@(0,%t0)"
11149 [(set_attr "length" "4,4")])
11150
11151 (define_insn "bsetmem_m2a"
11152 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11153 (ior:QI (match_dup 0)
11154 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
11155 "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
11156 "@
11157 bset.b\\t%V1,%0
11158 bset.b\\t%V1,@(0,%t0)"
11159 [(set_attr "length" "4,4")])
11160
11161 ;;; Transfer the contents of the T bit to a specified bit of memory.
11162 (define_insn "bst_m2a"
11163 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
11164 (if_then_else (eq (reg:SI T_REG) (const_int 0))
11165 (and:QI
11166 (not:QI (ashift:QI (const_int 1)
11167 (match_operand:QI 1 "const_int_operand" "K03,K03")))
11168 (match_dup 0))
11169 (ior:QI
11170 (ashift:QI (const_int 1) (match_dup 1))
11171 (match_dup 0))))]
11172 "TARGET_SH2A && TARGET_BITOPS"
11173 "@
11174 bst.b\\t%1,%0
11175 bst.b\\t%1,@(0,%t0)"
11176 [(set_attr "length" "4")])
11177
11178 ;; Store a specified bit of memory in the T bit.
11179 (define_insn "bld_m2a"
11180 [(set (reg:SI T_REG)
11181 (zero_extract:SI
11182 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
11183 (const_int 1)
11184 (match_operand 1 "const_int_operand" "K03,K03")))]
11185 "TARGET_SH2A && TARGET_BITOPS"
11186 "@
11187 bld.b\\t%1,%0
11188 bld.b\\t%1,@(0,%t0)"
11189 [(set_attr "length" "4,4")])
11190
11191 ;; Store a specified bit of memory in the T bit.
11192 (define_insn "bldsign_m2a"
11193 [(set (reg:SI T_REG)
11194 (sign_extract:SI
11195 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11196 (const_int 1)
11197 (match_operand 1 "const_int_operand" "K03,K03")))]
11198 "TARGET_SH2A && TARGET_BITOPS"
11199 "@
11200 bld.b\\t%1,%0
11201 bld.b\\t%1,@(0,%t0)"
11202 [(set_attr "length" "4,4")])
11203
11204 ;; Store a specified bit of the LSB 8 bits of a register in the T bit.
11205 (define_insn "bld_reg"
11206 [(set (reg:SI T_REG)
11207 (zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
11208 (const_int 1)
11209 (match_operand 1 "const_int_operand" "K03")))]
11210 "TARGET_SH2A"
11211 "bld\\t%1,%0")
11212
11213 (define_insn "*bld_regqi"
11214 [(set (reg:SI T_REG)
11215 (zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
11216 (const_int 1)
11217 (match_operand 1 "const_int_operand" "K03")))]
11218 "TARGET_SH2A"
11219 "bld\\t%1,%0")
11220
11221 ;; Take logical and of a specified bit of memory with the T bit and
11222 ;; store its result in the T bit.
11223 (define_insn "band_m2a"
11224 [(set (reg:SI T_REG)
11225 (and:SI (reg:SI T_REG)
11226 (zero_extract:SI
11227 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11228 (const_int 1)
11229 (match_operand 1 "const_int_operand" "K03,K03"))))]
11230 "TARGET_SH2A && TARGET_BITOPS"
11231 "@
11232 band.b\\t%1,%0
11233 band.b\\t%1,@(0,%t0)"
11234 [(set_attr "length" "4,4")])
11235
11236 (define_insn "bandreg_m2a"
11237 [(set (match_operand:SI 0 "register_operand" "=r,r")
11238 (and:SI (zero_extract:SI
11239 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11240 (const_int 1)
11241 (match_operand 2 "const_int_operand" "K03,K03"))
11242 (match_operand:SI 3 "register_operand" "r,r")))]
11243 "TARGET_SH2A && TARGET_BITOPS"
11244 "@
11245 band.b\\t%2,%1\;movt\\t%0
11246 band.b\\t%2,@(0,%t1)\;movt\\t%0"
11247 [(set_attr "length" "6,6")])
11248
11249 ;; Take logical or of a specified bit of memory with the T bit and
11250 ;; store its result in the T bit.
11251 (define_insn "bor_m2a"
11252 [(set (reg:SI T_REG)
11253 (ior:SI (reg:SI T_REG)
11254 (zero_extract:SI
11255 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11256 (const_int 1)
11257 (match_operand 1 "const_int_operand" "K03,K03"))))]
11258 "TARGET_SH2A && TARGET_BITOPS"
11259 "@
11260 bor.b\\t%1,%0
11261 bor.b\\t%1,@(0,%t0)"
11262 [(set_attr "length" "4,4")])
11263
11264 (define_insn "borreg_m2a"
11265 [(set (match_operand:SI 0 "register_operand" "=r,r")
11266 (ior:SI (zero_extract:SI
11267 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11268 (const_int 1)
11269 (match_operand 2 "const_int_operand" "K03,K03"))
11270 (match_operand:SI 3 "register_operand" "=r,r")))]
11271 "TARGET_SH2A && TARGET_BITOPS"
11272 "@
11273 bor.b\\t%2,%1\;movt\\t%0
11274 bor.b\\t%2,@(0,%t1)\;movt\\t%0"
11275 [(set_attr "length" "6,6")])
11276
11277 ;; Take exclusive or of a specified bit of memory with the T bit and
11278 ;; store its result in the T bit.
11279 (define_insn "bxor_m2a"
11280 [(set (reg:SI T_REG)
11281 (xor:SI (reg:SI T_REG)
11282 (zero_extract:SI
11283 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11284 (const_int 1)
11285 (match_operand 1 "const_int_operand" "K03,K03"))))]
11286 "TARGET_SH2A && TARGET_BITOPS"
11287 "@
11288 bxor.b\\t%1,%0
11289 bxor.b\\t%1,@(0,%t0)"
11290 [(set_attr "length" "4,4")])
11291
11292 (define_insn "bxorreg_m2a"
11293 [(set (match_operand:SI 0 "register_operand" "=r,r")
11294 (xor:SI (zero_extract:SI
11295 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11296 (const_int 1)
11297 (match_operand 2 "const_int_operand" "K03,K03"))
11298 (match_operand:SI 3 "register_operand" "=r,r")))]
11299 "TARGET_SH2A && TARGET_BITOPS"
11300 "@
11301 bxor.b\\t%2,%1\;movt\\t%0
11302 bxor.b\\t%2,@(0,%t1)\;movt\\t%0"
11303 [(set_attr "length" "6,6")])
11304
11305 \f
11306 ;; -------------------------------------------------------------------------
11307 ;; Peepholes
11308 ;; -------------------------------------------------------------------------
11309 ;; This matches cases where the bit in a memory location is set.
11310 (define_peephole2
11311 [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
11312 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
11313 (set (match_dup 0)
11314 (ior:SI (match_dup 0)
11315 (match_operand:SI 2 "const_int_operand" "Pso,Pso")))
11316 (set (match_dup 1)
11317 (match_operand 3 "arith_reg_operand" "r,r"))]
11318 "TARGET_SH2A && TARGET_BITOPS
11319 && satisfies_constraint_Pso (operands[2])
11320 && REGNO (operands[0]) == REGNO (operands[3])"
11321 [(set (match_dup 1)
11322 (ior:QI (match_dup 1)
11323 (match_dup 2)))]
11324 "")
11325
11326 ;; This matches cases where the bit in a memory location is cleared.
11327 (define_peephole2
11328 [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
11329 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
11330 (set (match_dup 0)
11331 (and:SI (match_dup 0)
11332 (match_operand:SI 2 "const_int_operand" "Psz,Psz")))
11333 (set (match_dup 1)
11334 (match_operand 3 "arith_reg_operand" "r,r"))]
11335 "TARGET_SH2A && TARGET_BITOPS
11336 && satisfies_constraint_Psz (operands[2])
11337 && REGNO (operands[0]) == REGNO (operands[3])"
11338 [(set (match_dup 1)
11339 (and:QI (match_dup 1)
11340 (match_dup 2)))]
11341 "")
11342
11343 ;; This matches cases where a stack pointer increment at the start of the
11344 ;; epilogue combines with a stack slot read loading the return value.
11345
11346 (define_peephole
11347 [(set (match_operand:SI 0 "arith_reg_operand" "")
11348 (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
11349 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11350 "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
11351 "mov.l @%1+,%0")
11352
11353 ;; See the comment on the dt combiner pattern above.
11354
11355 (define_peephole
11356 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11357 (plus:SI (match_dup 0)
11358 (const_int -1)))
11359 (set (reg:SI T_REG)
11360 (eq:SI (match_dup 0)
11361 (const_int 0)))]
11362 "TARGET_SH2"
11363 "dt %0")
11364
11365 ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
11366 ;; to `mov #k,r0; mov.l @(r0,r15),rn'. These sequences are generated by
11367 ;; reload when the constant is too large for a reg+offset address.
11368
11369 ;; ??? We would get much better code if this was done in reload. This would
11370 ;; require modifying find_reloads_address to recognize that if the constant
11371 ;; is out-of-range for an immediate add, then we get better code by reloading
11372 ;; the constant into a register than by reloading the sum into a register,
11373 ;; since the former is one instruction shorter if the address does not need
11374 ;; to be offsettable. Unfortunately this does not work, because there is
11375 ;; only one register, r0, that can be used as an index register. This register
11376 ;; is also the function return value register. So, if we try to force reload
11377 ;; to use double-reg addresses, then we end up with some instructions that
11378 ;; need to use r0 twice. The only way to fix this is to change the calling
11379 ;; convention so that r0 is not used to return values.
11380
11381 (define_peephole
11382 [(set (match_operand:SI 0 "register_operand" "=r")
11383 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11384 (set (mem:SI (match_dup 0))
11385 (match_operand:SI 2 "general_movsrc_operand" ""))]
11386 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11387 "mov.l %2,@(%0,%1)")
11388
11389 (define_peephole
11390 [(set (match_operand:SI 0 "register_operand" "=r")
11391 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11392 (set (match_operand:SI 2 "general_movdst_operand" "")
11393 (mem:SI (match_dup 0)))]
11394 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11395 "mov.l @(%0,%1),%2")
11396
11397 (define_peephole
11398 [(set (match_operand:SI 0 "register_operand" "=r")
11399 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11400 (set (mem:HI (match_dup 0))
11401 (match_operand:HI 2 "general_movsrc_operand" ""))]
11402 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11403 "mov.w %2,@(%0,%1)")
11404
11405 (define_peephole
11406 [(set (match_operand:SI 0 "register_operand" "=r")
11407 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11408 (set (match_operand:HI 2 "general_movdst_operand" "")
11409 (mem:HI (match_dup 0)))]
11410 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11411 "mov.w @(%0,%1),%2")
11412
11413 (define_peephole
11414 [(set (match_operand:SI 0 "register_operand" "=r")
11415 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11416 (set (mem:QI (match_dup 0))
11417 (match_operand:QI 2 "general_movsrc_operand" ""))]
11418 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11419 "mov.b %2,@(%0,%1)")
11420
11421 (define_peephole
11422 [(set (match_operand:SI 0 "register_operand" "=r")
11423 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11424 (set (match_operand:QI 2 "general_movdst_operand" "")
11425 (mem:QI (match_dup 0)))]
11426 "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11427 "mov.b @(%0,%1),%2")
11428
11429 (define_peephole
11430 [(set (match_operand:SI 0 "register_operand" "=r")
11431 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11432 (set (mem:SF (match_dup 0))
11433 (match_operand:SF 2 "general_movsrc_operand" ""))]
11434 "TARGET_SH1 && REGNO (operands[0]) == 0
11435 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
11436 || (GET_CODE (operands[2]) == SUBREG
11437 && REGNO (SUBREG_REG (operands[2])) < 16))
11438 && reg_unused_after (operands[0], insn)"
11439 "mov.l %2,@(%0,%1)")
11440
11441 (define_peephole
11442 [(set (match_operand:SI 0 "register_operand" "=r")
11443 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11444 (set (match_operand:SF 2 "general_movdst_operand" "")
11445
11446 (mem:SF (match_dup 0)))]
11447 "TARGET_SH1 && REGNO (operands[0]) == 0
11448 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
11449 || (GET_CODE (operands[2]) == SUBREG
11450 && REGNO (SUBREG_REG (operands[2])) < 16))
11451 && reg_unused_after (operands[0], insn)"
11452 "mov.l @(%0,%1),%2")
11453
11454 (define_peephole
11455 [(set (match_operand:SI 0 "register_operand" "=r")
11456 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11457 (set (mem:SF (match_dup 0))
11458 (match_operand:SF 2 "general_movsrc_operand" ""))]
11459 "TARGET_SH2E && REGNO (operands[0]) == 0
11460 && ((REG_P (operands[2])
11461 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11462 || (GET_CODE (operands[2]) == SUBREG
11463 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11464 && reg_unused_after (operands[0], insn)"
11465 "fmov{.s|} %2,@(%0,%1)")
11466
11467 (define_peephole
11468 [(set (match_operand:SI 0 "register_operand" "=r")
11469 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11470 (set (match_operand:SF 2 "general_movdst_operand" "")
11471
11472 (mem:SF (match_dup 0)))]
11473 "TARGET_SH2E && REGNO (operands[0]) == 0
11474 && ((REG_P (operands[2])
11475 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11476 || (GET_CODE (operands[2]) == SUBREG
11477 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11478 && reg_unused_after (operands[0], insn)"
11479 "fmov{.s|} @(%0,%1),%2")
11480
11481 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF). */
11482 (define_insn "sp_switch_1"
11483 [(const_int 1) (match_operand:SI 0 "symbol_ref_operand" "s")]
11484 "TARGET_SH1"
11485 "*
11486 {
11487 output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", operands);
11488 output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", operands);
11489 return \"mov r0,r15\";
11490 }"
11491 [(set_attr "length" "10")])
11492
11493 ;; Switch back to the original stack for interrupt functions with the
11494 ;; sp_switch attribute. */
11495 (define_insn "sp_switch_2"
11496 [(const_int 2)]
11497 "TARGET_SH1"
11498 "mov.l @r15+,r15\;mov.l @r15+,r0"
11499 [(set_attr "length" "4")])
11500
11501 ;; Integer vector moves
11502
11503 (define_expand "movv8qi"
11504 [(set (match_operand:V8QI 0 "general_movdst_operand" "")
11505 (match_operand:V8QI 1 "general_movsrc_operand" ""))]
11506 "TARGET_SHMEDIA"
11507 "{ if (prepare_move_operands (operands, V8QImode)) DONE; }")
11508
11509 (define_insn "movv8qi_i"
11510 [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
11511 (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11512 "TARGET_SHMEDIA
11513 && (register_operand (operands[0], V8QImode)
11514 || sh_register_operand (operands[1], V8QImode))"
11515 "@
11516 add %1, r63, %0
11517 movi %1, %0
11518 #
11519 ld%M1.q %m1, %0
11520 st%M0.q %m0, %N1"
11521 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
11522 (set_attr "length" "4,4,16,4,4")])
11523
11524 (define_split
11525 [(set (match_operand:V8QI 0 "arith_reg_dest" "")
11526 (subreg:V8QI (const_int 0) 0))]
11527 "TARGET_SHMEDIA"
11528 [(set (match_dup 0)
11529 (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
11530 (const_int 0) (const_int 0) (const_int 0)
11531 (const_int 0) (const_int 0)]))])
11532
11533 (define_split
11534 [(set (match_operand 0 "arith_reg_dest" "")
11535 (match_operand 1 "sh_rep_vec" ""))]
11536 "TARGET_SHMEDIA && reload_completed
11537 && GET_MODE (operands[0]) == GET_MODE (operands[1])
11538 && sh_vector_mode_supported_p (GET_MODE (operands[0]))
11539 && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
11540 && (XVECEXP (operands[1], 0, 0) != const0_rtx
11541 || XVECEXP (operands[1], 0, 1) != const0_rtx)
11542 && (XVECEXP (operands[1], 0, 0) != constm1_rtx
11543 || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
11544 [(set (match_dup 0) (match_dup 1))
11545 (match_dup 2)]
11546 "
11547 {
11548 int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
11549 rtx elt1 = XVECEXP (operands[1], 0, 1);
11550
11551 if (unit_size > 2)
11552 operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
11553 else
11554 {
11555 if (unit_size < 2)
11556 operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
11557 operands[2] = gen_mperm_w0 (operands[0], operands[0]);
11558 }
11559 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
11560 operands[1] = XVECEXP (operands[1], 0, 0);
11561 if (unit_size < 2)
11562 {
11563 if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
11564 operands[1]
11565 = GEN_INT (TARGET_LITTLE_ENDIAN
11566 ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
11567 : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
11568 else
11569 {
11570 operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
11571 operands[1]
11572 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
11573 }
11574 }
11575 }")
11576
11577 (define_split
11578 [(set (match_operand 0 "arith_reg_dest" "")
11579 (match_operand 1 "sh_const_vec" ""))]
11580 "TARGET_SHMEDIA && reload_completed
11581 && GET_MODE (operands[0]) == GET_MODE (operands[1])
11582 && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
11583 [(set (match_dup 0) (match_dup 1))]
11584 "
11585 {
11586 rtx v = operands[1];
11587 enum machine_mode new_mode
11588 = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
11589
11590 operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
11591 operands[1]
11592 = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
11593 }")
11594
11595 (define_expand "movv2hi"
11596 [(set (match_operand:V2HI 0 "general_movdst_operand" "")
11597 (match_operand:V2HI 1 "general_movsrc_operand" ""))]
11598 "TARGET_SHMEDIA"
11599 "{ if (prepare_move_operands (operands, V2HImode)) DONE; }")
11600
11601 (define_insn "movv2hi_i"
11602 [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
11603 (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11604 "TARGET_SHMEDIA
11605 && (register_operand (operands[0], V2HImode)
11606 || sh_register_operand (operands[1], V2HImode))"
11607 "@
11608 add.l %1, r63, %0
11609 movi %1, %0
11610 #
11611 ld%M1.l %m1, %0
11612 st%M0.l %m0, %N1"
11613 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
11614 (set_attr "length" "4,4,16,4,4")
11615 (set (attr "highpart")
11616 (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
11617 (const_string "user")]
11618 (const_string "ignore")))])
11619
11620 (define_expand "movv4hi"
11621 [(set (match_operand:V4HI 0 "general_movdst_operand" "")
11622 (match_operand:V4HI 1 "general_movsrc_operand" ""))]
11623 "TARGET_SHMEDIA"
11624 "{ if (prepare_move_operands (operands, V4HImode)) DONE; }")
11625
11626 (define_insn "movv4hi_i"
11627 [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
11628 (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11629 "TARGET_SHMEDIA
11630 && (register_operand (operands[0], V4HImode)
11631 || sh_register_operand (operands[1], V4HImode))"
11632 "@
11633 add %1, r63, %0
11634 movi %1, %0
11635 #
11636 ld%M1.q %m1, %0
11637 st%M0.q %m0, %N1"
11638 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
11639 (set_attr "length" "4,4,16,4,4")
11640 (set_attr "highpart" "depend")])
11641
11642 (define_expand "movv2si"
11643 [(set (match_operand:V2SI 0 "general_movdst_operand" "")
11644 (match_operand:V2SI 1 "general_movsrc_operand" ""))]
11645 "TARGET_SHMEDIA"
11646 "{ if (prepare_move_operands (operands, V2SImode)) DONE; }")
11647
11648 (define_insn "movv2si_i"
11649 [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
11650 (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11651 "TARGET_SHMEDIA
11652 && (register_operand (operands[0], V2SImode)
11653 || sh_register_operand (operands[1], V2SImode))"
11654 "@
11655 add %1, r63, %0
11656 #
11657 #
11658 ld%M1.q %m1, %0
11659 st%M0.q %m0, %N1"
11660 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
11661 (set_attr "length" "4,4,16,4,4")
11662 (set_attr "highpart" "depend")])
11663
11664 ;; Multimedia Intrinsics
11665
11666 (define_insn "absv2si2"
11667 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11668 (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
11669 "TARGET_SHMEDIA"
11670 "mabs.l %1, %0"
11671 [(set_attr "type" "mcmp_media")
11672 (set_attr "highpart" "depend")])
11673
11674 (define_insn "absv4hi2"
11675 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11676 (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
11677 "TARGET_SHMEDIA"
11678 "mabs.w %1, %0"
11679 [(set_attr "type" "mcmp_media")
11680 (set_attr "highpart" "depend")])
11681
11682 (define_insn "addv2si3"
11683 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11684 (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
11685 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11686 "TARGET_SHMEDIA"
11687 "madd.l %1, %2, %0"
11688 [(set_attr "type" "arith_media")
11689 (set_attr "highpart" "depend")])
11690
11691 (define_insn "addv4hi3"
11692 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11693 (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
11694 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11695 "TARGET_SHMEDIA"
11696 "madd.w %1, %2, %0"
11697 [(set_attr "type" "arith_media")
11698 (set_attr "highpart" "depend")])
11699
11700 (define_insn_and_split "addv2hi3"
11701 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
11702 (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
11703 (match_operand:V2HI 2 "extend_reg_operand" "r")))]
11704 "TARGET_SHMEDIA"
11705 "#"
11706 "TARGET_SHMEDIA"
11707 [(const_int 0)]
11708 "
11709 {
11710 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
11711 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
11712 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
11713 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
11714 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
11715
11716 emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
11717 emit_insn (gen_truncdisi2 (si_dst, di_dst));
11718 DONE;
11719 }"
11720 [(set_attr "highpart" "must_split")])
11721
11722 (define_insn "ssaddv2si3"
11723 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11724 (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
11725 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11726 "TARGET_SHMEDIA"
11727 "madds.l %1, %2, %0"
11728 [(set_attr "type" "mcmp_media")
11729 (set_attr "highpart" "depend")])
11730
11731 (define_insn "usaddv8qi3"
11732 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11733 (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
11734 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
11735 "TARGET_SHMEDIA"
11736 "madds.ub %1, %2, %0"
11737 [(set_attr "type" "mcmp_media")
11738 (set_attr "highpart" "depend")])
11739
11740 (define_insn "ssaddv4hi3"
11741 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11742 (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
11743 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11744 "TARGET_SHMEDIA"
11745 "madds.w %1, %2, %0"
11746 [(set_attr "type" "mcmp_media")
11747 (set_attr "highpart" "depend")])
11748
11749 (define_insn "negcmpeqv8qi"
11750 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11751 (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
11752 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
11753 "TARGET_SHMEDIA"
11754 "mcmpeq.b %N1, %N2, %0"
11755 [(set_attr "type" "mcmp_media")
11756 (set_attr "highpart" "depend")])
11757
11758 (define_insn "negcmpeqv2si"
11759 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11760 (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
11761 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11762 "TARGET_SHMEDIA"
11763 "mcmpeq.l %N1, %N2, %0"
11764 [(set_attr "type" "mcmp_media")
11765 (set_attr "highpart" "depend")])
11766
11767 (define_insn "negcmpeqv4hi"
11768 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11769 (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
11770 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11771 "TARGET_SHMEDIA"
11772 "mcmpeq.w %N1, %N2, %0"
11773 [(set_attr "type" "mcmp_media")
11774 (set_attr "highpart" "depend")])
11775
11776 (define_insn "negcmpgtuv8qi"
11777 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11778 (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
11779 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
11780 "TARGET_SHMEDIA"
11781 "mcmpgt.ub %N1, %N2, %0"
11782 [(set_attr "type" "mcmp_media")
11783 (set_attr "highpart" "depend")])
11784
11785 (define_insn "negcmpgtv2si"
11786 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11787 (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
11788 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11789 "TARGET_SHMEDIA"
11790 "mcmpgt.l %N1, %N2, %0"
11791 [(set_attr "type" "mcmp_media")
11792 (set_attr "highpart" "depend")])
11793
11794 (define_insn "negcmpgtv4hi"
11795 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11796 (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
11797 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11798 "TARGET_SHMEDIA"
11799 "mcmpgt.w %N1, %N2, %0"
11800 [(set_attr "type" "mcmp_media")
11801 (set_attr "highpart" "depend")])
11802
11803 (define_insn "mcmv"
11804 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11805 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11806 (match_operand:DI 2 "arith_reg_operand" "r"))
11807 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
11808 (not:DI (match_dup 2)))))]
11809 "TARGET_SHMEDIA"
11810 "mcmv %N1, %2, %0"
11811 [(set_attr "type" "arith_media")
11812 (set_attr "highpart" "depend")])
11813
11814 (define_insn "mcnvs_lw"
11815 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11816 (vec_concat:V4HI
11817 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
11818 (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11819 "TARGET_SHMEDIA"
11820 "mcnvs.lw %N1, %N2, %0"
11821 [(set_attr "type" "mcmp_media")])
11822
11823 (define_insn "mcnvs_wb"
11824 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11825 (vec_concat:V8QI
11826 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
11827 (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11828 "TARGET_SHMEDIA"
11829 "mcnvs.wb %N1, %N2, %0"
11830 [(set_attr "type" "mcmp_media")])
11831
11832 (define_insn "mcnvs_wub"
11833 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11834 (vec_concat:V8QI
11835 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
11836 (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11837 "TARGET_SHMEDIA"
11838 "mcnvs.wub %N1, %N2, %0"
11839 [(set_attr "type" "mcmp_media")])
11840
11841 (define_insn "mextr_rl"
11842 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11843 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11844 (match_operand:HI 3 "mextr_bit_offset" "i"))
11845 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
11846 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
11847 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
11848 "*
11849 {
11850 static char templ[21];
11851
11852 sprintf (templ, \"mextr%d\\t%%N1, %%N2, %%0\",
11853 (int) INTVAL (operands[3]) >> 3);
11854 return templ;
11855 }"
11856 [(set_attr "type" "arith_media")])
11857
11858 (define_insn "*mextr_lr"
11859 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11860 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11861 (match_operand:HI 3 "mextr_bit_offset" "i"))
11862 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
11863 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
11864 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
11865 "*
11866 {
11867 static char templ[21];
11868
11869 sprintf (templ, \"mextr%d\\t%%N2, %%N1, %%0\",
11870 (int) INTVAL (operands[4]) >> 3);
11871 return templ;
11872 }"
11873 [(set_attr "type" "arith_media")])
11874
11875 ; mextrN can be modelled with vec_select / vec_concat, but the selection
11876 ; vector then varies depending on endianness.
11877 (define_expand "mextr1"
11878 [(match_operand:DI 0 "arith_reg_dest" "")
11879 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11880 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11881 "TARGET_SHMEDIA"
11882 "
11883 {
11884 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11885 GEN_INT (1 * 8), GEN_INT (7 * 8)));
11886 DONE;
11887 }")
11888
11889 (define_expand "mextr2"
11890 [(match_operand:DI 0 "arith_reg_dest" "")
11891 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11892 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11893 "TARGET_SHMEDIA"
11894 "
11895 {
11896 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11897 GEN_INT (2 * 8), GEN_INT (6 * 8)));
11898 DONE;
11899 }")
11900
11901 (define_expand "mextr3"
11902 [(match_operand:DI 0 "arith_reg_dest" "")
11903 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11904 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11905 "TARGET_SHMEDIA"
11906 "
11907 {
11908 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11909 GEN_INT (3 * 8), GEN_INT (5 * 8)));
11910 DONE;
11911 }")
11912
11913 (define_expand "mextr4"
11914 [(match_operand:DI 0 "arith_reg_dest" "")
11915 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11916 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11917 "TARGET_SHMEDIA"
11918 "
11919 {
11920 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11921 GEN_INT (4 * 8), GEN_INT (4 * 8)));
11922 DONE;
11923 }")
11924
11925 (define_expand "mextr5"
11926 [(match_operand:DI 0 "arith_reg_dest" "")
11927 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11928 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11929 "TARGET_SHMEDIA"
11930 "
11931 {
11932 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11933 GEN_INT (5 * 8), GEN_INT (3 * 8)));
11934 DONE;
11935 }")
11936
11937 (define_expand "mextr6"
11938 [(match_operand:DI 0 "arith_reg_dest" "")
11939 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11940 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11941 "TARGET_SHMEDIA"
11942 "
11943 {
11944 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11945 GEN_INT (6 * 8), GEN_INT (2 * 8)));
11946 DONE;
11947 }")
11948
11949 (define_expand "mextr7"
11950 [(match_operand:DI 0 "arith_reg_dest" "")
11951 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11952 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11953 "TARGET_SHMEDIA"
11954 "
11955 {
11956 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11957 GEN_INT (7 * 8), GEN_INT (1 * 8)));
11958 DONE;
11959 }")
11960
11961 (define_expand "mmacfx_wl"
11962 [(match_operand:V2SI 0 "arith_reg_dest" "")
11963 (match_operand:V2HI 1 "extend_reg_operand" "")
11964 (match_operand:V2HI 2 "extend_reg_operand" "")
11965 (match_operand:V2SI 3 "arith_reg_operand" "")]
11966 "TARGET_SHMEDIA"
11967 "
11968 {
11969 emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
11970 operands[1], operands[2]));
11971 DONE;
11972 }")
11973
11974 ;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
11975 ;; is depend
11976 (define_insn "mmacfx_wl_i"
11977 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11978 (ss_plus:V2SI
11979 (match_operand:V2SI 1 "arith_reg_operand" "0")
11980 (ss_truncate:V2SI
11981 (ashift:V2DI
11982 (sign_extend:V2DI
11983 (mult:V2SI
11984 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
11985 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
11986 (const_int 1)))))]
11987 "TARGET_SHMEDIA"
11988 "mmacfx.wl %2, %3, %0"
11989 [(set_attr "type" "mac_media")
11990 (set_attr "highpart" "depend")])
11991
11992 (define_expand "mmacnfx_wl"
11993 [(match_operand:V2SI 0 "arith_reg_dest" "")
11994 (match_operand:V2HI 1 "extend_reg_operand" "")
11995 (match_operand:V2HI 2 "extend_reg_operand" "")
11996 (match_operand:V2SI 3 "arith_reg_operand" "")]
11997 "TARGET_SHMEDIA"
11998 "
11999 {
12000 emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
12001 operands[1], operands[2]));
12002 DONE;
12003 }")
12004
12005 (define_insn "mmacnfx_wl_i"
12006 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12007 (ss_minus:V2SI
12008 (match_operand:V2SI 1 "arith_reg_operand" "0")
12009 (ss_truncate:V2SI
12010 (ashift:V2DI
12011 (sign_extend:V2DI
12012 (mult:V2SI
12013 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
12014 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
12015 (const_int 1)))))]
12016 "TARGET_SHMEDIA"
12017 "mmacnfx.wl %2, %3, %0"
12018 [(set_attr "type" "mac_media")
12019 (set_attr "highpart" "depend")])
12020
12021 (define_insn "mulv2si3"
12022 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12023 (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12024 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12025 "TARGET_SHMEDIA"
12026 "mmul.l %1, %2, %0"
12027 [(set_attr "type" "d2mpy_media")
12028 (set_attr "highpart" "depend")])
12029
12030 (define_insn "mulv4hi3"
12031 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12032 (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12033 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12034 "TARGET_SHMEDIA"
12035 "mmul.w %1, %2, %0"
12036 [(set_attr "type" "dmpy_media")
12037 (set_attr "highpart" "depend")])
12038
12039 (define_insn "mmulfx_l"
12040 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12041 (ss_truncate:V2SI
12042 (ashiftrt:V2DI
12043 (mult:V2DI
12044 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12045 (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
12046 (const_int 31))))]
12047 "TARGET_SHMEDIA"
12048 "mmulfx.l %1, %2, %0"
12049 [(set_attr "type" "d2mpy_media")
12050 (set_attr "highpart" "depend")])
12051
12052 (define_insn "mmulfx_w"
12053 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12054 (ss_truncate:V4HI
12055 (ashiftrt:V4SI
12056 (mult:V4SI
12057 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12058 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12059 (const_int 15))))]
12060 "TARGET_SHMEDIA"
12061 "mmulfx.w %1, %2, %0"
12062 [(set_attr "type" "dmpy_media")
12063 (set_attr "highpart" "depend")])
12064
12065 (define_insn "mmulfxrp_w"
12066 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12067 (ss_truncate:V4HI
12068 (ashiftrt:V4SI
12069 (plus:V4SI
12070 (mult:V4SI
12071 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12072 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12073 (const_int 16384))
12074 (const_int 15))))]
12075 "TARGET_SHMEDIA"
12076 "mmulfxrp.w %1, %2, %0"
12077 [(set_attr "type" "dmpy_media")
12078 (set_attr "highpart" "depend")])
12079
12080
12081 (define_expand "mmulhi_wl"
12082 [(match_operand:V2SI 0 "arith_reg_dest" "")
12083 (match_operand:V4HI 1 "arith_reg_operand" "")
12084 (match_operand:V4HI 2 "arith_reg_operand" "")]
12085 "TARGET_SHMEDIA"
12086 "
12087 {
12088 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
12089 (operands[0], operands[1], operands[2]));
12090 DONE;
12091 }")
12092
12093 (define_expand "mmullo_wl"
12094 [(match_operand:V2SI 0 "arith_reg_dest" "")
12095 (match_operand:V4HI 1 "arith_reg_operand" "")
12096 (match_operand:V4HI 2 "arith_reg_operand" "")]
12097 "TARGET_SHMEDIA"
12098 "
12099 {
12100 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
12101 (operands[0], operands[1], operands[2]));
12102 DONE;
12103 }")
12104
12105 (define_insn "mmul23_wl"
12106 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12107 (vec_select:V2SI
12108 (mult:V4SI
12109 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12110 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12111 (parallel [(const_int 2) (const_int 3)])))]
12112 "TARGET_SHMEDIA"
12113 "* return (TARGET_LITTLE_ENDIAN
12114 ? \"mmulhi.wl %1, %2, %0\"
12115 : \"mmullo.wl %1, %2, %0\");"
12116 [(set_attr "type" "dmpy_media")
12117 (set (attr "highpart")
12118 (cond [(eq_attr "endian" "big") (const_string "ignore")]
12119 (const_string "user")))])
12120
12121 (define_insn "mmul01_wl"
12122 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12123 (vec_select:V2SI
12124 (mult:V4SI
12125 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12126 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12127 (parallel [(const_int 0) (const_int 1)])))]
12128 "TARGET_SHMEDIA"
12129 "* return (TARGET_LITTLE_ENDIAN
12130 ? \"mmullo.wl %1, %2, %0\"
12131 : \"mmulhi.wl %1, %2, %0\");"
12132 [(set_attr "type" "dmpy_media")
12133 (set (attr "highpart")
12134 (cond [(eq_attr "endian" "little") (const_string "ignore")]
12135 (const_string "user")))])
12136
12137
12138 (define_expand "mmulsum_wq"
12139 [(match_operand:DI 0 "arith_reg_dest" "")
12140 (match_operand:V4HI 1 "arith_reg_operand" "")
12141 (match_operand:V4HI 2 "arith_reg_operand" "")
12142 (match_operand:DI 3 "arith_reg_operand" "")]
12143 "TARGET_SHMEDIA"
12144 "
12145 {
12146 emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
12147 operands[1], operands[2]));
12148 DONE;
12149 }")
12150
12151 (define_insn "mmulsum_wq_i"
12152 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12153 (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
12154 (plus:DI
12155 (plus:DI
12156 (vec_select:DI
12157 (mult:V4DI
12158 (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
12159 (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
12160 (parallel [(const_int 0)]))
12161 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12162 (sign_extend:V4DI (match_dup 3)))
12163 (parallel [(const_int 1)])))
12164 (plus:DI
12165 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12166 (sign_extend:V4DI (match_dup 3)))
12167 (parallel [(const_int 2)]))
12168 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12169 (sign_extend:V4DI (match_dup 3)))
12170 (parallel [(const_int 3)]))))))]
12171 "TARGET_SHMEDIA"
12172 "mmulsum.wq %2, %3, %0"
12173 [(set_attr "type" "mac_media")])
12174
12175 (define_expand "mperm_w"
12176 [(match_operand:V4HI 0 "arith_reg_dest" "=r")
12177 (match_operand:V4HI 1 "arith_reg_operand" "r")
12178 (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
12179 "TARGET_SHMEDIA"
12180 "
12181 {
12182 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
12183 (operands[0], operands[1], operands[2]));
12184 DONE;
12185 }")
12186
12187 ; This use of vec_select isn't exactly correct according to rtl.texi
12188 ; (because not constant), but it seems a straightforward extension.
12189 (define_insn "mperm_w_little"
12190 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12191 (vec_select:V4HI
12192 (match_operand:V4HI 1 "arith_reg_operand" "r")
12193 (parallel
12194 [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
12195 (const_int 2) (const_int 0))
12196 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
12197 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
12198 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
12199 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
12200 "mperm.w %1, %N2, %0"
12201 [(set_attr "type" "arith_media")])
12202
12203 (define_insn "mperm_w_big"
12204 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12205 (vec_select:V4HI
12206 (match_operand:V4HI 1 "arith_reg_operand" "r")
12207 (parallel
12208 [(zero_extract:QI (not:QI (match_operand:QI 2
12209 "extend_reg_or_0_operand" "rZ"))
12210 (const_int 2) (const_int 0))
12211 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
12212 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
12213 (zero_extract:QI (not:QI (match_dup 2))
12214 (const_int 2) (const_int 6))])))]
12215 "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
12216 "mperm.w %1, %N2, %0"
12217 [(set_attr "type" "arith_media")])
12218
12219 (define_insn "mperm_w0"
12220 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12221 (vec_duplicate:V4HI (truncate:HI (match_operand 1
12222 "trunc_hi_operand" "r"))))]
12223 "TARGET_SHMEDIA"
12224 "mperm.w %1, r63, %0"
12225 [(set_attr "type" "arith_media")
12226 (set_attr "highpart" "ignore")])
12227
12228 (define_expand "msad_ubq"
12229 [(match_operand:DI 0 "arith_reg_dest" "")
12230 (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
12231 (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
12232 (match_operand:DI 3 "arith_reg_operand" "")]
12233 "TARGET_SHMEDIA"
12234 "
12235 {
12236 emit_insn (gen_msad_ubq_i (operands[0], operands[3],
12237 operands[1], operands[2]));
12238 DONE;
12239 }")
12240
12241 (define_insn "msad_ubq_i"
12242 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12243 (plus:DI
12244 (plus:DI
12245 (plus:DI
12246 (plus:DI
12247 (match_operand:DI 1 "arith_reg_operand" "0")
12248 (abs:DI (vec_select:DI
12249 (minus:V8DI
12250 (zero_extend:V8DI
12251 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12252 (zero_extend:V8DI
12253 (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
12254 (parallel [(const_int 0)]))))
12255 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12256 (zero_extend:V8DI (match_dup 3)))
12257 (parallel [(const_int 1)]))))
12258 (plus:DI
12259 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12260 (zero_extend:V8DI (match_dup 3)))
12261 (parallel [(const_int 2)])))
12262 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12263 (zero_extend:V8DI (match_dup 3)))
12264 (parallel [(const_int 3)])))))
12265 (plus:DI
12266 (plus:DI
12267 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12268 (zero_extend:V8DI (match_dup 3)))
12269 (parallel [(const_int 4)])))
12270 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12271 (zero_extend:V8DI (match_dup 3)))
12272 (parallel [(const_int 5)]))))
12273 (plus:DI
12274 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12275 (zero_extend:V8DI (match_dup 3)))
12276 (parallel [(const_int 6)])))
12277 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12278 (zero_extend:V8DI (match_dup 3)))
12279 (parallel [(const_int 7)])))))))]
12280 "TARGET_SHMEDIA"
12281 "msad.ubq %N2, %N3, %0"
12282 [(set_attr "type" "mac_media")])
12283
12284 (define_insn "mshalds_l"
12285 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12286 (ss_truncate:V2SI
12287 (ashift:V2DI
12288 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12289 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12290 (const_int 31)))))]
12291 "TARGET_SHMEDIA"
12292 "mshalds.l %1, %2, %0"
12293 [(set_attr "type" "mcmp_media")
12294 (set_attr "highpart" "depend")])
12295
12296 (define_insn "mshalds_w"
12297 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12298 (ss_truncate:V4HI
12299 (ashift:V4SI
12300 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12301 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12302 (const_int 15)))))]
12303 "TARGET_SHMEDIA"
12304 "mshalds.w %1, %2, %0"
12305 [(set_attr "type" "mcmp_media")
12306 (set_attr "highpart" "depend")])
12307
12308 (define_insn "ashrv2si3"
12309 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12310 (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12311 (match_operand:DI 2 "arith_reg_operand" "r")))]
12312 "TARGET_SHMEDIA"
12313 "mshard.l %1, %2, %0"
12314 [(set_attr "type" "arith_media")
12315 (set_attr "highpart" "depend")])
12316
12317 (define_insn "ashrv4hi3"
12318 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12319 (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12320 (match_operand:DI 2 "arith_reg_operand" "r")))]
12321 "TARGET_SHMEDIA"
12322 "mshard.w %1, %2, %0"
12323 [(set_attr "type" "arith_media")
12324 (set_attr "highpart" "depend")])
12325
12326 (define_insn "mshards_q"
12327 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
12328 (ss_truncate:HI
12329 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
12330 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
12331 "TARGET_SHMEDIA"
12332 "mshards.q %1, %N2, %0"
12333 [(set_attr "type" "mcmp_media")])
12334
12335 (define_expand "mshfhi_b"
12336 [(match_operand:V8QI 0 "arith_reg_dest" "")
12337 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12338 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12339 "TARGET_SHMEDIA"
12340 "
12341 {
12342 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
12343 (operands[0], operands[1], operands[2]));
12344 DONE;
12345 }")
12346
12347 (define_expand "mshflo_b"
12348 [(match_operand:V8QI 0 "arith_reg_dest" "")
12349 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12350 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12351 "TARGET_SHMEDIA"
12352 "
12353 {
12354 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
12355 (operands[0], operands[1], operands[2]));
12356 DONE;
12357 }")
12358
12359 (define_insn "mshf4_b"
12360 [(set
12361 (match_operand:V8QI 0 "arith_reg_dest" "=r")
12362 (vec_select:V8QI
12363 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12364 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12365 (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
12366 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
12367 "TARGET_SHMEDIA"
12368 "* return (TARGET_LITTLE_ENDIAN
12369 ? \"mshfhi.b %N1, %N2, %0\"
12370 : \"mshflo.b %N1, %N2, %0\");"
12371 [(set_attr "type" "arith_media")
12372 (set (attr "highpart")
12373 (cond [(eq_attr "endian" "big") (const_string "ignore")]
12374 (const_string "user")))])
12375
12376 (define_insn "mshf0_b"
12377 [(set
12378 (match_operand:V8QI 0 "arith_reg_dest" "=r")
12379 (vec_select:V8QI
12380 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12381 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12382 (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
12383 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
12384 "TARGET_SHMEDIA"
12385 "* return (TARGET_LITTLE_ENDIAN
12386 ? \"mshflo.b %N1, %N2, %0\"
12387 : \"mshfhi.b %N1, %N2, %0\");"
12388 [(set_attr "type" "arith_media")
12389 (set (attr "highpart")
12390 (cond [(eq_attr "endian" "little") (const_string "ignore")]
12391 (const_string "user")))])
12392
12393 (define_expand "mshfhi_l"
12394 [(match_operand:V2SI 0 "arith_reg_dest" "")
12395 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12396 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12397 "TARGET_SHMEDIA"
12398 "
12399 {
12400 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
12401 (operands[0], operands[1], operands[2]));
12402 DONE;
12403 }")
12404
12405 (define_expand "mshflo_l"
12406 [(match_operand:V2SI 0 "arith_reg_dest" "")
12407 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12408 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12409 "TARGET_SHMEDIA"
12410 "
12411 {
12412 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
12413 (operands[0], operands[1], operands[2]));
12414 DONE;
12415 }")
12416
12417 (define_insn "mshf4_l"
12418 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12419 (vec_select:V2SI
12420 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12421 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12422 (parallel [(const_int 1) (const_int 3)])))]
12423 "TARGET_SHMEDIA"
12424 "* return (TARGET_LITTLE_ENDIAN
12425 ? \"mshfhi.l %N1, %N2, %0\"
12426 : \"mshflo.l %N1, %N2, %0\");"
12427 [(set_attr "type" "arith_media")
12428 (set (attr "highpart")
12429 (cond [(eq_attr "endian" "big") (const_string "ignore")]
12430 (const_string "user")))])
12431
12432 (define_insn "mshf0_l"
12433 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12434 (vec_select:V2SI
12435 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12436 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12437 (parallel [(const_int 0) (const_int 2)])))]
12438 "TARGET_SHMEDIA"
12439 "* return (TARGET_LITTLE_ENDIAN
12440 ? \"mshflo.l %N1, %N2, %0\"
12441 : \"mshfhi.l %N1, %N2, %0\");"
12442 [(set_attr "type" "arith_media")
12443 (set (attr "highpart")
12444 (cond [(eq_attr "endian" "little") (const_string "ignore")]
12445 (const_string "user")))])
12446
12447 (define_expand "mshfhi_w"
12448 [(match_operand:V4HI 0 "arith_reg_dest" "")
12449 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12450 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12451 "TARGET_SHMEDIA"
12452 "
12453 {
12454 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
12455 (operands[0], operands[1], operands[2]));
12456 DONE;
12457 }")
12458
12459 (define_expand "mshflo_w"
12460 [(match_operand:V4HI 0 "arith_reg_dest" "")
12461 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12462 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12463 "TARGET_SHMEDIA"
12464 "
12465 {
12466 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
12467 (operands[0], operands[1], operands[2]));
12468 DONE;
12469 }")
12470
12471 (define_insn "mshf4_w"
12472 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12473 (vec_select:V4HI
12474 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12475 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12476 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
12477 "TARGET_SHMEDIA"
12478 "* return (TARGET_LITTLE_ENDIAN
12479 ? \"mshfhi.w %N1, %N2, %0\"
12480 : \"mshflo.w %N1, %N2, %0\");"
12481 [(set_attr "type" "arith_media")
12482 (set (attr "highpart")
12483 (cond [(eq_attr "endian" "big") (const_string "ignore")]
12484 (const_string "user")))])
12485
12486 (define_insn "mshf0_w"
12487 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12488 (vec_select:V4HI
12489 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12490 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12491 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
12492 "TARGET_SHMEDIA"
12493 "* return (TARGET_LITTLE_ENDIAN
12494 ? \"mshflo.w %N1, %N2, %0\"
12495 : \"mshfhi.w %N1, %N2, %0\");"
12496 [(set_attr "type" "arith_media")
12497 (set (attr "highpart")
12498 (cond [(eq_attr "endian" "little") (const_string "ignore")]
12499 (const_string "user")))])
12500
12501 (define_insn "mshflo_w_x"
12502 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12503 (vec_select:V4HI
12504 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
12505 (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
12506 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
12507 "TARGET_SHMEDIA"
12508 "mshflo.w %N1, %N2, %0"
12509 [(set_attr "type" "arith_media")
12510 (set_attr "highpart" "ignore")])
12511
12512 /* These are useful to expand ANDs and as combiner patterns. */
12513 (define_insn_and_split "mshfhi_l_di"
12514 [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
12515 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
12516 (const_int 32))
12517 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
12518 (const_int -4294967296))))]
12519 "TARGET_SHMEDIA"
12520 "@
12521 mshfhi.l %N1, %N2, %0
12522 #"
12523 "TARGET_SHMEDIA && reload_completed
12524 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12525 [(set (match_dup 3) (match_dup 4))
12526 (set (match_dup 5) (match_dup 6))]
12527 "
12528 {
12529 operands[3] = gen_lowpart (SImode, operands[0]);
12530 operands[4] = gen_highpart (SImode, operands[1]);
12531 operands[5] = gen_highpart (SImode, operands[0]);
12532 operands[6] = gen_highpart (SImode, operands[2]);
12533 }"
12534 [(set_attr "type" "arith_media")])
12535
12536 (define_insn "*mshfhi_l_di_rev"
12537 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12538 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12539 (const_int -4294967296))
12540 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12541 (const_int 32))))]
12542 "TARGET_SHMEDIA"
12543 "mshfhi.l %N2, %N1, %0"
12544 [(set_attr "type" "arith_media")])
12545
12546 (define_split
12547 [(set (match_operand:DI 0 "arith_reg_dest" "")
12548 (ior:DI (zero_extend:DI (match_operand:SI 1
12549 "extend_reg_or_0_operand" ""))
12550 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
12551 (const_int -4294967296))))
12552 (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
12553 "TARGET_SHMEDIA"
12554 [(const_int 0)]
12555 "
12556 {
12557 emit_insn (gen_ashldi3_media (operands[3],
12558 simplify_gen_subreg (DImode, operands[1],
12559 SImode, 0),
12560 GEN_INT (32)));
12561 emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
12562 DONE;
12563 }")
12564
12565 (define_insn "mshflo_l_di"
12566 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12567 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12568 (const_int 4294967295))
12569 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12570 (const_int 32))))]
12571
12572 "TARGET_SHMEDIA"
12573 "mshflo.l %N1, %N2, %0"
12574 [(set_attr "type" "arith_media")
12575 (set_attr "highpart" "ignore")])
12576
12577 (define_insn "*mshflo_l_di_rev"
12578 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12579 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12580 (const_int 32))
12581 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12582 (const_int 4294967295))))]
12583
12584 "TARGET_SHMEDIA"
12585 "mshflo.l %N2, %N1, %0"
12586 [(set_attr "type" "arith_media")
12587 (set_attr "highpart" "ignore")])
12588
12589 ;; Combiner pattern for trampoline initialization.
12590 (define_insn_and_split "*double_shori"
12591 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12592 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
12593 (const_int 32))
12594 (match_operand:DI 2 "const_int_operand" "n")))]
12595 "TARGET_SHMEDIA
12596 && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
12597 "#"
12598 "rtx_equal_p (operands[0], operands[1])"
12599 [(const_int 0)]
12600 "
12601 {
12602 HOST_WIDE_INT v = INTVAL (operands[2]);
12603
12604 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
12605 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
12606 DONE;
12607 }"
12608 [(set_attr "highpart" "ignore")])
12609
12610
12611 (define_insn "*mshflo_l_di_x"
12612 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12613 (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
12614 "rZ"))
12615 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12616 (const_int 32))))]
12617
12618 "TARGET_SHMEDIA"
12619 "mshflo.l %N1, %N2, %0"
12620 [(set_attr "type" "arith_media")
12621 (set_attr "highpart" "ignore")])
12622
12623 (define_insn_and_split "concat_v2sf"
12624 [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
12625 ;; (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
12626 (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
12627 (match_operand:SF 2 "register_operand" "rZ,f,f")))]
12628
12629 "TARGET_SHMEDIA"
12630 "@
12631 mshflo.l %N1, %N2, %0
12632 #
12633 #"
12634 "TARGET_SHMEDIA && reload_completed
12635 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12636 [(set (match_dup 3) (match_dup 1))
12637 (set (match_dup 4) (match_dup 2))]
12638 "
12639 {
12640 operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
12641 operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
12642 }"
12643 [(set_attr "type" "arith_media")
12644 (set_attr "highpart" "ignore")])
12645
12646 (define_insn "*mshflo_l_di_x_rev"
12647 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12648 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12649 (const_int 32))
12650 (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
12651
12652 "TARGET_SHMEDIA"
12653 "mshflo.l %N2, %N1, %0"
12654 [(set_attr "type" "arith_media")
12655 (set_attr "highpart" "ignore")])
12656
12657 (define_insn "ashlv2si3"
12658 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12659 (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12660 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12661 "TARGET_SHMEDIA"
12662 "mshlld.l %1, %2, %0"
12663 [(set_attr "type" "arith_media")
12664 (set_attr "highpart" "depend")])
12665
12666 (define_split
12667 [(set (match_operand 0 "any_register_operand" "")
12668 (match_operator 3 "shift_operator"
12669 [(match_operand 1 "any_register_operand" "")
12670 (match_operand 2 "shift_count_reg_operand" "")]))]
12671 "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
12672 [(set (match_dup 0) (match_dup 3))]
12673 "
12674 {
12675 rtx count = operands[2];
12676 enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
12677
12678 while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
12679 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
12680 || GET_CODE (count) == TRUNCATE)
12681 count = XEXP (count, 0);
12682 inner_mode = GET_MODE (count);
12683 count = simplify_gen_subreg (outer_mode, count, inner_mode,
12684 subreg_lowpart_offset (outer_mode, inner_mode));
12685 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
12686 operands[1], count);
12687 }")
12688
12689 (define_insn "ashlv4hi3"
12690 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12691 (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12692 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12693 "TARGET_SHMEDIA"
12694 "mshlld.w %1, %2, %0"
12695 [(set_attr "type" "arith_media")
12696 (set_attr "highpart" "depend")])
12697
12698 (define_insn "lshrv2si3"
12699 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12700 (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12701 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12702 "TARGET_SHMEDIA"
12703 "mshlrd.l %1, %2, %0"
12704 [(set_attr "type" "arith_media")
12705 (set_attr "highpart" "depend")])
12706
12707 (define_insn "lshrv4hi3"
12708 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12709 (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12710 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12711 "TARGET_SHMEDIA"
12712 "mshlrd.w %1, %2, %0"
12713 [(set_attr "type" "arith_media")
12714 (set_attr "highpart" "depend")])
12715
12716 (define_insn "subv2si3"
12717 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12718 (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12719 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12720 "TARGET_SHMEDIA"
12721 "msub.l %N1, %2, %0"
12722 [(set_attr "type" "arith_media")
12723 (set_attr "highpart" "depend")])
12724
12725 (define_insn "subv4hi3"
12726 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12727 (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12728 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12729 "TARGET_SHMEDIA"
12730 "msub.w %N1, %2, %0"
12731 [(set_attr "type" "arith_media")
12732 (set_attr "highpart" "depend")])
12733
12734 (define_insn_and_split "subv2hi3"
12735 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
12736 (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
12737 (match_operand:V2HI 2 "arith_reg_operand" "r")))]
12738 "TARGET_SHMEDIA"
12739 "#"
12740 "TARGET_SHMEDIA"
12741 [(const_int 0)]
12742 "
12743 {
12744 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
12745 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
12746 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
12747 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
12748 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
12749
12750 emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
12751 emit_insn (gen_truncdisi2 (si_dst, di_dst));
12752 DONE;
12753 }"
12754 [(set_attr "highpart" "must_split")])
12755
12756 (define_insn "sssubv2si3"
12757 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12758 (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12759 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12760 "TARGET_SHMEDIA"
12761 "msubs.l %N1, %2, %0"
12762 [(set_attr "type" "mcmp_media")
12763 (set_attr "highpart" "depend")])
12764
12765 (define_insn "ussubv8qi3"
12766 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12767 (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12768 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
12769 "TARGET_SHMEDIA"
12770 "msubs.ub %N1, %2, %0"
12771 [(set_attr "type" "mcmp_media")
12772 (set_attr "highpart" "depend")])
12773
12774 (define_insn "sssubv4hi3"
12775 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12776 (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12777 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12778 "TARGET_SHMEDIA"
12779 "msubs.w %N1, %2, %0"
12780 [(set_attr "type" "mcmp_media")
12781 (set_attr "highpart" "depend")])
12782
12783 ;; Floating Point Intrinsics
12784
12785 (define_insn "fcosa_s"
12786 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12787 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
12788 UNSPEC_FCOSA))]
12789 "TARGET_SHMEDIA"
12790 "fcosa.s %1, %0"
12791 [(set_attr "type" "atrans_media")])
12792
12793 (define_insn "fsina_s"
12794 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12795 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
12796 UNSPEC_FSINA))]
12797 "TARGET_SHMEDIA"
12798 "fsina.s %1, %0"
12799 [(set_attr "type" "atrans_media")])
12800
12801 (define_insn "fipr"
12802 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12803 (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
12804 "fp_arith_reg_operand" "f")
12805 (match_operand:V4SF 2
12806 "fp_arith_reg_operand" "f"))
12807 (parallel [(const_int 0)]))
12808 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12809 (parallel [(const_int 1)])))
12810 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12811 (parallel [(const_int 2)]))
12812 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12813 (parallel [(const_int 3)])))))]
12814 "TARGET_SHMEDIA"
12815 "fipr.s %1, %2, %0"
12816 [(set_attr "type" "fparith_media")])
12817
12818 (define_insn "fsrra_s"
12819 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12820 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
12821 UNSPEC_FSRRA))]
12822 "TARGET_SHMEDIA"
12823 "fsrra.s %1, %0"
12824 [(set_attr "type" "atrans_media")])
12825
12826 (define_insn "ftrv"
12827 [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
12828 (plus:V4SF
12829 (plus:V4SF
12830 (mult:V4SF
12831 (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
12832 (parallel [(const_int 0) (const_int 5)
12833 (const_int 10) (const_int 15)]))
12834 (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
12835 (mult:V4SF
12836 (vec_select:V4SF (match_dup 1)
12837 (parallel [(const_int 4) (const_int 9)
12838 (const_int 14) (const_int 3)]))
12839 (vec_select:V4SF (match_dup 2)
12840 (parallel [(const_int 1) (const_int 2)
12841 (const_int 3) (const_int 0)]))))
12842 (plus:V4SF
12843 (mult:V4SF
12844 (vec_select:V4SF (match_dup 1)
12845 (parallel [(const_int 8) (const_int 13)
12846 (const_int 2) (const_int 7)]))
12847 (vec_select:V4SF (match_dup 2)
12848 (parallel [(const_int 2) (const_int 3)
12849 (const_int 0) (const_int 1)])))
12850 (mult:V4SF
12851 (vec_select:V4SF (match_dup 1)
12852 (parallel [(const_int 12) (const_int 1)
12853 (const_int 6) (const_int 11)]))
12854 (vec_select:V4SF (match_dup 2)
12855 (parallel [(const_int 3) (const_int 0)
12856 (const_int 1) (const_int 2)]))))))]
12857 "TARGET_SHMEDIA"
12858 "ftrv.s %1, %2, %0"
12859 [(set_attr "type" "fparith_media")])
12860
12861 (define_insn "ldhi_l"
12862 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12863 (zero_extract:SI
12864 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
12865 (const_int 3))
12866 (const_int -3)))
12867 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
12868 (const_int 0)))]
12869 "TARGET_SHMEDIA32"
12870 "ldhi.l %U1, %0"
12871 [(set_attr "type" "load_media")])
12872
12873 (define_insn "ldhi_q"
12874 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12875 (zero_extract:DI
12876 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
12877 (const_int 7))
12878 (const_int -7)))
12879 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
12880 (const_int 0)))]
12881 "TARGET_SHMEDIA32"
12882 "ldhi.q %U1, %0"
12883 [(set_attr "type" "load_media")])
12884
12885 (define_insn_and_split "*ldhi_q_comb0"
12886 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12887 (zero_extract:DI
12888 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
12889 "register_operand" "r")
12890 (match_operand:SI 2
12891 "ua_offset" "I06"))
12892 (const_int 7))
12893 (const_int -7)))
12894 (plus:SI (and:SI (match_dup 1) (const_int 7))
12895 (const_int 1))
12896 (const_int 0)))]
12897 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
12898 "#"
12899 ""
12900 [(pc)]
12901 "emit_insn (gen_ldhi_q (operands[0],
12902 gen_rtx_PLUS (SImode, operands[1], operands[2])));
12903 DONE;")
12904
12905
12906 (define_insn_and_split "*ldhi_q_comb1"
12907 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12908 (zero_extract:DI
12909 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
12910 "register_operand" "r")
12911 (match_operand:SI 2
12912 "ua_offset" "I06"))
12913 (const_int 7))
12914 (const_int -7)))
12915 (plus:SI (and:SI (plus:SI (match_dup 1) (match_operand:SI 3
12916 "ua_offset" "I06"))
12917 (const_int 7))
12918 (const_int 1))
12919 (const_int 0)))]
12920 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
12921 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
12922 "#"
12923 ""
12924 [(pc)]
12925 "emit_insn (gen_ldhi_q (operands[0],
12926 gen_rtx_PLUS (SImode, operands[1], operands[2])));
12927 DONE;")
12928
12929
12930 (define_insn "ldlo_l"
12931 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12932 (zero_extract:SI
12933 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
12934 (const_int -4)))
12935 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
12936 (and:SI (match_dup 1) (const_int 3))))]
12937 "TARGET_SHMEDIA32"
12938 "ldlo.l %U1, %0"
12939 [(set_attr "type" "load_media")])
12940
12941 (define_insn "ldlo_q"
12942 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12943 (zero_extract:DI
12944 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
12945 (const_int -8)))
12946 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
12947 (and:SI (match_dup 1) (const_int 7))))]
12948 "TARGET_SHMEDIA32"
12949 "ldlo.q %U1, %0"
12950 [(set_attr "type" "load_media")])
12951
12952 (define_insn_and_split "*ldlo_q_comb0"
12953 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12954 (zero_extract:DI
12955 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
12956 (match_operand:SI 2 "ua_offset" "I06"))
12957 (const_int -8)))
12958 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
12959 (and:SI (match_dup 1) (const_int 7))))]
12960 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
12961 "#"
12962 ""
12963 [(pc)]
12964 "emit_insn (gen_ldlo_q (operands[0],
12965 gen_rtx_PLUS (SImode, operands[1], operands[2])));
12966 DONE;")
12967
12968 (define_insn_and_split "*ldlo_q_comb1"
12969 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12970 (zero_extract:DI
12971 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
12972 (match_operand:SI 2 "ua_offset" "I06"))
12973 (const_int -8)))
12974 (minus:SI (const_int 8)
12975 (and:SI (plus:SI (match_dup 1)
12976 (match_operand:SI 3 "ua_offset" "I06"))
12977 (const_int 7)))
12978 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
12979 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
12980 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
12981 "#"
12982 ""
12983 [(pc)]
12984 "emit_insn (gen_ldlo_q (operands[0],
12985 gen_rtx_PLUS (SImode, operands[1], operands[2])));
12986 DONE;")
12987
12988 (define_insn "sthi_l"
12989 [(set (zero_extract:SI
12990 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
12991 (const_int 3))
12992 (const_int -3)))
12993 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
12994 (const_int 0))
12995 (match_operand:SI 1 "arith_reg_operand" "r"))]
12996 "TARGET_SHMEDIA32"
12997 "sthi.l %U0, %1"
12998 [(set_attr "type" "ustore_media")])
12999
13000 ;; All unaligned stores are considered to be 'narrow' because they typically
13001 ;; operate on less that a quadword, and when they operate on a full quadword,
13002 ;; the vanilla store high / store low sequence will cause a stall if not
13003 ;; scheduled apart.
13004 (define_insn "sthi_q"
13005 [(set (zero_extract:DI
13006 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
13007 (const_int 7))
13008 (const_int -7)))
13009 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
13010 (const_int 0))
13011 (match_operand:DI 1 "arith_reg_operand" "r"))]
13012 "TARGET_SHMEDIA32"
13013 "sthi.q %U0, %1"
13014 [(set_attr "type" "ustore_media")])
13015
13016 (define_insn_and_split "*sthi_q_comb0"
13017 [(set (zero_extract:DI
13018 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
13019 "register_operand" "r")
13020 (match_operand:SI 1 "ua_offset"
13021 "I06"))
13022 (const_int 7))
13023 (const_int -7)))
13024 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
13025 (const_int 0))
13026 (match_operand:DI 2 "arith_reg_operand" "r"))]
13027 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
13028 "#"
13029 ""
13030 [(pc)]
13031 "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13032 operands[2]));
13033 DONE;")
13034
13035 (define_insn_and_split "*sthi_q_comb1"
13036 [(set (zero_extract:DI
13037 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
13038 "register_operand" "r")
13039 (match_operand:SI 1 "ua_offset"
13040 "I06"))
13041 (const_int 7))
13042 (const_int -7)))
13043 (plus:SI (and:SI (plus:SI (match_dup 0)
13044 (match_operand:SI 2 "ua_offset" "I06"))
13045 (const_int 7))
13046 (const_int 1))
13047 (const_int 0))
13048 (match_operand:DI 3 "arith_reg_operand" "r"))]
13049 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
13050 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
13051 "#"
13052 ""
13053 [(pc)]
13054 "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13055 operands[3]));
13056 DONE;")
13057
13058 ;; This is highpart user because the address is used as full 64 bit.
13059 (define_insn "stlo_l"
13060 [(set (zero_extract:SI
13061 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
13062 (const_int -4)))
13063 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
13064 (and:SI (match_dup 0) (const_int 3)))
13065 (match_operand:SI 1 "arith_reg_operand" "r"))]
13066 "TARGET_SHMEDIA32"
13067 "stlo.l %U0, %1"
13068 [(set_attr "type" "ustore_media")])
13069
13070 (define_insn "stlo_q"
13071 [(set (zero_extract:DI
13072 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
13073 (const_int -8)))
13074 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
13075 (and:SI (match_dup 0) (const_int 7)))
13076 (match_operand:DI 1 "arith_reg_operand" "r"))]
13077 "TARGET_SHMEDIA32"
13078 "stlo.q %U0, %1"
13079 [(set_attr "type" "ustore_media")])
13080
13081 (define_insn_and_split "*stlo_q_comb0"
13082 [(set (zero_extract:DI
13083 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
13084 (match_operand:SI 1 "ua_offset" "I06"))
13085 (const_int -8)))
13086 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
13087 (and:SI (match_dup 0) (const_int 7)))
13088 (match_operand:DI 2 "arith_reg_operand" "r"))]
13089 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
13090 "#"
13091 ""
13092 [(pc)]
13093 "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13094 operands[2]));
13095 DONE;")
13096
13097 (define_insn_and_split "*stlo_q_comb1"
13098 [(set (zero_extract:DI
13099 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
13100 (match_operand:SI 1 "ua_offset" "I06"))
13101 (const_int -8)))
13102 (minus:SI (const_int 8) (and:SI (plus:SI (match_dup 0)
13103 (match_operand:SI 2
13104 "ua_offset" "I06"))
13105 (const_int 7)))
13106 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
13107 (match_operand:DI 3 "arith_reg_operand" "r"))]
13108 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
13109 "#"
13110 ""
13111 [(pc)]
13112 "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13113 operands[3]));
13114 DONE;")
13115
13116 (define_insn "ldhi_l64"
13117 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13118 (zero_extract:SI
13119 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13120 (const_int 3))
13121 (const_int -3)))
13122 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
13123 (const_int 0)))]
13124 "TARGET_SHMEDIA64"
13125 "ldhi.l %U1, %0"
13126 [(set_attr "type" "load_media")])
13127
13128 (define_insn "ldhi_q64"
13129 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13130 (zero_extract:DI
13131 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13132 (const_int 7))
13133 (const_int -7)))
13134 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
13135 (const_int 0)))]
13136 "TARGET_SHMEDIA64"
13137 "ldhi.q %U1, %0"
13138 [(set_attr "type" "load_media")])
13139
13140 (define_insn "ldlo_l64"
13141 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13142 (zero_extract:SI
13143 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13144 (const_int -4)))
13145 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
13146 (and:DI (match_dup 1) (const_int 3))))]
13147 "TARGET_SHMEDIA64"
13148 "ldlo.l %U1, %0"
13149 [(set_attr "type" "load_media")])
13150
13151 (define_insn "ldlo_q64"
13152 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13153 (zero_extract:DI
13154 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13155 (const_int -8)))
13156 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
13157 (and:DI (match_dup 1) (const_int 7))))]
13158 "TARGET_SHMEDIA64"
13159 "ldlo.q %U1, %0"
13160 [(set_attr "type" "load_media")])
13161
13162 (define_insn "sthi_l64"
13163 [(set (zero_extract:SI
13164 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13165 (const_int 3))
13166 (const_int -3)))
13167 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
13168 (const_int 0))
13169 (match_operand:SI 1 "arith_reg_operand" "r"))]
13170 "TARGET_SHMEDIA64"
13171 "sthi.l %U0, %1"
13172 [(set_attr "type" "ustore_media")])
13173
13174 (define_insn "sthi_q64"
13175 [(set (zero_extract:DI
13176 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13177 (const_int 7))
13178 (const_int -7)))
13179 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
13180 (const_int 0))
13181 (match_operand:DI 1 "arith_reg_operand" "r"))]
13182 "TARGET_SHMEDIA64"
13183 "sthi.q %U0, %1"
13184 [(set_attr "type" "ustore_media")])
13185
13186 (define_insn "stlo_l64"
13187 [(set (zero_extract:SI
13188 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13189 (const_int -4)))
13190 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
13191 (and:DI (match_dup 0) (const_int 3)))
13192 (match_operand:SI 1 "arith_reg_operand" "r"))]
13193 "TARGET_SHMEDIA64"
13194 "stlo.l %U0, %1"
13195 [(set_attr "type" "ustore_media")])
13196
13197 (define_insn "stlo_q64"
13198 [(set (zero_extract:DI
13199 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13200 (const_int -8)))
13201 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
13202 (and:DI (match_dup 0) (const_int 7)))
13203 (match_operand:DI 1 "arith_reg_operand" "r"))]
13204 "TARGET_SHMEDIA64"
13205 "stlo.q %U0, %1"
13206 [(set_attr "type" "ustore_media")])
13207
13208 (define_insn "nsb"
13209 [(set (match_operand:QI 0 "arith_reg_dest" "=r")
13210 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13211 UNSPEC_NSB))]
13212 "TARGET_SHMEDIA"
13213 "nsb %1, %0"
13214 [(set_attr "type" "arith_media")])
13215
13216 (define_insn "nsbsi"
13217 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13218 (zero_extend:SI
13219 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13220 UNSPEC_NSB)))]
13221 "TARGET_SHMEDIA"
13222 "nsb %1, %0"
13223 [(set_attr "type" "arith_media")])
13224
13225 (define_insn "nsbdi"
13226 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13227 (zero_extend:DI
13228 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13229 UNSPEC_NSB)))]
13230 "TARGET_SHMEDIA"
13231 "nsb %1, %0"
13232 [(set_attr "type" "arith_media")])
13233
13234 (define_expand "ffsdi2"
13235 [(set (match_operand:DI 0 "arith_reg_dest" "")
13236 (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
13237 "TARGET_SHMEDIA"
13238 "
13239 {
13240 rtx scratch = gen_reg_rtx (DImode);
13241 rtx last;
13242
13243 emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
13244 emit_insn (gen_xordi3 (scratch, operands[1], scratch));
13245 emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
13246 emit_insn (gen_nsbdi (scratch, scratch));
13247 emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
13248 emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
13249 last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
13250 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
13251
13252 DONE;
13253 }")
13254
13255 (define_expand "ffssi2"
13256 [(set (match_operand:SI 0 "arith_reg_dest" "")
13257 (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
13258 "TARGET_SHMEDIA"
13259 "
13260 {
13261 rtx scratch = gen_reg_rtx (SImode);
13262 rtx discratch = gen_reg_rtx (DImode);
13263 rtx last;
13264
13265 emit_insn (gen_adddi3 (discratch,
13266 simplify_gen_subreg (DImode, operands[1], SImode, 0),
13267 constm1_rtx));
13268 emit_insn (gen_andcdi3 (discratch,
13269 simplify_gen_subreg (DImode, operands[1], SImode, 0),
13270 discratch));
13271 emit_insn (gen_nsbsi (scratch, discratch));
13272 last = emit_insn (gen_subsi3 (operands[0],
13273 force_reg (SImode, GEN_INT (63)), scratch));
13274 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
13275
13276 DONE;
13277 }")
13278
13279 (define_insn "byterev"
13280 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13281 (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
13282 (parallel [(const_int 7) (const_int 6) (const_int 5)
13283 (const_int 4) (const_int 3) (const_int 2)
13284 (const_int 1) (const_int 0)])))]
13285 "TARGET_SHMEDIA"
13286 "byterev %1, %0"
13287 [(set_attr "type" "arith_media")])
13288
13289 (define_insn "*prefetch_media"
13290 [(prefetch (match_operand:QI 0 "address_operand" "p")
13291 (match_operand:SI 1 "const_int_operand" "n")
13292 (match_operand:SI 2 "const_int_operand" "n"))]
13293 "TARGET_SHMEDIA"
13294 "*
13295 {
13296 operands[0] = gen_rtx_MEM (QImode, operands[0]);
13297 output_asm_insn (\"ld%M0.b %m0,r63\", operands);
13298 return \"\";
13299 }"
13300 [(set_attr "type" "other")])
13301
13302 (define_insn "*prefetch_i4"
13303 [(prefetch (match_operand:SI 0 "register_operand" "r")
13304 (match_operand:SI 1 "const_int_operand" "n")
13305 (match_operand:SI 2 "const_int_operand" "n"))]
13306 "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && !TARGET_VXWORKS_RTP"
13307 "*
13308 {
13309 return \"pref @%0\";
13310 }"
13311 [(set_attr "type" "other")])
13312
13313 ;; In user mode, the "pref" instruction will raise a RADDERR exception
13314 ;; for accesses to [0x80000000,0xffffffff]. This makes it an unsuitable
13315 ;; implementation of __builtin_prefetch for VxWorks RTPs.
13316 (define_expand "prefetch"
13317 [(prefetch (match_operand 0 "address_operand" "p")
13318 (match_operand:SI 1 "const_int_operand" "n")
13319 (match_operand:SI 2 "const_int_operand" "n"))]
13320 "TARGET_SH2A || ((TARGET_HARD_SH4 || TARGET_SH5)
13321 && (TARGET_SHMEDIA || !TARGET_VXWORKS_RTP))"
13322 "
13323 {
13324 if (GET_MODE (operands[0]) != Pmode
13325 || !CONST_INT_P (operands[1])
13326 || !CONST_INT_P (operands[2]))
13327 FAIL;
13328 if (! TARGET_SHMEDIA)
13329 operands[0] = force_reg (Pmode, operands[0]);
13330 }")
13331
13332 (define_insn "prefetch_m2a"
13333 [(prefetch (match_operand:SI 0 "register_operand" "r")
13334 (match_operand:SI 1 "const_int_operand" "n")
13335 (match_operand:SI 2 "const_int_operand" "n"))]
13336 "TARGET_SH2A"
13337 "pref\\t@%0"
13338 [(set_attr "type" "other")])
13339
13340 (define_insn "alloco_i"
13341 [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
13342 (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
13343 "TARGET_SHMEDIA32"
13344 "*
13345 {
13346 rtx xops[2];
13347
13348 if (GET_CODE (operands[0]) == PLUS)
13349 {
13350 xops[0] = XEXP (operands[0], 0);
13351 xops[1] = XEXP (operands[0], 1);
13352 }
13353 else
13354 {
13355 xops[0] = operands[0];
13356 xops[1] = const0_rtx;
13357 }
13358 output_asm_insn (\"alloco %0, %1\", xops);
13359 return \"\";
13360 }"
13361 [(set_attr "type" "other")])
13362
13363 (define_split
13364 [(set (match_operand 0 "any_register_operand" "")
13365 (match_operand 1 "" ""))]
13366 "TARGET_SHMEDIA && reload_completed"
13367 [(set (match_dup 0) (match_dup 1))]
13368 "
13369 {
13370 int n_changes = 0;
13371
13372 for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
13373 if (!n_changes)
13374 FAIL;
13375 }")
13376
13377 ; Stack Protector Patterns
13378
13379 (define_expand "stack_protect_set"
13380 [(set (match_operand 0 "memory_operand" "")
13381 (match_operand 1 "memory_operand" ""))]
13382 ""
13383 {
13384 if (TARGET_SHMEDIA)
13385 {
13386 if (TARGET_SHMEDIA64)
13387 emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
13388 else
13389 emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
13390 }
13391 else
13392 emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
13393
13394 DONE;
13395 })
13396
13397 (define_insn "stack_protect_set_si"
13398 [(set (match_operand:SI 0 "memory_operand" "=m")
13399 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13400 (set (match_scratch:SI 2 "=&r") (const_int 0))]
13401 "!TARGET_SHMEDIA"
13402 "mov.l\t%1, %2\;mov.l\t%2, %0\;mov\t#0, %2"
13403 [(set_attr "type" "other")
13404 (set_attr "length" "6")])
13405
13406 (define_insn "stack_protect_set_si_media"
13407 [(set (match_operand:SI 0 "memory_operand" "=m")
13408 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13409 (set (match_scratch:SI 2 "=&r") (const_int 0))]
13410 "TARGET_SHMEDIA"
13411 "ld%M1.l\t%m1, %2\;st%M0.l\t%m0, %2\;movi\t0, %2"
13412 [(set_attr "type" "other")
13413 (set_attr "length" "12")])
13414
13415 (define_insn "stack_protect_set_di_media"
13416 [(set (match_operand:DI 0 "memory_operand" "=m")
13417 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13418 (set (match_scratch:DI 2 "=&r") (const_int 0))]
13419 "TARGET_SHMEDIA64"
13420 "ld%M1.q\t%m1, %2\;st%M0.q\t%m0, %2\;movi\t0, %2"
13421 [(set_attr "type" "other")
13422 (set_attr "length" "12")])
13423
13424 (define_expand "stack_protect_test"
13425 [(match_operand 0 "memory_operand" "")
13426 (match_operand 1 "memory_operand" "")
13427 (match_operand 2 "" "")]
13428 ""
13429 {
13430 if (TARGET_SHMEDIA)
13431 {
13432 rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
13433 rtx test;
13434
13435 test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
13436 if (TARGET_SHMEDIA64)
13437 {
13438 emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
13439 operands[1]));
13440 emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
13441 }
13442 else
13443 {
13444 emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
13445 operands[1]));
13446 emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
13447 }
13448 }
13449 else
13450 {
13451 emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
13452 emit_jump_insn (gen_branch_true (operands[2]));
13453 }
13454
13455 DONE;
13456 })
13457
13458 (define_insn "stack_protect_test_si"
13459 [(set (reg:SI T_REG)
13460 (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
13461 (match_operand:SI 1 "memory_operand" "m")]
13462 UNSPEC_SP_TEST))
13463 (set (match_scratch:SI 2 "=&r") (const_int 0))
13464 (set (match_scratch:SI 3 "=&r") (const_int 0))]
13465 "!TARGET_SHMEDIA"
13466 "mov.l\t%0, %2\;mov.l\t%1, %3\;cmp/eq\t%2, %3\;mov\t#0, %2\;mov\t#0, %3"
13467 [(set_attr "type" "other")
13468 (set_attr "length" "10")])
13469
13470 (define_insn "stack_protect_test_si_media"
13471 [(set (match_operand:SI 0 "register_operand" "=&r")
13472 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
13473 (match_operand:SI 2 "memory_operand" "m")]
13474 UNSPEC_SP_TEST))
13475 (set (match_scratch:SI 3 "=&r") (const_int 0))]
13476 "TARGET_SHMEDIA"
13477 "ld%M1.l\t%m1, %0\;ld%M2.l\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13478 [(set_attr "type" "other")
13479 (set_attr "length" "16")])
13480
13481 (define_insn "stack_protect_test_di_media"
13482 [(set (match_operand:DI 0 "register_operand" "=&r")
13483 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
13484 (match_operand:DI 2 "memory_operand" "m")]
13485 UNSPEC_SP_TEST))
13486 (set (match_scratch:DI 3 "=&r") (const_int 0))]
13487 "TARGET_SHMEDIA64"
13488 "ld%M1.q\t%m1, %0\;ld%M2.q\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13489 [(set_attr "type" "other")
13490 (set_attr "length" "16")])