PR target/50814.
[official-gcc.git] / gcc / config / sh / sh.md
blobb63c8572d740faf23b658dd6f09c240155ae9d6c
1 ;;- Machine description for Renesas / SuperH SH.
2 ;;  Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3 ;;  2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
4 ;;  Free Software Foundation, Inc.
5 ;;  Contributed by Steve Chamberlain (sac@cygnus.com).
6 ;;  Improved by Jim Wilson (wilson@cygnus.com).
8 ;; This file is part of GCC.
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.
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.
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/>.
25 ;; ??? Should prepend a * to all pattern names which are not used.
26 ;; This will make the compiler smaller, and rebuilds after changes faster.
28 ;; ??? Should be enhanced to include support for many more GNU superoptimizer
29 ;; sequences.  Especially the sequences for arithmetic right shifts.
31 ;; ??? Should check all DImode patterns for consistency and usefulness.
33 ;; ??? The MAC.W and MAC.L instructions are not supported.  There is no
34 ;; way to generate them.
36 ;; ??? The cmp/str instruction is not supported.  Perhaps it can be used
37 ;; for a str* inline function.
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
43 ;; Special constraints for SH machine description:
45 ;;    t -- T
46 ;;    x -- mac
47 ;;    l -- pr
48 ;;    z -- r0
50 ;; Special formats used for outputting SH instructions:
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
60 ;; Special predicates:
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
68 ;; -------------------------------------------------------------------------
69 ;; Constants
70 ;; -------------------------------------------------------------------------
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)
82   (FPSCR_REG    151)
84   (PIC_REG      12)
85   (FP_REG       14)
86   (SP_REG       15)
88   (PR_MEDIA_REG 18)
89   (T_MEDIA_REG  19)
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)
107   (DR0_REG      64)
108   (DR2_REG      66)
109   (DR4_REG      68)
110   (FR23_REG     87)
112   (TR0_REG      128)
113   (TR1_REG      129)
114   (TR2_REG      130)
116   (XD0_REG      136)
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)
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)
163   ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR.
164   (UNSPEC_SYMOFF        45)
166   ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
167   (UNSPEC_PCREL_SYMOFF  46)
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)
180 ;; -------------------------------------------------------------------------
181 ;; Attributes
182 ;; -------------------------------------------------------------------------
184 ;; Target CPU.
186 (define_attr "cpu"
187  "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
188   (const (symbol_ref "sh_cpu_attr")))
190 (define_attr "endian" "big,little"
191  (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
192                       (const_string "little") (const_string "big"))))
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"))))
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"))))
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.
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"))
287 ;; We define a new attribute namely "insn_class".We use
288 ;; this for the DFA based pipeline description.
290 ;; mt_group      SH4 "mt" group instructions.
292 ;; ex_group      SH4 "ex" group instructions.
294 ;; ls_group      SH4 "ls" group instructions.
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.
311 ;; Indicate what precision must be selected in fpscr for this insn, if any.
313 (define_attr "fp_mode" "single,double,none" (const_string "none"))
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"))
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.
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.
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.
346 ;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
347 ;; inside an le.
348 (define_attr "short_cbranch_p" "no,yes"
349   (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
350          (const_string "no")
351          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
352          (const_string "yes")
353          (match_test "NEXT_INSN (PREV_INSN (insn)) != insn")
354          (const_string "no")
355          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
356          (const_string "yes")
357          ] (const_string "no")))
359 (define_attr "med_branch_p" "no,yes"
360   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
361               (const_int 1988))
362          (const_string "yes")
363          (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
364          (const_string "no")
365          (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
366               (const_int 8186))
367          (const_string "yes")
368          ] (const_string "no")))
370 (define_attr "med_cbranch_p" "no,yes"
371   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
372               (const_int 1986))
373          (const_string "yes")
374          (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
375          (const_string "no")
376          (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
377                (const_int 8184))
378          (const_string "yes")
379          ] (const_string "no")))
381 (define_attr "braf_branch_p" "no,yes"
382   (cond [(match_test "! TARGET_SH2")
383          (const_string "no")
384          (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
385               (const_int 20660))
386          (const_string "yes")
387          (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
388          (const_string "no")
389          (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
390               (const_int 65530))
391          (const_string "yes")
392          ] (const_string "no")))
394 (define_attr "braf_cbranch_p" "no,yes"
395   (cond [(match_test "! TARGET_SH2")
396          (const_string "no")
397          (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
398               (const_int 20658))
399          (const_string "yes")
400          (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
401          (const_string "no")
402          (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
403               (const_int 65528))
404          (const_string "yes")
405          ] (const_string "no")))
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.
414 ; All other instructions are two bytes long by default.
416 ;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
417 ;; but getattrtab doesn't understand this.
418 (define_attr "length" ""
419   (cond [(eq_attr "type" "cbranch")
420          (cond [(eq_attr "short_cbranch_p" "yes")
421                 (const_int 2)
422                 (eq_attr "med_cbranch_p" "yes")
423                 (const_int 6)
424                 (eq_attr "braf_cbranch_p" "yes")
425                 (const_int 12)
426 ;; ??? using pc is not computed transitively.
427                 (ne (match_dup 0) (match_dup 0))
428                 (const_int 14)
429                 (match_test "flag_pic")
430                 (const_int 24)
431                 ] (const_int 16))
432          (eq_attr "type" "jump")
433          (cond [(eq_attr "med_branch_p" "yes")
434                 (const_int 2)
435                 (and (match_test "prev_nonnote_insn (insn)")
436                      (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")                              (symbol_ref "INSN"))
437                           (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")                             (symbol_ref "code_for_indirect_jump_scratch"))))
438                 (cond [(eq_attr "braf_branch_p" "yes")
439                        (const_int 6)
440                        (not (match_test "flag_pic"))
441                        (const_int 10)
442                        (match_test "TARGET_SH2")
443                        (const_int 10)] (const_int 18))
444                 (eq_attr "braf_branch_p" "yes")
445                 (const_int 10)
446 ;; ??? using pc is not computed transitively.
447                 (ne (match_dup 0) (match_dup 0))
448                 (const_int 12)
449                 (match_test "flag_pic")
450                 (const_int 22)
451                 ] (const_int 14))
452          (eq_attr "type" "pt_media")
453          (if_then_else (match_test "TARGET_SHMEDIA64")
454                        (const_int 20) (const_int 12))
455          (and (eq_attr "type" "jump_media")
456               (match_test "TARGET_SH5_CUT2_WORKAROUND"))
457          (const_int 8)
458          ] (if_then_else (match_test "TARGET_SHMEDIA")
459                          (const_int 4)
460                          (const_int 2))))
462 ;; DFA descriptions for the pipelines
464 (include "sh1.md")
465 (include "shmedia.md")
466 (include "sh4.md")
468 (include "predicates.md")
469 (include "constraints.md")
471 ;; Definitions for filling delay slots
473 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
475 (define_attr "banked" "yes,no" 
476         (cond [(match_test "sh_loads_bankedreg_p (insn)")
477                (const_string "yes")]
478               (const_string "no")))
480 ;; ??? This should be (nil) instead of (const_int 0)
481 (define_attr "hit_stack" "yes,no"
482         (cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)"))
483                (const_string "no")]
484               (const_string "yes")))
486 (define_attr "interrupt_function" "no,yes"
487   (const (symbol_ref "current_function_interrupt")))
489 (define_attr "in_delay_slot" "yes,no"
490   (cond [(eq_attr "type" "cbranch") (const_string "no")
491          (eq_attr "type" "pcload,pcload_si") (const_string "no")
492          (eq_attr "needs_delay_slot" "yes") (const_string "no")
493          (eq_attr "length" "2") (const_string "yes")
494          ] (const_string "no")))
496 (define_attr "cond_delay_slot" "yes,no"
497   (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
498          ] (const_string "no")))
500 (define_attr "is_sfunc" ""
501   (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
503 (define_attr "is_mac_media" ""
504   (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
506 (define_attr "branch_zero" "yes,no"
507   (cond [(eq_attr "type" "!cbranch") (const_string "no")
508          (ne (symbol_ref "(next_active_insn (insn)\
509                            == (prev_active_insn\
510                                (XEXP (SET_SRC (PATTERN (insn)), 1))))\
511                           && get_attr_length (next_active_insn (insn)) == 2")
512              (const_int 0))
513          (const_string "yes")]
514         (const_string "no")))
516 ;; SH4 Double-precision computation with double-precision result -
517 ;; the two halves are ready at different times.
518 (define_attr "dfp_comp" "yes,no"
519   (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
520         (const_string "no")))
522 ;; Insns for which the latency of a preceding fp insn is decreased by one.
523 (define_attr "late_fp_use" "yes,no" (const_string "no"))
524 ;; And feeding insns for which this relevant.
525 (define_attr "any_fp_comp" "yes,no"
526   (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
527          (const_string "yes")]
528         (const_string "no")))
530 (define_attr "any_int_load" "yes,no"
531   (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
532          (const_string "yes")]
533         (const_string "no")))
535 (define_attr "highpart" "user, ignore, extend, depend, must_split"
536   (const_string "user"))
538 (define_delay
539   (eq_attr "needs_delay_slot" "yes")
540   [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
542 ;; On the SH and SH2, the rte instruction reads the return pc from the stack,
543 ;; and thus we can't put a pop instruction in its delay slot.
544 ;; ??? On the SH3, the rte instruction does not use the stack, so a pop
545 ;; instruction can go in the delay slot.
547 ;; Since a normal return (rts) implicitly uses the PR register,
548 ;; we can't allow PR register loads in an rts delay slot.
550 (define_delay
551   (eq_attr "type" "return")
552   [(and (eq_attr "in_delay_slot" "yes")
553         (ior (and (eq_attr "interrupt_function" "no")
554                   (eq_attr "type" "!pload,prset"))
555              (and (eq_attr "interrupt_function" "yes")
556                   (ior
557                    (not (match_test "TARGET_SH3"))
558                    (eq_attr "hit_stack" "no")
559                    (eq_attr "banked" "no"))))) (nil) (nil)])
561 ;; Since a call implicitly uses the PR register, we can't allow
562 ;; a PR register store in a jsr delay slot.
564 (define_delay
565   (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
566   [(and (eq_attr "in_delay_slot" "yes")
567         (eq_attr "type" "!pstore,prget")) (nil) (nil)])
569 ;; Say that we have annulled true branches, since this gives smaller and
570 ;; faster code when branches are predicted as not taken.
572 ;; ??? The non-annulled condition should really be "in_delay_slot",
573 ;; but insns that can be filled in non-annulled get priority over insns
574 ;; that can only be filled in anulled.
576 (define_delay
577   (and (eq_attr "type" "cbranch")
578        (match_test "TARGET_SH2"))
579   ;; SH2e has a hardware bug that pretty much prohibits the use of
580   ;; annuled delay slots.
581   [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
582                                           (not (eq_attr "cpu" "sh2e"))) (nil)])
584 ;; -------------------------------------------------------------------------
585 ;; SImode signed integer comparisons
586 ;; -------------------------------------------------------------------------
588 ;; Various patterns to generate the TST #imm, R0 instruction.
589 ;; Although this adds some pressure on the R0 register, it can potentially
590 ;; result in faster code, even if the operand has to be moved to R0 first.
591 ;; This is because on SH4 TST #imm, R0 and MOV Rm, Rn are both MT group 
592 ;; instructions and thus will be executed in parallel.  On SH4A TST #imm, R0
593 ;; is an EX group instruction but still can be executed in parallel with the
594 ;; MT group MOV Rm, Rn instruction.
596 ;; Usual TST #imm, R0 patterns for SI, HI and QI
597 ;; This is usually used for bit patterns other than contiguous bits 
598 ;; and single bits.
600 (define_insn "tstsi_t"
601   [(set (reg:SI T_REG)
602         (eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r")
603                        (match_operand:SI 1 "logical_operand" "K08,r"))
604                (const_int 0)))]
605   "TARGET_SH1"
606   "tst  %1,%0"
607   [(set_attr "type" "mt_group")])
609 (define_insn "tsthi_t"
610   [(set (reg:SI T_REG)
611         (eq:SI (subreg:SI (and:HI (match_operand:HI 0 "logical_operand" "%z")
612                                   (match_operand 1 "const_int_operand")) 0)
613                (const_int 0)))]
614   "TARGET_SH1
615    && CONST_OK_FOR_K08 (INTVAL (operands[1]))"
616   "tst  %1,%0"
617   [(set_attr "type" "mt_group")])
619 (define_insn "tstqi_t"
620   [(set (reg:SI T_REG)
621         (eq:SI (subreg:SI (and:QI (match_operand:QI 0 "logical_operand" "%z")
622                                   (match_operand 1 "const_int_operand")) 0)
623                (const_int 0)))]
624   "TARGET_SH1
625    && (CONST_OK_FOR_K08 (INTVAL (operands[1])) 
626        || CONST_OK_FOR_I08 (INTVAL (operands[1])))"
628   operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
629   return "tst   %1,%0";
631   [(set_attr "type" "mt_group")])
633 ;; Test low QI subreg against zero.
634 ;; This avoids unecessary zero extension before the test.
636 (define_insn "tstqi_t_zero"
637   [(set (reg:SI T_REG)
638         (eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))]
639   "TARGET_SH1"
640   "tst  #255,%0"
641   [(set_attr "type" "mt_group")])
643 ;; Extract LSB, negate and store in T bit.
645 (define_insn "tstsi_t_and_not"
646   [(set (reg:SI T_REG)
647          (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z"))
648                  (const_int 1)))]
649   "TARGET_SH1"
650   "tst  #1,%0"
651   [(set_attr "type" "mt_group")])
653 ;; Extract contiguous bits and compare them against zero.
655 (define_insn "tstsi_t_zero_extract_eq"
656   [(set (reg:SI T_REG)
657         (eq:SI (zero_extract:SI (match_operand 0 "logical_operand" "z")
658                 (match_operand:SI 1 "const_int_operand")
659                 (match_operand:SI 2 "const_int_operand"))
660          (const_int 0)))]
661   "TARGET_SH1
662    && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))"
664   operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
665   return "tst   %1,%0";
667   [(set_attr "type" "mt_group")])
669 ;; This split is required when testing bits in a QI subreg.
671 (define_split
672   [(set (reg:SI T_REG)
673    (eq:SI (if_then_else:SI (zero_extract:SI
674                             (match_operand 0 "logical_operand" "")
675                             (match_operand 1 "const_int_operand")
676                             (match_operand 2 "const_int_operand"))
677                            (match_operand 3 "const_int_operand")
678                            (const_int 0))
679           (const_int 0)))]
680   "TARGET_SH1
681    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
682    && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
683   [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3))
684                               (const_int 0)))]
685   "
687   if (GET_MODE (operands[0]) == QImode)
688     operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
691 ;; Extract single bit, negate and store it in the T bit.
692 ;; Not used for SH4A.
694 (define_insn "tstsi_t_zero_extract_xor"
695   [(set (reg:SI T_REG)
696         (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
697                           (match_operand:SI 3 "const_int_operand"))
698                          (match_operand:SI 1 "const_int_operand")
699                          (match_operand:SI 2 "const_int_operand")))]
700   "TARGET_SH1
701    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
702    && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
703   "tst  %3,%0"
704   [(set_attr "type" "mt_group")])
706 ;; Extract single bit, negate and store it in the T bit.
707 ;; Used for SH4A little endian.
709 (define_insn "tstsi_t_zero_extract_subreg_xor_little"
710   [(set (reg:SI T_REG)
711         (zero_extract:SI
712          (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
713                             (match_operand:SI 3 "const_int_operand")) 0)
714          (match_operand:SI 1 "const_int_operand")
715          (match_operand:SI 2 "const_int_operand")))]
716   "TARGET_SH1 && TARGET_LITTLE_ENDIAN
717    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
718       == (INTVAL (operands[3]) & 255)
719    && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
721   operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
722   return "tst   %3,%0";
724   [(set_attr "type" "mt_group")])
726 ;; Extract single bit, negate and store it in the T bit.
727 ;; Used for SH4A big endian.
729 (define_insn "tstsi_t_zero_extract_subreg_xor_big"
730   [(set (reg:SI T_REG)
731         (zero_extract:SI
732          (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
733                             (match_operand:SI 3 "const_int_operand")) 3)
734          (match_operand:SI 1 "const_int_operand")
735          (match_operand:SI 2 "const_int_operand")))]
736   "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN
737    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
738       == (INTVAL (operands[3]) & 255)
739    && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
741   operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
742   return "tst   %3,%0";
744   [(set_attr "type" "mt_group")])
746 ;; ??? Perhaps should only accept reg/constant if the register is reg 0.
747 ;; That would still allow reload to create cmpi instructions, but would
748 ;; perhaps allow forcing the constant into a register when that is better.
749 ;; Probably should use r0 for mem/imm compares, but force constant into a
750 ;; register for pseudo/imm compares.
752 (define_insn "cmpeqsi_t"
753   [(set (reg:SI T_REG)
754         (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
755                (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
756   "TARGET_SH1"
757   "@
758         tst     %0,%0
759         cmp/eq  %1,%0
760         cmp/eq  %1,%0"
761    [(set_attr "type" "mt_group")])
763 (define_insn "cmpgtsi_t"
764   [(set (reg:SI T_REG)
765         (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
766                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
767   "TARGET_SH1"
768   "@
769         cmp/gt  %1,%0
770         cmp/pl  %0"
771    [(set_attr "type" "mt_group")])
773 (define_insn "cmpgesi_t"
774   [(set (reg:SI T_REG)
775         (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
776                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
777   "TARGET_SH1"
778   "@
779         cmp/ge  %1,%0
780         cmp/pz  %0"
781    [(set_attr "type" "mt_group")])
783 ;; -------------------------------------------------------------------------
784 ;; SImode compare and branch
785 ;; -------------------------------------------------------------------------
787 (define_expand "cbranchsi4"
788   [(set (pc)
789         (if_then_else (match_operator 0 "comparison_operator"
790                         [(match_operand:SI 1 "arith_operand" "")
791                          (match_operand:SI 2 "arith_operand" "")])
792                       (label_ref (match_operand 3 "" ""))
793                       (pc)))
794    (clobber (reg:SI T_REG))]
795   ""
796   "if (TARGET_SHMEDIA)
797       emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
798                                              operands[2], operands[3]));
799    else if (TARGET_CBRANCHDI4)
800      expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
801    else
802      sh_emit_compare_and_branch (operands, SImode);
803    DONE;")
805 ;; -------------------------------------------------------------------------
806 ;; SImode unsigned integer comparisons
807 ;; -------------------------------------------------------------------------
809 (define_insn_and_split "cmpgeusi_t"
810   [(set (reg:SI T_REG)
811         (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
812                 (match_operand:SI 1 "arith_reg_or_0_operand" "rN")))]
813   "TARGET_SH1"
814   "cmp/hs       %1,%0"
815   "&& operands[1] == CONST0_RTX (SImode)"
816   [(pc)]
817   "
819   emit_insn (gen_sett ());
820   DONE;
822    [(set_attr "type" "mt_group")])
824 (define_insn "cmpgtusi_t"
825   [(set (reg:SI T_REG)
826         (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
827                 (match_operand:SI 1 "arith_reg_operand" "r")))]
828   "TARGET_SH1"
829   "cmp/hi       %1,%0"
830    [(set_attr "type" "mt_group")])
833 ;; -------------------------------------------------------------------------
834 ;; DImode compare and branch
835 ;; -------------------------------------------------------------------------
838 ;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
839 ;; Therefore, we aim to have a set of three branches that go straight to the
840 ;; destination, i.e. only one of them is taken at any one time.
841 ;; This mechanism should also be slightly better for the sh4-200.
843 (define_expand "cbranchdi4"
844   [(set (pc)
845         (if_then_else (match_operator 0 "comparison_operator"
846                         [(match_operand:DI 1 "arith_operand" "")
847                          (match_operand:DI 2 "arith_operand" "")])
848                       (label_ref (match_operand 3 "" ""))
849                       (pc)))
850    (clobber (match_dup 4))
851    (clobber (reg:SI T_REG))]
852   "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
853   "
855   enum rtx_code comparison;
857   if (TARGET_SHMEDIA)
858     {
859       emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
860                                              operands[2], operands[3]));
861       DONE;
862     }
864   else if (!TARGET_CBRANCHDI4)
865     {
866       sh_emit_compare_and_branch (operands, DImode);
867       DONE;
868     }
870   else
871     {
872       if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
873         DONE;
875       comparison = prepare_cbranch_operands (operands, DImode,
876                                              LAST_AND_UNUSED_RTX_CODE);
877       if (comparison != GET_CODE (operands[0]))
878         operands[0]
879           = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
880        operands[4] = gen_rtx_SCRATCH (SImode);
881     }
884 (define_insn_and_split "cbranchdi4_i"
885   [(set (pc)
886         (if_then_else (match_operator 0 "comparison_operator"
887                         [(match_operand:DI 1 "arith_operand" "r,r")
888                          (match_operand:DI 2 "arith_operand" "rN,I08")])
889                       (label_ref (match_operand 3 "" ""))
890                       (pc)))
891    (clobber (match_scratch:SI 4 "=X,&r"))
892    (clobber (reg:SI T_REG))]
893   "TARGET_CBRANCHDI4"
894   "#"
895   "&& reload_completed"
896   [(pc)]
897   "
899   if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
900     FAIL;
901   DONE;
904 ;; -------------------------------------------------------------------------
905 ;; DImode signed integer comparisons
906 ;; -------------------------------------------------------------------------
908 (define_insn ""
909   [(set (reg:SI T_REG)
910         (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
911                        (match_operand:DI 1 "arith_operand" "r"))
912                (const_int 0)))]
913   "TARGET_SH1"
914   "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",
915                                  insn, operands);"
916   [(set_attr "length" "6")
917    (set_attr "type" "arith3b")])
919 (define_insn "cmpeqdi_t"
920   [(set (reg:SI T_REG)
921         (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
922                (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
923   "TARGET_SH1"
924   "@
925         tst     %S0,%S0\;bf     %,Ldi%=\;tst    %R0,%R0\\n%,Ldi%=:
926         cmp/eq  %S1,%S0\;bf     %,Ldi%=\;cmp/eq %R1,%R0\\n%,Ldi%=:"
927   [(set_attr "length" "6")
928    (set_attr "type" "arith3b")])
930 (define_split
931   [(set (reg:SI T_REG)
932         (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
933                (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
934 ;; If we applied this split when not optimizing, it would only be
935 ;; applied during the machine-dependent reorg, when no new basic blocks
936 ;; may be created.
937   "TARGET_SH1 && reload_completed && optimize"
938   [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
939    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
940                            (label_ref (match_dup 6))
941                            (pc)))
942    (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
943    (match_dup 6)]
944   "
946   operands[2]
947     = gen_rtx_REG (SImode,
948                    true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
949   operands[3]
950     = (operands[1] == const0_rtx
951        ? const0_rtx
952        : gen_rtx_REG (SImode,
953                       true_regnum (operands[1])
954                       + (TARGET_LITTLE_ENDIAN ? 1 : 0)));
955   operands[4] = gen_lowpart (SImode, operands[0]);
956   operands[5] = gen_lowpart (SImode, operands[1]);
957   operands[6] = gen_label_rtx ();
960 (define_insn "cmpgtdi_t"
961   [(set (reg:SI T_REG)
962         (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
963                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
964   "TARGET_SH2"
965   "@
966         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:
967         tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"
968   [(set_attr "length" "8")
969    (set_attr "type" "arith3")])
971 (define_insn "cmpgedi_t"
972   [(set (reg:SI T_REG)
973         (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
974                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
975   "TARGET_SH2"
976   "@
977         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:
978         cmp/pz\\t%S0"
979   [(set_attr "length" "8,2")
980    (set_attr "type" "arith3,mt_group")])
982 ;; -------------------------------------------------------------------------
983 ;; DImode unsigned integer comparisons
984 ;; -------------------------------------------------------------------------
986 (define_insn "cmpgeudi_t"
987   [(set (reg:SI T_REG)
988         (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
989                 (match_operand:DI 1 "arith_reg_operand" "r")))]
990   "TARGET_SH2"
991   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"
992   [(set_attr "length" "8")
993    (set_attr "type" "arith3")])
995 (define_insn "cmpgtudi_t"
996   [(set (reg:SI T_REG)
997         (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
998                 (match_operand:DI 1 "arith_reg_operand" "r")))]
999   "TARGET_SH2"
1000   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"
1001   [(set_attr "length" "8")
1002    (set_attr "type" "arith3")])
1004 (define_insn "cmpeqsi_media"
1005   [(set (match_operand:SI 0 "register_operand" "=r")
1006         (eq:SI (match_operand:SI 1 "logical_operand" "%r")
1007                (match_operand:SI 2 "cmp_operand" "Nr")))]
1008   "TARGET_SHMEDIA"
1009   "cmpeq        %1, %N2, %0"
1010   [(set_attr "type" "cmp_media")])
1012 (define_insn "cmpeqdi_media"
1013   [(set (match_operand:SI 0 "register_operand" "=r")
1014         (eq:SI (match_operand:DI 1 "register_operand" "%r")
1015                (match_operand:DI 2 "cmp_operand" "Nr")))]
1016   "TARGET_SHMEDIA"
1017   "cmpeq        %1, %N2, %0"
1018   [(set_attr "type" "cmp_media")])
1020 (define_insn "cmpgtsi_media"
1021   [(set (match_operand:SI 0 "register_operand" "=r")
1022         (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
1023                (match_operand:SI 2 "cmp_operand" "rN")))]
1024   "TARGET_SHMEDIA"
1025   "cmpgt        %N1, %N2, %0"
1026   [(set_attr "type" "cmp_media")])
1028 (define_insn "cmpgtdi_media"
1029   [(set (match_operand:SI 0 "register_operand" "=r")
1030         (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1031                (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1032   "TARGET_SHMEDIA"
1033   "cmpgt        %N1, %N2, %0"
1034   [(set_attr "type" "cmp_media")])
1036 (define_insn "cmpgtusi_media"
1037   [(set (match_operand:SI 0 "register_operand" "=r")
1038         (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
1039                 (match_operand:SI 2 "cmp_operand" "rN")))]
1040   "TARGET_SHMEDIA"
1041   "cmpgtu       %N1, %N2, %0"
1042   [(set_attr "type" "cmp_media")])
1044 (define_insn "cmpgtudi_media"
1045   [(set (match_operand:SI 0 "register_operand" "=r")
1046         (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1047                 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1048   "TARGET_SHMEDIA"
1049   "cmpgtu       %N1, %N2, %0"
1050   [(set_attr "type" "cmp_media")])
1052 ; These two patterns are for combine.
1053 (define_insn "*cmpne0sisi_media"
1054   [(set (match_operand:SI 0 "register_operand" "=r")
1055         (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
1056   "TARGET_SHMEDIA"
1057   "cmpgtu       %1,r63,%0"
1058   [(set_attr "type" "cmp_media")])
1060 ;; -------------------------------------------------------------------------
1061 ;; Conditional move instructions
1062 ;; -------------------------------------------------------------------------
1064 ;; The insn names may seem reversed, but note that cmveq performs the move
1065 ;; if op1 == 0, and cmvne does it if op1 != 0.
1067 (define_insn "movdicc_false"
1068   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1069         (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
1070                              (const_int 0))
1071          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1072          (match_operand:DI 3 "arith_reg_operand" "0")))]
1073   "TARGET_SHMEDIA"
1074   "cmveq        %1, %N2, %0"
1075   [(set_attr "type" "arith_media")])
1077 (define_insn "movdicc_true"
1078   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1079         (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
1080                              (const_int 0))
1081          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1082          (match_operand:DI 3 "arith_reg_operand" "0")))]
1083   "TARGET_SHMEDIA"
1084   "cmvne        %1, %N2, %0"
1085   [(set_attr "type" "arith_media")])
1087 (define_peephole2
1088   [(set (match_operand:DI 0 "arith_reg_dest" "")
1089         (if_then_else:DI (match_operator 3 "equality_comparison_operator"
1090                            [(match_operand:DI 1 "arith_reg_operand" "")
1091                             (const_int 0)])
1092          (match_operand:DI 2 "arith_reg_dest" "")
1093          (match_dup 0)))
1094    (set (match_dup 2) (match_dup 0))]
1095   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1096   [(set (match_dup 2)
1097         (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
1098   "
1100   operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1101                                 VOIDmode, operands[1], CONST0_RTX (DImode));
1104 (define_peephole2
1105   [(set (match_operand:DI 0 "general_movdst_operand" "")
1106         (match_operand:DI 1 "arith_reg_or_0_operand" ""))
1107    (set (match_operand:DI 2 "arith_reg_dest" "")
1108         (if_then_else:DI (match_operator 4 "equality_comparison_operator"
1109                            [(match_operand:DI 3 "arith_reg_operand" "")
1110                             (const_int 0)])
1111          (match_dup 0)
1112          (match_dup 2)))]
1113   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1114   [(set (match_dup 2)
1115         (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
1116   "")
1118 (define_expand "movdicc"
1119   [(set (match_operand:DI 0 "register_operand" "")
1120         (if_then_else:DI (match_operand 1 "comparison_operator" "")
1121                          (match_operand:DI 2 "register_operand" "")
1122                          (match_operand:DI 3 "register_operand" "")))]
1123   "TARGET_SHMEDIA"
1124   "
1126   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1127       && GET_MODE (XEXP (operands[1], 0)) == DImode
1128       && XEXP (operands[1], 1) == const0_rtx)
1129     ;
1130   else
1131     {
1132       if (!can_create_pseudo_p ())
1133         FAIL;
1135       operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1136                                               GET_CODE (operands[1]),
1137                                               XEXP (operands[1], 0),
1138                                               XEXP (operands[1], 1));
1139       if (!operands[1])
1140         FAIL;
1141     }
1144 ;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1145 ;; SImode to DImode.
1146 (define_insn "movsicc_false"
1147   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1148         (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1149                           (const_int 0))
1150          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1151          (match_operand:SI 3 "arith_reg_operand" "0")))]
1152   "TARGET_SHMEDIA"
1153   "cmveq        %1, %N2, %0"
1154   [(set_attr "type" "arith_media")])
1156 (define_insn "movsicc_true"
1157   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1158         (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1159                           (const_int 0))
1160          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1161          (match_operand:SI 3 "arith_reg_operand" "0")))]
1162   "TARGET_SHMEDIA"
1163   "cmvne        %1, %N2, %0"
1164   [(set_attr "type" "arith_media")])
1166 (define_peephole2
1167   [(set (match_operand:SI 0 "arith_reg_dest" "")
1168         (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1169                            [(match_operand:SI 1 "arith_reg_operand" "")
1170                             (const_int 0)])
1171          (match_operand:SI 2 "arith_reg_dest" "")
1172          (match_dup 0)))
1173    (set (match_dup 2) (match_dup 0))]
1174   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1175   [(set (match_dup 2)
1176         (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1177   "
1179   operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1180                                 VOIDmode, operands[1], CONST0_RTX (SImode));
1183 (define_peephole2
1184   [(set (match_operand:SI 0 "general_movdst_operand" "")
1185         (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1186    (set (match_operand:SI 2 "arith_reg_dest" "")
1187         (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1188                            [(match_operand:SI 3 "arith_reg_operand" "")
1189                             (const_int 0)])
1190          (match_dup 0)
1191          (match_dup 2)))]
1192   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1193    && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1194   [(set (match_dup 2)
1195         (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1196   "
1198   replace_rtx (operands[4], operands[0], operands[1]);
1201 (define_peephole2
1202   [(set (match_operand 0 "any_register_operand" "")
1203         (match_operand 1 "any_register_operand" ""))
1204    (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1205    (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1206   "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1207     <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1208    && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1209    && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1210    && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1211    && ! reg_overlap_mentioned_p (operands[0], operands[3])
1212    && ! reg_overlap_mentioned_p (operands[2], operands[0])
1213    && ! reg_overlap_mentioned_p (operands[0], operands[1])
1214    && (REGNO_REG_CLASS (REGNO (operands[0]))
1215        == REGNO_REG_CLASS (REGNO (operands[2])))
1216    && (REGNO_REG_CLASS (REGNO (operands[1]))
1217        == REGNO_REG_CLASS (REGNO (operands[0])))"
1218   [(set (match_dup 0) (match_dup 3))
1219    (set (match_dup 4) (match_dup 5))]
1220   "
1222   rtx set1, set2, insn2;
1223   rtx replacements[4];
1225   /* We want to replace occurrences of operands[0] with operands[1] and
1226      operands[2] with operands[0] in operands[4]/operands[5].
1227      Doing just two replace_rtx calls naively would result in the second
1228      replacement undoing all that the first did if operands[1] and operands[2]
1229      are identical, so we must do this simultaneously.  */
1230   replacements[0] = operands[0];
1231   replacements[1] = operands[1];
1232   replacements[2] = operands[2];
1233   replacements[3] = operands[0];
1234   if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1235       || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1236       || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1237     FAIL;
1239   operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1240   replace_n_hard_rtx (operands[4], replacements, 2, 1);
1241   operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1242   /* The operands array is aliased to recog_data.operand, which gets
1243      clobbered by extract_insn, so finish with it now.  */
1244   set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1245   set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1246   /* ??? The last insn might be a jump insn, but the generic peephole2 code
1247      always uses emit_insn.  */
1248   /* Check that we don't violate matching constraints or earlyclobbers.  */
1249   extract_insn (emit_insn (set1));
1250   if (! constrain_operands (1))
1251     goto failure;
1252   insn2 = emit (set2);
1253   if (GET_CODE (insn2) == BARRIER)
1254     goto failure;
1255   extract_insn (insn2);
1256   if (! constrain_operands (1))
1257     {
1258       rtx tmp;
1259     failure:
1260       tmp = replacements[0];
1261       replacements[0] = replacements[1];
1262       replacements[1] = tmp;
1263       tmp = replacements[2];
1264       replacements[2] = replacements[3];
1265       replacements[3] = tmp;
1266       replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1267       replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1268       replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1269       FAIL;
1270     }
1271   DONE;
1274 ;; The register allocator is rather clumsy in handling multi-way conditional
1275 ;; moves, so allow the combiner to make them, and we split them up after
1276 ;; reload.  */
1277 (define_insn_and_split "*movsicc_umin"
1278   [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1279         (umin:SI (if_then_else:SI
1280                    (eq (match_operand:SI 1 "arith_reg_operand" "r")
1281                        (const_int 0))
1282                    (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1283                    (match_operand:SI 3 "register_operand" "0"))
1284                  (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1285    (clobber (match_scratch:SI 5 "=&r"))]
1286   "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1287   "#"
1288   "TARGET_SHMEDIA && reload_completed"
1289   [(pc)]
1290   "
1292   emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1293                                 operands[3]));
1294   emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1295   emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1296                                 operands[0]));
1297   DONE;
1300 (define_insn "*movsicc_t_false"
1301   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1302         (if_then_else (eq (reg:SI T_REG) (const_int 0))
1303                       (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1304                       (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1305   "TARGET_PRETEND_CMOVE
1306    && (arith_reg_operand (operands[1], SImode)
1307        || (immediate_operand (operands[1], SImode)
1308            && satisfies_constraint_I08 (operands[1])))"
1309   "bt   0f\;mov %1,%0\\n0:"
1310   [(set_attr "type" "mt_group,arith") ;; poor approximation
1311    (set_attr "length" "4")])
1313 (define_insn "*movsicc_t_true"
1314   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1315         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1316                       (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1317                       (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1318   "TARGET_PRETEND_CMOVE
1319    && (arith_reg_operand (operands[1], SImode)
1320        || (immediate_operand (operands[1], SImode)
1321            && satisfies_constraint_I08 (operands[1])))"
1322   "bf   0f\;mov %1,%0\\n0:"
1323   [(set_attr "type" "mt_group,arith") ;; poor approximation
1324    (set_attr "length" "4")])
1326 (define_expand "movsicc"
1327   [(set (match_operand:SI 0 "arith_reg_dest" "")
1328         (if_then_else:SI (match_operand 1 "comparison_operator" "")
1329                          (match_operand:SI 2 "arith_reg_or_0_operand" "")
1330                          (match_operand:SI 3 "arith_reg_operand" "")))]
1331   "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1332   "
1334   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1335       && GET_MODE (XEXP (operands[1], 0)) == SImode
1336       && (TARGET_SHMEDIA
1337           || (REG_P (XEXP (operands[1], 0))
1338               && REGNO (XEXP (operands[1], 0)) == T_REG))
1339       && XEXP (operands[1], 1) == const0_rtx)
1340     ;
1342   else if (TARGET_PRETEND_CMOVE)
1343     {
1344       enum rtx_code code = GET_CODE (operands[1]);
1345       enum rtx_code new_code = code;
1346       rtx op0 = XEXP (operands[1], 0);
1347       rtx op1 = XEXP (operands[1], 1);
1349       if (! currently_expanding_to_rtl)
1350         FAIL;
1351       switch (code)
1352         {
1353         case LT: case LE: case LEU: case LTU:
1354           if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1355             break;
1356         case NE:
1357           new_code = reverse_condition (code);
1358           break;
1359         case EQ: case GT: case GE: case GEU: case GTU:
1360           break;
1361         default:
1362           FAIL;
1363         }
1364       sh_emit_scc_to_t (new_code, op0, op1);
1365       operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1366                                     gen_rtx_REG (SImode, T_REG), const0_rtx);
1367     }
1368   else
1369     {
1370       if (!can_create_pseudo_p ())
1371         FAIL;
1373       operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1374                                               GET_CODE (operands[1]),
1375                                               XEXP (operands[1], 0),
1376                                               XEXP (operands[1], 1));
1377       if (!operands[1])
1378         FAIL;
1379     }
1382 (define_expand "movqicc"
1383   [(set (match_operand:QI 0 "register_operand" "")
1384         (if_then_else:QI (match_operand 1 "comparison_operator" "")
1385                          (match_operand:QI 2 "register_operand" "")
1386                          (match_operand:QI 3 "register_operand" "")))]
1387   "TARGET_SHMEDIA"
1388   "
1390   operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1391   operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1392   operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1393   emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1394   DONE;
1397 ;; -------------------------------------------------------------------------
1398 ;; Addition instructions
1399 ;; -------------------------------------------------------------------------
1401 (define_expand "adddi3"
1402   [(set (match_operand:DI 0 "arith_reg_operand" "")
1403         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1404                  (match_operand:DI 2 "arith_operand" "")))]
1405   ""
1406   "
1408   if (TARGET_SH1)
1409     {
1410       if (!can_create_pseudo_p () && ! arith_reg_operand (operands[2], DImode))
1411         FAIL;
1412       operands[2] = force_reg (DImode, operands[2]);
1413       emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1414       DONE;
1415     }
1418 (define_insn "*adddi3_media"
1419   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1420         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1421                  (match_operand:DI 2 "arith_operand" "r,I10")))]
1422   "TARGET_SHMEDIA"
1423   "@
1424         add     %1, %2, %0
1425         addi    %1, %2, %0"
1426   [(set_attr "type" "arith_media")])
1428 (define_insn "*adddisi3_media"
1429   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1430         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1431                  (match_operand:DI 2 "arith_operand" "r,I10")))]
1432   "TARGET_SHMEDIA"
1433   "@
1434         add.l   %1, %2, %0
1435         addi.l  %1, %2, %0"
1436   [(set_attr "type" "arith_media")
1437    (set_attr "highpart" "ignore")])
1439 (define_insn "adddi3z_media"
1440   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1441         (zero_extend:DI
1442          (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1443                   (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1444   "TARGET_SHMEDIA"
1445   "addz.l       %1, %N2, %0"
1446   [(set_attr "type" "arith_media")
1447    (set_attr "highpart" "ignore")])
1449 (define_insn "adddi3_compact"
1450   [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1451         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1452                  (match_operand:DI 2 "arith_reg_operand" "r")))
1453    (clobber (reg:SI T_REG))]
1454   "TARGET_SH1"
1455   "#"
1456   [(set_attr "length" "6")])
1458 (define_split
1459   [(set (match_operand:DI 0 "arith_reg_dest" "")
1460         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1461                  (match_operand:DI 2 "arith_reg_operand" "")))
1462    (clobber (reg:SI T_REG))]
1463   "TARGET_SH1 && reload_completed"
1464   [(const_int 0)]
1465   "
1467   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1468   high0 = gen_rtx_REG (SImode,
1469                        true_regnum (operands[0])
1470                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1471   high2 = gen_rtx_REG (SImode,
1472                        true_regnum (operands[2])
1473                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1474   emit_insn (gen_clrt ());
1475   emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
1476   emit_insn (gen_addc1 (high0, high0, high2));
1477   DONE;
1480 (define_insn "addc"
1481   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1482         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1483                           (match_operand:SI 2 "arith_reg_operand" "r"))
1484                  (reg:SI T_REG)))
1485    (set (reg:SI T_REG)
1486         (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1487   "TARGET_SH1"
1488   "addc %2,%0"
1489   [(set_attr "type" "arith")])
1491 (define_insn "addc1"
1492   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1493         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1494                           (match_operand:SI 2 "arith_reg_operand" "r"))
1495                  (reg:SI T_REG)))
1496    (clobber (reg:SI T_REG))]
1497   "TARGET_SH1"
1498   "addc %2,%0"
1499   [(set_attr "type" "arith")])
1501 (define_expand "addsi3"
1502   [(set (match_operand:SI 0 "arith_reg_operand" "")
1503         (plus:SI (match_operand:SI 1 "arith_operand" "")
1504                  (match_operand:SI 2 "arith_operand" "")))]
1505   ""
1506   "
1508   if (TARGET_SHMEDIA)
1509     operands[1] = force_reg (SImode, operands[1]);
1512 (define_insn "addsi3_media"
1513   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1514         (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1515                  (match_operand:SI 2 "arith_operand" "r,I10")))]
1516   "TARGET_SHMEDIA"
1517   "@
1518         add.l   %1, %2, %0
1519         addi.l  %1, %2, %0"
1520   [(set_attr "type" "arith_media")
1521    (set_attr "highpart" "ignore")])
1523 (define_insn "addsidi3_media"
1524   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1525         (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
1526                                   "%r,r")
1527                                  (match_operand:SI 2 "arith_operand"
1528                                   "r,I10"))))]
1529   "TARGET_SHMEDIA"
1530   "@
1531         add.l   %1, %2, %0
1532         addi.l  %1, %2, %0"
1533   [(set_attr "type" "arith_media")
1534    (set_attr "highpart" "ignore")])
1536 (define_insn "*addsi3_compact"
1537   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1538         (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1539                  (match_operand:SI 2 "arith_operand" "rI08")))]
1540   "TARGET_SH1"
1541   "add  %2,%0"
1542   [(set_attr "type" "arith")])
1544 ;; -------------------------------------------------------------------------
1545 ;; Subtraction instructions
1546 ;; -------------------------------------------------------------------------
1548 (define_expand "subdi3"
1549   [(set (match_operand:DI 0 "arith_reg_operand" "")
1550         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1551                   (match_operand:DI 2 "arith_reg_operand" "")))]
1552   ""
1553   "
1555   if (TARGET_SH1)
1556     {
1557       operands[1] = force_reg (DImode, operands[1]);
1558       emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1559       DONE;
1560     }
1563 (define_insn "*subdi3_media"
1564   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1565         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1566                   (match_operand:DI 2 "arith_reg_operand" "r")))]
1567   "TARGET_SHMEDIA"
1568   "sub  %N1, %2, %0"
1569   [(set_attr "type" "arith_media")])
1570   
1571 (define_insn "subdisi3_media"
1572   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
1573         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1574                   (match_operand:DI 2 "arith_reg_operand" "r")))]
1575   "TARGET_SHMEDIA"
1576   "sub.l        %N1, %2, %0"
1577   [(set_attr "type" "arith_media")
1578    (set_attr "highpart" "ignore")])
1580 (define_insn "subdi3_compact"
1581   [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1582         (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1583                  (match_operand:DI 2 "arith_reg_operand" "r")))
1584    (clobber (reg:SI T_REG))]
1585   "TARGET_SH1"
1586   "#"
1587   [(set_attr "length" "6")])
1589 (define_split
1590   [(set (match_operand:DI 0 "arith_reg_dest" "")
1591         (minus:DI (match_operand:DI 1 "arith_reg_operand" "")
1592                   (match_operand:DI 2 "arith_reg_operand" "")))
1593    (clobber (reg:SI T_REG))]
1594   "TARGET_SH1 && reload_completed"
1595   [(const_int 0)]
1596   "
1598   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1599   high0 = gen_rtx_REG (SImode,
1600                        true_regnum (operands[0])
1601                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1602   high2 = gen_rtx_REG (SImode,
1603                        true_regnum (operands[2])
1604                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1605   emit_insn (gen_clrt ());
1606   emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1607   emit_insn (gen_subc1 (high0, high0, high2));
1608   DONE;
1611 (define_insn "subc"
1612   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1613         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1614                             (match_operand:SI 2 "arith_reg_operand" "r"))
1615                   (reg:SI T_REG)))
1616    (set (reg:SI T_REG)
1617         (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1618                           (reg:SI T_REG))
1619                 (match_dup 1)))]
1620   "TARGET_SH1"
1621   "subc %2,%0"
1622   [(set_attr "type" "arith")])
1624 (define_insn "subc1"
1625   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1626         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1627                             (match_operand:SI 2 "arith_reg_operand" "r"))
1628                   (reg:SI T_REG)))
1629    (clobber (reg:SI T_REG))]
1630   "TARGET_SH1"
1631   "subc %2,%0"
1632   [(set_attr "type" "arith")])
1634 ;; life_analysis thinks rn is live before subc rn,rn, so make a special
1635 ;; pattern for this case.  This helps multimedia applications that compute
1636 ;; the sum of absolute differences.
1637 (define_insn "mov_neg_si_t"
1638   [(set (match_operand:SI 0 "arith_reg_dest" "=r") (neg:SI (reg:SI T_REG)))]
1639   "TARGET_SH1"
1640   "subc %0,%0"
1641   [(set_attr "type" "arith")])
1643 (define_insn "*subsi3_internal"
1644   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1645         (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1646                   (match_operand:SI 2 "arith_reg_operand" "r")))]
1647   "TARGET_SH1"
1648   "sub  %2,%0"
1649   [(set_attr "type" "arith")])
1651 (define_insn_and_split "*subsi3_media"
1652   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1653         (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
1654                   (match_operand:SI 2 "extend_reg_operand" "r")))]
1655   "TARGET_SHMEDIA
1656    && (operands[1] != constm1_rtx
1657        || (GET_CODE (operands[2]) != TRUNCATE
1658            && GET_CODE (operands[2]) != SUBREG))"
1659   "sub.l        %N1, %2, %0"
1660   "operands[1] == constm1_rtx"
1661   [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
1662   ""
1663   [(set_attr "type" "arith_media")
1664    (set_attr "highpart" "ignore")])
1666 (define_split
1667   [(set (match_operand:SI 0 "arith_reg_dest" "")
1668         (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1669                                                        "general_extend_operand"
1670                                                        "") 0)) 0)))]
1671   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
1672   [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1673    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1674   "")
1676 (define_split
1677   [(set (match_operand:SI 0 "arith_reg_dest" "")
1678         (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1679                                                        "general_extend_operand"
1680                                                        "") 0)) 3)))]
1681   "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
1682   [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1683    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1684   "")
1685 ;; Convert `constant - reg' to `neg rX; add rX, #const' since this
1686 ;; will sometimes save one instruction.  Otherwise we might get
1687 ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
1688 ;; are the same.
1690 (define_expand "subsi3"
1691   [(set (match_operand:SI 0 "arith_reg_operand" "")
1692         (minus:SI (match_operand:SI 1 "arith_operand" "")
1693                   (match_operand:SI 2 "arith_reg_operand" "")))]
1694   ""
1695   "
1697   if (TARGET_SH1 && CONST_INT_P (operands[1]))
1698     {
1699       emit_insn (gen_negsi2 (operands[0], operands[2]));
1700       emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
1701       DONE;
1702     }
1703   if (TARGET_SHMEDIA)
1704     {
1705       if (!can_create_pseudo_p ()
1706           && ! arith_reg_or_0_operand (operands[1], SImode))
1707         FAIL;
1708       if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
1709         operands[1] = force_reg (SImode, operands[1]);
1710     }
1713 ;; -------------------------------------------------------------------------
1714 ;; Division instructions
1715 ;; -------------------------------------------------------------------------
1717 ;; We take advantage of the library routines which don't clobber as many
1718 ;; registers as a normal function call would.
1720 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
1721 ;; also has an effect on the register that holds the address of the sfunc.
1722 ;; To make this work, we have an extra dummy insn that shows the use
1723 ;; of this register for reorg.
1725 (define_insn "use_sfunc_addr"
1726   [(set (reg:SI PR_REG)
1727         (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
1728   "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
1729   ""
1730   [(set_attr "length" "0")])
1732 (define_insn "udivsi3_sh2a"
1733   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1734         (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
1735                 (match_operand:SI 2 "arith_reg_operand" "z")))]
1736   "TARGET_SH2A"
1737   "divu %2,%1"
1738   [(set_attr "type" "arith")
1739    (set_attr "in_delay_slot" "no")])
1741 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
1742 ;; hard register 0.  If we used hard register 0, then the next instruction
1743 ;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
1744 ;; gets allocated to a stack slot that needs its address reloaded, then
1745 ;; there is nothing to prevent reload from using r0 to reload the address.
1746 ;; This reload would clobber the value in r0 we are trying to store.
1747 ;; If we let reload allocate r0, then this problem can never happen.
1749 (define_insn "udivsi3_i1"
1750   [(set (match_operand:SI 0 "register_operand" "=z")
1751         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1752    (clobber (reg:SI T_REG))
1753    (clobber (reg:SI PR_REG))
1754    (clobber (reg:SI R4_REG))
1755    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1756   "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
1757   "jsr  @%1%#"
1758   [(set_attr "type" "sfunc")
1759    (set_attr "needs_delay_slot" "yes")])
1761 ; Since shmedia-nofpu code could be linked against shcompact code, and
1762 ; the udivsi3 libcall has the same name, we must consider all registers
1763 ; clobbered that are in the union of the registers clobbered by the
1764 ; shmedia and the shcompact implementation.  Note, if the shcompact
1765 ; implementation actually used shcompact code, we'd need to clobber
1766 ; also r23 and fr23.
1767 (define_insn "udivsi3_i1_media"
1768   [(set (match_operand:SI 0 "register_operand" "=z")
1769         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1770    (clobber (reg:SI T_MEDIA_REG))
1771    (clobber (reg:SI PR_MEDIA_REG))
1772    (clobber (reg:SI R20_REG))
1773    (clobber (reg:SI R21_REG))
1774    (clobber (reg:SI R22_REG))
1775    (clobber (reg:DI TR0_REG))
1776    (clobber (reg:DI TR1_REG))
1777    (clobber (reg:DI TR2_REG))
1778    (use (match_operand 1 "target_reg_operand" "b"))]
1779   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1780   "blink        %1, r18"
1781   [(set_attr "type" "sfunc")
1782    (set_attr "needs_delay_slot" "yes")])
1784 (define_expand "udivsi3_i4_media"
1785   [(set (match_dup 3)
1786         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
1787    (set (match_dup 4)
1788         (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1789    (set (match_dup 5) (float:DF (match_dup 3)))
1790    (set (match_dup 6) (float:DF (match_dup 4)))
1791    (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
1792    (set (match_dup 8) (fix:DI (match_dup 7)))
1793    (set (match_operand:SI 0 "register_operand" "")
1794         (truncate:SI (match_dup 8)))]
1795   "TARGET_SHMEDIA_FPU"
1796   "
1798   operands[3] = gen_reg_rtx (DImode);
1799   operands[4] = gen_reg_rtx (DImode);
1800   operands[5] = gen_reg_rtx (DFmode);
1801   operands[6] = gen_reg_rtx (DFmode);
1802   operands[7] = gen_reg_rtx (DFmode);
1803   operands[8] = gen_reg_rtx (DImode);
1806 (define_insn "udivsi3_i4"
1807   [(set (match_operand:SI 0 "register_operand" "=y")
1808         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1809    (clobber (reg:SI T_REG))
1810    (clobber (reg:SI PR_REG))
1811    (clobber (reg:DF DR0_REG))
1812    (clobber (reg:DF DR2_REG))
1813    (clobber (reg:DF DR4_REG))
1814    (clobber (reg:SI R0_REG))
1815    (clobber (reg:SI R1_REG))
1816    (clobber (reg:SI R4_REG))
1817    (clobber (reg:SI R5_REG))
1818    (use (reg:PSI FPSCR_REG))
1819    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1820   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1821   "jsr  @%1%#"
1822   [(set_attr "type" "sfunc")
1823    (set_attr "fp_mode" "double")
1824    (set_attr "needs_delay_slot" "yes")])
1826 (define_insn "udivsi3_i4_single"
1827   [(set (match_operand:SI 0 "register_operand" "=y")
1828         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1829    (clobber (reg:SI T_REG))
1830    (clobber (reg:SI PR_REG))
1831    (clobber (reg:DF DR0_REG))
1832    (clobber (reg:DF DR2_REG))
1833    (clobber (reg:DF DR4_REG))
1834    (clobber (reg:SI R0_REG))
1835    (clobber (reg:SI R1_REG))
1836    (clobber (reg:SI R4_REG))
1837    (clobber (reg:SI R5_REG))
1838    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1839   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1840   "jsr  @%1%#"
1841   [(set_attr "type" "sfunc")
1842    (set_attr "needs_delay_slot" "yes")])
1844 (define_insn "udivsi3_i4_int"
1845   [(set (match_operand:SI 0 "register_operand" "=z")
1846         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1847    (clobber (reg:SI T_REG))
1848    (clobber (reg:SI R1_REG))
1849    (clobber (reg:SI PR_REG))
1850    (clobber (reg:SI MACH_REG))
1851    (clobber (reg:SI MACL_REG))
1852    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1853   "TARGET_SH1"
1854   "jsr  @%1%#"
1855   [(set_attr "type" "sfunc")
1856    (set_attr "needs_delay_slot" "yes")])
1859 (define_expand "udivsi3"
1860   [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
1861    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1862    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1863    (parallel [(set (match_operand:SI 0 "register_operand" "")
1864                    (udiv:SI (reg:SI R4_REG)
1865                             (reg:SI R5_REG)))
1866               (clobber (reg:SI T_REG))
1867               (clobber (reg:SI PR_REG))
1868               (clobber (reg:SI R4_REG))
1869               (use (match_dup 3))])]
1870   ""
1871   "
1873   rtx last;
1875   operands[3] = gen_reg_rtx (Pmode);
1876   /* Emit the move of the address to a pseudo outside of the libcall.  */
1877   if (TARGET_DIVIDE_CALL_TABLE)
1878     {
1879       /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
1880          that causes problems when the divide code is supposed to come from a
1881          separate library.  Division by zero is undefined, so dividing 1 can be
1882          implemented by comparing with the divisor.  */
1883       if (operands[1] == const1_rtx && currently_expanding_to_rtl)
1884         {
1885           rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
1886           emit_insn (gen_cstoresi4 (operands[0], test,
1887                                     operands[1], operands[2]));
1888           DONE;
1889         }
1890       else if (operands[2] == const0_rtx)
1891         {
1892           emit_move_insn (operands[0], operands[2]);
1893           DONE;
1894         }
1895       function_symbol (operands[3], \"__udivsi3_i4i\", SFUNC_GOT);
1896       last = gen_udivsi3_i4_int (operands[0], operands[3]);
1897     }
1898   else if (TARGET_DIVIDE_CALL_FP)
1899     {
1900       function_symbol (operands[3], \"__udivsi3_i4\", SFUNC_STATIC);
1901       if (TARGET_FPU_SINGLE)
1902         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1903       else
1904         last = gen_udivsi3_i4 (operands[0], operands[3]);
1905     }
1906   else if (TARGET_SHMEDIA_FPU)
1907     {
1908       operands[1] = force_reg (SImode, operands[1]);
1909       operands[2] = force_reg (SImode, operands[2]);
1910       emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
1911       DONE;
1912     }
1913   else if (TARGET_SH2A)
1914     {
1915       operands[1] = force_reg (SImode, operands[1]);
1916       operands[2] = force_reg (SImode, operands[2]);
1917       emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
1918       DONE;
1919     }
1920   else if (TARGET_SH5)
1921     {
1922       function_symbol (operands[3],
1923                        TARGET_FPU_ANY ? \"__udivsi3_i4\" : \"__udivsi3\",
1924                        SFUNC_STATIC);
1926       if (TARGET_SHMEDIA)
1927         last = gen_udivsi3_i1_media (operands[0], operands[3]);
1928       else if (TARGET_FPU_ANY)
1929         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1930       else
1931         last = gen_udivsi3_i1 (operands[0], operands[3]);
1932     }
1933   else
1934     {
1935       function_symbol (operands[3], \"__udivsi3\", SFUNC_STATIC);
1936       last = gen_udivsi3_i1 (operands[0], operands[3]);
1937     }
1938   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1939   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1940   emit_insn (last);
1941   DONE;
1944 (define_insn "divsi3_sh2a"
1945   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1946         (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
1947                 (match_operand:SI 2 "arith_reg_operand" "z")))]
1948   "TARGET_SH2A"
1949   "divs %2,%1"
1950   [(set_attr "type" "arith")
1951    (set_attr "in_delay_slot" "no")])
1953 (define_insn "divsi3_i1"
1954   [(set (match_operand:SI 0 "register_operand" "=z")
1955         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1956    (clobber (reg:SI T_REG))
1957    (clobber (reg:SI PR_REG))
1958    (clobber (reg:SI R1_REG))
1959    (clobber (reg:SI R2_REG))
1960    (clobber (reg:SI R3_REG))
1961    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1962   "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
1963   "jsr  @%1%#"
1964   [(set_attr "type" "sfunc")
1965    (set_attr "needs_delay_slot" "yes")])
1967 (define_insn "divsi3_i1_media"
1968   [(set (match_operand:SI 0 "register_operand" "=z")
1969         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1970    (clobber (reg:SI T_MEDIA_REG))
1971    (clobber (reg:SI PR_MEDIA_REG))
1972    (clobber (reg:SI R1_REG))
1973    (clobber (reg:SI R20_REG))
1974    (clobber (reg:SI R21_REG))
1975    (clobber (reg:SI TR0_REG))
1976    (use (match_operand 1 "target_reg_operand" "b"))]
1977   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1978   "blink        %1, r18"
1979   [(set_attr "type" "sfunc")])
1981 (define_insn "divsi3_media_2"
1982   [(set (match_operand:SI 0 "register_operand" "=z")
1983         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1984    (clobber (reg:SI T_MEDIA_REG))
1985    (clobber (reg:SI PR_MEDIA_REG))
1986    (clobber (reg:SI R1_REG))
1987    (clobber (reg:SI R21_REG))
1988    (clobber (reg:SI TR0_REG))
1989    (use (reg:SI R20_REG))
1990    (use (match_operand 1 "target_reg_operand" "b"))]
1991   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1992   "blink        %1, r18"
1993   [(set_attr "type" "sfunc")])
1995 ;; This pattern acts as a placeholder for -mdiv=inv:call to carry
1996 ;; hard reg clobbers and data dependencies that we need when we want
1997 ;; to rematerialize the division into a call.
1998 (define_insn_and_split "divsi_inv_call"
1999   [(set (match_operand:SI 0 "register_operand" "=r")
2000         (div:SI (match_operand:SI 1 "register_operand" "r")
2001                 (match_operand:SI 2 "register_operand" "r")))
2002    (clobber (reg:SI R4_REG))
2003    (clobber (reg:SI R5_REG))
2004    (clobber (reg:SI T_MEDIA_REG))
2005    (clobber (reg:SI PR_MEDIA_REG))
2006    (clobber (reg:SI R1_REG))
2007    (clobber (reg:SI R21_REG))
2008    (clobber (reg:SI TR0_REG))
2009    (clobber (reg:SI R20_REG))
2010    (use (match_operand:SI 3 "register_operand" "r"))]
2011   "TARGET_SHMEDIA"
2012   "#"
2013   "&& (high_life_started || reload_completed)"
2014   [(set (match_dup 0) (match_dup 3))]
2015   ""
2016   [(set_attr "highpart" "must_split")])
2018 ;; This is the combiner pattern for -mdiv=inv:call .
2019 (define_insn_and_split "*divsi_inv_call_combine"
2020   [(set (match_operand:SI 0 "register_operand" "=z")
2021         (div:SI (match_operand:SI 1 "register_operand" "r")
2022                 (match_operand:SI 2 "register_operand" "r")))
2023    (clobber (reg:SI R4_REG))
2024    (clobber (reg:SI R5_REG))
2025    (clobber (reg:SI T_MEDIA_REG))
2026    (clobber (reg:SI PR_MEDIA_REG))
2027    (clobber (reg:SI R1_REG))
2028    (clobber (reg:SI R21_REG))
2029    (clobber (reg:SI TR0_REG))
2030    (clobber (reg:SI R20_REG))
2031    (use (unspec:SI [(match_dup 1)
2032                     (match_operand:SI 3 "" "")
2033                     (unspec:SI [(match_operand:SI 4 "" "")
2034                                 (match_dup 3)
2035                                 (match_operand:DI 5 "" "")]
2036                      UNSPEC_DIV_INV_M2)
2037                     (match_operand:DI 6 "" "")
2038                     (const_int 0)
2039                     (const_int 0)]
2040          UNSPEC_DIV_INV_M3))]
2041   "TARGET_SHMEDIA"
2042   "#"
2043   "&& (high_life_started || reload_completed)"
2044   [(pc)]
2045   "
2047   const char *name = sh_divsi3_libfunc;
2048   enum sh_function_kind kind = SFUNC_GOT;
2049   rtx sym;
2051   emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2052   emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2053   while (TARGET_DIVIDE_INV_CALL2)
2054     {
2055       rtx x = operands[3];
2057       if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2058         break;
2059       x = XVECEXP (x, 0, 0);
2060       name = \"__sdivsi3_2\";
2061       kind = SFUNC_STATIC;
2062       emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2063       break;
2064     }
2065   sym = function_symbol (NULL, name, kind);
2066   emit_insn (gen_divsi3_media_2 (operands[0], sym));
2067   DONE;
2069   [(set_attr "highpart" "must_split")])
2071 (define_expand "divsi3_i4_media"
2072   [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2073    (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2074    (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2075    (set (match_operand:SI 0 "register_operand" "=r")
2076         (fix:SI (match_dup 5)))]
2077   "TARGET_SHMEDIA_FPU"
2078   "
2080   operands[3] = gen_reg_rtx (DFmode);
2081   operands[4] = gen_reg_rtx (DFmode);
2082   operands[5] = gen_reg_rtx (DFmode);
2085 (define_insn "divsi3_i4"
2086   [(set (match_operand:SI 0 "register_operand" "=y")
2087         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2088    (clobber (reg:SI PR_REG))
2089    (clobber (reg:DF DR0_REG))
2090    (clobber (reg:DF DR2_REG))
2091    (use (reg:PSI FPSCR_REG))
2092    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2093   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
2094   "jsr  @%1%#"
2095   [(set_attr "type" "sfunc")
2096    (set_attr "fp_mode" "double")
2097    (set_attr "needs_delay_slot" "yes")])
2099 (define_insn "divsi3_i4_single"
2100   [(set (match_operand:SI 0 "register_operand" "=y")
2101         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2102    (clobber (reg:SI PR_REG))
2103    (clobber (reg:DF DR0_REG))
2104    (clobber (reg:DF DR2_REG))
2105    (clobber (reg:SI R2_REG))
2106    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2107   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
2108   "jsr  @%1%#"
2109   [(set_attr "type" "sfunc")
2110    (set_attr "needs_delay_slot" "yes")])
2112 (define_insn "divsi3_i4_int"
2113   [(set (match_operand:SI 0 "register_operand" "=z")
2114         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2115    (clobber (reg:SI T_REG))
2116    (clobber (reg:SI PR_REG))
2117    (clobber (reg:SI R1_REG))
2118    (clobber (reg:SI MACH_REG))
2119    (clobber (reg:SI MACL_REG))
2120    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2121   "TARGET_SH1"
2122   "jsr  @%1%#"
2123   [(set_attr "type" "sfunc")
2124    (set_attr "needs_delay_slot" "yes")])
2126 (define_expand "divsi3"
2127   [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2128    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2129    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2130    (parallel [(set (match_operand:SI 0 "register_operand" "")
2131                    (div:SI (reg:SI R4_REG)
2132                            (reg:SI R5_REG)))
2133               (clobber (reg:SI T_REG))
2134               (clobber (reg:SI PR_REG))
2135               (clobber (reg:SI R1_REG))
2136               (clobber (reg:SI R2_REG))
2137               (clobber (reg:SI R3_REG))
2138               (use (match_dup 3))])]
2139   ""
2140   "
2142   rtx last;
2144   operands[3] = gen_reg_rtx (Pmode);
2145   /* Emit the move of the address to a pseudo outside of the libcall.  */
2146   if (TARGET_DIVIDE_CALL_TABLE)
2147     {
2148       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2149       last = gen_divsi3_i4_int (operands[0], operands[3]);
2150     }
2151   else if (TARGET_DIVIDE_CALL_FP)
2152     {
2153       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2154       if (TARGET_FPU_SINGLE)
2155         last = gen_divsi3_i4_single (operands[0], operands[3]);
2156       else
2157         last = gen_divsi3_i4 (operands[0], operands[3]);
2158     }
2159   else if (TARGET_SH2A)
2160     {
2161       operands[1] = force_reg (SImode, operands[1]);
2162       operands[2] = force_reg (SImode, operands[2]);
2163       emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2164       DONE;
2165     }
2166   else if (TARGET_DIVIDE_INV)
2167     {
2168       rtx dividend = operands[1];
2169       rtx divisor = operands[2];
2170       rtx tab_base;
2171       rtx nsb_res = gen_reg_rtx (DImode);
2172       rtx norm64 = gen_reg_rtx (DImode);
2173       rtx tab_ix = gen_reg_rtx (DImode);
2174       rtx norm32 = gen_reg_rtx (SImode);
2175       rtx i92 = force_reg (DImode, GEN_INT (92));
2176       rtx scratch0a = gen_reg_rtx (DImode);
2177       rtx scratch0b = gen_reg_rtx (DImode);
2178       rtx inv0 = gen_reg_rtx (SImode);
2179       rtx scratch1a = gen_reg_rtx (DImode);
2180       rtx scratch1b = gen_reg_rtx (DImode);
2181       rtx shift = gen_reg_rtx (DImode);
2182       rtx i2p27, i43;
2183       rtx inv1 = gen_reg_rtx (SImode);
2184       rtx scratch2a = gen_reg_rtx (DImode);
2185       rtx scratch2b = gen_reg_rtx (SImode);
2186       rtx inv2 = gen_reg_rtx (SImode);
2187       rtx scratch3a = gen_reg_rtx (DImode);
2188       rtx scratch3b = gen_reg_rtx (DImode);
2189       rtx scratch3c = gen_reg_rtx (DImode);
2190       rtx scratch3d = gen_reg_rtx (SImode);
2191       rtx scratch3e = gen_reg_rtx (DImode);
2192       rtx result = gen_reg_rtx (SImode);
2194       if (! arith_reg_or_0_operand (dividend, SImode))
2195         dividend = force_reg (SImode, dividend);
2196       if (! arith_reg_operand (divisor, SImode))
2197         divisor = force_reg (SImode, divisor);
2198       if (flag_pic && Pmode != DImode)
2199         {
2200           tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2201           tab_base = gen_datalabel_ref (tab_base);
2202           tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2203         }
2204       else
2205         {
2206           tab_base = gen_rtx_SYMBOL_REF (DImode, \"__div_table\");
2207           tab_base = gen_datalabel_ref (tab_base);
2208           tab_base = force_reg (DImode, tab_base);
2209         }
2210       if (TARGET_DIVIDE_INV20U)
2211         i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2212       else
2213         i2p27 = GEN_INT (0);
2214       if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2215         i43 = force_reg (DImode, GEN_INT (43));
2216       else
2217         i43 = GEN_INT (0);
2218       emit_insn (gen_nsbdi (nsb_res,
2219                             simplify_gen_subreg (DImode, divisor, SImode, 0)));
2220       emit_insn (gen_ashldi3_media (norm64,
2221                                     gen_rtx_SUBREG (DImode, divisor, 0),
2222                                     nsb_res));
2223       emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2224       emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2225       emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2226                                    inv0, scratch0a, scratch0b,
2227                                    scratch1a, scratch1b));
2228       emit_insn (gen_subdi3 (shift, i92, nsb_res));
2229       emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2230                                    scratch2a));
2231       emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2232                                    i2p27, i43,
2233                                    scratch3a, scratch3b, scratch3c,
2234                                    scratch2a, scratch2b, scratch3d, scratch3e));
2235       if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2236         emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2237       else if (TARGET_DIVIDE_INV_FP)
2238         emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2239                                      gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2240                                      gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2241                                      gen_reg_rtx (DFmode)));
2242       else
2243         emit_move_insn (operands[0], result);
2244       DONE;
2245     }
2246   else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2247     {
2248       operands[1] = force_reg (SImode, operands[1]);
2249       operands[2] = force_reg (SImode, operands[2]);
2250       emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2251       DONE;
2252     }
2253   else if (TARGET_SH5)
2254     {
2255       if (TARGET_DIVIDE_CALL2)
2256         {
2257           rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2258           tab_base = gen_datalabel_ref (tab_base);
2259           emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2260         }
2261       if (TARGET_FPU_ANY && TARGET_SH1)
2262         function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2263       else if (TARGET_DIVIDE_CALL2)
2264         function_symbol (operands[3], \"__sdivsi3_2\", SFUNC_STATIC);
2265       else
2266         function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2268       if (TARGET_SHMEDIA)
2269         last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2270                 (operands[0], operands[3]));
2271       else if (TARGET_FPU_ANY)
2272         last = gen_divsi3_i4_single (operands[0], operands[3]);
2273       else
2274         last = gen_divsi3_i1 (operands[0], operands[3]);
2275     }
2276   else
2277     {
2278       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2279       last = gen_divsi3_i1 (operands[0], operands[3]);
2280     }
2281   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2282   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2283   emit_insn (last);
2284   DONE;
2287 ;; operands: scratch, tab_base, tab_ix
2288 ;; These are unspecs because we could generate an indexed addressing mode
2289 ;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2290 ;; confuse reload.  See PR27117.
2292 (define_insn "divsi_inv_qitable"
2293   [(set (match_operand:DI 0 "register_operand" "=r")
2294         (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2295                                     (match_operand:DI 2 "register_operand" "r")]
2296                          UNSPEC_DIV_INV_TABLE)))]
2297   "TARGET_SHMEDIA"
2298   "@
2299         ldx.ub  %1, %2, %0"
2300   [(set_attr "type" "load_media")
2301    (set_attr "highpart" "user")])
2303 ;; operands: scratch, tab_base, tab_ix
2304 (define_insn "divsi_inv_hitable"
2305   [(set (match_operand:DI 0 "register_operand" "=r")
2306         (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2307                                     (match_operand:DI 2 "register_operand" "r")]
2308                          UNSPEC_DIV_INV_TABLE)))]
2309   "TARGET_SHMEDIA"
2310   "@
2311         ldx.w   %1, %2, %0"
2312   [(set_attr "type" "load_media")
2313    (set_attr "highpart" "user")])
2315 ;; operands: inv0, tab_base, tab_ix, norm32
2316 ;; scratch equiv in sdivsi3_2: r19, r21
2317 (define_expand "divsi_inv_m0"
2318   [(set (match_operand:SI 0 "register_operand" "=r")
2319         (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2320                     (match_operand:DI 2 "register_operand" "r")
2321                     (match_operand:SI 3 "register_operand" "r")]
2322          UNSPEC_DIV_INV_M0))
2323    (clobber (match_operand:DI 4 "register_operand" "=r"))
2324    (clobber (match_operand:DI 5 "register_operand" "=r"))]
2325   "TARGET_SHMEDIA"
2326   "
2329 tab_base: r20
2330 tab_ix: r21
2331 norm32: r25
2332  ldx.ub r20, r21, r19 // u0.8
2333  shlli r21, 1, r21
2334  muls.l r25, r19, r19 // s2.38
2335  ldx.w r20, r21, r21  // s2.14
2336  shari r19, 24, r19   // truncate to s2.14
2337  sub r21, r19, r19    // some 11 bit inverse in s1.14
2340   rtx inv0 = operands[0];
2341   rtx tab_base = operands[1];
2342   rtx tab_ix = operands[2];
2343   rtx norm32 = operands[3];
2344   rtx scratch0 = operands[4];
2345   rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2346   rtx scratch1 = operands[5];
2348   emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2349   emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2350   emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2351   emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2352   emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2353   emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2354   DONE;
2357 ;; operands: inv1, tab_base, tab_ix, norm32
2358 (define_insn_and_split "divsi_inv_m1"
2359   [(set (match_operand:SI 0 "register_operand" "=r")
2360         (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2361                     (match_operand:DI 2 "register_operand" "r")
2362                     (match_operand:SI 3 "register_operand" "r")]
2363          UNSPEC_DIV_INV_M1))
2364    (clobber (match_operand:SI 4 "register_operand" "=r"))
2365    (clobber (match_operand:DI 5 "register_operand" "=r"))
2366    (clobber (match_operand:DI 6 "register_operand" "=r"))
2367    (clobber (match_operand:DI 7 "register_operand" "=r"))
2368    (clobber (match_operand:DI 8 "register_operand" "=r"))]
2369   "TARGET_SHMEDIA"
2370   "#"
2371   "&& !can_create_pseudo_p ()"
2372   [(pc)]
2373   "
2375 /* inv0: r19
2376  muls.l r19, r19, r18 // u0.28
2377  muls.l r25, r18, r18 // s2.58
2378  shlli r19, 45, r0    // multiply by two and convert to s2.58
2379  sub r0, r18, r18
2380  shari r18, 28, r18   // some 18 bit inverse in s1.30
2383   rtx inv1 = operands[0];
2384   rtx tab_base = operands[1];
2385   rtx tab_ix = operands[2];
2386   rtx norm32 = operands[3];
2387   rtx inv0 = operands[4];
2388   rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2389   rtx scratch0a = operands[5];
2390   rtx scratch0b = operands[6];
2391   rtx scratch0 = operands[7];
2392   rtx scratch1 = operands[8];
2393   rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2395   emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2396                                scratch0a, scratch0b));
2397   emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2398   emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2399   emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2400   emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2401   emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2402   DONE;
2405 ;; operands: inv2, norm32, inv1, i92
2406 (define_insn_and_split "divsi_inv_m2"
2407   [(set (match_operand:SI 0 "register_operand" "=r")
2408         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2409                     (match_operand:SI 2 "register_operand" "r")
2410                     (match_operand:DI 3 "register_operand" "r")]
2411          UNSPEC_DIV_INV_M2))
2412    (clobber (match_operand:DI 4 "register_operand" "=r"))]
2413   "TARGET_SHMEDIA"
2414   "#"
2415   "&& !can_create_pseudo_p ()"
2416   [(pc)]
2417   "
2420  muls.l r18, r25, r0  // s2.60
2421  shari r0, 16, r0     // s-16.44
2422   sub
2423  muls.l r0, r18, r19  // s-16.74
2424  shari r19, 30, r19   // s-16.44
2426   rtx inv2 = operands[0];
2427   rtx norm32 = operands[1];
2428   rtx inv1 = operands[2];
2429   rtx i92 = operands[3];
2430   rtx scratch0 = operands[4];
2431   rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2433   emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2434   emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2435   emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2436   emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2437   emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2438   DONE;
2441 (define_insn_and_split "divsi_inv_m3"
2442   [(set (match_operand:SI 0 "register_operand" "=r")
2443         (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2444                     (match_operand:SI 2 "register_operand" "r")
2445                     (match_operand:SI 3 "register_operand" "r")
2446                     (match_operand:DI 4 "register_operand" "r")
2447                     (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
2448                     (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
2449          UNSPEC_DIV_INV_M3))
2450    (clobber (match_operand:DI 7 "register_operand" "=r"))
2451    (clobber (match_operand:DI 8 "register_operand" "=r"))
2452    (clobber (match_operand:DI 9 "register_operand" "=r"))
2453    (clobber (match_operand:DI 10 "register_operand" "=r"))
2454    (clobber (match_operand:SI 11 "register_operand" "=r"))
2455    (clobber (match_operand:SI 12 "register_operand" "=r"))
2456    (clobber (match_operand:DI 13 "register_operand" "=r"))]
2457   "TARGET_SHMEDIA"
2458   "#"
2459   "&& !can_create_pseudo_p ()"
2460   [(pc)]
2461   "
2464   r0: result  r1: shift  r4: dividend  r18: inv1  r19: inv2
2465   r0: scratch0  r19: scratch1 r21: scratch2
2467   muls.l r18, r4, r25 // s32.30
2468  muls.l r19, r4, r19  // s15.30
2469  shari r25, 63, r21
2470   shari r19, 14, r19  // s18.-14
2471  sub r25, r19, r0
2472  shard r0, r1, r0
2473  sub r0, r21, r0
2476   rtx result = operands[0];
2477   rtx dividend = operands[1];
2478   rtx inv1 = operands[2];
2479   rtx inv2 = operands[3];
2480   rtx shift = operands[4];
2481   rtx scratch0 = operands[7];
2482   rtx scratch1 = operands[8];
2483   rtx scratch2 = operands[9];
2485   if (satisfies_constraint_N (dividend))
2486     {
2487       emit_move_insn (result, dividend);
2488       DONE;
2489     }
2491   emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
2492   emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
2493   emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
2494   emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
2495   emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
2496   emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
2497   emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
2498   DONE;
2501 ;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
2502 ;; inv1: tab_base, tab_ix, norm32
2503 ;; inv2: norm32, inv1, i92
2504 (define_insn_and_split "divsi_inv_m1_3"
2505   [(set (match_operand:SI 0 "register_operand" "=r")
2506         (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2507                     (unspec:SI [(match_operand:DI 2 "register_operand" "r")
2508                                 (match_operand:DI 3 "register_operand" "r")
2509                                 (match_operand:SI 4 "register_operand" "r")]
2510                      UNSPEC_DIV_INV_M1)
2511                     (unspec:SI [(match_dup 4)
2512                                 (unspec:SI [(match_dup 2)
2513                                             (match_dup 3)
2514                                             (match_dup 4)] UNSPEC_DIV_INV_M1)
2515                                 (match_operand:SI 5 "" "")]
2516                      UNSPEC_DIV_INV_M2)
2517                     (match_operand:DI 6 "register_operand" "r")
2518                     (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
2519                     (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
2520          UNSPEC_DIV_INV_M3))
2521    (clobber (match_operand:DI 9 "register_operand" "=r"))
2522    (clobber (match_operand:DI 10 "register_operand" "=r"))
2523    (clobber (match_operand:DI 11 "register_operand" "=r"))
2524    (clobber (match_operand:DI 12 "register_operand" "=r"))
2525    (clobber (match_operand:SI 13 "register_operand" "=r"))
2526    (clobber (match_operand:SI 14 "register_operand" "=r"))
2527    (clobber (match_operand:DI 15 "register_operand" "=r"))]
2528   "TARGET_SHMEDIA
2529    && (TARGET_DIVIDE_INV_MINLAT
2530        || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2531   "#"
2532   "&& !can_create_pseudo_p ()"
2533   [(pc)]
2534   "
2536   rtx result = operands[0];
2537   rtx dividend = operands[1];
2538   rtx tab_base = operands[2];
2539   rtx tab_ix = operands[3];
2540   rtx norm32 = operands[4];
2541   /* rtx i92 = operands[5]; */
2542   rtx shift = operands[6];
2543   rtx i2p27 = operands[7];
2544   rtx i43 = operands[8];
2545   rtx scratch0 = operands[9];
2546   rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2547   rtx scratch1 = operands[10];
2548   rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2549   rtx scratch2 = operands[11];
2550   rtx scratch3 = operands[12];
2551   rtx scratch4 = operands[13];
2552   rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
2553   rtx scratch5 = operands[14];
2554   rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
2555   rtx scratch6 = operands[15];
2557   emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
2558                                scratch0, scratch1));
2559   /* inv0 == scratch4 */
2560   if (! TARGET_DIVIDE_INV20U)
2561     {
2562       emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
2563       i2p27 = scratch0;
2564       emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
2565     }
2566   else
2567     {
2568       emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
2569       emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2570     }
2571   emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
2572   emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
2573   emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
2574   /* inv1 == scratch4 */
2576   if (TARGET_DIVIDE_INV_MINLAT)
2577     {
2578       emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
2579       emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
2580       emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
2581       emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
2582       emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
2583       emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
2584       emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
2585       emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
2586       emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
2587       emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
2588       emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
2589     }
2590   else
2591     {
2592       rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
2593       /* Use separate scratch regs for nsb and sign to allow scheduling.  */
2594       emit_insn (gen_nsbdi (scratch6,
2595                             simplify_gen_subreg (DImode, dividend, SImode, 0)));
2596       emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
2597       emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
2598       emit_insn (gen_divsi_inv20 (scratch2,
2599                                   norm32, scratch4, dividend,
2600                                   scratch6, scratch3, i43,
2601                                   /* scratch0 may be shared with i2p27.  */
2602                                   scratch0, scratch1, scratch5,
2603                                   label, label, i2p27));
2604     }
2605   emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
2606   emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
2607   DONE;
2610 (define_insn "divsi_inv20"
2611   [(set (match_operand:DI 0 "register_operand" "=&r")
2612         (unspec:DI [(match_operand:SI 1 "register_operand" "r")
2613                     (match_operand:SI 2 "register_operand" "r")
2614                     (match_operand:SI 3 "register_operand" "r")
2615                     (match_operand:DI 4 "register_operand" "r")
2616                     (match_operand:DI 5 "register_operand" "r")
2617                     (match_operand:DI 6 "register_operand" "r")
2618                     (match_operand:DI 12 "register_operand" "r")
2619                     (match_operand 10 "target_operand" "b")
2620                     (match_operand 11 "immediate_operand" "i")]
2621          UNSPEC_DIV_INV20))
2622    (clobber (match_operand:DI 7 "register_operand" "=&r"))
2623    (clobber (match_operand:DI 8 "register_operand" "=&r"))
2624    (clobber (match_operand:SI 9 "register_operand" "=r"))]
2625   "TARGET_SHMEDIA
2626    && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2627   "*
2629 /* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
2630              %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
2631              %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
2632              %10 label (tr), %11 label (imm)
2634  muls.l inv1, norm32, scratch0  // s2.60
2635   muls.l inv1, dividend, result // s32.30
2636   xor i2p27, result_sign, round_scratch
2637  bge/u dividend_nsb, i43, tr.. (label)
2638  shari scratch0, 16, scratch0   // s-16.44
2639  muls.l sratch0_si, inv1, scratch0 // s-16.74
2640   sub result, round_scratch, result
2641   shari dividend, 14, scratch1   // s19.-14
2642  shari scratch0, 30, scratch0   // s-16.44
2643  muls.l scratch0, scratch1, round_scratch // s15.30
2644 label:
2645  sub result, round_scratch, result */
2647   int likely = TARGET_DIVIDE_INV20L;
2649   if (! likely) output_asm_insn (\"muls.l\t%2, %1 , %8\", operands);
2650   output_asm_insn (\"muls.l\t%2, %3, %0\;xor\t%12, %5, %7\", operands);
2651   output_asm_insn (likely
2652                    ? \"bge/l\t%4, %6, %10\;muls.l\t%2, %1 , %8\"
2653                    : \"bge/u\t%4, %6, %10\", operands);
2654   output_asm_insn (\"shari\t%8, 16, %8\;muls.l\t%8, %2, %8\", operands);
2655   if (! likely) output_asm_insn (\"sub\t%0, %7, %0\", operands);
2656   output_asm_insn (\"shari\t%3, 14, %9\;shari\t%8, 30, %8\", operands);
2657   return (likely
2658           ? \"muls.l\t%8, %9, %8\;sub\t%0, %8, %0\n%11:\tadd\t%0, %7, %0\"
2659           : \"muls.l\t%8, %9, %7\n%11:\tsub\t%0, %7, %0\");
2662 (define_insn_and_split "divsi_inv_fp"
2663   [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
2664         (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
2665                 (match_operand:SI 2 "register_operand" "rf")))
2666    (use (match_operand:SI 3 "general_movsrc_operand" "r"))
2667    (clobber (match_operand:SI 4 "register_operand" "=r"))
2668    (clobber (match_operand:SI 5 "register_operand" "=r"))
2669    (clobber (match_operand:DF 6 "register_operand" "=r"))
2670    (clobber (match_operand:DF 7 "register_operand" "=r"))
2671    (clobber (match_operand:DF 8 "register_operand" "=r"))]
2672   "TARGET_SHMEDIA_FPU"
2673   "#"
2674   "&& (high_life_started || reload_completed)"
2675   [(set (match_dup 0) (match_dup 3))]
2676   ""
2677   [(set_attr "highpart" "must_split")])
2679 ;; If a matching group of divide-by-inverse instructions is in the same
2680 ;; basic block after gcse & loop optimizations, we want to transform them
2681 ;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
2682 (define_insn_and_split "*divsi_inv_fp_combine"
2683   [(set (match_operand:SI 0 "register_operand" "=f")
2684         (div:SI (match_operand:SI 1 "register_operand" "f")
2685                 (match_operand:SI 2 "register_operand" "f")))
2686    (use (unspec:SI [(match_dup 1)
2687                     (match_operand:SI 3 "" "")
2688                     (unspec:SI [(match_operand:SI 4 "" "")
2689                                 (match_dup 3)
2690                                 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
2691                     (match_operand:DI 6 "" "")
2692                     (const_int 0)
2693                     (const_int 0)] UNSPEC_DIV_INV_M3))
2694    (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
2695    (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
2696    (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
2697    (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
2698    (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
2699   "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
2700   "#"
2701   "&& 1"
2702   [(set (match_dup 9) (float:DF (match_dup 1)))
2703    (set (match_dup 10) (float:DF (match_dup 2)))
2704    (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
2705    (set (match_dup 8)
2706         (fix:SI (match_dup 11)))
2707    (set (match_dup 0) (match_dup 8))]
2708   "
2710   if (! fp_arith_reg_operand (operands[1], SImode))
2711     {
2712       emit_move_insn (operands[7], operands[1]);
2713       operands[1] = operands[7];
2714     }
2715   if (! fp_arith_reg_operand (operands[2], SImode))
2716     {
2717       emit_move_insn (operands[8], operands[2]);
2718       operands[2] = operands[8];
2719     }
2721   [(set_attr "highpart" "must_split")])
2723 ;; -------------------------------------------------------------------------
2724 ;; Multiplication instructions
2725 ;; -------------------------------------------------------------------------
2727 (define_insn "umulhisi3_i"
2728   [(set (reg:SI MACL_REG)
2729         (mult:SI (zero_extend:SI
2730                   (match_operand:HI 0 "arith_reg_operand" "r"))
2731                  (zero_extend:SI
2732                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
2733   "TARGET_SH1"
2734   "mulu.w       %1,%0"
2735   [(set_attr "type" "smpy")])
2737 (define_insn "mulhisi3_i"
2738   [(set (reg:SI MACL_REG)
2739         (mult:SI (sign_extend:SI
2740                   (match_operand:HI 0 "arith_reg_operand" "r"))
2741                  (sign_extend:SI
2742                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
2743   "TARGET_SH1"
2744   "muls.w       %1,%0"
2745   [(set_attr "type" "smpy")])
2747 (define_expand "mulhisi3"
2748   [(set (reg:SI MACL_REG)
2749         (mult:SI (sign_extend:SI
2750                   (match_operand:HI 1 "arith_reg_operand" ""))
2751                  (sign_extend:SI
2752                   (match_operand:HI 2 "arith_reg_operand" ""))))
2753    (set (match_operand:SI 0 "arith_reg_operand" "")
2754         (reg:SI MACL_REG))]
2755   "TARGET_SH1"
2756   "
2758   rtx insn, macl;
2760   macl = gen_rtx_REG (SImode, MACL_REG);
2761   start_sequence ();
2762   emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
2763   insn = get_insns ();  
2764   end_sequence ();
2765   /* expand_binop can't find a suitable code in umul_widen_optab to
2766      make a REG_EQUAL note from, so make one here.
2767      See also smulsi3_highpart.
2768      ??? Alternatively, we could put this at the calling site of expand_binop,
2769      i.e. expand_expr.  */
2770   /* Use emit_libcall_block for loop invariant code motion and to make
2771      a REG_EQUAL note.  */
2772   emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
2774   DONE;
2777 (define_expand "umulhisi3"
2778   [(set (reg:SI MACL_REG)
2779         (mult:SI (zero_extend:SI
2780                   (match_operand:HI 1 "arith_reg_operand" ""))
2781                  (zero_extend:SI
2782                   (match_operand:HI 2 "arith_reg_operand" ""))))
2783    (set (match_operand:SI 0 "arith_reg_operand" "")
2784         (reg:SI MACL_REG))]
2785   "TARGET_SH1"
2786   "
2788   rtx insn, macl;
2790   macl = gen_rtx_REG (SImode, MACL_REG);
2791   start_sequence ();
2792   emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
2793   insn = get_insns ();  
2794   end_sequence ();
2795   /* expand_binop can't find a suitable code in umul_widen_optab to
2796      make a REG_EQUAL note from, so make one here.
2797      See also smulsi3_highpart.
2798      ??? Alternatively, we could put this at the calling site of expand_binop,
2799      i.e. expand_expr.  */
2800   /* Use emit_libcall_block for loop invariant code motion and to make
2801      a REG_EQUAL note.  */
2802   emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
2804   DONE;
2807 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
2808 ;; a call to a routine which clobbers known registers.
2810 (define_insn ""
2811   [(set (match_operand:SI 1 "register_operand" "=z")
2812         (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2813    (clobber (reg:SI MACL_REG))
2814    (clobber (reg:SI T_REG))
2815    (clobber (reg:SI PR_REG))
2816    (clobber (reg:SI R3_REG))
2817    (clobber (reg:SI R2_REG))
2818    (clobber (reg:SI R1_REG))
2819    (use (match_operand:SI 0 "arith_reg_operand" "r"))]
2820   "TARGET_SH1"
2821   "jsr  @%0%#"
2822   [(set_attr "type" "sfunc")
2823    (set_attr "needs_delay_slot" "yes")])
2825 (define_expand "mulsi3_call"
2826   [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2827    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2828    (parallel[(set (match_operand:SI 0 "register_operand" "")
2829                   (mult:SI (reg:SI R4_REG)
2830                            (reg:SI R5_REG)))
2831              (clobber (reg:SI MACL_REG))
2832              (clobber (reg:SI T_REG))
2833              (clobber (reg:SI PR_REG))
2834              (clobber (reg:SI R3_REG))
2835              (clobber (reg:SI R2_REG))
2836              (clobber (reg:SI R1_REG))
2837              (use (match_operand:SI 3 "register_operand" ""))])]
2838   "TARGET_SH1"
2839   "")
2841 (define_insn "mul_r"
2842   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2843         (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
2844                  (match_operand:SI 2 "arith_reg_operand" "z")))]
2845   "TARGET_SH2A"
2846   "mulr %2,%0"
2847   [(set_attr "type" "dmpy")])
2849 (define_insn "mul_l"
2850   [(set (reg:SI MACL_REG)
2851         (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
2852                  (match_operand:SI 1 "arith_reg_operand" "r")))]
2853   "TARGET_SH2"
2854   "mul.l        %1,%0"
2855   [(set_attr "type" "dmpy")])
2857 (define_expand "mulsi3"
2858   [(set (reg:SI MACL_REG)
2859         (mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
2860                   (match_operand:SI 2 "arith_reg_operand" "")))
2861    (set (match_operand:SI 0 "arith_reg_operand" "")
2862         (reg:SI MACL_REG))]
2863   "TARGET_SH1"
2864   "
2866   if (!TARGET_SH2)
2867     {
2868       /* The address must be set outside the libcall,
2869          since it goes into a pseudo.  */
2870       rtx sym = function_symbol (NULL, \"__mulsi3\", SFUNC_STATIC);
2871       rtx addr = force_reg (SImode, sym);
2872       rtx insns = gen_mulsi3_call (operands[0], operands[1],
2873                                    operands[2], addr);
2874       emit_insn (insns);
2875     }
2876   else
2877     {
2878       rtx macl = gen_rtx_REG (SImode, MACL_REG);
2880       emit_insn (gen_mul_l (operands[1], operands[2]));
2881       /* consec_sets_giv can only recognize the first insn that sets a
2882          giv as the giv insn.  So we must tag this also with a REG_EQUAL
2883          note.  */
2884       emit_insn (gen_movsi_i ((operands[0]), macl));
2885     }
2886   DONE;
2889 (define_insn "mulsidi3_i"
2890   [(set (reg:SI MACH_REG)
2891         (truncate:SI
2892          (lshiftrt:DI
2893           (mult:DI
2894            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2895            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2896           (const_int 32))))
2897    (set (reg:SI MACL_REG)
2898         (mult:SI (match_dup 0)
2899                  (match_dup 1)))]
2900   "TARGET_SH2"
2901   "dmuls.l      %1,%0"
2902   [(set_attr "type" "dmpy")])
2904 (define_expand "mulsidi3"
2905   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2906         (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2907                  (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2908   "TARGET_SH2 || TARGET_SHMEDIA"
2909   "
2911   if (TARGET_SH2)
2912     {
2913        emit_insn (gen_mulsidi3_compact (operands[0], operands[1],
2914                                         operands[2]));
2915        DONE;
2916     }
2919 (define_insn "mulsidi3_media"
2920   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2921         (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2922                  (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2923   "TARGET_SHMEDIA"
2924   "muls.l       %1, %2, %0"
2925   [(set_attr "type" "dmpy_media")
2926    (set_attr "highpart" "ignore")])
2928 (define_insn "mulsidi3_compact"
2929   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2930         (mult:DI
2931          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2932          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2933    (clobber (reg:SI MACH_REG))
2934    (clobber (reg:SI MACL_REG))]
2935   "TARGET_SH2"
2936   "#")
2938 (define_split
2939   [(set (match_operand:DI 0 "arith_reg_dest" "")
2940         (mult:DI
2941          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2942          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2943    (clobber (reg:SI MACH_REG))
2944    (clobber (reg:SI MACL_REG))]
2945   "TARGET_SH2"
2946   [(const_int 0)]
2947   "
2949   rtx low_dst = gen_lowpart (SImode, operands[0]);
2950   rtx high_dst = gen_highpart (SImode, operands[0]);
2952   emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
2954   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
2955   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
2956   /* We need something to tag the possible REG_EQUAL notes on to.  */
2957   emit_move_insn (operands[0], operands[0]);
2958   DONE;
2961 (define_insn "umulsidi3_i"
2962   [(set (reg:SI MACH_REG)
2963         (truncate:SI
2964          (lshiftrt:DI
2965           (mult:DI
2966            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2967            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2968           (const_int 32))))
2969    (set (reg:SI MACL_REG)
2970         (mult:SI (match_dup 0)
2971                  (match_dup 1)))]
2972   "TARGET_SH2"
2973   "dmulu.l      %1,%0"
2974   [(set_attr "type" "dmpy")])
2976 (define_expand "umulsidi3"
2977   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2978         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2979                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2980   "TARGET_SH2 || TARGET_SHMEDIA"
2981   "
2983   if (TARGET_SH2)
2984     {
2985        emit_insn (gen_umulsidi3_compact (operands[0], operands[1],
2986                                          operands[2]));
2987        DONE;
2988     }
2991 (define_insn "umulsidi3_media"
2992   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2993         (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2994                  (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2995   "TARGET_SHMEDIA"
2996   "mulu.l       %1, %2, %0"
2997   [(set_attr "type" "dmpy_media")
2998    (set_attr "highpart" "ignore")])
3000 (define_insn "umulsidi3_compact"
3001   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3002         (mult:DI
3003          (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3004          (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3005    (clobber (reg:SI MACH_REG))
3006    (clobber (reg:SI MACL_REG))]
3007   "TARGET_SH2"
3008   "#")
3010 (define_split
3011   [(set (match_operand:DI 0 "arith_reg_dest" "")
3012         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3013                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
3014    (clobber (reg:SI MACH_REG))
3015    (clobber (reg:SI MACL_REG))]
3016   "TARGET_SH2"
3017   [(const_int 0)]
3018   "
3020   rtx low_dst = gen_lowpart (SImode, operands[0]);
3021   rtx high_dst = gen_highpart (SImode, operands[0]);
3023   emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
3025   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3026   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3027   /* We need something to tag the possible REG_EQUAL notes on to.  */
3028   emit_move_insn (operands[0], operands[0]);
3029   DONE;
3032 (define_insn "smulsi3_highpart_i"
3033   [(set (reg:SI MACH_REG)
3034         (truncate:SI
3035          (lshiftrt:DI
3036           (mult:DI
3037            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3038            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3039           (const_int 32))))
3040    (clobber (reg:SI MACL_REG))]
3041   "TARGET_SH2"
3042   "dmuls.l      %1,%0"
3043   [(set_attr "type" "dmpy")])
3045 (define_expand "smulsi3_highpart"
3046   [(parallel
3047     [(set (reg:SI MACH_REG)
3048           (truncate:SI
3049            (lshiftrt:DI
3050             (mult:DI
3051              (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3052              (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3053             (const_int 32))))
3054     (clobber (reg:SI MACL_REG))])
3055    (set (match_operand:SI 0 "arith_reg_operand" "")
3056         (reg:SI MACH_REG))]
3057   "TARGET_SH2"
3058   "
3060   rtx insn, mach;
3062   mach = gen_rtx_REG (SImode, MACH_REG);
3063   start_sequence ();
3064   emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3065   insn = get_insns ();  
3066   end_sequence ();
3067   /* expand_binop can't find a suitable code in mul_highpart_optab to
3068      make a REG_EQUAL note from, so make one here.
3069      See also {,u}mulhisi.
3070      ??? Alternatively, we could put this at the calling site of expand_binop,
3071      i.e. expand_mult_highpart.  */
3072   /* Use emit_libcall_block for loop invariant code motion and to make
3073      a REG_EQUAL note.  */
3074   emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3076   DONE;
3079 (define_insn "umulsi3_highpart_i"
3080   [(set (reg:SI MACH_REG)
3081         (truncate:SI
3082          (lshiftrt:DI
3083           (mult:DI
3084            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3085            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3086           (const_int 32))))
3087    (clobber (reg:SI MACL_REG))]
3088   "TARGET_SH2"
3089   "dmulu.l      %1,%0"
3090   [(set_attr "type" "dmpy")])
3092 (define_expand "umulsi3_highpart"
3093   [(parallel
3094     [(set (reg:SI MACH_REG)
3095           (truncate:SI
3096            (lshiftrt:DI
3097             (mult:DI
3098              (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3099              (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3100             (const_int 32))))
3101     (clobber (reg:SI MACL_REG))])
3102    (set (match_operand:SI 0 "arith_reg_operand" "")
3103         (reg:SI MACH_REG))]
3104   "TARGET_SH2"
3105   "
3107   rtx insn, mach;
3109   mach = gen_rtx_REG (SImode, MACH_REG);
3110   start_sequence ();
3111   emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3112   insn = get_insns ();  
3113   end_sequence ();
3114   /* Use emit_libcall_block for loop invariant code motion and to make
3115      a REG_EQUAL note.  */
3116   emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3118   DONE;
3121 (define_insn_and_split "muldi3"
3122   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3123         (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3124                  (match_operand:DI 2 "arith_reg_operand" "r")))
3125    (clobber (match_scratch:DI 3 "=&r"))
3126    (clobber (match_scratch:DI 4 "=r"))]
3127   "TARGET_SHMEDIA"
3128   "#"
3129   "reload_completed"
3130   [(const_int 0)]
3131   "
3133   rtx op3_v2si, op2_v2si;
3135   op3_v2si = operands[3];
3136   if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3137     {
3138       op3_v2si = XEXP (op3_v2si, 0);
3139       op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3140     }
3141   op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3142   op2_v2si = operands[2];
3143   if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3144     {
3145       op2_v2si = XEXP (op2_v2si, 0);
3146       op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3147     }
3148   op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3149   emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3150   emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3151   emit_insn (gen_umulsidi3_media (operands[4],
3152                                  sh_gen_truncate (SImode, operands[1], 0),
3153                                  sh_gen_truncate (SImode, operands[2], 0)));
3154   emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3155   emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3156   emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3157   emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3158   DONE;
3162 ;; -------------------------------------------------------------------------
3163 ;; Logical operations
3164 ;; -------------------------------------------------------------------------
3166 (define_insn "*andsi3_compact"
3167   [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3168         (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3169                 (match_operand:SI 2 "logical_operand" "K08,r")))]
3170   "TARGET_SH1"
3171   "and  %2,%0"
3172   [(set_attr "type" "arith")])
3174 (define_insn "*andsi3_media"
3175   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3176         (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3177                 (match_operand:SI 2 "logical_operand" "r,I10")))]
3178   "TARGET_SHMEDIA"
3179   "@
3180         and     %1, %2, %0
3181         andi    %1, %2, %0"
3182   [(set_attr "type" "arith_media")])
3184 (define_insn "*andsi3_bclr"
3185   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3186         (and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3187                 (match_operand:SI 2 "const_int_operand" "Psz")))]
3188   "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
3189   "bclr\\t%W2,%0"
3190   [(set_attr "type" "arith")])
3192 ;; If the constant is 255, then emit an extu.b instruction instead of an
3193 ;; and, since that will give better code.
3195 (define_expand "andsi3"
3196   [(set (match_operand:SI 0 "arith_reg_operand" "")
3197         (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3198                 (match_operand:SI 2 "logical_operand" "")))]
3199   ""
3200   "
3202   if (TARGET_SH1
3203       && CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 255)
3204     {
3205       emit_insn (gen_zero_extendqisi2 (operands[0],
3206                                        gen_lowpart (QImode, operands[1])));
3207       DONE;
3208     }
3211 (define_insn_and_split "anddi3"
3212   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3213         (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3214                 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
3215   "TARGET_SHMEDIA"
3216   "@
3217         and     %1, %2, %0
3218         andi    %1, %2, %0
3219         #"
3220   "reload_completed
3221    && ! logical_operand (operands[2], DImode)"
3222   [(const_int 0)]
3223   "
3225   if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3226     emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3227   else
3228     emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3229   DONE;
3231   [(set_attr "type" "arith_media")])
3233 (define_insn "andcsi3"
3234   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3235         (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3236                 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3237   "TARGET_SHMEDIA"
3238   "andc %1,%2,%0"
3239   [(set_attr "type" "arith_media")])
3241 (define_insn "andcdi3"
3242   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3243         (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3244                 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3245   "TARGET_SHMEDIA"
3246   "andc %1,%2,%0"
3247   [(set_attr "type" "arith_media")])
3249 (define_expand "iorsi3"
3250   [(set (match_operand:SI 0 "arith_reg_operand" "")
3251         (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3252                 (match_operand:SI 2 "logical_operand" "")))]
3253   ""
3254   "")
3256 (define_insn "*iorsi3_compact"
3257   [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3258         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3259                 (match_operand:SI 2 "logical_operand" "r,K08")))]
3260   "TARGET_SH1
3261    && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
3262   "or   %2,%0"
3263   [(set_attr "type" "arith")])
3265 (define_insn "*iorsi3_media"
3266   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3267         (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3268                 (match_operand:SI 2 "logical_operand" "r,I10")))]
3269   "TARGET_SHMEDIA"
3270   "@
3271         or      %1, %2, %0
3272         ori     %1, %2, %0"
3273   [(set_attr "type" "arith_media")])
3275 (define_insn "*iorsi3_bset"
3276   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3277         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3278         (match_operand:SI 2 "const_int_operand" "Pso")))]
3279   "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
3280   "bset\\t%V2,%0"
3281   [(set_attr "type" "arith")])
3283 (define_insn "iordi3"
3284   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3285         (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3286                 (match_operand:DI 2 "logical_operand" "r,I10")))]
3287   "TARGET_SHMEDIA"
3288   "@
3289         or      %1, %2, %0
3290         ori     %1, %2, %0"
3291   [(set_attr "type" "arith_media")])
3293 (define_insn_and_split "*logical_sidi3"
3294   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3295         (sign_extend:DI (match_operator:SI 3 "logical_operator"
3296                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3297                            (match_operand:SI 2 "logical_operand" "r,I10")])))]
3298   "TARGET_SHMEDIA"
3299   "#"
3300   "&& reload_completed"
3301   [(set (match_dup 0) (match_dup 3))]
3302   "
3304   operands[3]
3305     = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3306                       simplify_gen_subreg (DImode, operands[1], SImode, 0),
3307                       simplify_gen_subreg (DImode, operands[2], SImode, 0));
3310 (define_insn_and_split "*logical_sidisi3"
3311   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3312         (truncate:SI (sign_extend:DI
3313                         (match_operator:SI 3 "logical_operator"
3314                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3315                            (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3316   "TARGET_SHMEDIA"
3317   "#"
3318   "&& 1"
3319   [(set (match_dup 0) (match_dup 3))])
3321 (define_insn_and_split "*logical_sidi3_2"
3322   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3323         (sign_extend:DI (truncate:SI (sign_extend:DI
3324                         (match_operator:SI 3 "logical_operator"
3325                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3326                            (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3327   "TARGET_SHMEDIA"
3328   "#"
3329   "&& 1"
3330   [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3332 (define_expand "xorsi3"
3333   [(set (match_operand:SI 0 "arith_reg_operand" "")
3334         (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3335                 (match_operand:SI 2 "xor_operand" "")))]
3336   ""
3337   "")
3339 (define_insn "*xorsi3_compact"
3340   [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3341         (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3342                 (match_operand:SI 2 "logical_operand" "K08,r")))]
3343   "TARGET_SH1"
3344   "xor  %2,%0"
3345   [(set_attr "type" "arith")])
3347 (define_insn "*xorsi3_media"
3348   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3349         (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3350                 (match_operand:SI 2 "xor_operand" "r,I06")))]
3351   "TARGET_SHMEDIA"
3352   "@
3353         xor     %1, %2, %0
3354         xori    %1, %2, %0"
3355   [(set_attr "type" "arith_media")])
3357 ;; Store the complements of the T bit in a register.
3358 (define_insn "xorsi3_movrt"
3359   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3360         (xor:SI (reg:SI T_REG)
3361                 (const_int 1)))]
3362   "TARGET_SH2A"
3363   "movrt\\t%0"
3364   [(set_attr "type" "arith")])
3366 (define_insn "xordi3"
3367   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3368         (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3369                 (match_operand:DI 2 "xor_operand" "r,I06")))]
3370   "TARGET_SHMEDIA"
3371   "@
3372         xor     %1, %2, %0
3373         xori    %1, %2, %0"
3374   [(set_attr "type" "arith_media")])
3376 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3377 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
3378 (define_split
3379   [(set (match_operand:DI 0 "arith_reg_dest" "")
3380         (sign_extend:DI (match_operator 4 "binary_logical_operator"
3381                           [(match_operand 1 "any_register_operand" "")
3382                            (match_operand 2 "any_register_operand" "")])))]
3383   "TARGET_SHMEDIA"
3384   [(set (match_dup 5) (match_dup 4))
3385    (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3388   enum machine_mode inmode = GET_MODE (operands[1]);
3389   int offset = 0;
3391   if (GET_CODE (operands[0]) == SUBREG)
3392     {
3393       offset = SUBREG_BYTE (operands[0]);
3394       operands[0] = SUBREG_REG (operands[0]);
3395     }
3396   gcc_assert (REG_P (operands[0]));
3397   if (! TARGET_LITTLE_ENDIAN)
3398     offset += 8 - GET_MODE_SIZE (inmode);
3399   operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3402 ;; -------------------------------------------------------------------------
3403 ;; Shifts and rotates
3404 ;; -------------------------------------------------------------------------
3406 (define_expand "rotldi3"
3407   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3408         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3409                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
3410   "TARGET_SHMEDIA"
3411   "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3413 (define_insn "rotldi3_mextr"
3414   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3415         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3416                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
3417   "TARGET_SHMEDIA"
3418   "*
3420   static char templ[16];
3422   sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\",
3423            8 - (int) (INTVAL (operands[2]) >> 3));
3424   return templ;
3426   [(set_attr "type" "arith_media")])
3428 (define_expand "rotrdi3"
3429   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3430         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3431                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
3432   "TARGET_SHMEDIA"
3433   "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3435 (define_insn "rotrdi3_mextr"
3436   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3437         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3438                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
3439   "TARGET_SHMEDIA"
3440   "*
3442   static char templ[16];
3444   sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\", (int) INTVAL (operands[2]) >> 3);
3445   return templ;
3447   [(set_attr "type" "arith_media")])
3449 (define_split
3450   [(set (match_operand:DI 0 "arith_reg_dest" "")
3451         (ior:DI (zero_extend:DI (mem:QI (match_operand 1
3452                                          "ua_address_operand" "")))
3453                 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
3454                            (const_int 8))))
3455    (clobber (match_operand:DI 3 "register_operand" ""))]
3456   "TARGET_SHMEDIA"
3457   [(match_dup 4) (match_dup 5)]
3458   "
3460   operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
3461                  (operands[3], operands[1]));
3462   operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
3463                               GEN_INT (56), GEN_INT (8));
3466 (define_insn "rotlsi3_1"
3467   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3468         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3469                    (const_int 1)))
3470    (set (reg:SI T_REG)
3471         (lshiftrt:SI (match_dup 1) (const_int 31)))]
3472   "TARGET_SH1"
3473   "rotl %0"
3474   [(set_attr "type" "arith")])
3476 (define_insn "rotlsi3_31"
3477   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3478         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3479                    (const_int 31)))
3480    (clobber (reg:SI T_REG))]
3481   "TARGET_SH1"
3482   "rotr %0"
3483   [(set_attr "type" "arith")])
3485 (define_insn "rotlsi3_16"
3486   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3487         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
3488                    (const_int 16)))]
3489   "TARGET_SH1"
3490   "swap.w       %1,%0"
3491   [(set_attr "type" "arith")])
3493 (define_expand "rotlsi3"
3494   [(set (match_operand:SI 0 "arith_reg_dest" "")
3495         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
3496                    (match_operand:SI 2 "immediate_operand" "")))]
3497   "TARGET_SH1"
3498   "
3500   static const char rot_tab[] = {
3501     000, 000, 000, 000, 000, 000, 010, 001,
3502     001, 001, 011, 013, 003, 003, 003, 003,
3503     003, 003, 003, 003, 003, 013, 012, 002,
3504     002, 002, 010, 000, 000, 000, 000, 000,
3505   };
3507   int count, choice;
3509   if (!CONST_INT_P (operands[2]))
3510     FAIL;
3511   count = INTVAL (operands[2]);
3512   choice = rot_tab[count];
3513   if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
3514     FAIL;
3515   choice &= 7;
3516   switch (choice)
3517     {
3518     case 0:
3519       emit_move_insn (operands[0], operands[1]);
3520       count -= (count & 16) * 2;
3521       break;
3522     case 3:
3523      emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
3524      count -= 16;
3525      break;
3526     case 1:
3527     case 2:
3528       {
3529         rtx parts[2];
3530         parts[0] = gen_reg_rtx (SImode);
3531         parts[1] = gen_reg_rtx (SImode);
3532         emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
3533         emit_move_insn (parts[choice-1], operands[1]);
3534         emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
3535         emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
3536         emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
3537         count = (count & ~16) - 8;
3538       }
3539     }
3541   for (; count > 0; count--)
3542     emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
3543   for (; count < 0; count++)
3544     emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
3546   DONE;
3549 (define_insn "*rotlhi3_8"
3550   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3551         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
3552                    (const_int 8)))]
3553   "TARGET_SH1"
3554   "swap.b       %1,%0"
3555   [(set_attr "type" "arith")])
3557 (define_expand "rotlhi3"
3558   [(set (match_operand:HI 0 "arith_reg_operand" "")
3559         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "")
3560                    (match_operand:HI 2 "immediate_operand" "")))]
3561   "TARGET_SH1"
3562   "
3564   if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 8)
3565     FAIL;
3569 ;; shift left
3571 ;; This pattern is used by init_expmed for computing the costs of shift
3572 ;; insns.
3574 (define_insn_and_split "ashlsi3_std"
3575   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,r,r")
3576         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
3577                    (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
3578    (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
3579   "(TARGET_SH3 || TARGET_SH2A)
3580    || (TARGET_SH1 && satisfies_constraint_P27 (operands[2]))"
3581   "@
3582    shld %2,%0
3583    add  %0,%0
3584    shll%O2      %0
3585    #"
3586   "(TARGET_SH3 || TARGET_SH2A)
3587    && reload_completed
3588    && CONST_INT_P (operands[2])
3589    && ! satisfies_constraint_P27 (operands[2])"
3590   [(set (match_dup 3) (match_dup 2))
3591    (parallel
3592     [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
3593      (clobber (match_dup 4))])]
3594   "operands[4] = gen_rtx_SCRATCH (SImode);"
3595   [(set_attr "length" "*,*,*,4")
3596    (set_attr "type" "dyn_shift,arith,arith,arith")])
3598 (define_insn "ashlhi3_k"
3599   [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
3600         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
3601                    (match_operand:HI 2 "const_int_operand" "M,P27")))]
3602   "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
3603   "@
3604         add     %0,%0
3605         shll%O2 %0"
3606   [(set_attr "type" "arith")])
3608 (define_insn "ashlsi3_n"
3609   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3610         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3611                    (match_operand:SI 2 "const_int_operand" "n")))
3612    (clobber (reg:SI T_REG))]
3613   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3614   "#"
3615   [(set (attr "length")
3616         (cond [(match_test "shift_insns_rtx (insn)")
3617                (const_string "2")
3618                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3619                (const_string "4")
3620                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3621                (const_string "6")]
3622               (const_string "8")))
3623    (set_attr "type" "arith")])
3625 (define_split
3626   [(set (match_operand:SI 0 "arith_reg_dest" "")
3627         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3628                    (match_operand:SI 2 "const_int_operand" "")))
3629    (clobber (reg:SI T_REG))]
3630   "TARGET_SH1 && reload_completed"
3631   [(use (reg:SI R0_REG))]
3632   "
3634   gen_shifty_op (ASHIFT, operands);
3635   DONE;
3638 (define_insn "ashlsi3_media"
3639   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3640         (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3641                    (match_operand:SI 2 "shift_count_operand" "r,n")))]
3642   "TARGET_SHMEDIA"
3643   "@
3644         shlld.l %1, %2, %0
3645         shlli.l %1, %2, %0"
3646   [(set_attr "type" "arith_media")
3647    (set_attr "highpart" "ignore")])
3649 (define_expand "ashlsi3"
3650   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3651                    (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3652                               (match_operand:SI 2 "nonmemory_operand" "")))
3653               (clobber (reg:SI T_REG))])]
3654   ""
3655   "
3657   if (TARGET_SHMEDIA)
3658     {
3659       emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
3660       DONE;
3661     }
3662   if (CONST_INT_P (operands[2])
3663       && sh_dynamicalize_shift_p (operands[2]))
3664     operands[2] = force_reg (SImode, operands[2]);
3665   if (TARGET_SH3 || TARGET_SH2A)
3666     {
3667       emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
3668       DONE;
3669     }
3670   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3671     FAIL;
3674 (define_insn "*ashlhi3_n"
3675   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3676         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
3677                    (match_operand:HI 2 "const_int_operand" "n")))
3678    (clobber (reg:SI T_REG))]
3679   "TARGET_SH1"
3680   "#"
3681   [(set (attr "length")
3682         (cond [(match_test "shift_insns_rtx (insn)")
3683                (const_string "2")
3684                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3685                (const_string "4")]
3686               (const_string "6")))
3687    (set_attr "type" "arith")])
3689 (define_expand "ashlhi3"
3690   [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
3691                    (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3692                               (match_operand:SI 2 "nonmemory_operand" "")))
3693               (clobber (reg:SI T_REG))])]
3694   "TARGET_SH1"
3695   "
3697   if (!CONST_INT_P (operands[2]))
3698     FAIL;
3699   /* It may be possible to call gen_ashlhi3 directly with more generic
3700      operands.  Make sure operands[1] is a HImode register here.  */
3701   if (!arith_reg_operand (operands[1], HImode))
3702     operands[1] = copy_to_mode_reg (HImode, operands[1]);
3705 (define_split
3706   [(set (match_operand:HI 0 "arith_reg_dest" "")
3707         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3708                    (match_operand:HI 2 "const_int_operand" "")))
3709    (clobber (reg:SI T_REG))]
3710   "TARGET_SH1 && reload_completed"
3711   [(use (reg:SI R0_REG))]
3712   "
3714   gen_shifty_hi_op (ASHIFT, operands);
3715   DONE;
3719 ; arithmetic shift right
3722 (define_insn "ashrsi3_k"
3723   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3724         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3725                      (match_operand:SI 2 "const_int_operand" "M")))
3726    (clobber (reg:SI T_REG))]
3727   "TARGET_SH1 && INTVAL (operands[2]) == 1"
3728   "shar %0"
3729   [(set_attr "type" "arith")])
3731 ;; We can't do HImode right shifts correctly unless we start out with an
3732 ;; explicit zero / sign extension; doing that would result in worse overall
3733 ;; code, so just let the machine independent code widen the mode.
3734 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
3737 ;; ??? This should be a define expand.
3739 (define_insn "ashrsi2_16"
3740   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3741         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
3742                      (const_int 16)))]
3743   "TARGET_SH1"
3744   "#"
3745   [(set_attr "length" "4")])
3747 (define_split
3748   [(set (match_operand:SI 0 "arith_reg_dest" "")
3749         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3750                      (const_int 16)))]
3751   "TARGET_SH1"
3752   [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
3753    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3754   "operands[2] = gen_lowpart (HImode, operands[0]);")
3756 ;; ??? This should be a define expand.
3758 (define_insn "ashrsi2_31"
3759   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3760         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3761                      (const_int 31)))
3762    (clobber (reg:SI T_REG))]
3763   "TARGET_SH1"
3764   "#"
3765   [(set_attr "length" "4")])
3767 (define_split
3768   [(set (match_operand:SI 0 "arith_reg_dest" "")
3769         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3770                      (const_int 31)))
3771    (clobber (reg:SI T_REG))]
3772   "TARGET_SH1"
3773   [(const_int 0)]
3774   "
3776   emit_insn (gen_ashlsi_c (operands[0], operands[1]));
3777   emit_insn (gen_mov_neg_si_t (copy_rtx (operands[0])));
3778   DONE;
3781 (define_peephole2
3782   [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
3783    (set (reg:SI T_REG)
3784         (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
3785   "TARGET_SH1
3786    && peep2_reg_dead_p (2, operands[0])
3787    && peep2_reg_dead_p (2, operands[1])"
3788   [(const_int 0)]
3789   "
3791   emit_insn (gen_ashlsi_c (operands[1], operands[1]));
3792   DONE;
3795 (define_insn "ashlsi_c"
3796   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3797         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
3798    (set (reg:SI T_REG)
3799         (lt:SI (match_dup 1) (const_int 0)))]
3800   "TARGET_SH1"
3801   "shll %0"
3802   [(set_attr "type" "arith")])
3804 (define_insn "*ashlsi_c_void"
3805   [(set (reg:SI T_REG)
3806         (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
3807    (clobber (match_scratch:SI 1 "=0"))]
3808   "TARGET_SH1 && cse_not_expected"
3809   "shll %0"
3810   [(set_attr "type" "arith")])
3812 (define_insn "ashrsi3_d"
3813   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3814         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3815                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3816   "TARGET_SH3 || TARGET_SH2A"
3817   "shad %2,%0"
3818   [(set_attr "type" "dyn_shift")])
3820 (define_insn "ashrsi3_n"
3821   [(set (reg:SI R4_REG)
3822         (ashiftrt:SI (reg:SI R4_REG)
3823                      (match_operand:SI 0 "const_int_operand" "i")))
3824    (clobber (reg:SI T_REG))
3825    (clobber (reg:SI PR_REG))
3826    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
3827   "TARGET_SH1"
3828   "jsr  @%1%#"
3829   [(set_attr "type" "sfunc")
3830    (set_attr "needs_delay_slot" "yes")])
3832 (define_insn "ashrsi3_media"
3833   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3834         (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3835                      (match_operand:SI 2 "shift_count_operand" "r,n")))]
3836   "TARGET_SHMEDIA"
3837   "@
3838         shard.l %1, %2, %0
3839         shari.l %1, %2, %0"
3840   [(set_attr "type" "arith_media")
3841    (set_attr "highpart" "ignore")])
3843 (define_expand "ashrsi3"
3844   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3845                    (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3846                                 (match_operand:SI 2 "nonmemory_operand" "")))
3847               (clobber (reg:SI T_REG))])]
3848   ""
3849   "
3851   if (TARGET_SHMEDIA)
3852     {
3853       emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
3854       DONE;
3855     }
3856   if (expand_ashiftrt (operands))
3857     DONE;
3858   else
3859     FAIL;
3862 ;; logical shift right
3864 (define_insn "lshrsi3_d"
3865   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3866         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3867                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3868   "TARGET_SH3 || TARGET_SH2A"
3869   "shld %2,%0"
3870   [(set_attr "type" "dyn_shift")])
3872 ;;  Only the single bit shift clobbers the T bit.
3874 (define_insn "lshrsi3_m"
3875   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3876         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3877                      (match_operand:SI 2 "const_int_operand" "M")))
3878    (clobber (reg:SI T_REG))]
3879   "TARGET_SH1 && satisfies_constraint_M (operands[2])"
3880   "shlr %0"
3881   [(set_attr "type" "arith")])
3883 (define_insn "lshrsi3_k"
3884   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3885         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3886                      (match_operand:SI 2 "const_int_operand" "P27")))]
3887   "TARGET_SH1 && satisfies_constraint_P27 (operands[2])
3888    && ! satisfies_constraint_M (operands[2])"
3889   "shlr%O2      %0"
3890   [(set_attr "type" "arith")])
3892 (define_insn "lshrsi3_n"
3893   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3894         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3895                      (match_operand:SI 2 "const_int_operand" "n")))
3896    (clobber (reg:SI T_REG))]
3897   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3898   "#"
3899   [(set (attr "length")
3900         (cond [(match_test "shift_insns_rtx (insn)")
3901                (const_string "2")
3902                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3903                (const_string "4")
3904                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3905                (const_string "6")]
3906               (const_string "8")))
3907    (set_attr "type" "arith")])
3909 (define_split
3910   [(set (match_operand:SI 0 "arith_reg_dest" "")
3911         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3912                      (match_operand:SI 2 "const_int_operand" "")))
3913    (clobber (reg:SI T_REG))]
3914   "TARGET_SH1 && reload_completed"
3915   [(use (reg:SI R0_REG))]
3916   "
3918   gen_shifty_op (LSHIFTRT, operands);
3919   DONE;
3922 (define_insn "lshrsi3_media"
3923   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3924         (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3925                      (match_operand:SI 2 "shift_count_operand" "r,n")))]
3926   "TARGET_SHMEDIA"
3927   "@
3928         shlrd.l %1, %2, %0
3929         shlri.l %1, %2, %0"
3930   [(set_attr "type" "arith_media")
3931    (set_attr "highpart" "ignore")])
3933 (define_expand "lshrsi3"
3934   [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
3935                    (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3936                                 (match_operand:SI 2 "nonmemory_operand" "")))
3937               (clobber (reg:SI T_REG))])]
3938   ""
3939   "
3941   if (TARGET_SHMEDIA)
3942     {
3943       emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
3944       DONE;
3945     }
3946   if (CONST_INT_P (operands[2])
3947       && sh_dynamicalize_shift_p (operands[2]))
3948     operands[2] = force_reg (SImode, operands[2]);
3949   if ((TARGET_SH3 || TARGET_SH2A)
3950       && arith_reg_operand (operands[2], GET_MODE (operands[2])))
3951     {
3952       rtx count = copy_to_mode_reg (SImode, operands[2]);
3953       emit_insn (gen_negsi2 (count, count));
3954       emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
3955       DONE;
3956     }
3957   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3958     FAIL;
3961 ;; ??? This should be a define expand.
3963 (define_insn "ashldi3_k"
3964   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3965         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
3966                    (const_int 1)))
3967    (clobber (reg:SI T_REG))]
3968   "TARGET_SH1"
3969   "shll %R0\;rotcl      %S0"
3970   [(set_attr "length" "4")
3971    (set_attr "type" "arith")])
3973 ;; Expander for DImode shift left with SImode operations.
3975 (define_expand "ashldi3_std"
3976   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3977         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
3978                    (match_operand:DI 2 "const_int_operand" "n")))]
3979   "TARGET_SH1 && INTVAL (operands[2]) < 32"
3980   "
3982   int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
3983   int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
3984   rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
3985   rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
3986   rtx dst = gen_reg_rtx (DImode);
3987   rtx low_dst = operand_subword (dst, low_word, 1, DImode);
3988   rtx high_dst = operand_subword (dst, high_word, 1, DImode);
3989   rtx tmp0, tmp1;
3991   tmp0 = gen_reg_rtx (SImode);
3992   tmp1 = gen_reg_rtx (SImode);
3993   emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
3994   emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));  
3995   emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));  
3996   emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
3997   emit_move_insn (operands[0], dst);
3998   DONE;
4001 (define_insn "ashldi3_media"
4002   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4003         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4004                    (match_operand:DI 2 "shift_count_operand" "r,n")))]
4005   "TARGET_SHMEDIA"
4006   "@
4007         shlld   %1, %2, %0
4008         shlli   %1, %2, %0"
4009   [(set_attr "type" "arith_media")])
4011 (define_insn "*ashldisi3_media"
4012   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4013         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4014                    (match_operand:DI 2 "const_int_operand" "n")))]
4015   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4016   "shlli.l      %1, %2, %0"
4017   [(set_attr "type" "arith_media")
4018    (set_attr "highpart" "ignore")])
4020 (define_expand "ashldi3"
4021   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4022                    (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
4023                               (match_operand:DI 2 "immediate_operand" "")))
4024               (clobber (reg:SI T_REG))])]
4025   ""
4026   "
4028   if (TARGET_SHMEDIA)
4029     {
4030       emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
4031       DONE;
4032     }
4033   if (CONST_INT_P (operands[2])
4034       && INTVAL (operands[2]) == 1)
4035     {
4036       emit_insn (gen_ashldi3_k (operands[0], operands[1]));
4037       DONE;
4038     }
4039   else if (CONST_INT_P (operands[2])
4040       && INTVAL (operands[2]) < 32)
4041     {
4042       emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
4043       DONE;
4044     }
4045   else
4046     FAIL;
4049 ;; ??? This should be a define expand.
4051 (define_insn "lshrdi3_k"
4052   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4053         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4054                      (const_int 1)))
4055    (clobber (reg:SI T_REG))]
4056   "TARGET_SH1"
4057   "shlr %S0\;rotcr      %R0"
4058   [(set_attr "length" "4")
4059    (set_attr "type" "arith")])
4061 (define_insn "lshrdi3_media"
4062   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4063         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4064                      (match_operand:DI 2 "shift_count_operand" "r,n")))]
4065   "TARGET_SHMEDIA
4066    && (arith_reg_dest (operands[0], DImode)
4067        || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
4068   "@
4069         shlrd   %1, %2, %0
4070         shlri   %1, %2, %0"
4071   [(set_attr "type" "arith_media")])
4073 (define_insn "*lshrdisi3_media"
4074   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4075         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4076                      (match_operand:DI 2 "const_int_operand" "n")))]
4077   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4078   "shlri.l      %1, %2, %0"
4079   [(set_attr "type" "arith_media")
4080    (set_attr "highpart" "ignore")])
4082 (define_expand "lshrdi3"
4083   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4084                    (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4085                                (match_operand:DI 2 "immediate_operand" "")))
4086              (clobber (reg:SI T_REG))])]
4087   ""
4088   "
4090   if (TARGET_SHMEDIA)
4091     {
4092       emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
4093       DONE;
4094     }
4095   if (!CONST_INT_P (operands[2])
4096       || INTVAL (operands[2]) != 1)
4097     FAIL;
4100 ;; ??? This should be a define expand.
4102 (define_insn "ashrdi3_k"
4103   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4104         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4105                      (const_int 1)))
4106    (clobber (reg:SI T_REG))]
4107   "TARGET_SH1"
4108   "shar %S0\;rotcr      %R0"
4109   [(set_attr "length" "4")
4110    (set_attr "type" "arith")])
4112 (define_insn "ashrdi3_media"
4113   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4114         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4115                      (match_operand:DI 2 "shift_count_operand" "r,n")))]
4116   "TARGET_SHMEDIA
4117    && (arith_reg_dest (operands[0], DImode)
4118        || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
4119   "@
4120         shard   %1, %2, %0
4121         shari   %1, %2, %0"
4122   [(set_attr "type" "arith_media")])
4124 (define_insn "*ashrdisi3_media"
4125   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4126         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4127                      (match_operand:DI 2 "const_int_operand" "n")))]
4128   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4129   "shari.l      %1, %2, %0"
4130   [(set_attr "type" "arith_media")
4131    (set_attr "highpart" "ignore")])
4133 (define_insn "ashrdisi3_media_high"
4134   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4135         (truncate:SI
4136            (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4137                         (match_operand:DI 2 "const_int_operand" "n"))))]
4138   "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
4139   "shari        %1, %2, %0"
4140   [(set_attr "type" "arith_media")])
4142 (define_insn "ashrdisi3_media_opaque"
4143   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4144         (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
4145                     (match_operand:DI 2 "const_int_operand" "n")]
4146          UNSPEC_ASHIFTRT))]
4147   "TARGET_SHMEDIA"
4148   "shari        %1, %2, %0"
4149   [(set_attr "type" "arith_media")])
4151 (define_expand "ashrdi3"
4152   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4153                    (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4154                                 (match_operand:DI 2 "immediate_operand" "")))
4155               (clobber (reg:SI T_REG))])]
4156   ""
4157   "
4159   if (TARGET_SHMEDIA)
4160     {
4161       emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4162       DONE;
4163     }
4164   if (!CONST_INT_P (operands[2])
4165       || INTVAL (operands[2]) != 1)
4166     FAIL;
4169 ;; combined left/right shift
4171 (define_split
4172   [(set (match_operand:SI 0 "register_operand" "")
4173         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4174                            (match_operand:SI 2 "const_int_operand" ""))
4175                 (match_operand:SI 3 "const_int_operand" "")))]
4176   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4177   [(use (reg:SI R0_REG))]
4178   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4179    DONE;")
4181 (define_split
4182   [(set (match_operand:SI 0 "register_operand" "")
4183         (and:SI (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    (clobber (reg:SI T_REG))]
4187   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4188   [(use (reg:SI R0_REG))]
4189   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4190    DONE;")
4192 (define_insn ""
4193   [(set (match_operand:SI 0 "register_operand" "=r")
4194         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4195                            (match_operand:SI 2 "const_int_operand" "n"))
4196                 (match_operand:SI 3 "const_int_operand" "n")))
4197    (clobber (reg:SI T_REG))]
4198   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
4199  "#"
4200   [(set (attr "length")
4201         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4202                (const_string "4")
4203                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4204                (const_string "6")
4205                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4206                (const_string "8")
4207                (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
4208                (const_string "10")
4209                (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
4210                (const_string "12")
4211                (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
4212                (const_string "14")
4213                (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
4214                (const_string "16")]
4215               (const_string "18")))
4216    (set_attr "type" "arith")])
4218 (define_insn ""
4219   [(set (match_operand:SI 0 "register_operand" "=z")
4220         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4221                            (match_operand:SI 2 "const_int_operand" "n"))
4222                 (match_operand:SI 3 "const_int_operand" "n")))
4223    (clobber (reg:SI T_REG))]
4224   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
4225  "#"
4226   [(set (attr "length")
4227         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4228                (const_string "4")
4229                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4230                (const_string "6")
4231                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4232                (const_string "8")]
4233               (const_string "10")))
4234    (set_attr "type" "arith")])
4236 ;; shift left / and combination with a scratch register: The combine pass
4237 ;; does not accept the individual instructions, even though they are
4238 ;; cheap.  But it needs a precise description so that it is usable after
4239 ;; reload.
4240 (define_insn "and_shl_scratch"
4241   [(set (match_operand:SI 0 "register_operand" "=r,&r")
4242         (lshiftrt:SI
4243          (ashift:SI
4244           (and:SI
4245            (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
4246                         (match_operand:SI 2 "const_int_operand" "N,n"))
4247            (match_operand:SI 3 "" "0,r"))
4248           (match_operand:SI 4 "const_int_operand" "n,n"))
4249          (match_operand:SI 5 "const_int_operand" "n,n")))
4250    (clobber (reg:SI T_REG))]
4251   "TARGET_SH1"
4252   "#"
4253   [(set (attr "length")
4254         (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
4255                (const_string "4")
4256                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
4257                (const_string "6")
4258                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
4259                (const_string "8")
4260                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
4261                (const_string "10")]
4262               (const_string "12")))
4263    (set_attr "type" "arith")])
4265 (define_split
4266   [(set (match_operand:SI 0 "register_operand" "")
4267         (lshiftrt:SI
4268          (ashift:SI
4269           (and:SI
4270            (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
4271                         (match_operand:SI 2 "const_int_operand" ""))
4272            (match_operand:SI 3 "register_operand" ""))
4273           (match_operand:SI 4 "const_int_operand" ""))
4274          (match_operand:SI 5 "const_int_operand" "")))
4275    (clobber (reg:SI T_REG))]
4276   "TARGET_SH1"
4277   [(use (reg:SI R0_REG))]
4278   "
4280   rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
4282   if (INTVAL (operands[2]))
4283     {
4284       gen_shifty_op (LSHIFTRT, operands);
4285     }
4286   emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
4287   operands[2] = operands[4];
4288   gen_shifty_op (ASHIFT, operands);
4289   if (INTVAL (operands[5]))
4290     {
4291       operands[2] = operands[5];
4292       gen_shifty_op (LSHIFTRT, operands);
4293     }
4294   DONE;
4297 ;; signed left/right shift combination.
4298 (define_split
4299   [(set (match_operand:SI 0 "register_operand" "")
4300         (sign_extract:SI
4301          (ashift:SI (match_operand:SI 1 "register_operand" "")
4302                     (match_operand:SI 2 "const_int_operand" ""))
4303          (match_operand:SI 3 "const_int_operand" "")
4304          (const_int 0)))
4305    (clobber (reg:SI T_REG))]
4306   "TARGET_SH1"
4307   [(use (reg:SI R0_REG))]
4308   "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL;
4309    DONE;")
4311 (define_insn "shl_sext_ext"
4312   [(set (match_operand:SI 0 "register_operand" "=r")
4313         (sign_extract:SI
4314          (ashift:SI (match_operand:SI 1 "register_operand" "0")
4315                     (match_operand:SI 2 "const_int_operand" "n"))
4316          (match_operand:SI 3 "const_int_operand" "n")
4317          (const_int 0)))
4318    (clobber (reg:SI T_REG))]
4319   "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
4320   "#"
4321   [(set (attr "length")
4322         (cond [(match_test "shl_sext_length (insn)")
4323                (const_string "2")
4324                (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
4325                (const_string "4")
4326                (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4327                (const_string "6")
4328                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4329                (const_string "8")
4330                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4331                (const_string "10")
4332                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4333                (const_string "12")
4334                (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
4335                (const_string "14")
4336                (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
4337                (const_string "16")]
4338               (const_string "18")))
4339     (set_attr "type" "arith")])
4341 (define_insn "shl_sext_sub"
4342   [(set (match_operand:SI 0 "register_operand" "=z")
4343         (sign_extract:SI
4344          (ashift:SI (match_operand:SI 1 "register_operand" "0")
4345                     (match_operand:SI 2 "const_int_operand" "n"))
4346          (match_operand:SI 3 "const_int_operand" "n")
4347          (const_int 0)))
4348    (clobber (reg:SI T_REG))]
4349   "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
4350   "#"
4351   [(set (attr "length")
4352         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4353                (const_string "6")
4354                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4355                (const_string "8")
4356                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4357                (const_string "10")
4358                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4359                (const_string "12")]
4360               (const_string "14")))
4361     (set_attr "type" "arith")])
4363 ;; These patterns are found in expansions of DImode shifts by 16, and
4364 ;; allow the xtrct instruction to be generated from C source.
4366 (define_insn "xtrct_left"
4367   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4368         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
4369                            (const_int 16))
4370                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
4371                              (const_int 16))))]
4372   "TARGET_SH1"
4373   "xtrct        %1,%0"
4374   [(set_attr "type" "arith")])
4376 (define_insn "xtrct_right"
4377   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4378         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4379                              (const_int 16))
4380                 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
4381                            (const_int 16))))]
4382   "TARGET_SH1"
4383   "xtrct        %2,%0"
4384   [(set_attr "type" "arith")])
4386 ;; -------------------------------------------------------------------------
4387 ;; Unary arithmetic
4388 ;; -------------------------------------------------------------------------
4390 (define_insn "negc"
4391   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4392         (neg:SI (plus:SI (reg:SI T_REG)
4393                          (match_operand:SI 1 "arith_reg_operand" "r"))))
4394    (set (reg:SI T_REG)
4395         (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
4396                (const_int 0)))]
4397   "TARGET_SH1"
4398   "negc %1,%0"
4399   [(set_attr "type" "arith")])
4401 (define_insn "*negdi_media"
4402   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4403         (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
4404   "TARGET_SHMEDIA"
4405   "sub  r63, %1, %0"
4406   [(set_attr "type" "arith_media")])
4410 ;; Don't expand immediately because otherwise neg:DI (abs:DI) will not be
4411 ;; combined.
4412 (define_expand "negdi2"
4413   [(set (match_operand:DI 0 "arith_reg_dest" "")
4414         (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))
4415    (clobber (reg:SI T_REG))]
4416   ""
4417   "")
4419 (define_insn_and_split "*negdi2"
4420   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4421         (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
4422   "TARGET_SH1"
4423   "#"
4424   "TARGET_SH1"
4425   [(const_int 0)]
4426   "
4428   int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
4429   int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
4431   rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
4432   rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
4434   rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
4435   rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
4437   emit_insn (gen_clrt ());
4438   emit_insn (gen_negc (low_dst, low_src));
4439   emit_insn (gen_negc (high_dst, high_src));
4440   DONE;
4443 (define_insn "negsi2"
4444   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4445         (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4446   "TARGET_SH1"
4447   "neg  %1,%0"
4448   [(set_attr "type" "arith")])
4450 (define_insn "one_cmplsi2"
4451   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4452         (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4453   "TARGET_SH1"
4454   "not  %1,%0"
4455   [(set_attr "type" "arith")])
4457 (define_expand "one_cmpldi2"
4458   [(set (match_operand:DI 0 "arith_reg_dest" "")
4459         (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
4460                 (const_int -1)))]
4461   "TARGET_SHMEDIA" "")
4463 (define_expand "abssi2"
4464   [(set (match_operand:SI 0 "arith_reg_dest" "")
4465         (abs:SI (match_operand:SI 1 "arith_reg_operand" "")))
4466    (clobber (reg:SI T_REG))]
4467   ""
4468   "")
4470 (define_insn_and_split "*abssi2"
4471   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4472         (abs:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4473   "TARGET_SH1"
4474   "#"
4475   "TARGET_SH1"
4476   [(const_int 0)]
4477   "
4479   emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
4480   emit_insn (gen_negsi_cond (operands[0], operands[1], operands[1],
4481                  const1_rtx));
4482   DONE;
4485 (define_insn_and_split "*negabssi2"
4486   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4487         (neg:SI (abs:SI (match_operand:SI 1 "arith_reg_operand" "r"))))]
4488   "TARGET_SH1"
4489   "#"
4490   "TARGET_SH1"
4491   [(const_int 0)]
4492   "
4494   emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
4495   emit_insn (gen_negsi_cond (operands[0], operands[1], operands[1],
4496                  const0_rtx));
4497   DONE;
4501 ;; The SH4 202 can do zero-offset branches without pipeline stalls.
4502 ;; This can be used as some kind of conditional execution, which is useful
4503 ;; for abs.
4504 ;; Actually the instruction scheduling should decide whether to use a
4505 ;; zero-offset branch or not for any generic case involving a single
4506 ;; instruction on SH4 202.
4508 (define_insn_and_split "negsi_cond"
4509   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4510         (if_then_else:SI (eq:SI (reg:SI T_REG)
4511                           (match_operand:SI 3 "const_int_operand" "M,N"))
4512          (match_operand:SI 1 "arith_reg_operand" "0,0")
4513          (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
4514   "TARGET_HARD_SH4"
4515   "@
4516         bt\\t0f\;neg\\t%2,%0\\n0:
4517         bf\\t0f\;neg\\t%2,%0\\n0:"
4518   "!TARGET_HARD_SH4"
4519   [(const_int 0)]
4520   "
4522   rtx skip_neg_label = gen_label_rtx ();
4524   emit_insn (gen_movsi (operands[0], operands[1]));
4526   emit_jump_insn (INTVAL (operands[3])
4527                   ? gen_branch_true (skip_neg_label)
4528                   : gen_branch_false (skip_neg_label));
4530   emit_label_after (skip_neg_label,
4531                     emit_insn (gen_negsi2 (operands[0], operands[1])));
4532   DONE;
4534   [(set_attr "type" "arith") ;; poor approximation
4535    (set_attr "length" "4")])
4538 ;; -------------------------------------------------------------------------
4539 ;; Zero extension instructions
4540 ;; -------------------------------------------------------------------------
4542 (define_insn "zero_extendsidi2"
4543   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4544         (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
4545   "TARGET_SHMEDIA"
4546   "addz.l       %1, r63, %0"
4547   [(set_attr "type" "arith_media")
4548    (set_attr "highpart" "extend")])
4550 (define_insn "zero_extendhidi2"
4551   [(set (match_operand:DI 0 "register_operand" "=r,r")
4552         (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4553   "TARGET_SHMEDIA"
4554   "@
4555         #
4556         ld%M1.uw        %m1, %0"
4557   [(set_attr "type" "*,load_media")
4558    (set (attr "highpart")
4559         (cond [(match_test "sh_contains_memref_p (insn)")
4560                (const_string "user")]
4561               (const_string "ignore")))])
4563 (define_split
4564   [(set (match_operand:DI 0 "register_operand" "")
4565         (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4566   "TARGET_SHMEDIA && reload_completed"
4567   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4568    (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
4569   "
4571   if (GET_CODE (operands[1]) == TRUNCATE)
4572     operands[1] = XEXP (operands[1], 0);
4575 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
4576 ;; reload the entire truncate expression.
4577 (define_insn_and_split "*loaddi_trunc"
4578   [(set (match_operand 0 "any_register_operand" "=r")
4579         (truncate (match_operand:DI 1 "memory_operand" "m")))]
4580   "TARGET_SHMEDIA && reload_completed"
4581   "#"
4582   "TARGET_SHMEDIA && reload_completed"
4583   [(set (match_dup 0) (match_dup 1))]
4584   "operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));")
4586 (define_insn "zero_extendqidi2"
4587   [(set (match_operand:DI 0 "register_operand" "=r,r")
4588         (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4589   "TARGET_SHMEDIA"
4590   "@
4591         andi    %1, 255, %0
4592         ld%M1.ub        %m1, %0"
4593   [(set_attr "type" "arith_media,load_media")
4594    (set (attr "highpart")
4595         (cond [(match_test "sh_contains_memref_p (insn)")
4596                (const_string "user")]
4597               (const_string "ignore")))])
4599 (define_expand "zero_extendhisi2"
4600   [(set (match_operand:SI 0 "arith_reg_operand" "")
4601         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "")))]
4602   ""
4603   "
4605   if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], HImode))
4606     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4609 (define_insn "*zero_extendhisi2_compact"
4610   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4611         (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))]
4612   "TARGET_SH1"
4613   "extu.w       %1,%0"
4614   [(set_attr "type" "arith")])
4616 (define_insn "*zero_extendhisi2_media"
4617   [(set (match_operand:SI 0 "register_operand" "=r,r")
4618         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4619   "TARGET_SHMEDIA"
4620   "@
4621         #
4622         ld%M1.uw        %m1, %0"
4623   [(set_attr "type" "arith_media,load_media")
4624    (set (attr "highpart")
4625         (cond [(match_test "sh_contains_memref_p (insn)")
4626                (const_string "user")]
4627               (const_string "ignore")))])
4629 (define_split
4630   [(set (match_operand:SI 0 "register_operand" "")
4631         (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4632   "TARGET_SHMEDIA && reload_completed"
4633   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4634    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4635   "
4637   rtx op1 = operands[1];
4639   if (GET_CODE (op1) == TRUNCATE)
4640     op1 = XEXP (op1, 0);
4641   operands[2]
4642     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4643                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
4646 (define_expand "zero_extendqisi2"
4647   [(set (match_operand:SI 0 "arith_reg_operand" "")
4648         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
4649   ""
4650   "
4652   if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], QImode))
4653     operands[1] = copy_to_mode_reg (QImode, operands[1]);
4656 (define_insn "*zero_extendqisi2_compact"
4657   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4658         (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))]
4659   "TARGET_SH1"
4660   "extu.b       %1,%0"
4661   [(set_attr "type" "arith")])
4663 (define_insn "*zero_extendqisi2_media"
4664   [(set (match_operand:SI 0 "register_operand" "=r,r")
4665         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4666   "TARGET_SHMEDIA"
4667   "@
4668         andi    %1, 255, %0
4669         ld%M1.ub        %m1, %0"
4670   [(set_attr "type" "arith_media,load_media")
4671    (set (attr "highpart")
4672         (cond [(match_test "sh_contains_memref_p (insn)")
4673                (const_string "user")]
4674               (const_string "ignore")))])
4676 (define_insn "zero_extendqihi2"
4677   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4678         (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
4679   "TARGET_SH1"
4680   "extu.b       %1,%0"
4681   [(set_attr "type" "arith")])
4683 ;; -------------------------------------------------------------------------
4684 ;; Sign extension instructions
4685 ;; -------------------------------------------------------------------------
4687 ;; ??? This should be a define expand.
4688 ;; ??? Or perhaps it should be dropped?
4690 ;; convert_move generates good code for SH[1-4].
4691 (define_insn "extendsidi2"
4692   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
4693         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
4694   "TARGET_SHMEDIA"
4695   "@
4696         add.l   %1, r63, %0
4697         ld%M1.l %m1, %0
4698         fmov.sl %1, %0"
4699   [(set_attr "type" "arith_media,load_media,fpconv_media")
4700    (set (attr "highpart")
4701         (cond [(match_test "sh_contains_memref_p (insn)")
4702                (const_string "user")]
4703               (const_string "extend")))])
4705 (define_insn "extendhidi2"
4706   [(set (match_operand:DI 0 "register_operand" "=r,r")
4707         (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4708   "TARGET_SHMEDIA"
4709   "@
4710         #
4711         ld%M1.w %m1, %0"
4712   [(set_attr "type" "*,load_media")
4713    (set (attr "highpart")
4714         (cond [(match_test "sh_contains_memref_p (insn)")
4715                (const_string "user")]
4716               (const_string "ignore")))])
4718 (define_split
4719   [(set (match_operand:DI 0 "register_operand" "")
4720         (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4721   "TARGET_SHMEDIA && reload_completed"
4722   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4723    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
4724   "
4726   if (GET_CODE (operands[1]) == TRUNCATE)
4727     operands[1] = XEXP (operands[1], 0);
4730 (define_insn "extendqidi2"
4731   [(set (match_operand:DI 0 "register_operand" "=r,r")
4732         (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4733   "TARGET_SHMEDIA"
4734   "@
4735         #
4736         ld%M1.b %m1, %0"
4737   [(set_attr "type" "*,load_media")
4738    (set (attr "highpart")
4739         (cond [(match_test "sh_contains_memref_p (insn)")
4740                (const_string "user")]
4741               (const_string "ignore")))])
4743 (define_split
4744   [(set (match_operand:DI 0 "register_operand" "")
4745         (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
4746   "TARGET_SHMEDIA && reload_completed"
4747   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
4748    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
4749   "
4751   if (GET_CODE (operands[1]) == TRUNCATE)
4752     operands[1] = XEXP (operands[1], 0);
4755 (define_expand "extendhisi2"
4756   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4757         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4758   ""
4759   "")
4761 (define_insn "*extendhisi2_compact"
4762   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4763         (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))]
4764   "TARGET_SH1"
4765   "@
4766         exts.w  %1,%0
4767         mov.w   %1,%0"
4768   [(set_attr "type" "arith,load")])
4770 (define_insn "*extendhisi2_media"
4771   [(set (match_operand:SI 0 "register_operand" "=r,r")
4772         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4773   "TARGET_SHMEDIA"
4774   "@
4775         #
4776         ld%M1.w %m1, %0"
4777   [(set_attr "type" "arith_media,load_media")
4778    (set (attr "highpart")
4779         (cond [(match_test "sh_contains_memref_p (insn)")
4780                (const_string "user")]
4781               (const_string "ignore")))])
4783 (define_split
4784   [(set (match_operand:SI 0 "register_operand" "")
4785         (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4786   "TARGET_SHMEDIA && reload_completed"
4787   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4788    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4789   "
4791   rtx op1 = operands[1];
4792   if (GET_CODE (op1) == TRUNCATE)
4793     op1 = XEXP (op1, 0);
4794   operands[2]
4795     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4796                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
4799 (define_expand "extendqisi2"
4800   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4801         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4802   ""
4803   "")
4805 (define_insn "*extendqisi2_compact"
4806   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4807         (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
4808   "TARGET_SH1"
4809   "@
4810         exts.b  %1,%0
4811         mov.b   %1,%0"
4812   [(set_attr "type" "arith,load")
4813    (set_attr_alternative "length"
4814      [(const_int 2)
4815        (if_then_else
4816         (match_test "TARGET_SH2A")
4817         (const_int 4) (const_int 2))])])
4819 (define_insn "*extendqisi2_media"
4820   [(set (match_operand:SI 0 "register_operand" "=r,r")
4821         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4822   "TARGET_SHMEDIA"
4823   "@
4824         #
4825         ld%M1.b %m1, %0"
4826   [(set_attr "type" "arith_media,load_media")
4827    (set (attr "highpart")
4828         (cond [(match_test "sh_contains_memref_p (insn)")
4829                (const_string "user")]
4830               (const_string "ignore")))])
4832 (define_split
4833   [(set (match_operand:SI 0 "register_operand" "")
4834         (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
4835   "TARGET_SHMEDIA && reload_completed"
4836   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4837    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4838    "
4840   rtx op1 = operands[1];
4841   if (GET_CODE (op1) == TRUNCATE)
4842     op1 = XEXP (op1, 0);
4843   operands[2]
4844     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4845                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
4848 (define_insn "extendqihi2"
4849   [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4850         (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
4851   "TARGET_SH1"
4852   "@
4853         exts.b  %1,%0
4854         mov.b   %1,%0"
4855   [(set_attr "type" "arith,load")
4856    (set_attr_alternative "length"
4857      [(const_int 2)
4858        (if_then_else
4859         (match_test "TARGET_SH2A")
4860         (const_int 4) (const_int 2))])])
4862 /* It would seem useful to combine the truncXi patterns into the movXi
4863    patterns, but unary operators are ignored when matching constraints,
4864    so we need separate patterns.  */
4865 (define_insn "truncdisi2"
4866   [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
4867         (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
4868   "TARGET_SHMEDIA"
4869   "@
4870         add.l   %1, r63, %0
4871         st%M0.l %m0, %1
4872         fst%M0.s        %m0, %T1
4873         fmov.ls %1, %0
4874         fmov.sl %T1, %0
4875         fmov.s  %T1, %0"
4876   [(set_attr "type"   "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")
4877    (set (attr "highpart")
4878         (cond [(match_test "sh_contains_memref_p (insn)")
4879                (const_string "user")]
4880               (const_string "extend")))])
4882 (define_insn "truncdihi2"
4883   [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
4884         (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
4885   "TARGET_SHMEDIA"
4886   "@
4887         shlli\\t%1,48,%0\;shlri\\t%0,48,%0
4888         st%M0.w %m0, %1"
4889   [(set_attr "type"   "arith_media,store_media")
4890    (set_attr "length" "8,4")
4891    (set (attr "highpart")
4892         (cond [(match_test "sh_contains_memref_p (insn)")
4893                (const_string "user")]
4894               (const_string "extend")))])
4896 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
4897 ; Because we use zero extension, we can't provide signed QImode compares
4898 ; using a simple compare or conditional branch insn.
4899 (define_insn "truncdiqi2"
4900   [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
4901         (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
4902   "TARGET_SHMEDIA"
4903   "@
4904         andi    %1, 255, %0
4905         st%M0.b %m0, %1"
4906   [(set_attr "type"   "arith_media,store")
4907    (set (attr "highpart")
4908         (cond [(match_test "sh_contains_memref_p (insn)")
4909                (const_string "user")]
4910               (const_string "extend")))])
4911 ;; -------------------------------------------------------------------------
4912 ;; Move instructions
4913 ;; -------------------------------------------------------------------------
4915 ;; define push and pop so it is easy for sh.c
4916 ;; We can't use push and pop on SHcompact because the stack must always
4917 ;; be 8-byte aligned.
4919 (define_expand "push"
4920   [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
4921         (match_operand:SI 0 "register_operand" "r,l,x"))]
4922   "TARGET_SH1 && ! TARGET_SH5"
4923   "")
4925 (define_expand "pop"
4926   [(set (match_operand:SI 0 "register_operand" "=r,l,x")
4927         (mem:SI (post_inc:SI (reg:SI SP_REG))))]
4928   "TARGET_SH1 && ! TARGET_SH5"
4929   "")
4931 (define_expand "push_e"
4932   [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
4933                    (match_operand:SF 0 "" ""))
4934               (use (reg:PSI FPSCR_REG))
4935               (clobber (scratch:SI))])]
4936   "TARGET_SH1 && ! TARGET_SH5"
4937   "")
4939 (define_insn "push_fpul"
4940   [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
4941   "TARGET_SH2E && ! TARGET_SH5"
4942   "sts.l        fpul,@-r15"
4943   [(set_attr "type" "fstore")
4944    (set_attr "late_fp_use" "yes")
4945    (set_attr "hit_stack" "yes")])
4947 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
4948 ;; so use that.
4949 (define_expand "push_4"
4950   [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
4951                    (match_operand:DF 0 "" ""))
4952               (use (reg:PSI FPSCR_REG))
4953               (clobber (scratch:SI))])]
4954   "TARGET_SH1 && ! TARGET_SH5"
4955   "")
4957 (define_expand "pop_e"
4958   [(parallel [(set (match_operand:SF 0 "" "")
4959               (mem:SF (post_inc:SI (reg:SI SP_REG))))
4960               (use (reg:PSI FPSCR_REG))
4961               (clobber (scratch:SI))])]
4962   "TARGET_SH1 && ! TARGET_SH5"
4963   "")
4965 (define_insn "pop_fpul"
4966   [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
4967   "TARGET_SH2E && ! TARGET_SH5"
4968   "lds.l        @r15+,fpul"
4969   [(set_attr "type" "load")
4970    (set_attr "hit_stack" "yes")])
4972 (define_expand "pop_4"
4973   [(parallel [(set (match_operand:DF 0 "" "")
4974                    (mem:DF (post_inc:SI (reg:SI SP_REG))))
4975               (use (reg:PSI FPSCR_REG))
4976               (clobber (scratch:SI))])]
4977   "TARGET_SH1 && ! TARGET_SH5"
4978   "")
4980 (define_expand "push_fpscr"
4981   [(const_int 0)]
4982   "TARGET_SH2E"
4983   "
4985   rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
4986                                                  gen_rtx_PRE_DEC (Pmode,
4987                                                           stack_pointer_rtx)),
4988                                         get_fpscr_rtx ()));
4989   add_reg_note (insn, REG_INC, stack_pointer_rtx);
4990   DONE;
4993 (define_expand "pop_fpscr"
4994   [(const_int 0)]
4995   "TARGET_SH2E"
4996   "
4998   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
4999                                         gen_frame_mem (PSImode,
5000                                                  gen_rtx_POST_INC (Pmode,
5001                                                           stack_pointer_rtx))));
5002   add_reg_note (insn, REG_INC, stack_pointer_rtx);
5003   DONE;
5006 ;; These two patterns can happen as the result of optimization, when
5007 ;; comparisons get simplified to a move of zero or 1 into the T reg.
5008 ;; They don't disappear completely, because the T reg is a fixed hard reg.
5010 (define_insn "clrt"
5011   [(set (reg:SI T_REG) (const_int 0))]
5012   "TARGET_SH1"
5013   "clrt")
5015 (define_insn "sett"
5016   [(set (reg:SI T_REG) (const_int 1))]
5017   "TARGET_SH1"
5018   "sett")
5020 ;; Define additional pop for SH1 and SH2 so it does not get 
5021 ;; placed in the delay slot.
5022 (define_insn "*movsi_pop"
5023   [(set (match_operand:SI 0 "register_operand" "=r,x,l")
5024         (match_operand:SI 1 "sh_no_delay_pop_operand" ">,>,>"))]
5025   "(TARGET_SH1 || TARGET_SH2E || TARGET_SH2A)
5026    && ! TARGET_SH3"
5027   "@
5028    mov.l   %1,%0
5029    lds.l   %1,%0
5030    lds.l   %1,%0"
5031   [(set_attr "type" "load_si,mem_mac,pload")
5032    (set_attr "length" "2,2,2")
5033    (set_attr "in_delay_slot" "no,no,no")])
5035 ;; t/r must come after r/r, lest reload will try to reload stuff like
5036 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
5037 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
5038 (define_insn "movsi_i"
5039   [(set (match_operand:SI 0 "general_movdst_operand"
5040             "=r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
5041         (match_operand:SI 1 "general_movsrc_operand"
5042          "Q,r,I08,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
5043   "TARGET_SH1
5044    && ! TARGET_SH2E
5045    && ! TARGET_SH2A
5046    && (register_operand (operands[0], SImode)
5047        || register_operand (operands[1], SImode))"
5048   "@
5049         mov.l   %1,%0
5050         mov     %1,%0
5051         mov     %1,%0
5052         cmp/pl  %1
5053         mov.l   %1,%0
5054         sts     %1,%0
5055         sts     %1,%0
5056         movt    %0
5057         mov.l   %1,%0
5058         sts.l   %1,%0
5059         sts.l   %1,%0
5060         lds     %1,%0
5061         lds     %1,%0
5062         lds.l   %1,%0
5063         lds.l   %1,%0
5064         fake    %1,%0"
5065   [(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")
5066    (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
5068 ;; t/r must come after r/r, lest reload will try to reload stuff like
5069 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
5070 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
5071 ;; will require a reload.
5072 ;; ??? We can't include f/f because we need the proper FPSCR setting when
5073 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
5074 (define_insn "movsi_ie"
5075   [(set (match_operand:SI 0 "general_movdst_operand"
5076             "=r,r,r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
5077         (match_operand:SI 1 "general_movsrc_operand"
5078          "Q,r,I08,I20,I28,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
5079   "(TARGET_SH2E || TARGET_SH2A)
5080    && (register_operand (operands[0], SImode)
5081        || register_operand (operands[1], SImode))"
5082   "@
5083         mov.l   %1,%0
5084         mov     %1,%0
5085         mov     %1,%0
5086         movi20  %1,%0
5087         movi20s %1,%0
5088         cmp/pl  %1
5089         mov.l   %1,%0
5090         sts     %1,%0
5091         sts     %1,%0
5092         movt    %0
5093         mov.l   %1,%0
5094         sts.l   %1,%0
5095         sts.l   %1,%0
5096         lds     %1,%0
5097         lds     %1,%0
5098         lds.l   %1,%0
5099         lds.l   %1,%0
5100         lds.l   %1,%0
5101         sts.l   %1,%0
5102         fake    %1,%0
5103         lds     %1,%0
5104         sts     %1,%0
5105         fsts    fpul,%0
5106         flds    %1,fpul
5107         fmov    %1,%0
5108         ! move optimized away"
5109   [(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")
5110    (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
5111    (set_attr_alternative "length"
5112      [(const_int 2)
5113       (const_int 2)
5114       (const_int 2)
5115       (const_int 4)
5116       (const_int 4)
5117       (const_int 2)
5118       (if_then_else
5119         (match_test "TARGET_SH2A")
5120         (const_int 4) (const_int 2))
5121       (const_int 2)
5122       (const_int 2)
5123       (const_int 2)
5124       (if_then_else
5125         (match_test "TARGET_SH2A")
5126         (const_int 4) (const_int 2))
5127       (const_int 2)
5128       (const_int 2)
5129       (const_int 2)
5130       (const_int 2)
5131       (const_int 2)
5132       (const_int 2)
5133       (const_int 2)
5134       (const_int 2)
5135       (const_int 2)
5136       (const_int 2)
5137       (const_int 2)
5138       (const_int 2)
5139       (const_int 2)
5140       (const_int 2)
5141       (const_int 0)])])
5143 (define_insn "movsi_i_lowpart"
5144   [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,r,m,r"))
5145         (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,t,r,i"))]
5146    "TARGET_SH1
5147     && (register_operand (operands[0], SImode)
5148         || register_operand (operands[1], SImode))"
5149   "@
5150         mov.l   %1,%0
5151         mov     %1,%0
5152         mov     %1,%0
5153         mov.l   %1,%0
5154         sts     %1,%0
5155         sts     %1,%0
5156         movt    %0
5157         mov.l   %1,%0
5158         fake    %1,%0"
5159   [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,arith,store,pcload")])
5161 (define_insn_and_split "load_ra"
5162   [(set (match_operand:SI 0 "general_movdst_operand" "")
5163         (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
5164   "TARGET_SH1"
5165   "#"
5166   "&& ! currently_expanding_to_rtl"
5167   [(set (match_dup 0) (match_dup 1))]
5168   "
5170   if (TARGET_SHCOMPACT && crtl->saves_all_registers)
5171     operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
5174 ;; The '?'s in the following constraints may not reflect the time taken
5175 ;; to perform the move. They are there to discourage the use of floating-
5176 ;; point registers for storing integer values.
5177 (define_insn "*movsi_media"
5178   [(set (match_operand:SI 0 "general_movdst_operand"
5179                 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
5180         (match_operand:SI 1 "general_movsrc_operand"
5181          "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5182   "TARGET_SHMEDIA_FPU
5183    && (register_operand (operands[0], SImode)
5184        || sh_register_operand (operands[1], SImode)
5185        || GET_CODE (operands[1]) == TRUNCATE)"
5186   "@
5187         add.l   %1, r63, %0
5188         movi    %1, %0
5189         #
5190         ld%M1.l %m1, %0
5191         st%M0.l %m0, %N1
5192         fld%M1.s        %m1, %0
5193         fst%M0.s        %m0, %1
5194         fmov.ls %N1, %0
5195         fmov.sl %1, %0
5196         fmov.s  %1, %0
5197         ptabs   %1, %0
5198         gettr   %1, %0
5199         pt      %1, %0"
5200   [(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")
5201    (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
5202    (set (attr "highpart")
5203         (cond [(match_test "sh_contains_memref_p (insn)")
5204                (const_string "user")]
5205               (const_string "ignore")))])
5207 (define_insn "*movsi_media_nofpu"
5208   [(set (match_operand:SI 0 "general_movdst_operand"
5209                 "=r,r,r,r,m,*b,r,*b")
5210         (match_operand:SI 1 "general_movsrc_operand"
5211          "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
5212   "TARGET_SHMEDIA
5213    && (register_operand (operands[0], SImode)
5214        || sh_register_operand (operands[1], SImode)
5215        || GET_CODE (operands[1]) == TRUNCATE)"
5216   "@
5217         add.l   %1, r63, %0
5218         movi    %1, %0
5219         #
5220         ld%M1.l %m1, %0
5221         st%M0.l %m0, %N1
5222         ptabs   %1, %0
5223         gettr   %1, %0
5224         pt      %1, %0"
5225   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5226    (set_attr "length" "4,4,8,4,4,4,4,12")
5227    (set (attr "highpart")
5228         (cond [(match_test "sh_contains_memref_p (insn)")
5229                (const_string "user")]
5230               (const_string "ignore")))])
5232 (define_expand "movsi_const"
5233   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5234         (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
5235                               (const_int 16)] UNSPEC_EXTRACT_S16)))
5236    (set (match_dup 0)
5237         (ior:SI (ashift:SI (match_dup 0) (const_int 16))
5238                 (const:SI (unspec:SI [(match_dup 1)
5239                                       (const_int 0)] UNSPEC_EXTRACT_U16))))]
5240   "TARGET_SHMEDIA && reload_completed
5241    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5242   "
5244   if (GET_CODE (operands[1]) == LABEL_REF
5245       && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
5246     LABEL_NUSES (XEXP (operands[1], 0)) += 2;
5247   else if (GOTOFF_P (operands[1]))
5248     {
5249       rtx unspec = XEXP (operands[1], 0);
5251       if (! UNSPEC_GOTOFF_P (unspec))
5252         {
5253           unspec = XEXP (unspec, 0);
5254           if (! UNSPEC_GOTOFF_P (unspec))
5255             abort ();
5256         }
5257       if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
5258           && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
5259         LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
5260     }
5263 (define_expand "movsi_const_16bit"
5264   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5265         (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
5266                               (const_int 0)] UNSPEC_EXTRACT_S16)))]
5267   "TARGET_SHMEDIA && flag_pic && reload_completed
5268    && GET_CODE (operands[1]) == SYMBOL_REF"
5269   "")
5271 (define_split
5272   [(set (match_operand:SI 0 "arith_reg_dest" "")
5273         (match_operand:SI 1 "immediate_operand" ""))]
5274   "TARGET_SHMEDIA && reload_completed
5275    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5276   [(const_int 0)]
5277   "
5279   rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
5281   set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
5283   DONE;
5286 (define_split
5287   [(set (match_operand:SI 0 "register_operand" "")
5288         (match_operand:SI 1 "immediate_operand" ""))]
5289   "TARGET_SHMEDIA && reload_completed
5290    && ((CONST_INT_P (operands[1])
5291         && ! satisfies_constraint_I16 (operands[1]))
5292        || GET_CODE (operands[1]) == CONST_DOUBLE)"
5293   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5295 (define_expand "movsi"
5296   [(set (match_operand:SI 0 "general_movdst_operand" "")
5297         (match_operand:SI 1 "general_movsrc_operand" ""))]
5298   ""
5299   "{ if (prepare_move_operands (operands, SImode)) DONE; }")
5301 (define_expand "ic_invalidate_line"
5302   [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
5303                                 (match_dup 1)] UNSPEC_ICACHE)
5304               (clobber (scratch:SI))])]
5305   "TARGET_HARD_SH4 || TARGET_SH5"
5306   "
5308   if (TARGET_SHMEDIA)
5309     {
5310       emit_insn (gen_ic_invalidate_line_media (operands[0]));
5311       DONE;
5312     }
5313   else if (TARGET_SHCOMPACT)
5314     {
5315       operands[1] = function_symbol (NULL, \"__ic_invalidate\", SFUNC_STATIC);
5316       operands[1] = force_reg (Pmode, operands[1]);
5317       emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
5318       DONE;
5319     }
5320   else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
5321     {
5322       emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
5323       DONE;
5324     }
5325   operands[0] = force_reg (Pmode, operands[0]);
5326   operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
5327                                                                Pmode)));
5330 ;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
5331 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
5332 ;; the requirement *1*00 for associative address writes.  The alignment of
5333 ;; %0 implies that its least significant bit is cleared,
5334 ;; thus we clear the V bit of a matching entry if there is one.
5335 (define_insn "ic_invalidate_line_i"
5336   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
5337                      (match_operand:SI 1 "register_operand" "r")]
5338                      UNSPEC_ICACHE)
5339    (clobber (match_scratch:SI 2 "=&r"))]
5340   "TARGET_HARD_SH4"
5341   "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
5342   [(set_attr "length" "8")
5343    (set_attr "type" "cwb")])
5345 (define_insn "ic_invalidate_line_sh4a"
5346   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
5347                     UNSPEC_ICACHE)]
5348   "TARGET_SH4A_ARCH || TARGET_SH4_300"
5349   "ocbwb\\t@%0\;synco\;icbi\\t@%0"
5350   [(set_attr "length" "16")
5351    (set_attr "type" "cwb")])
5353 ;; ??? could make arg 0 an offsettable memory operand to allow to save
5354 ;; an add in the code that calculates the address.
5355 (define_insn "ic_invalidate_line_media"
5356   [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
5357                     UNSPEC_ICACHE)]
5358   "TARGET_SHMEDIA"
5359   "ocbwb        %0,0\;synco\;icbi       %0, 0\;synci"
5360   [(set_attr "length" "16")
5361    (set_attr "type" "invalidate_line_media")])
5363 (define_insn "ic_invalidate_line_compact"
5364   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5365                      (match_operand:SI 1 "register_operand" "r")]
5366                     UNSPEC_ICACHE)
5367    (clobber (reg:SI PR_REG))]
5368   "TARGET_SHCOMPACT"
5369   "jsr @%1%#"
5370   [(set_attr "type" "sfunc")
5371    (set_attr "needs_delay_slot" "yes")])
5373 (define_expand "initialize_trampoline"
5374   [(match_operand:SI 0 "" "")
5375    (match_operand:SI 1 "" "")
5376    (match_operand:SI 2 "" "")]
5377   "TARGET_SHCOMPACT"
5378   "
5380   rtx sfun, tramp;
5382   tramp = force_reg (Pmode, operands[0]);
5383   sfun = force_reg (Pmode, function_symbol (NULL, \"__init_trampoline\",
5384                                             SFUNC_STATIC));
5385   emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
5386   emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
5388   emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
5389   DONE;
5392 (define_insn "initialize_trampoline_compact"
5393   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5394                      (match_operand:SI 1 "register_operand" "r")
5395                      (reg:SI R2_REG) (reg:SI R3_REG)]
5396                     UNSPEC_INIT_TRAMP)
5398    (clobber (reg:SI PR_REG))]
5399   "TARGET_SHCOMPACT"
5400   "jsr @%1%#"
5401   [(set_attr "type" "sfunc")
5402    (set_attr "needs_delay_slot" "yes")])
5404 (define_insn "movqi_i"
5405   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m,r,r,l")
5406         (match_operand:QI 1 "general_movsrc_operand"  "r,i,m,r,t,l,r"))]
5407   "TARGET_SH1
5408    && (arith_reg_operand (operands[0], QImode)
5409        || arith_reg_operand (operands[1], QImode))"
5410   "@
5411         mov     %1,%0
5412         mov     %1,%0
5413         mov.b   %1,%0
5414         mov.b   %1,%0
5415         movt    %0
5416         sts     %1,%0
5417         lds     %1,%0"
5418  [(set_attr "type" "move,movi8,load,store,arith,prget,prset")
5419   (set_attr_alternative "length"
5420      [(const_int 2)
5421       (const_int 2)
5422       (if_then_else
5423         (match_test "TARGET_SH2A")
5424         (const_int 4) (const_int 2))
5425       (if_then_else
5426         (match_test "TARGET_SH2A")
5427         (const_int 4) (const_int 2))
5428       (const_int 2)
5429       (const_int 2)
5430       (const_int 2)])])
5432 (define_insn "*movqi_media"
5433   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
5434         (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
5435   "TARGET_SHMEDIA
5436    && (arith_reg_operand (operands[0], QImode)
5437        || extend_reg_or_0_operand (operands[1], QImode))"
5438   "@
5439         add.l   %1, r63, %0
5440         movi    %1, %0
5441         ld%M1.ub        %m1, %0
5442         st%M0.b %m0, %N1"
5443   [(set_attr "type" "arith_media,arith_media,load_media,store_media")
5444    (set (attr "highpart")
5445         (cond [(match_test "sh_contains_memref_p (insn)")
5446                (const_string "user")]
5447               (const_string "ignore")))])
5449 (define_expand "movqi"
5450   [(set (match_operand:QI 0 "general_operand" "")
5451         (match_operand:QI 1 "general_operand"  ""))]
5452   ""
5453   "{ if (prepare_move_operands (operands, QImode)) DONE; }")
5455 (define_expand "reload_inqi"
5456   [(set (match_operand:SI 2 "" "=&r")
5457         (match_operand:QI 1 "inqhi_operand" ""))
5458    (set (match_operand:QI 0 "arith_reg_operand" "=r")
5459         (truncate:QI (match_dup 3)))]
5460   "TARGET_SHMEDIA"
5461   "
5463   rtx inner = XEXP (operands[1], 0);
5464   int regno = REGNO (inner);
5466   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5467   operands[1] = gen_rtx_REG (SImode, regno);
5468   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5471 /* When storing r0, we have to avoid reg+reg addressing.  */
5472 (define_insn "movhi_i"
5473   [(set (match_operand:HI 0 "general_movdst_operand"   "=r,r,r,r,m,r,l,r")
5474         (match_operand:HI 1 "general_movsrc_operand" "Q,rI08,m,t,r,l,r,i"))]
5475   "TARGET_SH1
5476    && (arith_reg_operand (operands[0], HImode)
5477        || arith_reg_operand (operands[1], HImode))
5478    && (!MEM_P (operands[0])
5479        || GET_CODE (XEXP (operands[0], 0)) != PLUS
5480        || !REG_P (XEXP (XEXP (operands[0], 0), 1))
5481        || ! refers_to_regno_p (R0_REG, R0_REG + 1, operands[1], (rtx *)0))"
5482   "@
5483         mov.w   %1,%0
5484         mov     %1,%0
5485         mov.w   %1,%0
5486         movt    %0
5487         mov.w   %1,%0
5488         sts     %1,%0
5489         lds     %1,%0
5490         fake    %1,%0"
5491   [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
5493 (define_insn "*movhi_media"
5494   [(set (match_operand:HI 0 "general_movdst_operand"     "=r,r,r,r,m")
5495         (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
5496   "TARGET_SHMEDIA
5497    && (arith_reg_operand (operands[0], HImode)
5498        || arith_reg_or_0_operand (operands[1], HImode))"
5499   "@
5500         add.l   %1, r63, %0
5501         movi    %1, %0
5502         #
5503         ld%M1.w %m1, %0
5504         st%M0.w %m0, %N1"
5505   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
5506    (set (attr "highpart")
5507         (cond [(match_test "sh_contains_memref_p (insn)")
5508                (const_string "user")]
5509               (const_string "ignore")))])
5511 (define_split
5512   [(set (match_operand:HI 0 "register_operand" "")
5513         (match_operand:HI 1 "immediate_operand" ""))]
5514   "TARGET_SHMEDIA && reload_completed
5515    && ! satisfies_constraint_I16 (operands[1])"
5516   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5518 (define_expand "movhi"
5519   [(set (match_operand:HI 0 "general_movdst_operand" "")
5520         (match_operand:HI 1 "general_movsrc_operand"  ""))]
5521   ""
5522   "{ if (prepare_move_operands (operands, HImode)) DONE; }")
5524 (define_expand "reload_inhi"
5525   [(set (match_operand:SI 2 "" "=&r")
5526         (match_operand:HI 1 "inqhi_operand" ""))
5527    (set (match_operand:HI 0 "arith_reg_operand" "=r")
5528         (truncate:HI (match_dup 3)))]
5529   "TARGET_SHMEDIA"
5530   "
5532   rtx inner = XEXP (operands[1], 0);
5533   int regno = REGNO (inner);
5535   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5536   operands[1] = gen_rtx_REG (SImode, regno);
5537   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5540 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
5541 ;; compiled with -m2 -ml -O3 -funroll-loops
5542 (define_insn "*movdi_i"
5543   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
5544         (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
5545   "TARGET_SH1
5546    && (arith_reg_operand (operands[0], DImode)
5547        || arith_reg_operand (operands[1], DImode))"
5548   "* return output_movedouble (insn, operands, DImode);"
5549   [(set_attr "length" "4")
5550    (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
5552 ;; If the output is a register and the input is memory or a register, we have
5553 ;; to be careful and see which word needs to be loaded first.
5555 (define_split
5556   [(set (match_operand:DI 0 "general_movdst_operand" "")
5557         (match_operand:DI 1 "general_movsrc_operand" ""))]
5558   "TARGET_SH1 && reload_completed"
5559   [(set (match_dup 2) (match_dup 3))
5560    (set (match_dup 4) (match_dup 5))]
5561   "
5563   int regno;
5565   if ((MEM_P (operands[0])
5566        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
5567       || (MEM_P (operands[1])
5568           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
5569     FAIL;
5571   switch (GET_CODE (operands[0]))
5572     {
5573     case REG:
5574       regno = REGNO (operands[0]);
5575       break;
5576     case SUBREG:
5577       regno = subreg_regno (operands[0]);
5578       break;
5579     case MEM:
5580       regno = -1;
5581       break;
5582     default:
5583       gcc_unreachable ();
5584     }
5586   if (regno == -1
5587       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
5588     {
5589       operands[2] = operand_subword (operands[0], 0, 0, DImode);
5590       operands[3] = operand_subword (operands[1], 0, 0, DImode);
5591       operands[4] = operand_subword (operands[0], 1, 0, DImode);
5592       operands[5] = operand_subword (operands[1], 1, 0, DImode);
5593     }
5594   else
5595     {
5596       operands[2] = operand_subword (operands[0], 1, 0, DImode);
5597       operands[3] = operand_subword (operands[1], 1, 0, DImode);
5598       operands[4] = operand_subword (operands[0], 0, 0, DImode);
5599       operands[5] = operand_subword (operands[1], 0, 0, DImode);
5600     }
5602   if (operands[2] == 0 || operands[3] == 0
5603       || operands[4] == 0 || operands[5] == 0)
5604     FAIL;
5607 ;; The '?'s in the following constraints may not reflect the time taken
5608 ;; to perform the move. They are there to discourage the use of floating-
5609 ;; point registers for storing integer values.
5610 (define_insn "*movdi_media"
5611   [(set (match_operand:DI 0 "general_movdst_operand"
5612                  "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
5613         (match_operand:DI 1 "general_movsrc_operand"
5614          "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5615   "TARGET_SHMEDIA_FPU
5616    && (register_operand (operands[0], DImode)
5617        || sh_register_operand (operands[1], DImode))"
5618   "@
5619         add     %1, r63, %0
5620         movi    %1, %0
5621         #
5622         ld%M1.q %m1, %0
5623         st%M0.q %m0, %N1
5624         fld%M1.d        %m1, %0
5625         fst%M0.d        %m0, %1
5626         fmov.qd %N1, %0
5627         fmov.dq %1, %0
5628         fmov.d  %1, %0
5629         ptabs   %1, %0
5630         gettr   %1, %0
5631         pt      %1, %0"
5632   [(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")
5633    (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
5635 (define_insn "*movdi_media_nofpu"
5636   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
5637         (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
5638   "TARGET_SHMEDIA
5639    && (register_operand (operands[0], DImode)
5640        || sh_register_operand (operands[1], DImode))"
5641   "@
5642         add     %1, r63, %0
5643         movi    %1, %0
5644         #
5645         ld%M1.q %m1, %0
5646         st%M0.q %m0, %N1
5647         ptabs   %1, %0
5648         gettr   %1, %0
5649         pt      %1, %0"
5650   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5651    (set_attr "length" "4,4,16,4,4,4,4,*")])
5653 (define_insn "*movdi_media_I16"
5654   [(set (match_operand:DI 0 "ext_dest_operand" "=r")
5655         (match_operand:DI 1 "const_int_operand" "I16"))]
5656   "TARGET_SHMEDIA && reload_completed"
5657   "movi %1, %0"
5658   [(set_attr "type" "arith_media")
5659    (set_attr "length" "4")])
5661 (define_split
5662   [(set (match_operand:DI 0 "arith_reg_dest" "")
5663         (match_operand:DI 1 "immediate_operand" ""))]
5664   "TARGET_SHMEDIA && reload_completed
5665    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5666   [(set (match_dup 0) (match_dup 1))]
5667   "
5669   rtx insn;
5671   if (TARGET_SHMEDIA64)
5672     insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
5673   else
5674     insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
5676   set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
5678   DONE;
5681 (define_expand "movdi_const"
5682   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5683         (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5684                               (const_int 48)] UNSPEC_EXTRACT_S16)))
5685    (set (match_dup 0)
5686         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5687                 (const:DI (unspec:DI [(match_dup 1)
5688                                       (const_int 32)] UNSPEC_EXTRACT_U16))))
5689    (set (match_dup 0)
5690         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5691                 (const:DI (unspec:DI [(match_dup 1)
5692                                       (const_int 16)] UNSPEC_EXTRACT_U16))))
5693    (set (match_dup 0)
5694         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5695                 (const:DI (unspec:DI [(match_dup 1)
5696                                       (const_int 0)] UNSPEC_EXTRACT_U16))))]
5697   "TARGET_SHMEDIA64 && reload_completed
5698    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5699   "
5701   sh_mark_label (operands[1], 4);
5704 (define_expand "movdi_const_32bit"
5705   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5706         (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5707                               (const_int 16)] UNSPEC_EXTRACT_S16)))
5708    (set (match_dup 0)
5709         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5710                 (const:DI (unspec:DI [(match_dup 1)
5711                                       (const_int 0)] UNSPEC_EXTRACT_U16))))]
5712   "TARGET_SHMEDIA32 && reload_completed
5713    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5714   "
5716   sh_mark_label (operands[1], 2);
5719 (define_expand "movdi_const_16bit"
5720   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5721         (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5722                               (const_int 0)] UNSPEC_EXTRACT_S16)))]
5723   "TARGET_SHMEDIA && flag_pic && reload_completed
5724    && GET_CODE (operands[1]) == SYMBOL_REF"
5725   "")
5727 (define_split
5728   [(set (match_operand:DI 0 "ext_dest_operand" "")
5729         (match_operand:DI 1 "immediate_operand" ""))]
5730   "TARGET_SHMEDIA && reload_completed
5731    && CONST_INT_P (operands[1])
5732    && ! satisfies_constraint_I16 (operands[1])"
5733   [(set (match_dup 0) (match_dup 2))
5734    (match_dup 1)]
5735   "
5737   unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
5738   unsigned HOST_WIDE_INT low = val;
5739   unsigned HOST_WIDE_INT high = val;
5740   unsigned HOST_WIDE_INT sign;
5741   unsigned HOST_WIDE_INT val2 = val ^ (val-1);
5743   /* Zero-extend the 16 least-significant bits.  */
5744   low &= 0xffff;
5746   /* Arithmetic shift right the word by 16 bits.  */
5747   high >>= 16;
5748   if (GET_CODE (operands[0]) == SUBREG
5749       && GET_MODE (SUBREG_REG (operands[0])) == SImode)
5750     {
5751       high &= 0xffff;
5752       high ^= 0x8000;
5753       high -= 0x8000;
5754     }
5755   else
5756     {
5757       sign = 1;
5758       sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5759       high ^= sign;
5760       high -= sign;
5761     }
5762   do
5763     {
5764       /* If we can't generate the constant with a two-insn movi / shori
5765          sequence, try some other strategies.  */
5766       if (! CONST_OK_FOR_I16 (high))
5767         {
5768           /* Try constant load / left shift.  We know VAL != 0.  */
5769           val2 = val ^ (val-1);
5770           if (val2 > 0x1ffff)
5771             {
5772               int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
5774               if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
5775                   || (! CONST_OK_FOR_I16 (high >> 16)
5776                       && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
5777                 {
5778                   val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
5779                   operands[1] = gen_ashldi3_media (operands[0], operands[0],
5780                                                    GEN_INT (trailing_zeroes));
5781                   break;
5782                 }
5783             }
5784           /* Try constant load / right shift.  */
5785           val2 = (val >> 15) + 1;
5786           if (val2 == (val2 & -val2))
5787             {
5788               int shift = 49 - exact_log2 (val2);
5790               val2 = trunc_int_for_mode (val << shift, DImode);
5791               if (CONST_OK_FOR_I16 (val2))
5792                 {
5793                   operands[1] = gen_lshrdi3_media (operands[0], operands[0],
5794                                                    GEN_INT (shift));
5795                   break;
5796                 }
5797             }
5798           /* Try mperm.w .  */
5799           val2 = val & 0xffff;
5800           if ((val >> 16 & 0xffff) == val2
5801               && (val >> 32 & 0xffff) == val2
5802               && (val >> 48 & 0xffff) == val2)
5803             {
5804               val2 = (HOST_WIDE_INT) val >> 48;
5805               operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
5806               operands[1] = gen_mperm_w0 (operands[1], operands[1]);
5807               break;
5808             }
5809           /* Try movi / mshflo.l  */
5810           val2 = (HOST_WIDE_INT) val >> 32;
5811           if (val2 == ((unsigned HOST_WIDE_INT)
5812                         trunc_int_for_mode (val, SImode)))
5813             {
5814               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5815                                              operands[0]);
5816               break;
5817             }
5818           /* Try movi / mshflo.l w/ r63.  */
5819           val2 = val + ((HOST_WIDE_INT) -1 << 32);
5820           if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
5821             {
5822               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5823                                              const0_rtx);
5824               break;
5825             }
5826         }
5827       val2 = high;
5828       operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
5829     }
5830   while (0);
5831   operands[2] = GEN_INT (val2);
5834 (define_split
5835   [(set (match_operand:DI 0 "ext_dest_operand" "")
5836         (match_operand:DI 1 "immediate_operand" ""))]
5837   "TARGET_SHMEDIA && reload_completed
5838    && GET_CODE (operands[1]) == CONST_DOUBLE"
5839   [(set (match_dup 0) (match_dup 2))
5840   (set (match_dup 0)
5841        (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
5842   "
5844   unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
5845   unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
5846   unsigned HOST_WIDE_INT val = low;
5847   unsigned HOST_WIDE_INT sign;
5849   /* Zero-extend the 16 least-significant bits.  */
5850   val &= 0xffff;
5851   operands[1] = GEN_INT (val);
5853   /* Arithmetic shift right the double-word by 16 bits.  */
5854   low >>= 16;
5855   low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
5856   high >>= 16;
5857   sign = 1;
5858   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5859   high ^= sign;
5860   high -= sign;
5862   /* This will only be true if high is a sign-extension of low, i.e.,
5863      it must be either 0 or (unsigned)-1, and be zero iff the
5864      most-significant bit of low is set.  */
5865   if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
5866     operands[2] = GEN_INT (low);
5867   else
5868     operands[2] = immed_double_const (low, high, DImode);
5871 (define_insn "shori_media"
5872   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5873         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
5874                            (const_int 16))
5875                 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
5876   "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
5877   "@
5878         shori   %u2, %0
5879         #"
5880   [(set_attr "type" "arith_media,*")])
5882 (define_insn "*shori_media_si"
5883   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5884         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5885                            (const_int 16))
5886                 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
5887   "TARGET_SHMEDIA"
5888   "shori        %u2, %0")
5890 (define_expand "movdi"
5891   [(set (match_operand:DI 0 "general_movdst_operand" "")
5892         (match_operand:DI 1 "general_movsrc_operand" ""))]
5893   ""
5894   "{ if (prepare_move_operands (operands, DImode)) DONE; }")
5896 (define_insn "movdf_media"
5897   [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
5898         (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
5899   "TARGET_SHMEDIA_FPU
5900    && (register_operand (operands[0], DFmode)
5901        || sh_register_operand (operands[1], DFmode))"
5902   "@
5903         fmov.d  %1, %0
5904         fmov.qd %N1, %0
5905         fmov.dq %1, %0
5906         add     %1, r63, %0
5907         #
5908         fld%M1.d        %m1, %0
5909         fst%M0.d        %m0, %1
5910         ld%M1.q %m1, %0
5911         st%M0.q %m0, %N1"
5912   [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
5914 (define_insn "movdf_media_nofpu"
5915   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
5916         (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
5917   "TARGET_SHMEDIA
5918    && (register_operand (operands[0], DFmode)
5919        || sh_register_operand (operands[1], DFmode))"
5920   "@
5921         add     %1, r63, %0
5922         #
5923         ld%M1.q %m1, %0
5924         st%M0.q %m0, %N1"
5925   [(set_attr "type" "arith_media,*,load_media,store_media")])
5927 (define_split
5928   [(set (match_operand:DF 0 "arith_reg_dest" "")
5929         (match_operand:DF 1 "immediate_operand" ""))]
5930   "TARGET_SHMEDIA && reload_completed"
5931   [(set (match_dup 3) (match_dup 2))]
5932   "
5934   int endian = WORDS_BIG_ENDIAN ? 1 : 0;
5935   long values[2];
5936   REAL_VALUE_TYPE value;
5938   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
5939   REAL_VALUE_TO_TARGET_DOUBLE (value, values);
5941   if (HOST_BITS_PER_WIDE_INT >= 64)
5942     operands[2] = immed_double_const ((unsigned long) values[endian]
5943                                       | ((HOST_WIDE_INT) values[1 - endian]
5944                                          << 32), 0, DImode);
5945   else
5946     {
5947       gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
5948       operands[2] = immed_double_const (values[endian], values[1 - endian],
5949                                         DImode);
5950     }
5952   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
5955 ;; ??? This should be a define expand.
5957 (define_insn "movdf_k"
5958   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
5959         (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
5960   "TARGET_SH1
5961    && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
5962        /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
5963        || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
5964        || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
5965    && (arith_reg_operand (operands[0], DFmode)
5966        || arith_reg_operand (operands[1], DFmode))"
5967   "* return output_movedouble (insn, operands, DFmode);"
5968   [(set_attr "length" "4")
5969    (set_attr "type" "move,pcload,load,store")])
5971 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
5972 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
5973 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
5974 ;; the d/m/c/X alternative, which is split later into single-precision
5975 ;; instructions.  And when not optimizing, no splits are done before fixing
5976 ;; up pcloads, so we need usable length information for that.
5977 (define_insn "movdf_i4"
5978   [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
5979         (match_operand:DF 1 "general_movsrc_operand"  "d,r,F,m,d,FQ,m,r,d,r"))
5980    (use (match_operand:PSI 2 "fpscr_operand"          "c,c,c,c,c,c,c,c,c,c"))
5981    (clobber (match_scratch:SI 3                      "=X,X,&z,X,X,X,X,X,X,X"))]
5982   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
5983    && (arith_reg_operand (operands[0], DFmode)
5984        || arith_reg_operand (operands[1], DFmode))"
5985   {
5986     switch (which_alternative)
5987     {
5988     case 0:
5989       if (TARGET_FMOVD)
5990         return "fmov    %1,%0";
5991       else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
5992         return "fmov    %R1,%R0\n\tfmov %S1,%S0";
5993       else
5994         return "fmov    %S1,%S0\n\tfmov %R1,%R0";
5995     case 3:
5996     case 4:
5997       return "fmov.d    %1,%0";
5998     default:
5999       return "#";
6000     }
6001   }
6002   [(set_attr_alternative "length"
6003      [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
6004       (const_int 4)
6005       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
6006       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
6007       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
6008       (const_int 4)
6009       (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
6010       ;; We can't use 4-byte push/pop on SHcompact, so we have to
6011       ;; increment or decrement r15 explicitly.
6012       (if_then_else
6013        (match_test "TARGET_SHCOMPACT")
6014        (const_int 10) (const_int 8))
6015       (if_then_else
6016        (match_test "TARGET_SHCOMPACT")
6017        (const_int 10) (const_int 8))])
6018    (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
6019    (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
6020    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
6021                                            (const_string "double")
6022                                            (const_string "none")))])
6024 ;; Moving DFmode between fp/general registers through memory
6025 ;; (the top of the stack) is faster than moving through fpul even for
6026 ;; little endian.  Because the type of an instruction is important for its
6027 ;; scheduling,  it is beneficial to split these operations, rather than
6028 ;; emitting them in one single chunk, even if this will expose a stack
6029 ;; use that will prevent scheduling of other stack accesses beyond this
6030 ;; instruction.
6031 (define_split
6032   [(set (match_operand:DF 0 "register_operand" "")
6033         (match_operand:DF 1 "register_operand" ""))
6034    (use (match_operand:PSI 2 "fpscr_operand" ""))
6035    (clobber (match_scratch:SI 3 "=X"))]
6036   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
6037    && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
6038   [(const_int 0)]
6039   "
6041   rtx insn, tos;
6043   if (TARGET_SH5 && true_regnum (operands[1]) < 16)
6044     {
6045       emit_move_insn (stack_pointer_rtx,
6046                       plus_constant (stack_pointer_rtx, -8));
6047       tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
6048     }
6049   else
6050     tos = gen_tmp_stack_mem (DFmode,
6051                              gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
6052   insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
6053   if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
6054     add_reg_note (insn, REG_INC, stack_pointer_rtx);
6055   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
6056     tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
6057   else
6058     tos = gen_tmp_stack_mem (DFmode,
6059                              gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
6060   insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
6061   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
6062     emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
6063   else
6064     add_reg_note (insn, REG_INC, stack_pointer_rtx);
6065   DONE;
6068 ;; local-alloc sometimes allocates scratch registers even when not required,
6069 ;; so we must be prepared to handle these.
6071 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
6072 (define_split
6073   [(set (match_operand:DF 0 "general_movdst_operand" "")
6074         (match_operand:DF 1 "general_movsrc_operand"  ""))
6075    (use (match_operand:PSI 2 "fpscr_operand" ""))
6076    (clobber (match_scratch:SI 3 ""))]
6077   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
6078    && reload_completed
6079    && true_regnum (operands[0]) < 16
6080    && true_regnum (operands[1]) < 16"
6081   [(set (match_dup 0) (match_dup 1))]
6082   "
6084   /* If this was a reg <-> mem operation with base + index reg addressing,
6085      we have to handle this in a special way.  */
6086   rtx mem = operands[0];
6087   int store_p = 1;
6088   if (! memory_operand (mem, DFmode))
6089     {
6090       mem = operands[1];
6091       store_p = 0;
6092     }
6093   if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
6094     mem = SUBREG_REG (mem);
6095   if (MEM_P (mem))
6096     {
6097       rtx addr = XEXP (mem, 0);
6098       if (GET_CODE (addr) == PLUS
6099           && REG_P (XEXP (addr, 0))
6100           && REG_P (XEXP (addr, 1)))
6101         {
6102           int offset;
6103           rtx reg0 = gen_rtx_REG (Pmode, 0);
6104           rtx regop = operands[store_p], word0 ,word1;
6106           if (GET_CODE (regop) == SUBREG)
6107             alter_subreg (&regop);
6108           if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
6109             offset = 2;
6110           else
6111             offset = 4;
6112           mem = copy_rtx (mem);
6113           PUT_MODE (mem, SImode);
6114           word0 = gen_rtx_SUBREG (SImode, regop, 0);
6115           alter_subreg (&word0);
6116           word1 = gen_rtx_SUBREG (SImode, regop, 4);
6117           alter_subreg (&word1);
6118           if (store_p || ! refers_to_regno_p (REGNO (word0),
6119                                               REGNO (word0) + 1, addr, 0))
6120             {
6121               emit_insn (store_p
6122                          ? gen_movsi_ie (mem, word0)
6123                          : gen_movsi_ie (word0, mem));
6124               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
6125               mem = copy_rtx (mem);
6126               emit_insn (store_p
6127                          ? gen_movsi_ie (mem, word1)
6128                          : gen_movsi_ie (word1, mem));
6129               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
6130             }
6131           else
6132             {
6133               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
6134               emit_insn (gen_movsi_ie (word1, mem));
6135               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
6136               mem = copy_rtx (mem);
6137               emit_insn (gen_movsi_ie (word0, mem));
6138             }
6139           DONE;
6140         }
6141     }
6144 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
6145 (define_split
6146   [(set (match_operand:DF 0 "register_operand" "")
6147         (match_operand:DF 1 "memory_operand"  ""))
6148    (use (match_operand:PSI 2 "fpscr_operand" ""))
6149    (clobber (reg:SI R0_REG))]
6150   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
6151   [(parallel [(set (match_dup 0) (match_dup 1))
6152               (use (match_dup 2))
6153               (clobber (scratch:SI))])]
6154   "")
6156 (define_expand "reload_indf__frn"
6157   [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
6158                    (match_operand:DF 1 "immediate_operand" "FQ"))
6159               (use (reg:PSI FPSCR_REG))
6160               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6161   "TARGET_SH1"
6162   "")
6164 (define_expand "reload_outdf__RnFRm"
6165   [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
6166                    (match_operand:DF 1 "register_operand" "af,r"))
6167               (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
6168   "TARGET_SH1"
6169   "")
6171 ;; Simplify no-op moves.
6172 (define_split
6173   [(set (match_operand:SF 0 "register_operand" "")
6174         (match_operand:SF 1 "register_operand" ""))
6175    (use (match_operand:PSI 2 "fpscr_operand" ""))
6176    (clobber (match_scratch:SI 3 ""))]
6177   "TARGET_SH2E && reload_completed
6178    && true_regnum (operands[0]) == true_regnum (operands[1])"
6179   [(set (match_dup 0) (match_dup 0))]
6180   "")
6182 ;; fmovd substitute post-reload splits
6183 (define_split
6184   [(set (match_operand:DF 0 "register_operand" "")
6185         (match_operand:DF 1 "register_operand" ""))
6186    (use (match_operand:PSI 2 "fpscr_operand" ""))
6187    (clobber (match_scratch:SI 3 ""))]
6188   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
6189    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
6190    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6191   [(const_int 0)]
6192   "
6194   int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
6195   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
6196                            gen_rtx_REG (SFmode, src), operands[2]));
6197   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
6198                            gen_rtx_REG (SFmode, src + 1), operands[2]));
6199   DONE;
6202 (define_split
6203   [(set (match_operand:DF 0 "register_operand" "")
6204         (mem:DF (match_operand:SI 1 "register_operand" "")))
6205    (use (match_operand:PSI 2 "fpscr_operand" ""))
6206    (clobber (match_scratch:SI 3 ""))]
6207   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6208    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
6209    && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
6210   [(const_int 0)]
6211   "
6213   int regno = true_regnum (operands[0]);
6214   rtx insn;
6215   rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
6216   rtx mem2
6217     = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
6218   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6219                                            regno + !! TARGET_LITTLE_ENDIAN),
6220                                   mem2, operands[2]));
6221   add_reg_note (insn, REG_INC, operands[1]);
6222   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6223                                                regno + ! TARGET_LITTLE_ENDIAN),
6224                                   change_address (mem, SFmode, NULL_RTX),
6225                                   operands[2]));
6226   DONE;
6229 (define_split
6230   [(set (match_operand:DF 0 "register_operand" "")
6231         (match_operand:DF 1 "memory_operand" ""))
6232    (use (match_operand:PSI 2 "fpscr_operand" ""))
6233    (clobber (match_scratch:SI 3 ""))]
6234   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6235    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
6236   [(const_int 0)]
6238   int regno = true_regnum (operands[0]);
6239   rtx addr, insn;
6240   rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
6241   rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
6242   rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
6244   operands[1] = copy_rtx (mem2);
6245   addr = XEXP (mem2, 0);
6247   switch (GET_CODE (addr))
6248     {
6249     case REG:
6250       /* This is complicated.  If the register is an arithmetic register
6251          we can just fall through to the REG+DISP case below.  Otherwise
6252          we have to use a combination of POST_INC and REG addressing...  */
6253       if (! arith_reg_operand (operands[1], SFmode))
6254         {
6255           XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
6256           insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
6257           add_reg_note (insn, REG_INC, XEXP (addr, 0));
6258           
6259           emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6261           /* If we have modified the stack pointer, the value that we have
6262              read with post-increment might be modified by an interrupt,
6263              so write it back.  */
6264           if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
6265             emit_insn (gen_push_e (reg0));
6266           else
6267             emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0), GEN_INT (-4)));
6268           break;
6269         }
6270       /* Fall through.  */
6271          
6272     case PLUS:
6273       emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
6274       operands[1] = copy_rtx (operands[1]);
6275       XEXP (operands[1], 0) = plus_constant (addr, 4);
6276       emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6277       break;
6278       
6279     case POST_INC:
6280       insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
6281       add_reg_note (insn, REG_INC, XEXP (addr, 0));
6282     
6283       insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6284       add_reg_note (insn, REG_INC, XEXP (addr, 0));
6285       break;
6287     default:
6288       debug_rtx (addr);
6289       gcc_unreachable ();
6290     }
6292   DONE;
6295 (define_split
6296   [(set (match_operand:DF 0 "memory_operand" "")
6297         (match_operand:DF 1 "register_operand" ""))
6298    (use (match_operand:PSI 2 "fpscr_operand" ""))
6299    (clobber (match_scratch:SI 3 ""))]
6300   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6301    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6302   [(const_int 0)]
6304   int regno = true_regnum (operands[1]);
6305   rtx insn, addr;
6306   rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
6307   rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
6309   operands[0] = copy_rtx (operands[0]);
6310   PUT_MODE (operands[0], SFmode);
6311   addr = XEXP (operands[0], 0);
6313   switch (GET_CODE (addr))
6314     {
6315     case REG:
6316       /* This is complicated.  If the register is an arithmetic register
6317          we can just fall through to the REG+DISP case below.  Otherwise
6318          we have to use a combination of REG and PRE_DEC addressing...  */
6319       if (! arith_reg_operand (operands[0], SFmode))
6320         {
6321           emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
6322           emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
6324           operands[0] = copy_rtx (operands[0]);
6325           XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
6326           
6327           insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6328           add_reg_note (insn, REG_INC, XEXP (addr, 0));
6329           break;
6330         }
6331       /* Fall through.  */
6332       
6333     case PLUS:
6334       /* Since REG+DISP addressing has already been decided upon by gcc
6335          we can rely upon it having chosen an arithmetic register as the
6336          register component of the address.  Just emit the lower numbered
6337          register first, to the lower address, then the higher numbered
6338          register to the higher address.  */
6339       emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6341       operands[0] = copy_rtx (operands[0]);
6342       XEXP (operands[0], 0) = plus_constant (addr, 4);
6344       emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));         
6345       break;
6346       
6347     case PRE_DEC:
6348       /* This is easy.  Output the word to go to the higher address
6349          first (ie the word in the higher numbered register) then the
6350          word to go to the lower address.  */
6352       insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
6353       add_reg_note (insn, REG_INC, XEXP (addr, 0));
6355       insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6356       add_reg_note (insn, REG_INC, XEXP (addr, 0));
6357       break;
6358       
6359     default:
6360       /* FAIL; */
6361       debug_rtx (addr);
6362       gcc_unreachable ();
6363     }
6365   DONE;
6368 ;; If the output is a register and the input is memory or a register, we have
6369 ;; to be careful and see which word needs to be loaded first.
6371 (define_split
6372   [(set (match_operand:DF 0 "general_movdst_operand" "")
6373         (match_operand:DF 1 "general_movsrc_operand" ""))]
6374   "TARGET_SH1 && reload_completed"
6375   [(set (match_dup 2) (match_dup 3))
6376    (set (match_dup 4) (match_dup 5))]
6377   "
6379   int regno;
6381   if ((MEM_P (operands[0])
6382        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
6383       || (MEM_P (operands[1])
6384           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
6385     FAIL;
6387   switch (GET_CODE (operands[0]))
6388     {
6389     case REG:
6390       regno = REGNO (operands[0]);
6391       break;
6392     case SUBREG:
6393       regno = subreg_regno (operands[0]);
6394       break;
6395     case MEM:
6396       regno = -1;
6397       break;
6398     default:
6399       gcc_unreachable ();
6400     }
6402   if (regno == -1
6403       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
6404     {
6405       operands[2] = operand_subword (operands[0], 0, 0, DFmode);
6406       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
6407       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
6408       operands[5] = operand_subword (operands[1], 1, 0, DFmode);
6409     }
6410   else
6411     {
6412       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
6413       operands[3] = operand_subword (operands[1], 1, 0, DFmode);
6414       operands[4] = operand_subword (operands[0], 0, 0, DFmode);
6415       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
6416     }
6418   if (operands[2] == 0 || operands[3] == 0
6419       || operands[4] == 0 || operands[5] == 0)
6420     FAIL;
6423 ;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is
6424 ;; used only once, let combine add in the index again.
6426 (define_split
6427   [(set (match_operand:SI 0 "register_operand" "")
6428         (match_operand:SI 1 "" ""))
6429    (clobber (match_operand 2 "register_operand" ""))]
6430   "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6431    && ALLOW_INDEXED_ADDRESS"
6432   [(use (reg:SI R0_REG))]
6433   "
6435   rtx addr, reg, const_int;
6437   if (!MEM_P (operands[1]))
6438     FAIL;
6439   addr = XEXP (operands[1], 0);
6440   if (GET_CODE (addr) != PLUS)
6441     FAIL;
6442   reg = XEXP (addr, 0);
6443   const_int = XEXP (addr, 1);
6444   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6445          && CONST_INT_P (const_int)))
6446     FAIL;
6447   emit_move_insn (operands[2], const_int);
6448   emit_move_insn (operands[0],
6449                   change_address (operands[1], VOIDmode,
6450                                   gen_rtx_PLUS (SImode, reg, operands[2])));
6451   DONE;
6454 (define_split
6455   [(set (match_operand:SI 1 "" "")
6456         (match_operand:SI 0 "register_operand" ""))
6457    (clobber (match_operand 2 "register_operand" ""))]
6458   "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6459    && ALLOW_INDEXED_ADDRESS"
6460   [(use (reg:SI R0_REG))]
6461   "
6463   rtx addr, reg, const_int;
6465   if (!MEM_P (operands[1]))
6466     FAIL;
6467   addr = XEXP (operands[1], 0);
6468   if (GET_CODE (addr) != PLUS)
6469     FAIL;
6470   reg = XEXP (addr, 0);
6471   const_int = XEXP (addr, 1);
6472   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6473          && CONST_INT_P (const_int)))
6474     FAIL;
6475   emit_move_insn (operands[2], const_int);
6476   emit_move_insn (change_address (operands[1], VOIDmode,
6477                                   gen_rtx_PLUS (SImode, reg, operands[2])),
6478                   operands[0]);
6479   DONE;
6482 (define_expand "movdf"
6483   [(set (match_operand:DF 0 "general_movdst_operand" "")
6484         (match_operand:DF 1 "general_movsrc_operand" ""))]
6485   ""
6486   "
6488   if (prepare_move_operands (operands, DFmode)) DONE;
6489   if (TARGET_SHMEDIA)
6490     {
6491       if (TARGET_SHMEDIA_FPU)
6492         emit_insn (gen_movdf_media (operands[0], operands[1]));
6493       else
6494         emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
6495       DONE;
6496     }
6497   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
6498     {
6499       emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
6500       DONE;
6501     }
6504 ;;This is incompatible with the way gcc uses subregs.
6505 ;;(define_insn "movv2sf_i"
6506 ;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
6507 ;;      (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
6508 ;;  "TARGET_SHMEDIA_FPU
6509 ;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
6510 ;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
6511 ;;  "@
6512 ;;      #
6513 ;;      fld%M1.p        %m1, %0
6514 ;;      fst%M0.p        %m0, %1"
6515 ;;  [(set_attr "type" "*,fload_media,fstore_media")])
6517 (define_insn_and_split "movv2sf_i"
6518   [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6519         (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6520   "TARGET_SHMEDIA_FPU"
6521   "#"
6522   "TARGET_SHMEDIA_FPU && reload_completed"
6523   [(set (match_dup 0) (match_dup 1))]
6524   "
6526   operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
6527   operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
6530 (define_expand "movv2sf"
6531   [(set (match_operand:V2SF 0 "general_movdst_operand" "")
6532         (match_operand:V2SF 1 "nonimmediate_operand" ""))]
6533   "TARGET_SHMEDIA_FPU"
6534   "
6536   if (prepare_move_operands (operands, V2SFmode))
6537     DONE;
6540 (define_expand "addv2sf3"
6541   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6542    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6543    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6544   "TARGET_SHMEDIA_FPU"
6545   "
6547   sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
6548   DONE;
6551 (define_expand "subv2sf3"
6552   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6553    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6554    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6555   "TARGET_SHMEDIA_FPU"
6556   "
6558   sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
6559   DONE;
6562 (define_expand "mulv2sf3"
6563   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6564    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6565    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6566   "TARGET_SHMEDIA_FPU"
6567   "
6569   sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
6570   DONE;
6573 (define_expand "divv2sf3"
6574   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6575    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6576    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6577   "TARGET_SHMEDIA_FPU"
6578   "
6580   sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
6581   DONE;
6584 (define_insn_and_split "*movv4sf_i"
6585   [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6586         (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6587   "TARGET_SHMEDIA_FPU"
6588   "#"
6589   "&& reload_completed"
6590   [(const_int 0)]
6591   "
6593   int i;
6595   for (i = 0; i < 4/2; i++)
6596     {
6597       rtx x, y;
6599       if (MEM_P (operands[0]))
6600         x = adjust_address (operands[0], V2SFmode,
6601                             i * GET_MODE_SIZE (V2SFmode));
6602       else
6603         x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
6605       if (MEM_P (operands[1]))
6606         y = adjust_address (operands[1], V2SFmode,
6607                             i * GET_MODE_SIZE (V2SFmode));
6608       else
6609         y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
6611       emit_insn (gen_movv2sf_i (x, y));
6612     }
6614   DONE;
6616   [(set_attr "length" "8")])
6618 (define_expand "movv4sf"
6619   [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
6620         (match_operand:V4SF 1 "general_operand" ""))]
6621   "TARGET_SHMEDIA_FPU"
6622   "
6624   if (prepare_move_operands (operands, V4SFmode))
6625     DONE;
6628 (define_insn_and_split "*movv16sf_i"
6629   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6630         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6631   "TARGET_SHMEDIA_FPU"
6632   "#"
6633   "&& reload_completed"
6634   [(const_int 0)]
6635   "
6637   int i;
6639   for (i = 0; i < 16/2; i++)
6640     {
6641       rtx x,y;
6643       if (MEM_P (operands[0]))
6644         x = adjust_address (operands[0], V2SFmode,
6645                             i * GET_MODE_SIZE (V2SFmode));
6646       else
6647         {
6648           x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
6649           alter_subreg (&x);
6650         }
6652       if (MEM_P (operands[1]))
6653         y = adjust_address (operands[1], V2SFmode,
6654                             i * GET_MODE_SIZE (V2SFmode));
6655       else
6656         {
6657           y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
6658           alter_subreg (&y);
6659         }
6661       emit_insn (gen_movv2sf_i (x, y));
6662     }
6664   DONE;
6666   [(set_attr "length" "32")])
6668 (define_expand "movv16sf"
6669   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6670         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6671   "TARGET_SHMEDIA_FPU"
6672   "
6674   if (prepare_move_operands (operands, V16SFmode))
6675     DONE;
6678 (define_insn "movsf_media"
6679   [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
6680         (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
6681   "TARGET_SHMEDIA_FPU
6682    && (register_operand (operands[0], SFmode)
6683        || sh_register_operand (operands[1], SFmode))"
6684   "@
6685         fmov.s  %1, %0
6686         fmov.ls %N1, %0
6687         fmov.sl %1, %0
6688         add.l   %1, r63, %0
6689         #
6690         fld%M1.s        %m1, %0
6691         fst%M0.s        %m0, %1
6692         ld%M1.l %m1, %0
6693         st%M0.l %m0, %N1"
6694   [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
6695    (set (attr "highpart")
6696         (cond [(match_test "sh_contains_memref_p (insn)")
6697                (const_string "user")]
6698               (const_string "ignore")))])
6700 (define_insn "movsf_media_nofpu"
6701   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
6702         (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
6703   "TARGET_SHMEDIA
6704    && (register_operand (operands[0], SFmode)
6705        || sh_register_operand (operands[1], SFmode))"
6706   "@
6707         add.l   %1, r63, %0
6708         #
6709         ld%M1.l %m1, %0
6710         st%M0.l %m0, %N1"
6711   [(set_attr "type" "arith_media,*,load_media,store_media")
6712    (set (attr "highpart")
6713         (cond [(match_test "sh_contains_memref_p (insn)")
6714                (const_string "user")]
6715               (const_string "ignore")))])
6717 (define_split
6718   [(set (match_operand:SF 0 "arith_reg_dest" "")
6719         (match_operand:SF 1 "immediate_operand" ""))]
6720   "TARGET_SHMEDIA && reload_completed
6721    && ! FP_REGISTER_P (true_regnum (operands[0]))"
6722   [(set (match_dup 3) (match_dup 2))]
6723   "
6725   long values;
6726   REAL_VALUE_TYPE value;
6728   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
6729   REAL_VALUE_TO_TARGET_SINGLE (value, values);
6730   operands[2] = GEN_INT (values);
6732   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6735 (define_insn "movsf_i"
6736   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
6737         (match_operand:SF 1 "general_movsrc_operand"  "r,G,FQ,mr,r,r,l"))]
6738   "TARGET_SH1
6739    && (! TARGET_SH2E
6740        /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
6741        || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
6742        || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
6743    && (arith_reg_operand (operands[0], SFmode)
6744        || arith_reg_operand (operands[1], SFmode))"
6745   "@
6746         mov     %1,%0
6747         mov     #0,%0
6748         mov.l   %1,%0
6749         mov.l   %1,%0
6750         mov.l   %1,%0
6751         lds     %1,%0
6752         sts     %1,%0"
6753   [(set_attr "type" "move,move,pcload,load,store,move,move")])
6755 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
6756 ;; update_flow_info would not know where to put REG_EQUAL notes
6757 ;; when the destination changes mode.
6758 (define_insn "movsf_ie"
6759   [(set (match_operand:SF 0 "general_movdst_operand"
6760          "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
6761         (match_operand:SF 1 "general_movsrc_operand"
6762           "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
6763    (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"))
6764    (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
6766   "TARGET_SH2E
6767    && (arith_reg_operand (operands[0], SFmode)
6768        || arith_reg_operand (operands[1], SFmode)
6769        || arith_reg_operand (operands[3], SImode)
6770        || (fpul_operand (operands[0], SFmode)
6771            && memory_operand (operands[1], SFmode)
6772            && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
6773        || (fpul_operand (operands[1], SFmode)
6774            && memory_operand (operands[0], SFmode)
6775            && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
6776   "@
6777         fmov    %1,%0
6778         mov     %1,%0
6779         fldi0   %0
6780         fldi1   %0
6781         #
6782         fmov.s  %1,%0
6783         fmov.s  %1,%0
6784         mov.l   %1,%0
6785         mov.l   %1,%0
6786         mov.l   %1,%0
6787         fsts    fpul,%0
6788         flds    %1,fpul
6789         lds.l   %1,%0
6790         #
6791         sts     %1,%0
6792         lds     %1,%0
6793         sts.l   %1,%0
6794         lds.l   %1,%0
6795         ! move optimized away"
6796   [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
6797    (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
6798    (set_attr_alternative "length"
6799      [(const_int 2)
6800       (const_int 2)
6801       (const_int 2)
6802       (const_int 2)
6803       (const_int 4)
6804       (if_then_else
6805         (match_test "TARGET_SH2A")
6806         (const_int 4) (const_int 2))
6807       (if_then_else
6808         (match_test "TARGET_SH2A")
6809         (const_int 4) (const_int 2))
6810       (const_int 2)
6811       (if_then_else
6812         (match_test "TARGET_SH2A")
6813         (const_int 4) (const_int 2))
6814       (if_then_else
6815         (match_test "TARGET_SH2A")
6816         (const_int 4) (const_int 2))
6817       (const_int 2)
6818       (const_int 2)
6819       (const_int 2)
6820       (const_int 4)
6821       (const_int 2)
6822       (const_int 2)
6823       (const_int 2)
6824       (const_int 2)
6825       (const_int 0)])
6826    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
6827                                            (const_string "single")
6828                                            (const_string "single")))])
6830 (define_split
6831   [(set (match_operand:SF 0 "register_operand" "")
6832         (match_operand:SF 1 "register_operand" ""))
6833    (use (match_operand:PSI 2 "fpscr_operand" ""))
6834    (clobber (reg:SI FPUL_REG))]
6835   "TARGET_SH1"
6836   [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
6837               (use (match_dup 2))
6838               (clobber (scratch:SI))])
6839    (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
6840               (use (match_dup 2))
6841               (clobber (scratch:SI))])]
6842   "")
6844 (define_expand "movsf"
6845   [(set (match_operand:SF 0 "general_movdst_operand" "")
6846         (match_operand:SF 1 "general_movsrc_operand" ""))]
6847   ""
6848   "
6850   if (prepare_move_operands (operands, SFmode))
6851     DONE;
6852   if (TARGET_SHMEDIA)
6853     {
6854       if (TARGET_SHMEDIA_FPU)
6855         emit_insn (gen_movsf_media (operands[0], operands[1]));
6856       else
6857         emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
6858       DONE;
6859     }
6860   if (TARGET_SH2E)
6861     {
6862       emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
6863       DONE;
6864     }
6867 (define_insn "mov_nop"
6868   [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
6869   "TARGET_SH2E"
6870   ""
6871   [(set_attr "length" "0")
6872    (set_attr "type" "nil")])
6874 (define_expand "reload_insf__frn"
6875   [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
6876                    (match_operand:SF 1 "immediate_operand" "FQ"))
6877               (use (reg:PSI FPSCR_REG))
6878               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6879   "TARGET_SH1"
6880   "")
6882 (define_expand "reload_insi__i_fpul"
6883   [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
6884                    (match_operand:SI 1 "immediate_operand" "i"))
6885               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6886   "TARGET_SH1"
6887   "")
6889 (define_expand "ptabs"
6890   [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
6891   "TARGET_SHMEDIA"
6892   "
6894   if (!TARGET_PT_FIXED)
6895     {
6896       rtx eq = operands[1];
6898       /* ??? For canonical RTL we really should remove any CONST from EQ
6899          before wrapping it in the AND, and finally wrap the EQ into a
6900          const if is constant.  However, for reload we must expose the
6901          input register or symbolic constant, and we can't have
6902          different insn structures outside of the operands for different
6903          alternatives of the same pattern.  */
6904       eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
6905                        GEN_INT (3));
6906       operands[1]
6907         = (gen_rtx_IF_THEN_ELSE
6908             (PDImode,
6909              eq,
6910              gen_rtx_MEM (PDImode, operands[1]),
6911              gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
6912                             PDImode, operands[1])));
6913     }
6916 ;; expanded by ptabs expander.
6917 (define_insn "*extendsipdi_media"
6918   [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
6919         (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
6920                                                           "r,Csy")
6921                                       (const_int 3))
6922                               (const_int 3))
6923                           (mem:PDI (match_dup 1))
6924                           (sign_extend:PDI (match_dup 1))))]
6925   "TARGET_SHMEDIA && !TARGET_PT_FIXED"
6926   "@
6927         ptabs   %1, %0
6928         pt      %1, %0"
6929   [(set_attr "type"   "ptabs_media,pt_media")
6930    (set_attr "length" "4,*")])
6932 (define_insn "*truncdipdi_media"
6933   [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
6934         (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
6935                                                           "r,Csy")
6936                                       (const_int 3))
6937                               (const_int 3))
6938                           (mem:PDI (match_dup 1))
6939                           (truncate:PDI (match_dup 1))))]
6940   "TARGET_SHMEDIA && !TARGET_PT_FIXED"
6941   "@
6942         ptabs   %1, %0
6943         pt      %1, %0"
6944   [(set_attr "type"   "ptabs_media,pt_media")
6945    (set_attr "length" "4,*")])
6947 (define_insn "*movsi_y"
6948   [(set (match_operand:SI 0 "register_operand" "=y,y")
6949         (match_operand:SI 1 "immediate_operand" "Qi,I08"))
6950    (clobber (match_scratch:SI 2 "=&z,r"))]
6951   "TARGET_SH2E
6952    && (reload_in_progress || reload_completed)"
6953   "#"
6954   [(set_attr "length" "4")
6955    (set_attr "type" "pcload,move")])
6957 (define_split
6958   [(set (match_operand:SI 0 "register_operand" "")
6959         (match_operand:SI 1 "immediate_operand" ""))
6960    (clobber (match_operand:SI 2 "register_operand" ""))]
6961   "TARGET_SH1"
6962   [(set (match_dup 2) (match_dup 1))
6963    (set (match_dup 0) (match_dup 2))]
6964   "")
6966 (define_split
6967   [(set (match_operand:SI 0 "register_operand" "")
6968         (match_operand:SI 1 "memory_operand" ""))
6969    (clobber (reg:SI R0_REG))]
6970   "TARGET_SH1"
6971   [(set (match_dup 0) (match_dup 1))]
6972   "")
6974 ;; ------------------------------------------------------------------------
6975 ;; Define the real conditional branch instructions.
6976 ;; ------------------------------------------------------------------------
6978 (define_insn "branch_true"
6979   [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
6980                            (label_ref (match_operand 0 "" ""))
6981                            (pc)))]
6982   "TARGET_SH1"
6983   "* return output_branch (1, insn, operands);"
6984   [(set_attr "type" "cbranch")])
6986 (define_insn "branch_false"
6987   [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
6988                            (label_ref (match_operand 0 "" ""))
6989                            (pc)))]
6990   "TARGET_SH1"
6991   "* return output_branch (0, insn, operands);"
6992   [(set_attr "type" "cbranch")])
6994 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
6995 ;; which destination is too far away.
6996 ;; The const_int_operand is distinct for each branch target; it avoids
6997 ;; unwanted matches with redundant_insn.
6998 (define_insn "block_branch_redirect"
6999   [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
7000   "TARGET_SH1"
7001   ""
7002   [(set_attr "length" "0")])
7004 ;; This one has the additional purpose to record a possible scratch register
7005 ;; for the following branch.
7006 ;; ??? Unfortunately, just setting the scratch register is not good enough,
7007 ;; because the insn then might be deemed dead and deleted.  And we can't
7008 ;; make the use in the jump insn explicit because that would disable
7009 ;; delay slot scheduling from the target.
7010 (define_insn "indirect_jump_scratch"
7011   [(set (match_operand:SI 0 "register_operand" "=r")
7012         (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
7013    (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
7014   "TARGET_SH1"
7015   ""
7016   [(set_attr "length" "0")])
7018 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
7019 ;; being pulled into the delay slot of a condbranch that has been made to
7020 ;; jump around the unconditional jump because it was out of range.
7021 (define_insn "stuff_delay_slot"
7022   [(set (pc)
7023         (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
7024                  (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
7025   "TARGET_SH1"
7026   ""
7027   [(set_attr "length" "0")
7028    (set_attr "cond_delay_slot" "yes")])
7030 ;; Conditional branch insns
7032 (define_expand "cbranchint4_media"
7033   [(set (pc)
7034         (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
7035                        [(match_operand 1 "" "")
7036                         (match_operand 2 "" "")])
7037                       (match_operand 3 "" "")
7038                       (pc)))]
7039   "TARGET_SHMEDIA"
7040   "
7042   enum machine_mode mode = GET_MODE (operands[1]);
7043   if (mode == VOIDmode)
7044     mode = GET_MODE (operands[2]);
7045   if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
7046     {
7047       operands[1] = force_reg (mode, operands[1]);
7048       if (CONSTANT_P (operands[2])
7049           && (! satisfies_constraint_I06 (operands[2])))
7050         operands[2] = force_reg (mode, operands[2]);
7051     }
7052   else
7053     {
7054       if (operands[1] != const0_rtx)
7055         operands[1] = force_reg (mode, operands[1]);
7056       if (operands[2] != const0_rtx)
7057         operands[2] = force_reg (mode, operands[2]);
7058     }
7059   switch (GET_CODE (operands[0]))
7060     {
7061     case LEU:
7062     case LE:
7063     case LTU:
7064     case LT:
7065       operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
7066                                     VOIDmode, operands[2], operands[1]);
7067       operands[1] = XEXP (operands[0], 0);
7068       operands[2] = XEXP (operands[0], 1);
7069       break;
7070     default:
7071       operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
7072                                     VOIDmode, operands[1], operands[2]);
7073       break;
7074     }
7075   operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
7078 (define_expand "cbranchfp4_media"
7079   [(set (pc)
7080         (if_then_else (match_operator 0 "sh_float_comparison_operator"
7081                        [(match_operand 1 "" "")
7082                         (match_operand 2 "" "")])
7083                       (match_operand 3 "" "")
7084                       (pc)))]
7085   "TARGET_SHMEDIA"
7086   "
7088   rtx tmp = gen_reg_rtx (SImode);
7089   rtx cmp;
7090   if (GET_CODE (operands[0]) == NE)
7091     cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
7092   else
7093     cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
7094                           operands[1], operands[2]);
7096   emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
7098   if (GET_CODE (cmp) == GET_CODE (operands[0]))
7099     operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
7100   else
7101     operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
7102   operands[1] = tmp;
7103   operands[2] = const0_rtx;
7104   operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
7107 (define_insn "*beq_media_i"
7108   [(set (pc)
7109         (if_then_else (match_operator 3 "equality_comparison_operator"
7110                         [(match_operand:DI 1 "arith_reg_operand" "r,r")
7111                          (match_operand:DI 2 "arith_operand" "r,I06")])
7112                       (match_operand 0 "target_operand" "b,b")
7113                       (pc)))]
7114   "TARGET_SHMEDIA"
7115   "@
7116         b%o3%'  %1, %2, %0%>
7117         b%o3i%' %1, %2, %0%>"
7118   [(set_attr "type" "cbranch_media")])
7120 (define_insn "*beq_media_i32"
7121   [(set (pc)
7122         (if_then_else (match_operator 3 "equality_comparison_operator"
7123                         [(match_operand:SI 1 "arith_reg_operand" "r,r")
7124                          (match_operand:SI 2 "arith_operand" "r,I06")])
7125                       (match_operand 0 "target_operand" "b,b")
7126                       (pc)))]
7127   "TARGET_SHMEDIA"
7128   "@
7129         b%o3%'  %1, %2, %0%>
7130         b%o3i%' %1, %2, %0%>"
7131   [(set_attr "type" "cbranch_media")])
7133 (define_insn "*bgt_media_i"
7134   [(set (pc)
7135         (if_then_else (match_operator 3 "greater_comparison_operator"
7136                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
7137                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
7138                       (match_operand 0 "target_operand" "b")
7139                       (pc)))]
7140   "TARGET_SHMEDIA"
7141   "b%o3%'       %N1, %N2, %0%>"
7142   [(set_attr "type" "cbranch_media")])
7144 (define_insn "*bgt_media_i32"
7145   [(set (pc)
7146         (if_then_else (match_operator 3 "greater_comparison_operator"
7147                         [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
7148                          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
7149                       (match_operand 0 "target_operand" "b")
7150                       (pc)))]
7151   "TARGET_SHMEDIA"
7152   "b%o3%'       %N1, %N2, %0%>"
7153   [(set_attr "type" "cbranch_media")])
7155 ;; These are only needed to make invert_jump() happy - otherwise, jump
7156 ;; optimization will be silently disabled.
7157 (define_insn "*blt_media_i"
7158   [(set (pc)
7159         (if_then_else (match_operator 3 "less_comparison_operator"
7160                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
7161                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
7162                       (match_operand 0 "target_operand" "b")
7163                       (pc)))]
7164   "TARGET_SHMEDIA"
7165   "b%o3%'       %N2, %N1, %0%>"
7166   [(set_attr "type" "cbranch_media")])
7168 (define_insn "*blt_media_i32"
7169   [(set (pc)
7170         (if_then_else (match_operator 3 "less_comparison_operator"
7171                         [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
7172                          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
7173                       (match_operand 0 "target_operand" "b")
7174                       (pc)))]
7175   "TARGET_SHMEDIA"
7176   "b%o3%'       %N2, %N1, %0%>"
7177   [(set_attr "type" "cbranch_media")])
7179 ;; combiner splitter for test-and-branch on single bit in register.  This
7180 ;; is endian dependent because the non-paradoxical subreg looks different
7181 ;; on big endian.
7182 (define_split
7183   [(set (pc)
7184         (if_then_else
7185           (match_operator 3 "equality_comparison_operator"
7186             [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1
7187                                                       "extend_reg_operand" "")
7188                                                     0)
7189                                          (const_int 1)
7190                                          (match_operand 2
7191                                           "const_int_operand" "")) 0)
7192              (const_int 0)])
7193           (match_operand 0 "target_operand" "")
7194           (pc)))
7195    (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
7196   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
7197   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
7198    (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
7200   "
7202   operands[5] = GEN_INT (31 - INTVAL (operands[2]));
7203   operands[6] = (GET_CODE (operands[3]) == EQ
7204                  ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
7205                  : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
7208 ; operand 0 is the loop count pseudo register
7209 ; operand 1 is the number of loop iterations or 0 if it is unknown
7210 ; operand 2 is the maximum number of loop iterations
7211 ; operand 3 is the number of levels of enclosed loops
7212 ; operand 4 is the label to jump to at the top of the loop
7214 (define_expand "doloop_end"
7215   [(parallel [(set (pc) (if_then_else
7216                           (ne:SI (match_operand:SI 0 "" "")
7217                               (const_int 1))
7218                           (label_ref (match_operand 4 "" ""))
7219                           (pc)))
7220               (set (match_dup 0)
7221                    (plus:SI (match_dup 0) (const_int -1)))
7222               (clobber (reg:SI T_REG))])]
7223   "TARGET_SH2"
7224   "
7226   if (GET_MODE (operands[0]) != SImode)
7227     FAIL;
7231 (define_insn_and_split "doloop_end_split"
7232   [(set (pc)
7233         (if_then_else (ne:SI  (match_operand:SI 2 "arith_reg_dest" "0")
7234                           (const_int 1))
7235                       (label_ref (match_operand 1 "" ""))
7236                       (pc)))
7237    (set (match_operand:SI 0 "arith_reg_dest" "=r")
7238         (plus (match_dup 2) (const_int -1)))
7239    (clobber (reg:SI T_REG))]
7240   "TARGET_SH2"
7241   "#"
7242   ""
7243   [(parallel [(set (reg:SI T_REG)
7244                    (eq:SI (match_dup 2) (const_int 1)))
7245               (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
7246    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
7247                            (label_ref (match_dup 1))
7248                            (pc)))]
7250    [(set_attr "type" "cbranch")])
7253 ;; ------------------------------------------------------------------------
7254 ;; Jump and linkage insns
7255 ;; ------------------------------------------------------------------------
7257 (define_insn "jump_compact"
7258   [(set (pc)
7259         (label_ref (match_operand 0 "" "")))]
7260   "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
7261   "*
7263   /* The length is 16 if the delay slot is unfilled.  */
7264   if (get_attr_length(insn) > 4)
7265     return output_far_jump(insn, operands[0]);
7266   else
7267     return   \"bra      %l0%#\";
7269   [(set_attr "type" "jump")
7270    (set_attr "needs_delay_slot" "yes")])
7272 ;; ??? It would be much saner to explicitly use the scratch register
7273 ;; in the jump insn, and have indirect_jump_scratch only set it,
7274 ;; but fill_simple_delay_slots would refuse to do delay slot filling
7275 ;; from the target then, as it uses simplejump_p.
7276 ;;(define_insn "jump_compact_far"
7277 ;;  [(set (pc)
7278 ;;      (label_ref (match_operand 0 "" "")))
7279 ;;   (use (match_operand 1 "register_operand" "r")]
7280 ;;  "TARGET_SH1"
7281 ;;  "* return output_far_jump(insn, operands[0], operands[1]);"
7282 ;;  [(set_attr "type" "jump")
7283 ;;   (set_attr "needs_delay_slot" "yes")])
7285 (define_insn "jump_media"
7286   [(set (pc)
7287         (match_operand 0 "target_operand" "b"))]
7288   "TARGET_SHMEDIA"
7289   "blink        %0, r63%>"
7290   [(set_attr "type" "jump_media")])
7292 (define_expand "jump"
7293   [(set (pc)
7294         (label_ref (match_operand 0 "" "")))]
7295   ""
7296   "
7298   if (TARGET_SH1)
7299     emit_jump_insn (gen_jump_compact (operands[0]));
7300   else if (TARGET_SHMEDIA)
7301     {
7302       if (reload_in_progress || reload_completed)
7303         FAIL;
7304       emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode,
7305                                                          operands[0])));
7306     }
7307   DONE;
7310 (define_insn "force_mode_for_call"
7311   [(use (reg:PSI FPSCR_REG))]
7312   "TARGET_SHCOMPACT"
7313   ""
7314   [(set_attr "length" "0")
7315    (set (attr "fp_mode")
7316         (if_then_else (eq_attr "fpu_single" "yes")
7317                       (const_string "single") (const_string "double")))])
7319 (define_insn "calli"
7320   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7321          (match_operand 1 "" ""))
7322    (use (reg:PSI FPSCR_REG))
7323    (clobber (reg:SI PR_REG))]
7324   "TARGET_SH1"
7325   "*
7326    {
7327      if (TARGET_SH2A && (dbr_sequence_length () == 0))
7328         return \"jsr/n\\t@%0\";
7329      else
7330         return \"jsr\\t@%0%#\";
7331    }"
7333   [(set_attr "type" "call")
7334    (set (attr "fp_mode")
7335         (if_then_else (eq_attr "fpu_single" "yes")
7336                       (const_string "single") (const_string "double")))
7337    (set_attr "needs_delay_slot" "yes")
7338    (set_attr "fp_set" "unknown")])
7340 ;; This is TBR relative jump instruction for SH2A architecture.
7341 ;; Its use is enabled assigning an attribute "function_vector"
7342 ;; and the vector number to a function during its declaration.
7344 (define_insn "calli_tbr_rel"
7345   [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
7346          (match_operand 1 "" ""))
7347    (use (reg:PSI FPSCR_REG))
7348    (clobber (reg:SI PR_REG))]
7349   "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
7350   "*
7352   unsigned HOST_WIDE_INT vect_num;
7353   vect_num = sh2a_get_function_vector_number (operands[0]);
7354   operands[2] = GEN_INT (vect_num * 4);
7356   return \"jsr/n\\t@@(%O2,tbr)\";
7358   [(set_attr "type" "call")
7359    (set (attr "fp_mode")
7360         (if_then_else (eq_attr "fpu_single" "yes")
7361                       (const_string "single") (const_string "double")))
7362    (set_attr "needs_delay_slot" "no")
7363    (set_attr "fp_set" "unknown")])
7365 ;; This is a pc-rel call, using bsrf, for use with PIC.
7367 (define_insn "calli_pcrel"
7368   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7369          (match_operand 1 "" ""))
7370    (use (reg:PSI FPSCR_REG))
7371    (use (reg:SI PIC_REG))
7372    (use (match_operand 2 "" ""))
7373    (clobber (reg:SI PR_REG))]
7374   "TARGET_SH2"
7375   "bsrf %0\\n%O2:%#"
7376   [(set_attr "type" "call")
7377    (set (attr "fp_mode")
7378         (if_then_else (eq_attr "fpu_single" "yes")
7379                       (const_string "single") (const_string "double")))
7380    (set_attr "needs_delay_slot" "yes")
7381    (set_attr "fp_set" "unknown")])
7383 (define_insn_and_split "call_pcrel"
7384   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7385          (match_operand 1 "" ""))
7386    (use (reg:PSI FPSCR_REG))
7387    (use (reg:SI PIC_REG))
7388    (clobber (reg:SI PR_REG))
7389    (clobber (match_scratch:SI 2 "=r"))]
7390   "TARGET_SH2"
7391   "#"
7392   "reload_completed"
7393   [(const_int 0)]
7394   "
7396   rtx lab = PATTERN (gen_call_site ());
7398   if (SYMBOL_REF_LOCAL_P (operands[0]))
7399     emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7400   else
7401     emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
7402   emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
7403   DONE;
7405   [(set_attr "type" "call")
7406    (set (attr "fp_mode")
7407         (if_then_else (eq_attr "fpu_single" "yes")
7408                       (const_string "single") (const_string "double")))
7409    (set_attr "needs_delay_slot" "yes")
7410    (set_attr "fp_set" "unknown")])
7412 (define_insn "call_compact"
7413   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7414          (match_operand 1 "" ""))
7415    (match_operand 2 "immediate_operand" "n")
7416    (use (reg:SI R0_REG))
7417    (use (reg:SI R1_REG))
7418    (use (reg:PSI FPSCR_REG))
7419    (clobber (reg:SI PR_REG))]
7420   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7421   "jsr  @%0%#"
7422   [(set_attr "type" "call")
7423    (set (attr "fp_mode")
7424         (if_then_else (eq_attr "fpu_single" "yes")
7425                       (const_string "single") (const_string "double")))
7426    (set_attr "needs_delay_slot" "yes")])
7428 (define_insn "call_compact_rettramp"
7429   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7430          (match_operand 1 "" ""))
7431    (match_operand 2 "immediate_operand" "n")
7432    (use (reg:SI R0_REG))
7433    (use (reg:SI R1_REG))
7434    (use (reg:PSI FPSCR_REG))
7435    (clobber (reg:SI R10_REG))
7436    (clobber (reg:SI PR_REG))]
7437   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7438   "jsr  @%0%#"
7439   [(set_attr "type" "call")
7440    (set (attr "fp_mode")
7441         (if_then_else (eq_attr "fpu_single" "yes")
7442                       (const_string "single") (const_string "double")))
7443    (set_attr "needs_delay_slot" "yes")])
7445 (define_insn "call_media"
7446   [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
7447          (match_operand 1 "" ""))
7448    (clobber (reg:DI PR_MEDIA_REG))]
7449   "TARGET_SHMEDIA"
7450   "blink        %0, r18"
7451   [(set_attr "type" "jump_media")])
7453 (define_insn "call_valuei"
7454   [(set (match_operand 0 "" "=rf")
7455         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7456               (match_operand 2 "" "")))
7457    (use (reg:PSI FPSCR_REG))
7458    (clobber (reg:SI PR_REG))]
7459   "TARGET_SH1"
7460   "*
7461    {
7462      if (TARGET_SH2A && (dbr_sequence_length () == 0))
7463         return \"jsr/n\\t@%1\";
7464      else
7465         return \"jsr\\t@%1%#\";
7466    }"
7467   [(set_attr "type" "call")
7468    (set (attr "fp_mode")
7469         (if_then_else (eq_attr "fpu_single" "yes")
7470                       (const_string "single") (const_string "double")))
7471    (set_attr "needs_delay_slot" "yes")
7472    (set_attr "fp_set" "unknown")])
7474 ;; This is TBR relative jump instruction for SH2A architecture.
7475 ;; Its use is enabled assigning an attribute "function_vector"
7476 ;; and the vector number to a function during its declaration.
7478 (define_insn "call_valuei_tbr_rel"
7479   [(set (match_operand 0 "" "=rf")
7480         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7481               (match_operand 2 "" "")))
7482    (use (reg:PSI FPSCR_REG))
7483    (clobber (reg:SI PR_REG))]
7484   "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
7485   "*
7487   unsigned HOST_WIDE_INT vect_num;
7488   vect_num = sh2a_get_function_vector_number (operands[1]);
7489   operands[3] = GEN_INT (vect_num * 4);
7491   return \"jsr/n\\t@@(%O3,tbr)\";
7493   [(set_attr "type" "call")
7494    (set (attr "fp_mode")
7495         (if_then_else (eq_attr "fpu_single" "yes")
7496                       (const_string "single") (const_string "double")))
7497    (set_attr "needs_delay_slot" "no")
7498    (set_attr "fp_set" "unknown")])
7500 (define_insn "call_valuei_pcrel"
7501   [(set (match_operand 0 "" "=rf")
7502         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7503               (match_operand 2 "" "")))
7504    (use (reg:PSI FPSCR_REG))
7505    (use (reg:SI PIC_REG))
7506    (use (match_operand 3 "" ""))
7507    (clobber (reg:SI PR_REG))]
7508   "TARGET_SH2"
7509   "bsrf %1\\n%O3:%#"
7510   [(set_attr "type" "call")
7511    (set (attr "fp_mode")
7512         (if_then_else (eq_attr "fpu_single" "yes")
7513                       (const_string "single") (const_string "double")))
7514    (set_attr "needs_delay_slot" "yes")
7515    (set_attr "fp_set" "unknown")])
7517 (define_insn_and_split "call_value_pcrel"
7518   [(set (match_operand 0 "" "=rf")
7519         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7520               (match_operand 2 "" "")))
7521    (use (reg:PSI FPSCR_REG))
7522    (use (reg:SI PIC_REG))
7523    (clobber (reg:SI PR_REG))
7524    (clobber (match_scratch:SI 3 "=r"))]
7525   "TARGET_SH2"
7526   "#"
7527   "reload_completed"
7528   [(const_int 0)]
7529   "
7531   rtx lab = PATTERN (gen_call_site ());
7533   if (SYMBOL_REF_LOCAL_P (operands[1]))
7534     emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
7535   else
7536     emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
7537   emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
7538                                          operands[2], copy_rtx (lab)));
7539   DONE;
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    (set_attr "fp_set" "unknown")])
7548 (define_insn "call_value_compact"
7549   [(set (match_operand 0 "" "=rf")
7550         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7551               (match_operand 2 "" "")))
7552    (match_operand 3 "immediate_operand" "n")
7553    (use (reg:SI R0_REG))
7554    (use (reg:SI R1_REG))
7555    (use (reg:PSI FPSCR_REG))
7556    (clobber (reg:SI PR_REG))]
7557   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7558   "jsr  @%1%#"
7559   [(set_attr "type" "call")
7560    (set (attr "fp_mode")
7561         (if_then_else (eq_attr "fpu_single" "yes")
7562                       (const_string "single") (const_string "double")))
7563    (set_attr "needs_delay_slot" "yes")])
7565 (define_insn "call_value_compact_rettramp"
7566   [(set (match_operand 0 "" "=rf")
7567         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7568               (match_operand 2 "" "")))
7569    (match_operand 3 "immediate_operand" "n")
7570    (use (reg:SI R0_REG))
7571    (use (reg:SI R1_REG))
7572    (use (reg:PSI FPSCR_REG))
7573    (clobber (reg:SI R10_REG))
7574    (clobber (reg:SI PR_REG))]
7575   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7576   "jsr  @%1%#"
7577   [(set_attr "type" "call")
7578    (set (attr "fp_mode")
7579         (if_then_else (eq_attr "fpu_single" "yes")
7580                       (const_string "single") (const_string "double")))
7581    (set_attr "needs_delay_slot" "yes")])
7583 (define_insn "call_value_media"
7584   [(set (match_operand 0 "" "=rf")
7585         (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
7586               (match_operand 2 "" "")))
7587    (clobber (reg:DI PR_MEDIA_REG))]
7588   "TARGET_SHMEDIA"
7589   "blink        %1, r18"
7590   [(set_attr "type" "jump_media")])
7592 (define_expand "call"
7593   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7594                             (match_operand 1 "" ""))
7595               (match_operand 2 "" "")
7596               (use (reg:PSI FPSCR_REG))
7597               (clobber (reg:SI PR_REG))])]
7598   ""
7599   "
7601   if (TARGET_SHMEDIA)
7602     {
7603       operands[0] = shmedia_prepare_call_address (operands[0], 0);
7604       emit_call_insn (gen_call_media (operands[0], operands[1]));
7605       DONE;
7606     }
7607   else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
7608     {
7609       rtx cookie_rtx = operands[2];
7610       long cookie = INTVAL (cookie_rtx);
7611       rtx func = XEXP (operands[0], 0);
7612       rtx r0, r1;
7614       if (flag_pic)
7615         {
7616           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7617             {
7618               rtx reg = gen_reg_rtx (Pmode);
7620               emit_insn (gen_symGOTPLT2reg (reg, func));
7621               func = reg;
7622             }
7623           else
7624             func = legitimize_pic_address (func, Pmode, 0);
7625         }
7627       r0 = gen_rtx_REG (SImode, R0_REG);
7628       r1 = gen_rtx_REG (SImode, R1_REG);
7630       /* Since such a call function may use all call-clobbered
7631          registers, we force a mode switch earlier, so that we don't
7632          run out of registers when adjusting fpscr for the call.  */
7633       emit_insn (gen_force_mode_for_call ());
7635       operands[0]
7636         = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7637                            SFUNC_GOT);
7638       operands[0] = force_reg (SImode, operands[0]);
7640       emit_move_insn (r0, func);
7641       emit_move_insn (r1, cookie_rtx);
7643       if (cookie & CALL_COOKIE_RET_TRAMP (1))
7644         emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
7645                                                    operands[2]));
7646       else
7647         emit_call_insn (gen_call_compact (operands[0], operands[1],
7648                                           operands[2]));
7650       DONE;
7651     }
7652   else if (TARGET_SHCOMPACT && flag_pic
7653            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7654            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7655     {
7656       rtx reg = gen_reg_rtx (Pmode);
7658       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
7659       XEXP (operands[0], 0) = reg;
7660     }
7661   if (!flag_pic && TARGET_SH2A
7662       && MEM_P (operands[0])
7663       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
7664     {
7665       if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
7666         {
7667           emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
7668                                              operands[1]));
7669           DONE;
7670         }
7671     }
7672   if (flag_pic && TARGET_SH2
7673       && MEM_P (operands[0])
7674       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
7675     {
7676       emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
7677       DONE;
7678     }
7679   else
7680   {
7681     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
7682     operands[1] = operands[2];
7683   }
7685   emit_call_insn (gen_calli (operands[0], operands[1]));
7686   DONE;
7689 (define_insn "call_pop_compact"
7690   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7691          (match_operand 1 "" ""))
7692    (match_operand 2 "immediate_operand" "n")
7693    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7694                                  (match_operand 3 "immediate_operand" "n")))
7695    (use (reg:SI R0_REG))
7696    (use (reg:SI R1_REG))
7697    (use (reg:PSI FPSCR_REG))
7698    (clobber (reg:SI PR_REG))]
7699   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7700   "jsr  @%0%#"
7701   [(set_attr "type" "call")
7702    (set (attr "fp_mode")
7703         (if_then_else (eq_attr "fpu_single" "yes")
7704                       (const_string "single") (const_string "double")))
7705    (set_attr "needs_delay_slot" "yes")])
7707 (define_insn "call_pop_compact_rettramp"
7708   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7709          (match_operand 1 "" ""))
7710    (match_operand 2 "immediate_operand" "n")
7711    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7712                                  (match_operand 3 "immediate_operand" "n")))
7713    (use (reg:SI R0_REG))
7714    (use (reg:SI R1_REG))
7715    (use (reg:PSI FPSCR_REG))
7716    (clobber (reg:SI R10_REG))
7717    (clobber (reg:SI PR_REG))]
7718   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7719   "jsr  @%0%#"
7720   [(set_attr "type" "call")
7721    (set (attr "fp_mode")
7722         (if_then_else (eq_attr "fpu_single" "yes")
7723                       (const_string "single") (const_string "double")))
7724    (set_attr "needs_delay_slot" "yes")])
7726 (define_expand "call_pop"
7727   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7728                     (match_operand 1 "" ""))
7729              (match_operand 2 "" "")
7730              (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7731                                            (match_operand 3 "" "")))])]
7732   "TARGET_SHCOMPACT"
7733   "
7735   rtx cookie_rtx;
7736   long cookie;
7737   rtx func;
7738   rtx r0, r1;
7740   gcc_assert (operands[2] && INTVAL (operands[2]));
7741   cookie_rtx = operands[2];
7742   cookie = INTVAL (cookie_rtx);
7743   func = XEXP (operands[0], 0);
7745   if (flag_pic)
7746     {
7747       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7748         {
7749           rtx reg = gen_reg_rtx (Pmode);
7750           emit_insn (gen_symGOTPLT2reg (reg, func));
7751           func = reg;
7752         }
7753       else
7754         func = legitimize_pic_address (func, Pmode, 0);
7755     }
7757   r0 = gen_rtx_REG (SImode, R0_REG);
7758   r1 = gen_rtx_REG (SImode, R1_REG);
7760   /* Since such a call function may use all call-clobbered
7761      registers, we force a mode switch earlier, so that we don't
7762      run out of registers when adjusting fpscr for the call.  */
7763   emit_insn (gen_force_mode_for_call ());
7765   operands[0] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7766                                  SFUNC_GOT);
7767   operands[0] = force_reg (SImode, operands[0]);
7769   emit_move_insn (r0, func);
7770   emit_move_insn (r1, cookie_rtx);
7772   if (cookie & CALL_COOKIE_RET_TRAMP (1))
7773     emit_call_insn (gen_call_pop_compact_rettramp
7774                      (operands[0], operands[1], operands[2], operands[3]));
7775   else
7776     emit_call_insn (gen_call_pop_compact
7777                      (operands[0], operands[1], operands[2], operands[3]));
7779   DONE;
7782 (define_expand "call_value"
7783   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
7784                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
7785                                  (match_operand 2 "" "")))
7786               (match_operand 3 "" "")
7787               (use (reg:PSI FPSCR_REG))
7788               (clobber (reg:SI PR_REG))])]
7789   ""
7790   "
7792   if (TARGET_SHMEDIA)
7793     {
7794       operands[1] = shmedia_prepare_call_address (operands[1], 0);
7795       emit_call_insn (gen_call_value_media (operands[0], operands[1],
7796                                             operands[2]));
7797       DONE;
7798     }
7799   else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
7800     {
7801       rtx cookie_rtx = operands[3];
7802       long cookie = INTVAL (cookie_rtx);
7803       rtx func = XEXP (operands[1], 0);
7804       rtx r0, r1;
7806       if (flag_pic)
7807         {
7808           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7809             {
7810               rtx reg = gen_reg_rtx (Pmode);
7812               emit_insn (gen_symGOTPLT2reg (reg, func));
7813               func = reg;
7814             }
7815           else
7816             func = legitimize_pic_address (func, Pmode, 0);
7817         }
7819       r0 = gen_rtx_REG (SImode, R0_REG);
7820       r1 = gen_rtx_REG (SImode, R1_REG);
7822       /* Since such a call function may use all call-clobbered
7823          registers, we force a mode switch earlier, so that we don't
7824          run out of registers when adjusting fpscr for the call.  */
7825       emit_insn (gen_force_mode_for_call ());
7827       operands[1]
7828         = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7829                            SFUNC_GOT);
7830       operands[1] = force_reg (SImode, operands[1]);
7832       emit_move_insn (r0, func);
7833       emit_move_insn (r1, cookie_rtx);
7835       if (cookie & CALL_COOKIE_RET_TRAMP (1))
7836         emit_call_insn (gen_call_value_compact_rettramp (operands[0],
7837                                                          operands[1],
7838                                                          operands[2],
7839                                                          operands[3]));
7840       else
7841         emit_call_insn (gen_call_value_compact (operands[0], operands[1],
7842                                                 operands[2], operands[3]));
7844       DONE;
7845     }
7846   else if (TARGET_SHCOMPACT && flag_pic
7847            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7848            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
7849     {
7850       rtx reg = gen_reg_rtx (Pmode);
7852       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
7853       XEXP (operands[1], 0) = reg;
7854     }
7855   if (!flag_pic && TARGET_SH2A
7856       && MEM_P (operands[1])
7857       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
7858     {
7859       if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
7860         {
7861           emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
7862                                  XEXP (operands[1], 0), operands[2]));
7863           DONE;
7864         }
7865     }
7866   if (flag_pic && TARGET_SH2
7867       && MEM_P (operands[1])
7868       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
7869     {
7870       emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
7871                                             operands[2]));
7872       DONE;
7873     }
7874   else
7875     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
7877   emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
7878   DONE;
7881 (define_insn "sibcalli"
7882   [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
7883          (match_operand 1 "" ""))
7884    (use (reg:PSI FPSCR_REG))
7885    (return)]
7886   "TARGET_SH1"
7887   "jmp  @%0%#"
7888   [(set_attr "needs_delay_slot" "yes")
7889    (set (attr "fp_mode")
7890         (if_then_else (eq_attr "fpu_single" "yes")
7891                       (const_string "single") (const_string "double")))
7892    (set_attr "type" "jump_ind")])
7894 (define_insn "sibcalli_pcrel"
7895   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
7896          (match_operand 1 "" ""))
7897    (use (match_operand 2 "" ""))
7898    (use (reg:PSI FPSCR_REG))
7899    (return)]
7900   "TARGET_SH2"
7901   "braf %0\\n%O2:%#"
7902   [(set_attr "needs_delay_slot" "yes")
7903    (set (attr "fp_mode")
7904         (if_then_else (eq_attr "fpu_single" "yes")
7905                       (const_string "single") (const_string "double")))
7906    (set_attr "type" "jump_ind")])
7908 ;; This uses an unspec to describe that the symbol_ref is very close.
7909 (define_insn "sibcalli_thunk"
7910   [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
7911                              UNSPEC_THUNK))
7912          (match_operand 1 "" ""))
7913    (use (reg:PSI FPSCR_REG))
7914    (return)]
7915   "TARGET_SH1"
7916   "bra  %O0"
7917   [(set_attr "needs_delay_slot" "yes")
7918    (set (attr "fp_mode")
7919         (if_then_else (eq_attr "fpu_single" "yes")
7920                       (const_string "single") (const_string "double")))
7921    (set_attr "type" "jump")
7922    (set_attr "length" "2")])
7924 (define_insn_and_split "sibcall_pcrel"
7925   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7926          (match_operand 1 "" ""))
7927    (use (reg:PSI FPSCR_REG))
7928    (clobber (match_scratch:SI 2 "=k"))
7929    (return)]
7930   "TARGET_SH2"
7931   "#"
7932   "reload_completed"
7933   [(const_int 0)]
7934   "
7936   rtx lab = PATTERN (gen_call_site ());
7937   rtx call_insn;
7939   emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7940   call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
7941                                                   copy_rtx (lab)));
7942   SIBLING_CALL_P (call_insn) = 1;
7943   DONE;
7945   [(set_attr "needs_delay_slot" "yes")
7946    (set (attr "fp_mode")
7947         (if_then_else (eq_attr "fpu_single" "yes")
7948                       (const_string "single") (const_string "double")))
7949    (set_attr "type" "jump_ind")])
7951 (define_insn "sibcall_compact"
7952   [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
7953          (match_operand 1 "" ""))
7954    (return)
7955    (use (match_operand:SI 2 "register_operand" "z,x"))
7956    (use (reg:SI R1_REG))
7957    (use (reg:PSI FPSCR_REG))
7958    ;; We want to make sure the `x' above will only match MACH_REG
7959    ;; because sibcall_epilogue may clobber MACL_REG.
7960    (clobber (reg:SI MACL_REG))]
7961   "TARGET_SHCOMPACT"
7962   "@
7963         jmp     @%0%#
7964         jmp     @%0\\n  sts     %2, r0"
7965   [(set_attr "needs_delay_slot" "yes,no")
7966    (set_attr "length" "2,4")
7967    (set (attr "fp_mode") (const_string "single"))
7968    (set_attr "type" "jump_ind")])
7970 (define_insn "sibcall_media"
7971   [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
7972          (match_operand 1 "" ""))
7973    (use (reg:SI PR_MEDIA_REG))
7974    (return)]
7975   "TARGET_SHMEDIA"
7976   "blink        %0, r63"
7977   [(set_attr "type" "jump_media")])
7979 (define_expand "sibcall"
7980   [(parallel
7981     [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7982            (match_operand 1 "" ""))
7983      (match_operand 2 "" "")
7984      (use (reg:PSI FPSCR_REG))
7985      (return)])]
7986   ""
7987   "
7989   if (TARGET_SHMEDIA)
7990     {
7991       operands[0] = shmedia_prepare_call_address (operands[0], 1);
7992       emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
7993       DONE;
7994     }
7995   else if (TARGET_SHCOMPACT && operands[2]
7996            && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
7997     {
7998       rtx cookie_rtx = operands[2];
7999       long cookie = INTVAL (cookie_rtx);
8000       rtx func = XEXP (operands[0], 0);
8001       rtx mach, r1;
8003       if (flag_pic)
8004         {
8005           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8006             {
8007               rtx reg = gen_reg_rtx (Pmode);
8009               emit_insn (gen_symGOT2reg (reg, func));
8010               func = reg;
8011             }
8012           else
8013             func = legitimize_pic_address (func, Pmode, 0);
8014         }
8016       /* FIXME: if we could tell whether all argument registers are
8017          already taken, we could decide whether to force the use of
8018          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
8019          simple way to tell.  We could use the CALL_COOKIE, but we
8020          can't currently tell a register used for regular argument
8021          passing from one that is unused.  If we leave it up to reload
8022          to decide which register to use, it seems to always choose
8023          R0_REG, which leaves no available registers in SIBCALL_REGS
8024          to hold the address of the trampoline.  */
8025       mach = gen_rtx_REG (SImode, MACH_REG);
8026       r1 = gen_rtx_REG (SImode, R1_REG);
8028       /* Since such a call function may use all call-clobbered
8029          registers, we force a mode switch earlier, so that we don't
8030          run out of registers when adjusting fpscr for the call.  */
8031       emit_insn (gen_force_mode_for_call ());
8033       operands[0]
8034         = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8035                            SFUNC_GOT);
8036       operands[0] = force_reg (SImode, operands[0]);
8038       /* We don't need a return trampoline, since the callee will
8039          return directly to the upper caller.  */
8040       if (cookie & CALL_COOKIE_RET_TRAMP (1))
8041         {
8042           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
8043           cookie_rtx = GEN_INT (cookie);
8044         }
8046       emit_move_insn (mach, func);
8047       emit_move_insn (r1, cookie_rtx);
8049       emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
8050       DONE;
8051     }
8052   else if (TARGET_SHCOMPACT && flag_pic
8053            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8054            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
8055     {
8056       rtx reg = gen_reg_rtx (Pmode);
8058       emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
8059       XEXP (operands[0], 0) = reg;
8060     }
8061   if (flag_pic && TARGET_SH2
8062       && MEM_P (operands[0])
8063       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8064       /* The PLT needs the PIC register, but the epilogue would have
8065          to restore it, so we can only use PC-relative PIC calls for
8066          static functions.  */
8067       && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
8068     {
8069       emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
8070       DONE;
8071     }
8072   else
8073     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
8075   emit_call_insn (gen_sibcalli (operands[0], operands[1]));
8076   DONE;
8079 (define_insn "sibcall_valuei"
8080   [(set (match_operand 0 "" "=rf")
8081         (call (mem:SI (match_operand:SI 1 "register_operand" "k"))
8082               (match_operand 2 "" "")))
8083    (use (reg:PSI FPSCR_REG))
8084    (return)]
8085   "TARGET_SH1"
8086   "jmp  @%1%#"
8087   [(set_attr "needs_delay_slot" "yes")
8088    (set (attr "fp_mode")
8089         (if_then_else (eq_attr "fpu_single" "yes")
8090                       (const_string "single") (const_string "double")))
8091    (set_attr "type" "jump_ind")])
8093 (define_insn "sibcall_valuei_pcrel"
8094   [(set (match_operand 0 "" "=rf")
8095         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
8096               (match_operand 2 "" "")))
8097    (use (match_operand 3 "" ""))
8098    (use (reg:PSI FPSCR_REG))
8099    (return)]
8100   "TARGET_SH2"
8101   "braf %1\\n%O3:%#"
8102   [(set_attr "needs_delay_slot" "yes")
8103    (set (attr "fp_mode")
8104         (if_then_else (eq_attr "fpu_single" "yes")
8105                       (const_string "single") (const_string "double")))
8106    (set_attr "type" "jump_ind")])
8108 (define_insn_and_split "sibcall_value_pcrel"
8109   [(set (match_operand 0 "" "=rf")
8110         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
8111               (match_operand 2 "" "")))
8112    (use (reg:PSI FPSCR_REG))
8113    (clobber (match_scratch:SI 3 "=k"))
8114    (return)]
8115   "TARGET_SH2"
8116   "#"
8117   "reload_completed"
8118   [(const_int 0)]
8119   "
8121   rtx lab = PATTERN (gen_call_site ());
8122   rtx call_insn;
8124   emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
8125   call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
8126                                                         operands[3],
8127                                                         operands[2],
8128                                                         copy_rtx (lab)));
8129   SIBLING_CALL_P (call_insn) = 1;
8130   DONE;
8132   [(set_attr "needs_delay_slot" "yes")
8133    (set (attr "fp_mode")
8134         (if_then_else (eq_attr "fpu_single" "yes")
8135                       (const_string "single") (const_string "double")))
8136    (set_attr "type" "jump_ind")])
8138 (define_insn "sibcall_value_compact"
8139   [(set (match_operand 0 "" "=rf,rf")
8140         (call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
8141               (match_operand 2 "" "")))
8142    (return)
8143    (use (match_operand:SI 3 "register_operand" "z,x"))
8144    (use (reg:SI R1_REG))
8145    (use (reg:PSI FPSCR_REG))
8146    ;; We want to make sure the `x' above will only match MACH_REG
8147    ;; because sibcall_epilogue may clobber MACL_REG.
8148    (clobber (reg:SI MACL_REG))]
8149   "TARGET_SHCOMPACT"
8150   "@
8151         jmp     @%1%#
8152         jmp     @%1\\n  sts     %3, r0"
8153   [(set_attr "needs_delay_slot" "yes,no")
8154    (set_attr "length" "2,4")
8155    (set (attr "fp_mode") (const_string "single"))
8156    (set_attr "type" "jump_ind")])
8158 (define_insn "sibcall_value_media"
8159   [(set (match_operand 0 "" "=rf")
8160         (call (mem:DI (match_operand 1 "target_reg_operand" "k"))
8161               (match_operand 2 "" "")))
8162    (use (reg:SI PR_MEDIA_REG))
8163    (return)]
8164   "TARGET_SHMEDIA"
8165   "blink        %1, r63"
8166   [(set_attr "type" "jump_media")])
8168 (define_expand "sibcall_value"
8169   [(parallel
8170     [(set (match_operand 0 "arith_reg_operand" "")
8171           (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
8172                 (match_operand 2 "" "")))
8173      (match_operand 3 "" "")
8174      (use (reg:PSI FPSCR_REG))
8175      (return)])]
8176   ""
8177   "
8179   if (TARGET_SHMEDIA)
8180     {
8181       operands[1] = shmedia_prepare_call_address (operands[1], 1);
8182       emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
8183                                                operands[2]));
8184       DONE;
8185     }
8186   else if (TARGET_SHCOMPACT && operands[3]
8187            && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
8188     {
8189       rtx cookie_rtx = operands[3];
8190       long cookie = INTVAL (cookie_rtx);
8191       rtx func = XEXP (operands[1], 0);
8192       rtx mach, r1;
8194       if (flag_pic)
8195         {
8196           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8197             {
8198               rtx reg = gen_reg_rtx (Pmode);
8200               emit_insn (gen_symGOT2reg (reg, func));
8201               func = reg;
8202             }
8203           else
8204             func = legitimize_pic_address (func, Pmode, 0);
8205         }
8207       /* FIXME: if we could tell whether all argument registers are
8208          already taken, we could decide whether to force the use of
8209          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
8210          simple way to tell.  We could use the CALL_COOKIE, but we
8211          can't currently tell a register used for regular argument
8212          passing from one that is unused.  If we leave it up to reload
8213          to decide which register to use, it seems to always choose
8214          R0_REG, which leaves no available registers in SIBCALL_REGS
8215          to hold the address of the trampoline.  */
8216       mach = gen_rtx_REG (SImode, MACH_REG);
8217       r1 = gen_rtx_REG (SImode, R1_REG);
8219       /* Since such a call function may use all call-clobbered
8220          registers, we force a mode switch earlier, so that we don't
8221          run out of registers when adjusting fpscr for the call.  */
8222       emit_insn (gen_force_mode_for_call ());
8224       operands[1]
8225         = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8226                            SFUNC_GOT);
8227       operands[1] = force_reg (SImode, operands[1]);
8229       /* We don't need a return trampoline, since the callee will
8230          return directly to the upper caller.  */
8231       if (cookie & CALL_COOKIE_RET_TRAMP (1))
8232         {
8233           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
8234           cookie_rtx = GEN_INT (cookie);
8235         }
8237       emit_move_insn (mach, func);
8238       emit_move_insn (r1, cookie_rtx);
8240       emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
8241                                                  operands[2], mach));
8242       DONE;
8243     }
8244   else if (TARGET_SHCOMPACT && flag_pic
8245            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8246            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
8247     {
8248       rtx reg = gen_reg_rtx (Pmode);
8250       emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
8251       XEXP (operands[1], 0) = reg;
8252     }
8253   if (flag_pic && TARGET_SH2
8254       && MEM_P (operands[1])
8255       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8256       /* The PLT needs the PIC register, but the epilogue would have
8257          to restore it, so we can only use PC-relative PIC calls for
8258          static functions.  */
8259       && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
8260     {
8261       emit_call_insn (gen_sibcall_value_pcrel (operands[0],
8262                                                XEXP (operands[1], 0),
8263                                                operands[2]));
8264       DONE;
8265     }
8266   else
8267     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
8269   emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
8270   DONE;
8273 (define_insn "call_value_pop_compact"
8274   [(set (match_operand 0 "" "=rf")
8275         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8276               (match_operand 2 "" "")))
8277    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8278                                  (match_operand 4 "immediate_operand" "n")))
8279    (match_operand 3 "immediate_operand" "n")
8280    (use (reg:SI R0_REG))
8281    (use (reg:SI R1_REG))
8282    (use (reg:PSI FPSCR_REG))
8283    (clobber (reg:SI PR_REG))]
8284   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8285   "jsr  @%1%#"
8286   [(set_attr "type" "call")
8287    (set (attr "fp_mode")
8288         (if_then_else (eq_attr "fpu_single" "yes")
8289                       (const_string "single") (const_string "double")))
8290    (set_attr "needs_delay_slot" "yes")])
8292 (define_insn "call_value_pop_compact_rettramp"
8293   [(set (match_operand 0 "" "=rf")
8294         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8295               (match_operand 2 "" "")))
8296    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8297                                  (match_operand 4 "immediate_operand" "n")))
8298    (match_operand 3 "immediate_operand" "n")
8299    (use (reg:SI R0_REG))
8300    (use (reg:SI R1_REG))
8301    (use (reg:PSI FPSCR_REG))
8302    (clobber (reg:SI R10_REG))
8303    (clobber (reg:SI PR_REG))]
8304   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8305   "jsr  @%1%#"
8306   [(set_attr "type" "call")
8307    (set (attr "fp_mode")
8308         (if_then_else (eq_attr "fpu_single" "yes")
8309                       (const_string "single") (const_string "double")))
8310    (set_attr "needs_delay_slot" "yes")])
8312 (define_expand "call_value_pop"
8313   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
8314                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
8315                                  (match_operand 2 "" "")))
8316               (match_operand 3 "" "")
8317               (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8318                                             (match_operand 4 "" "")))])]
8319   "TARGET_SHCOMPACT"
8320   "
8322   rtx cookie_rtx;
8323   long cookie;
8324   rtx func;
8325   rtx r0, r1;
8327   gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
8328   cookie_rtx = operands[3];
8329   cookie = INTVAL (cookie_rtx);
8330   func = XEXP (operands[1], 0);
8332   if (flag_pic)
8333     {
8334       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8335         {
8336           rtx reg = gen_reg_rtx (Pmode);
8338           emit_insn (gen_symGOTPLT2reg (reg, func));
8339           func = reg;
8340         }
8341       else
8342         func = legitimize_pic_address (func, Pmode, 0);
8343     }
8345   r0 = gen_rtx_REG (SImode, R0_REG);
8346   r1 = gen_rtx_REG (SImode, R1_REG);
8348   /* Since such a call function may use all call-clobbered
8349      registers, we force a mode switch earlier, so that we don't
8350      run out of registers when adjusting fpscr for the call.  */
8351   emit_insn (gen_force_mode_for_call ());
8353   operands[1] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8354                                  SFUNC_GOT);
8355   operands[1] = force_reg (SImode, operands[1]);
8357   emit_move_insn (r0, func);
8358   emit_move_insn (r1, cookie_rtx);
8360   if (cookie & CALL_COOKIE_RET_TRAMP (1))
8361     emit_call_insn (gen_call_value_pop_compact_rettramp
8362                         (operands[0], operands[1], operands[2],
8363                          operands[3], operands[4]));
8364   else
8365     emit_call_insn (gen_call_value_pop_compact
8366                         (operands[0], operands[1], operands[2],
8367                          operands[3], operands[4]));
8369   DONE;
8372 (define_expand "sibcall_epilogue"
8373   [(return)]
8374   ""
8375   "
8377   sh_expand_epilogue (1);
8378   if (TARGET_SHCOMPACT)
8379     {
8380       rtx insn, set;
8382       /* If epilogue clobbers r0, preserve it in macl.  */
8383       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
8384         if ((set = single_set (insn))
8385             && REG_P (SET_DEST (set))
8386             && REGNO (SET_DEST (set)) == R0_REG)
8387           {
8388             rtx r0 = gen_rtx_REG (SImode, R0_REG);
8389             rtx tmp = gen_rtx_REG (SImode, MACL_REG);
8391             /* We can't tell at this point whether the sibcall is a
8392                sibcall_compact and, if it is, whether it uses r0 or
8393                mach as operand 2, so let the instructions that
8394                preserve r0 be optimized away if r0 turns out to be
8395                dead.  */
8396             emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
8397             emit_move_insn (r0, tmp);
8398             break;
8399           }
8400     }
8401   DONE;
8404 (define_insn "indirect_jump_compact"
8405   [(set (pc)
8406         (match_operand:SI 0 "arith_reg_operand" "r"))]
8407   "TARGET_SH1"
8408   "jmp  @%0%#"
8409   [(set_attr "needs_delay_slot" "yes")
8410    (set_attr "type" "jump_ind")])
8412 (define_expand "indirect_jump"
8413   [(set (pc)
8414         (match_operand 0 "register_operand" ""))]
8415   ""
8416   "
8418   if (GET_MODE (operands[0]) != Pmode)
8419     operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
8422 ;; The use of operand 1 / 2 helps us distinguish case table jumps
8423 ;; which can be present in structured code from indirect jumps which can not
8424 ;; be present in structured code.  This allows -fprofile-arcs to work.
8426 ;; For SH1 processors.
8427 (define_insn "casesi_jump_1"
8428   [(set (pc)
8429         (match_operand:SI 0 "register_operand" "r"))
8430    (use (label_ref (match_operand 1 "" "")))]
8431   "TARGET_SH1"
8432   "jmp  @%0%#"
8433   [(set_attr "needs_delay_slot" "yes")
8434    (set_attr "type" "jump_ind")])
8436 ;; For all later processors.
8437 (define_insn "casesi_jump_2"
8438   [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
8439                       (label_ref (match_operand 1 "" ""))))
8440    (use (label_ref (match_operand 2 "" "")))]
8441   "TARGET_SH2
8442    && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
8443   "braf %0%#"
8444   [(set_attr "needs_delay_slot" "yes")
8445    (set_attr "type" "jump_ind")])
8447 (define_insn "casesi_jump_media"
8448   [(set (pc) (match_operand 0 "target_reg_operand" "b"))
8449    (use (label_ref (match_operand 1 "" "")))]
8450   "TARGET_SHMEDIA"
8451   "blink        %0, r63"
8452   [(set_attr "type" "jump_media")])
8454 ;; Call subroutine returning any type.
8455 ;; ??? This probably doesn't work.
8457 (define_expand "untyped_call"
8458   [(parallel [(call (match_operand 0 "" "")
8459                     (const_int 0))
8460               (match_operand 1 "" "")
8461               (match_operand 2 "" "")])]
8462   "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
8463   "
8465   int i;
8467   emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
8469   for (i = 0; i < XVECLEN (operands[2], 0); i++)
8470     {
8471       rtx set = XVECEXP (operands[2], 0, i);
8472       emit_move_insn (SET_DEST (set), SET_SRC (set));
8473     }
8475   /* The optimizer does not know that the call sets the function value
8476      registers we stored in the result block.  We avoid problems by
8477      claiming that all hard registers are used and clobbered at this
8478      point.  */
8479   emit_insn (gen_blockage ());
8481   DONE;
8484 ;; ------------------------------------------------------------------------
8485 ;; Misc insns
8486 ;; ------------------------------------------------------------------------
8488 (define_insn "dect"
8489   [(set (reg:SI T_REG)
8490         (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
8491    (set (match_operand:SI 0 "arith_reg_dest" "=r")
8492         (plus:SI (match_dup 1) (const_int -1)))]
8493   "TARGET_SH2"
8494   "dt   %0"
8495   [(set_attr "type" "arith")])
8497 (define_insn "nop"
8498   [(const_int 0)]
8499   ""
8500   "nop")
8502 ;; Load address of a label. This is only generated by the casesi expand,
8503 ;; and by machine_dependent_reorg (fixing up fp moves).
8504 ;; This must use unspec, because this only works for labels that are
8505 ;; within range,
8507 (define_insn "mova"
8508   [(set (reg:SI R0_REG)
8509         (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
8510   "TARGET_SH1"
8511   "mova %O0,r0"
8512   [(set_attr "in_delay_slot" "no")
8513    (set_attr "type" "arith")])
8515 ;; machine_dependent_reorg will make this a `mova'.
8516 (define_insn "mova_const"
8517   [(set (reg:SI R0_REG)
8518         (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
8519   "TARGET_SH1"
8520   "#"
8521   [(set_attr "in_delay_slot" "no")
8522    (set_attr "type" "arith")])
8524 (define_expand "GOTaddr2picreg"
8525   [(set (reg:SI R0_REG)
8526         (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
8527                    UNSPEC_MOVA))
8528    (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
8529    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
8530   "" "
8532   if (TARGET_VXWORKS_RTP)
8533     {
8534       rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
8535       rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
8536       emit_insn (gen_vxworks_picreg (gott_base, gott_index));
8537       DONE;
8538     }
8540   operands[0] = gen_rtx_REG (Pmode, PIC_REG);
8541   operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
8543   if (TARGET_SHMEDIA)
8544     {
8545       rtx tr = gen_rtx_REG (Pmode, TR0_REG);
8546       rtx pic = operands[0];
8547       rtx lab = PATTERN (gen_call_site ());
8548       rtx insn, equiv;
8550       equiv = operands[1];
8551       operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
8552                                     UNSPEC_PCREL_SYMOFF);
8553       operands[1] = gen_rtx_CONST (Pmode, operands[1]);
8555       if (Pmode == SImode)
8556         {
8557           emit_insn (gen_movsi_const (pic, operands[1]));
8558           emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
8559         }
8560       else
8561         {
8562           emit_insn (gen_movdi_const (pic, operands[1]));
8563           emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
8564         }
8566       insn = emit_move_insn (operands[0], tr);
8568       set_unique_reg_note (insn, REG_EQUAL, equiv);
8570       DONE;
8571     }
8575 ;; A helper for GOTaddr2picreg to finish up the initialization of the
8576 ;; PIC register.
8578 (define_expand "vxworks_picreg"
8579   [(set (reg:SI PIC_REG)
8580         (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
8581    (set (reg:SI R0_REG)
8582         (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
8583    (set (reg:SI PIC_REG)
8584         (mem:SI (reg:SI PIC_REG)))
8585    (set (reg:SI PIC_REG)
8586         (mem:SI (plus:SI (reg:SI PIC_REG)
8587                          (reg:SI R0_REG))))]
8588   "TARGET_VXWORKS_RTP")
8590 (define_insn "*ptb"
8591   [(set (match_operand 0 "target_reg_operand" "=b")
8592         (const (unspec [(match_operand 1 "" "Csy")]
8593                              UNSPEC_DATALABEL)))]
8594   "TARGET_SHMEDIA && flag_pic
8595    && satisfies_constraint_Csy (operands[1])"
8596   "ptb/u        datalabel %1, %0"
8597   [(set_attr "type" "ptabs_media")
8598    (set_attr "length" "*")])
8600 (define_insn "ptrel_si"
8601   [(set (match_operand:SI 0 "target_reg_operand" "=b")
8602         (plus:SI (match_operand:SI 1 "register_operand" "r")
8603               (pc)))
8604    (match_operand:SI 2 "" "")]
8605   "TARGET_SHMEDIA"
8606   "%O2: ptrel/u %1, %0"
8607   [(set_attr "type" "ptabs_media")])
8609 (define_insn "ptrel_di"
8610   [(set (match_operand:DI 0 "target_reg_operand" "=b")
8611         (plus:DI (match_operand:DI 1 "register_operand" "r")
8612               (pc)))
8613    (match_operand:DI 2 "" "")]
8614   "TARGET_SHMEDIA"
8615   "%O2: ptrel/u %1, %0"
8616   [(set_attr "type" "ptabs_media")])
8618 (define_expand "builtin_setjmp_receiver"
8619   [(match_operand 0 "" "")]
8620   "flag_pic"
8621   "
8623   emit_insn (gen_GOTaddr2picreg ());
8624   DONE;
8627 (define_expand "call_site"
8628   [(unspec [(match_dup 0)] UNSPEC_CALLER)]
8629   "TARGET_SH1"
8630   "
8632   static HOST_WIDE_INT i = 0;
8633   operands[0] = GEN_INT (i);
8634   i++;
8637 ;; op0 = op1 + r12 but hide it before reload completed.  See the comment
8638 ;; in symGOT_load expand.
8640 (define_insn_and_split "chk_guard_add"
8641   [(set (match_operand:SI 0 "register_operand" "=&r")
8642         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
8643                     (reg:SI PIC_REG)]
8644                    UNSPEC_CHKADD))]
8645   "TARGET_SH1"
8646   "#"
8647   "TARGET_SH1 && reload_completed"
8648   [(set (match_dup 0) (reg:SI PIC_REG))
8649    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8650   ""
8651   [(set_attr "type" "arith")])
8653 (define_expand "sym_label2reg"
8654   [(set (match_operand:SI 0 "" "")
8655         (const:SI (unspec:SI [(match_operand:SI 1 "" "")
8656                               (const (plus:SI (match_operand:SI 2 "" "")
8657                                               (const_int 2)))]
8658                              UNSPEC_SYMOFF)))]
8659   "TARGET_SH1" "")
8661 (define_expand "symGOT_load"
8662   [(set (match_dup 2) (match_operand 1 "" ""))
8663    (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
8664    (set (match_operand 0 "" "") (mem (match_dup 3)))]
8665   ""
8666   "
8668   rtx mem;
8670   operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
8671   operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
8673   if (TARGET_SHMEDIA)
8674     {
8675       rtx reg = operands[2];
8677       if (Pmode == DImode)
8678         {      
8679           if (flag_pic > 1)
8680             emit_insn (gen_movdi_const_32bit (reg, operands[1]));
8681           else
8682             emit_insn (gen_movdi_const_16bit (reg, operands[1]));
8683         }
8684       else
8685         {
8686           if (flag_pic > 1)
8687             emit_insn (gen_movsi_const (reg, operands[1]));
8688           else
8689             emit_insn (gen_movsi_const_16bit (reg, operands[1]));
8690         }
8691     }
8692   else
8693     emit_move_insn (operands[2], operands[1]);
8695   /* When stack protector inserts codes after the result is set to
8696      R0, @(rX, r12) will cause a spill failure for R0.  Use a unspec
8697      insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
8698      when rX is a GOT address for the guard symbol.  Ugly but doesn't
8699      matter because this is a rare situation.  */
8700   if (!TARGET_SHMEDIA
8701       && flag_stack_protect
8702       && GET_CODE (operands[1]) == CONST
8703       && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
8704       && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
8705       && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
8706                  \"__stack_chk_guard\") == 0)
8707     emit_insn (gen_chk_guard_add (operands[3], operands[2]));
8708   else
8709     emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
8710                                                gen_rtx_REG (Pmode, PIC_REG)));
8712   /* N.B. This is not constant for a GOTPLT relocation.  */
8713   mem = gen_rtx_MEM (Pmode, operands[3]);
8714   MEM_NOTRAP_P (mem) = 1;
8715   /* ??? Should we have a special alias set for the GOT?  */
8716   emit_move_insn (operands[0], mem);
8718   DONE;
8721 (define_expand "sym2GOT"
8722   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
8723   ""
8724   "")
8726 (define_expand "symGOT2reg"
8727   [(match_operand 0 "" "") (match_operand 1 "" "")]
8728   ""
8729   "
8731   rtx gotsym, insn;
8733   gotsym = gen_sym2GOT (operands[1]);
8734   PUT_MODE (gotsym, Pmode);
8735   insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
8737   MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
8739   DONE;
8742 (define_expand "symGOTPLT2reg"
8743   [(match_operand 0 "" "") (match_operand 1 "" "")]
8744   ""
8745   "
8747   rtx pltsym = gen_rtx_CONST (Pmode,
8748                               gen_rtx_UNSPEC (Pmode,
8749                                               gen_rtvec (1, operands[1]),
8750                                               UNSPEC_GOTPLT));
8751   emit_insn (gen_symGOT_load (operands[0], pltsym));
8752   DONE;
8755 (define_expand "sym2GOTOFF"
8756   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
8757   ""
8758   "")
8760 (define_expand "symGOTOFF2reg"
8761   [(match_operand 0 "" "") (match_operand 1 "" "")]
8762   ""
8763   "
8765   rtx gotoffsym, insn;
8766   rtx t = (!can_create_pseudo_p ()
8767            ? operands[0]
8768            : gen_reg_rtx (GET_MODE (operands[0])));
8770   gotoffsym = gen_sym2GOTOFF (operands[1]);
8771   PUT_MODE (gotoffsym, Pmode);
8772   emit_move_insn (t, gotoffsym);
8773   insn = emit_move_insn (operands[0],
8774                          gen_rtx_PLUS (Pmode, t,
8775                                        gen_rtx_REG (Pmode, PIC_REG)));
8777   set_unique_reg_note (insn, REG_EQUAL, operands[1]);
8779   DONE;
8782 (define_expand "symPLT_label2reg"
8783   [(set (match_operand:SI 0 "" "")
8784         (const:SI
8785          (unspec:SI
8786           [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
8787            (const:SI (plus:SI (match_operand:SI 2 "" "")
8788                               (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
8789    ;; Even though the PIC register is not really used by the call
8790    ;; sequence in which this is expanded, the PLT code assumes the PIC
8791    ;; register is set, so we must not skip its initialization.  Since
8792    ;; we only use this expand as part of calling sequences, and never
8793    ;; to take the address of a function, this is the best point to
8794    ;; insert the (use).  Using the PLT to take the address of a
8795    ;; function would be wrong, not only because the PLT entry could
8796    ;; then be called from a function that doesn't initialize the PIC
8797    ;; register to the proper GOT, but also because pointers to the
8798    ;; same function might not compare equal, should they be set by
8799    ;; different shared libraries.
8800    (use (reg:SI PIC_REG))]
8801   "TARGET_SH1"
8802   "")
8804 (define_expand "sym2PIC"
8805   [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
8806   ""
8807   "")
8809 ;; TLS code generation.
8810 ;; ??? this should be a define_insn_and_split
8811 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
8812 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
8813 ;; for details.
8815 (define_insn "tls_global_dynamic"
8816   [(set (match_operand:SI 0 "register_operand" "=&z")
8817         (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8818                                   UNSPEC_TLSGD))
8819               (const_int 0)))
8820    (use (reg:PSI FPSCR_REG))
8821    (use (reg:SI PIC_REG))
8822    (clobber (reg:SI PR_REG))
8823    (clobber (scratch:SI))]
8824   "TARGET_SH1"
8825   "*
8827   return \"\\
8828 mov.l\\t1f,r4\\n\\
8829 \\tmova\\t2f,r0\\n\\
8830 \\tmov.l\\t2f,r1\\n\\
8831 \\tadd\\tr0,r1\\n\\
8832 \\tjsr\\t@r1\\n\\
8833 \\tadd\\tr12,r4\\n\\
8834 \\tbra\\t3f\\n\\
8835 \\tnop\\n\\
8836 \\t.align\\t2\\n\\
8837 1:\\t.long\\t%a1@TLSGD\\n\\
8838 2:\\t.long\\t__tls_get_addr@PLT\\n\\
8839 3:\";
8841   [(set_attr "type" "tls_load")
8842    (set_attr "length" "26")])
8844 (define_insn "tls_local_dynamic"
8845   [(set (match_operand:SI 0 "register_operand" "=&z")
8846         (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8847                                   UNSPEC_TLSLDM))
8848               (const_int 0)))
8849    (use (reg:PSI FPSCR_REG))
8850    (use (reg:SI PIC_REG))
8851    (clobber (reg:SI PR_REG))
8852    (clobber (scratch:SI))]
8853   "TARGET_SH1"
8854   "*
8856   return \"\\
8857 mov.l\\t1f,r4\\n\\
8858 \\tmova\\t2f,r0\\n\\
8859 \\tmov.l\\t2f,r1\\n\\
8860 \\tadd\\tr0,r1\\n\\
8861 \\tjsr\\t@r1\\n\\
8862 \\tadd\\tr12,r4\\n\\
8863 \\tbra\\t3f\\n\\
8864 \\tnop\\n\\
8865 \\t.align\\t2\\n\\
8866 1:\\t.long\\t%a1@TLSLDM\\n\\
8867 2:\\t.long\\t__tls_get_addr@PLT\\n\\
8868 3:\";
8870   [(set_attr "type" "tls_load")
8871    (set_attr "length" "26")])
8873 (define_expand "sym2DTPOFF"
8874   [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
8875   ""
8876   "")
8878 (define_expand "symDTPOFF2reg"
8879   [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
8880   ""
8881   "
8883   rtx dtpoffsym;
8884   rtx t = (!can_create_pseudo_p ()
8885            ? operands[0]
8886            : gen_reg_rtx (GET_MODE (operands[0])));
8888   dtpoffsym = gen_sym2DTPOFF (operands[1]);
8889   PUT_MODE (dtpoffsym, Pmode);
8890   emit_move_insn (t, dtpoffsym);
8891   emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
8892   DONE;
8895 (define_expand "sym2GOTTPOFF"
8896   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
8897   ""
8898   "")
8900 (define_insn "tls_initial_exec"
8901   [(set (match_operand:SI 0 "register_operand" "=&r")
8902         (unspec:SI [(match_operand:SI 1 "" "")]
8903                     UNSPEC_TLSIE))
8904    (use (reg:SI GBR_REG))
8905    (use (reg:SI PIC_REG))
8906    (clobber (reg:SI R0_REG))]
8907   ""
8908   "*
8910   return \"\\
8911 mov.l\\t1f,r0\\n\\
8912 \\tstc\\tgbr,%0\\n\\
8913 \\tmov.l\\t@(r0,r12),r0\\n\\
8914 \\tbra\\t2f\\n\\
8915 \\tadd\\tr0,%0\\n\\
8916 \\t.align\\t2\\n\\
8917 1:\\t.long\\t%a1\\n\\
8918 2:\";
8920   [(set_attr "type" "tls_load")
8921    (set_attr "length" "16")])
8923 (define_expand "sym2TPOFF"
8924   [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
8925   ""
8926   "")
8928 (define_expand "symTPOFF2reg"
8929   [(match_operand 0 "" "") (match_operand 1 "" "")]
8930   ""
8931   "
8933   rtx tpoffsym;
8935   tpoffsym = gen_sym2TPOFF (operands[1]);
8936   PUT_MODE (tpoffsym, Pmode);
8937   emit_move_insn (operands[0], tpoffsym);
8938   DONE;
8941 (define_insn "load_gbr"
8942   [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))
8943    (use (reg:SI GBR_REG))]
8944   ""
8945   "stc  gbr,%0"
8946   [(set_attr "type" "tls_load")])
8948 ;; case instruction for switch statements.
8950 ;; Operand 0 is index
8951 ;; operand 1 is the minimum bound
8952 ;; operand 2 is the maximum bound - minimum bound + 1
8953 ;; operand 3 is CODE_LABEL for the table;
8954 ;; operand 4 is the CODE_LABEL to go to if index out of range.
8956 (define_expand "casesi"
8957   [(match_operand:SI 0 "arith_reg_operand" "")
8958    (match_operand:SI 1 "arith_reg_operand" "")
8959    (match_operand:SI 2 "arith_reg_operand" "")
8960    (match_operand 3 "" "") (match_operand 4 "" "")]
8961   ""
8962   "
8964   rtx reg = gen_reg_rtx (SImode);
8965   rtx reg2 = gen_reg_rtx (SImode);
8966   if (TARGET_SHMEDIA)
8967     {
8968       rtx reg = gen_reg_rtx (DImode);
8969       rtx reg2 = gen_reg_rtx (DImode);
8970       rtx reg3 = gen_reg_rtx (Pmode);
8971       rtx reg4 = gen_reg_rtx (Pmode);
8972       rtx reg5 = gen_reg_rtx (Pmode);
8973       rtx load, test;
8975       operands[0] = convert_modes (DImode, SImode, operands[0], 0);
8976       operands[1] = convert_modes (DImode, SImode, operands[1], 0);
8977       operands[2] = convert_modes (DImode, SImode, operands[2], 1);
8979       test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
8980       emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0], operands[4]));
8981       emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
8982       test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
8983       emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
8984       emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
8985       emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
8986                                                (Pmode, operands[3])));
8987       /* Messy: can we subreg to clean this up? */
8988       if (Pmode == DImode)
8989         load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
8990       else
8991         load = gen_casesi_load_media (reg4,
8992                                       gen_rtx_SUBREG (DImode, reg3, 0),
8993                                       reg2, operands[3]);
8994       PUT_MODE (SET_SRC (load), Pmode);
8995       emit_insn (load);
8996       /* ??? The following add could be eliminated if we used ptrel.  */
8997       emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
8998       emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
8999       emit_barrier ();
9000       DONE;
9001     }
9002   operands[1] = copy_to_mode_reg (SImode, operands[1]);
9003   operands[2] = copy_to_mode_reg (SImode, operands[2]);
9004   /* If optimizing, casesi_worker depends on the mode of the instruction
9005      before label it 'uses' - operands[3].  */
9006   emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
9007                            reg));
9008   emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
9009   if (TARGET_SH2)
9010     emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
9011   else
9012     emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
9013   /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
9014      operands[3], but to lab.  We will fix this up in
9015      machine_dependent_reorg.  */
9016   emit_barrier ();
9017   DONE;
9020 (define_expand "casesi_0"
9021   [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
9022    (set (match_dup 4) (minus:SI (match_dup 4)
9023                                 (match_operand:SI 1 "arith_operand" "")))
9024    (set (reg:SI T_REG)
9025         (gtu:SI (match_dup 4)
9026                 (match_operand:SI 2 "arith_reg_operand" "")))
9027    (set (pc)
9028         (if_then_else (ne (reg:SI T_REG)
9029                           (const_int 0))
9030                       (label_ref (match_operand 3 "" ""))
9031                       (pc)))]
9032   "TARGET_SH1"
9033   "")
9035 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
9036 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
9037 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
9039 (define_insn "casesi_worker_0"
9040   [(set (match_operand:SI 0 "register_operand" "=r,r")
9041         (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
9042                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9043    (clobber (match_scratch:SI 3 "=X,1"))
9044    (clobber (match_scratch:SI 4 "=&z,z"))]
9045   "TARGET_SH1"
9046   "#")
9048 (define_split
9049   [(set (match_operand:SI 0 "register_operand" "")
9050         (unspec:SI [(match_operand:SI 1 "register_operand" "")
9051                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9052    (clobber (match_scratch:SI 3 ""))
9053    (clobber (match_scratch:SI 4 ""))]
9054   "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
9055   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
9056    (parallel [(set (match_dup 0)
9057               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
9058                           (label_ref (match_dup 2))] UNSPEC_CASESI))
9059               (clobber (match_dup 3))])
9060    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
9061   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
9063 (define_split
9064   [(set (match_operand:SI 0 "register_operand" "")
9065         (unspec:SI [(match_operand:SI 1 "register_operand" "")
9066                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9067    (clobber (match_scratch:SI 3 ""))
9068    (clobber (match_scratch:SI 4 ""))]
9069   "TARGET_SH2 && reload_completed"
9070   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
9071    (parallel [(set (match_dup 0)
9072               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
9073                           (label_ref (match_dup 2))] UNSPEC_CASESI))
9074               (clobber (match_dup 3))])]
9075   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
9077 (define_insn "casesi_worker_1"
9078   [(set (match_operand:SI 0 "register_operand" "=r,r")
9079         (unspec:SI [(reg:SI R0_REG)
9080                     (match_operand:SI 1 "register_operand" "0,r")
9081                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9082    (clobber (match_scratch:SI 3 "=X,1"))]
9083   "TARGET_SH1"
9084   "*
9086   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
9088   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9090   switch (GET_MODE (diff_vec))
9091     {
9092     case SImode:
9093       return \"shll2    %1\;mov.l       @(r0,%1),%0\";
9094     case HImode:
9095       return \"add      %1,%1\;mov.w    @(r0,%1),%0\";
9096     case QImode:
9097       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9098         return \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
9099       return \"mov.b    @(r0,%1),%0\";
9100     default:
9101       gcc_unreachable ();
9102     }
9104   [(set_attr "length" "4")])
9106 (define_insn "casesi_worker_2"
9107   [(set (match_operand:SI 0 "register_operand" "=r,r")
9108         (unspec:SI [(reg:SI R0_REG)
9109                     (match_operand:SI 1 "register_operand" "0,r")
9110                     (label_ref (match_operand 2 "" ""))
9111                     (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
9112    (clobber (match_operand:SI 4 "" "=X,1"))]
9113   "TARGET_SH2 && reload_completed && flag_pic"
9114   "*
9116   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
9117   const char *load;
9119   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9121   switch (GET_MODE (diff_vec))
9122     {
9123     case SImode:
9124       output_asm_insn (\"shll2    %1\", operands);
9125       load = \"mov.l    @(r0,%1),%0\"; break;
9126     case HImode:
9127       output_asm_insn (\"add    %1,%1\", operands);
9128       load = \"mov.w    @(r0,%1),%0\"; break;
9129     case QImode:
9130       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9131         load = \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
9132       else
9133         load = \"mov.b  @(r0,%1),%0\";
9134       break;
9135     default:
9136       gcc_unreachable ();
9137     }
9138   output_asm_insn (\"add\tr0,%1\;mova\t%O3,r0\\n\", operands);
9139   return load;
9141   [(set_attr "length" "8")])
9143 (define_insn "casesi_shift_media"
9144   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9145         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
9146                    (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
9147                     UNSPEC_CASESI)))]
9148   "TARGET_SHMEDIA"
9149   "*
9151   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
9153   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9155   switch (GET_MODE (diff_vec))
9156     {
9157     case SImode:
9158       return \"shlli    %1, 2, %0\";
9159     case HImode:
9160       return \"shlli    %1, 1, %0\";
9161     case QImode:
9162       if (rtx_equal_p (operands[0], operands[1]))
9163         return \"\";
9164       return \"add      %1, r63, %0\";
9165     default:
9166       gcc_unreachable ();
9167     }
9169   [(set_attr "type" "arith_media")])
9171 (define_insn "casesi_load_media"
9172   [(set (match_operand 0 "any_arith_reg_dest" "=r")
9173         (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
9174                          (match_operand:DI 2 "arith_reg_operand" "r")
9175                          (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
9176   "TARGET_SHMEDIA"
9177   "*
9179   rtx diff_vec = PATTERN (next_real_insn (operands[3]));
9181   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9183   switch (GET_MODE (diff_vec))
9184     {
9185     case SImode:
9186       return \"ldx.l    %1, %2, %0\";
9187     case HImode:
9188 #if 0
9189       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9190         return \"ldx.uw %1, %2, %0\";
9191 #endif
9192       return \"ldx.w    %1, %2, %0\";
9193     case QImode:
9194       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9195         return \"ldx.ub %1, %2, %0\";
9196       return \"ldx.b    %1, %2, %0\";
9197     default:
9198       gcc_unreachable ();
9199     }
9201   [(set_attr "type" "load_media")])
9203 (define_expand "return"
9204   [(return)]
9205   "reload_completed && ! sh_need_epilogue ()"
9206   "
9208   if (TARGET_SHMEDIA)
9209     {
9210       emit_jump_insn (gen_return_media ());
9211       DONE;
9212     }
9214   if (TARGET_SHCOMPACT
9215       && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
9216     {
9217       emit_jump_insn (gen_shcompact_return_tramp ());
9218       DONE;
9219     }
9222 (define_insn "*return_i"
9223   [(return)]
9224   "TARGET_SH1 && ! (TARGET_SHCOMPACT
9225                     && (crtl->args.info.call_cookie
9226                         & CALL_COOKIE_RET_TRAMP (1)))
9227    && reload_completed
9228    && lookup_attribute (\"trap_exit\",
9229                         DECL_ATTRIBUTES (current_function_decl)) == NULL_TREE"
9230   "*
9231   {
9232     if (TARGET_SH2A && (dbr_sequence_length () == 0)
9233                         && !current_function_interrupt)
9234        return \"rts/n\";
9235     else
9236        return \"%@      %#\";
9237   }"
9238   [(set_attr "type" "return")
9239    (set_attr "needs_delay_slot" "yes")])
9241 ;; trapa has no delay slot.
9242 (define_insn "*return_trapa"
9243   [(return)]
9244   "TARGET_SH1 && !TARGET_SHCOMPACT
9245    && reload_completed"
9246   "%@"
9247   [(set_attr "type" "return")])
9249 (define_expand "shcompact_return_tramp"
9250   [(return)]
9251   "TARGET_SHCOMPACT
9252    && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
9253   "
9255   rtx reg = gen_rtx_REG (Pmode, R0_REG);
9257   function_symbol (reg, \"__GCC_shcompact_return_trampoline\", SFUNC_STATIC);
9258   emit_jump_insn (gen_shcompact_return_tramp_i ());
9259   DONE;
9262 (define_insn "shcompact_return_tramp_i"
9263   [(parallel [(return) (use (reg:SI R0_REG))])]
9264   "TARGET_SHCOMPACT
9265    && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
9266   "jmp  @r0%#"
9267   [(set_attr "type" "jump_ind")
9268    (set_attr "needs_delay_slot" "yes")])
9270 (define_insn "return_media_i"
9271   [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
9272   "TARGET_SHMEDIA && reload_completed"
9273   "blink        %0, r63"
9274   [(set_attr "type" "jump_media")])
9276 (define_insn "return_media_rte"
9277   [(return)]
9278   "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
9279   "rte"
9280   [(set_attr "type" "jump_media")])
9282 (define_expand "return_media"
9283   [(return)]
9284   "TARGET_SHMEDIA && reload_completed"
9285   "
9287   int tr_regno = sh_media_register_for_return ();
9288   rtx tr;
9290   if (current_function_interrupt)
9291     {
9292       emit_jump_insn (gen_return_media_rte ());
9293       DONE;
9294     }
9295   if (tr_regno < 0)
9296     {
9297       rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
9299       gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
9300       tr_regno = TR0_REG;
9301       tr = gen_rtx_REG (Pmode, tr_regno);
9302       emit_move_insn (tr, r18);
9303     }
9304   else
9305     tr = gen_rtx_REG (Pmode, tr_regno);
9307   emit_jump_insn (gen_return_media_i (tr));
9308   DONE;
9311 (define_insn "shcompact_preserve_incoming_args"
9312   [(set (match_operand:SI 0 "register_operand" "+r")
9313         (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
9314   "TARGET_SHCOMPACT"
9315   ""
9316   [(set_attr "length" "0")])
9318 (define_insn "shcompact_incoming_args"
9319   [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
9320    (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
9321    (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
9322    (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
9323    (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
9324    (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
9325    (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
9326    (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
9327    (set (mem:BLK (reg:SI MACL_REG))
9328         (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
9329    (use (reg:SI R0_REG))
9330    (clobber (reg:SI R0_REG))
9331    (clobber (reg:SI MACL_REG))
9332    (clobber (reg:SI MACH_REG))
9333    (clobber (reg:SI PR_REG))]
9334   "TARGET_SHCOMPACT"
9335   "jsr  @r0%#"
9336   [(set_attr "needs_delay_slot" "yes")])
9338 (define_insn "shmedia_save_restore_regs_compact"
9339   [(set (reg:SI SP_REG)
9340         (plus:SI (reg:SI SP_REG)
9341                  (match_operand:SI 0 "immediate_operand" "i")))
9342    (use (reg:SI R0_REG))
9343    (clobber (reg:SI PR_REG))]
9344   "TARGET_SHCOMPACT
9345    && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
9346        || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
9347   "jsr @r0%#"
9348   [(set_attr "needs_delay_slot" "yes")])
9350 (define_expand "prologue"
9351   [(const_int 0)]
9352   ""
9353   "sh_expand_prologue (); DONE;")
9355 (define_expand "epilogue"
9356   [(return)]
9357   ""
9358   "
9360   sh_expand_epilogue (0);
9361   emit_jump_insn (gen_return ());
9362   DONE;
9365 (define_expand "eh_return"
9366   [(use (match_operand 0 "register_operand" ""))]
9367   ""
9369   rtx ra = operands[0];
9371   if (TARGET_SHMEDIA64)
9372     emit_insn (gen_eh_set_ra_di (ra));
9373   else
9374     emit_insn (gen_eh_set_ra_si (ra));
9376   DONE;
9379 ;; Clobber the return address on the stack.  We can't expand this
9380 ;; until we know where it will be put in the stack frame.
9382 (define_insn "eh_set_ra_si"
9383   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
9384       UNSPECV_EH_RETURN)
9385    (clobber (match_scratch:SI 1 "=&r"))]
9386   "! TARGET_SHMEDIA64"
9387   "#")
9389 (define_insn "eh_set_ra_di"
9390   [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
9391       UNSPECV_EH_RETURN)
9392    (clobber (match_scratch:DI 1 "=&r"))]
9393   "TARGET_SHMEDIA64"
9394   "#")
9396 (define_split
9397   [(unspec_volatile [(match_operand 0 "register_operand" "")]
9398       UNSPECV_EH_RETURN)
9399    (clobber (match_scratch 1 ""))]
9400   "reload_completed"
9401   [(const_int 0)]
9402   "
9404   sh_set_return_address (operands[0], operands[1]);
9405   DONE;
9408 (define_insn "blockage"
9409   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
9410   ""
9411   ""
9412   [(set_attr "length" "0")])
9414 ;; Define movml instructions for SH2A target.  Currently they are
9415 ;; used to push and pop all banked registers only.
9417 (define_insn "movml_push_banked"
9418   [(set (match_operand:SI 0 "register_operand" "=r")
9419           (plus (match_dup 0) (const_int -32)))
9420    (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
9421    (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
9422    (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
9423    (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
9424    (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
9425    (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
9426    (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
9427    (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
9428   "TARGET_SH2A && REGNO (operands[0]) == 15"
9429   "movml.l\tr7,@-r15"
9430   [(set_attr "in_delay_slot" "no")])
9432 (define_insn "movml_pop_banked"
9433   [(set (match_operand:SI 0 "register_operand" "=r")
9434           (plus (match_dup 0) (const_int 32)))
9435    (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
9436    (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
9437    (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
9438    (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
9439    (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
9440    (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
9441    (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
9442    (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
9443   "TARGET_SH2A && REGNO (operands[0]) == 15"
9444   "movml.l\t@r15+,r7"
9445   [(set_attr "in_delay_slot" "no")])
9447 ;; ------------------------------------------------------------------------
9448 ;; Scc instructions
9449 ;; ------------------------------------------------------------------------
9451 (define_insn "movt"
9452   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9453         (eq:SI (reg:SI T_REG) (const_int 1)))]
9454   "TARGET_SH1"
9455   "movt %0"
9456   [(set_attr "type" "arith")])
9458 (define_expand "cstore4_media"
9459   [(set (match_operand:SI 0 "register_operand" "=r")
9460         (match_operator:SI 1 "sh_float_comparison_operator"
9461          [(match_operand 2 "logical_operand" "")
9462           (match_operand 3 "cmp_operand" "")]))]
9463   "TARGET_SHMEDIA"
9464   "
9466   enum machine_mode mode = GET_MODE (operands[2]);
9467   enum rtx_code code = GET_CODE (operands[1]);
9468   bool invert, swap;
9469   if (mode == VOIDmode)
9470     mode = GET_MODE (operands[3]);
9471   if (operands[2] == const0_rtx)
9472     {
9473       if (code == EQ || code == NE)
9474         operands[2] = operands[3], operands[3] = const0_rtx;
9475     }
9476   else
9477     operands[2] = force_reg (mode, operands[2]);
9478   if (operands[3] != const0_rtx)
9479     operands[3] = force_reg (mode, operands[3]);
9481   switch (code)
9482     {
9483     case GEU:
9484     case GE:
9485       swap = invert = !FLOAT_MODE_P (mode);
9486       break;
9488     case LEU:
9489     case LE:
9490       swap = FLOAT_MODE_P (mode), invert = !swap;
9491       break;
9493     case LTU:
9494     case LT:
9495       swap = true, invert = false;
9496       break;
9498     case GTU:
9499     case GT:
9500     case EQ:
9501     case UNORDERED:
9502       swap = invert = false;
9503       break;
9505     case NE:
9506       swap = invert = true;
9507       break;
9509     default:
9510       gcc_unreachable ();
9511   }
9513   if (swap)
9514     {
9515       rtx tem = operands[2];
9516       operands[2] = operands[3];
9517       operands[3] = tem;
9518       code = swap_condition (code);
9519     }
9521   if (invert)
9522     {
9523       rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
9524       code = reverse_condition (code);
9525       operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
9526       emit_insn (gen_cstore4_media (tem, operands[1],
9527                                     operands[2], operands[3]));
9528       code = EQ;
9529       operands[2] = tem;
9530       operands[3] = const0_rtx;
9531     }
9533   operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
9536 (define_expand "cstoresi4"
9537   [(set (match_operand:SI 0 "register_operand" "=r")
9538         (match_operator:SI 1 "comparison_operator"
9539          [(match_operand:SI 2 "cmpsi_operand" "")
9540           (match_operand:SI 3 "arith_operand" "")]))]
9541   "TARGET_SH1 || TARGET_SHMEDIA"
9542   "if (TARGET_SHMEDIA)
9543     {
9544       emit_insn (gen_cstore4_media (operands[0], operands[1],
9545                                     operands[2], operands[3]));
9546       DONE;
9547     }
9549    if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
9550        && sh_expand_t_scc (operands))
9551      DONE;
9553    if (! currently_expanding_to_rtl)
9554      FAIL;
9555    
9556    sh_emit_compare_and_set (operands, SImode);
9557    DONE;
9560 (define_expand "cstoredi4"
9561   [(set (match_operand:SI 0 "register_operand" "=r")
9562         (match_operator:SI 1 "comparison_operator"
9563          [(match_operand:DI 2 "arith_operand" "")
9564           (match_operand:DI 3 "arith_operand" "")]))]
9565   "TARGET_SH2 || TARGET_SHMEDIA"
9566   "if (TARGET_SHMEDIA)
9567     {
9568       emit_insn (gen_cstore4_media (operands[0], operands[1],
9569                                     operands[2], operands[3]));
9570       DONE;
9571     }
9573    if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
9574        && sh_expand_t_scc (operands))
9575      DONE;
9577    if (! currently_expanding_to_rtl)
9578      FAIL;
9579    
9580    sh_emit_compare_and_set (operands, DImode);
9581    DONE;
9586 ;; sne moves the complement of the T reg to DEST like this:
9587 ;;      cmp/eq ...
9588 ;;      mov    #-1,temp
9589 ;;      negc   temp,dest
9590 ;;   This is better than xoring compare result with 1 because it does
9591 ;;   not require r0 and further, the -1 may be CSE-ed or lifted out of a
9592 ;;   loop.
9594 (define_expand "movnegt"
9595   [(set (match_dup 1) (const_int -1))
9596    (parallel [(set (match_operand:SI 0 "" "")
9597                    (neg:SI (plus:SI (reg:SI T_REG)
9598                                     (match_dup 1))))
9599               (set (reg:SI T_REG)
9600                    (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
9601                           (const_int 0)))])]
9602   ""
9603   "
9605   operands[1] = gen_reg_rtx (SImode);
9609 ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
9610 ;; This prevents a regression that occurred when we switched from xor to
9611 ;; mov/neg for sne.
9613 (define_split
9614   [(set (match_operand:SI 0 "arith_reg_dest" "")
9615         (plus:SI (reg:SI T_REG)
9616                  (const_int -1)))]
9617   "TARGET_SH1"
9618   [(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1)))
9619    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
9620   "")
9622 (define_expand "cstoresf4"
9623   [(set (match_operand:SI 0 "register_operand" "=r")
9624         (match_operator:SI 1 "sh_float_comparison_operator"
9625          [(match_operand:SF 2 "arith_operand" "")
9626           (match_operand:SF 3 "arith_operand" "")]))]
9627   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
9628   "if (TARGET_SHMEDIA)
9629      {
9630        emit_insn (gen_cstore4_media (operands[0], operands[1],
9631                                      operands[2], operands[3]));
9632        DONE;
9633      }
9635    if (! currently_expanding_to_rtl)
9636      FAIL;
9637    
9638    sh_emit_compare_and_set (operands, SFmode);
9639    DONE;
9642 (define_expand "cstoredf4"
9643   [(set (match_operand:SI 0 "register_operand" "=r")
9644         (match_operator:SI 1 "sh_float_comparison_operator"
9645          [(match_operand:DF 2 "arith_operand" "")
9646           (match_operand:DF 3 "arith_operand" "")]))]
9647   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9648   "if (TARGET_SHMEDIA)
9649      {
9650        emit_insn (gen_cstore4_media (operands[0], operands[1],
9651                                      operands[2], operands[3]));
9652        DONE;
9653      }
9655     if (! currently_expanding_to_rtl)
9656       FAIL;
9657    
9658    sh_emit_compare_and_set (operands, DFmode);
9659    DONE;
9663 ;; -------------------------------------------------------------------------
9664 ;; Instructions to cope with inline literal tables
9665 ;; -------------------------------------------------------------------------
9667 ; 2 byte integer in line
9669 (define_insn "consttable_2"
9670  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9671                     (match_operand 1 "" "")]
9672                    UNSPECV_CONST2)]
9673  ""
9674  "*
9676   if (operands[1] != const0_rtx)
9677     assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
9678   return \"\";
9680  [(set_attr "length" "2")
9681  (set_attr "in_delay_slot" "no")])
9683 ; 4 byte integer in line
9685 (define_insn "consttable_4"
9686  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9687                     (match_operand 1 "" "")]
9688                    UNSPECV_CONST4)]
9689  ""
9690  "*
9692   if (operands[1] != const0_rtx)
9693     {
9694       assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
9695       mark_symbol_refs_as_used (operands[0]);
9696     }
9697   return \"\";
9699  [(set_attr "length" "4")
9700   (set_attr "in_delay_slot" "no")])
9702 ; 8 byte integer in line
9704 (define_insn "consttable_8"
9705  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9706                     (match_operand 1 "" "")]
9707                    UNSPECV_CONST8)]
9708  ""
9709  "*
9711   if (operands[1] != const0_rtx)
9712     assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
9713   return \"\";
9715  [(set_attr "length" "8")
9716   (set_attr "in_delay_slot" "no")])
9718 ; 4 byte floating point
9720 (define_insn "consttable_sf"
9721  [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
9722                     (match_operand 1 "" "")]
9723                    UNSPECV_CONST4)]
9724  ""
9725  "*
9727   if (operands[1] != const0_rtx)
9728     {
9729       REAL_VALUE_TYPE d;
9730       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9731       assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
9732     }
9733   return \"\";
9735  [(set_attr "length" "4")
9736   (set_attr "in_delay_slot" "no")])
9738 ; 8 byte floating point
9740 (define_insn "consttable_df"
9741  [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
9742                     (match_operand 1 "" "")]
9743                    UNSPECV_CONST8)]
9744  ""
9745  "*
9747   if (operands[1] != const0_rtx)
9748     {
9749       REAL_VALUE_TYPE d;
9750       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9751       assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
9752     }
9753   return \"\";
9755  [(set_attr "length" "8")
9756   (set_attr "in_delay_slot" "no")])
9758 ;; Alignment is needed for some constant tables; it may also be added for
9759 ;; Instructions at the start of loops, or after unconditional branches.
9760 ;; ??? We would get more accurate lengths if we did instruction
9761 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
9762 ;; here is too conservative.
9764 ; align to a two byte boundary
9766 (define_expand "align_2"
9767  [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
9768  ""
9769  "")
9771 ; align to a four byte boundary
9772 ;; align_4 and align_log are instructions for the starts of loops, or
9773 ;; after unconditional branches, which may take up extra room.
9775 (define_expand "align_4"
9776  [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
9777  ""
9778  "")
9780 ; align to a cache line boundary
9782 (define_insn "align_log"
9783  [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
9784  ""
9785  ""
9786  [(set_attr "length" "0")
9787   (set_attr "in_delay_slot" "no")])
9789 ; emitted at the end of the literal table, used to emit the
9790 ; 32bit branch labels if needed.
9792 (define_insn "consttable_end"
9793   [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
9794   ""
9795   "* return output_jump_label_table ();"
9796   [(set_attr "in_delay_slot" "no")])
9798 ; emitted at the end of the window in the literal table.
9800 (define_insn "consttable_window_end"
9801   [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
9802   ""
9803   ""
9804   [(set_attr "length" "0")
9805    (set_attr "in_delay_slot" "no")])
9807 ;; -------------------------------------------------------------------------
9808 ;; Misc
9809 ;; -------------------------------------------------------------------------
9811 ;; String/block move insn.
9813 (define_expand "movmemsi"
9814   [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
9815                    (mem:BLK (match_operand:BLK 1 "" "")))
9816               (use (match_operand:SI 2 "nonmemory_operand" ""))
9817               (use (match_operand:SI 3 "immediate_operand" ""))
9818               (clobber (reg:SI PR_REG))
9819               (clobber (reg:SI R4_REG))
9820               (clobber (reg:SI R5_REG))
9821               (clobber (reg:SI R0_REG))])]
9822   "TARGET_SH1 && ! TARGET_SH5"
9823   "
9825   if(expand_block_move (operands))
9826      DONE;
9827   else FAIL;
9830 (define_insn "block_move_real"
9831   [(parallel [(set (mem:BLK (reg:SI R4_REG))
9832                    (mem:BLK (reg:SI R5_REG)))
9833               (use (match_operand:SI 0 "arith_reg_operand" "r"))
9834               (clobber (reg:SI PR_REG))
9835               (clobber (reg:SI R0_REG))])]
9836   "TARGET_SH1 && ! TARGET_HARD_SH4"
9837   "jsr  @%0%#"
9838   [(set_attr "type" "sfunc")
9839    (set_attr "needs_delay_slot" "yes")])
9841 (define_insn "block_lump_real"
9842   [(parallel [(set (mem:BLK (reg:SI R4_REG))
9843                    (mem:BLK (reg:SI R5_REG)))
9844               (use (match_operand:SI 0 "arith_reg_operand" "r"))
9845               (use (reg:SI R6_REG))
9846               (clobber (reg:SI PR_REG))
9847               (clobber (reg:SI T_REG))
9848               (clobber (reg:SI R4_REG))
9849               (clobber (reg:SI R5_REG))
9850               (clobber (reg:SI R6_REG))
9851               (clobber (reg:SI R0_REG))])]
9852   "TARGET_SH1 && ! TARGET_HARD_SH4"
9853   "jsr  @%0%#"
9854   [(set_attr "type" "sfunc")
9855    (set_attr "needs_delay_slot" "yes")])
9857 (define_insn "block_move_real_i4"
9858   [(parallel [(set (mem:BLK (reg:SI R4_REG))
9859                    (mem:BLK (reg:SI R5_REG)))
9860               (use (match_operand:SI 0 "arith_reg_operand" "r"))
9861               (clobber (reg:SI PR_REG))
9862               (clobber (reg:SI R0_REG))
9863               (clobber (reg:SI R1_REG))
9864               (clobber (reg:SI R2_REG))])]
9865   "TARGET_HARD_SH4"
9866   "jsr  @%0%#"
9867   [(set_attr "type" "sfunc")
9868    (set_attr "needs_delay_slot" "yes")])
9870 (define_insn "block_lump_real_i4"
9871   [(parallel [(set (mem:BLK (reg:SI R4_REG))
9872                    (mem:BLK (reg:SI R5_REG)))
9873               (use (match_operand:SI 0 "arith_reg_operand" "r"))
9874               (use (reg:SI R6_REG))
9875               (clobber (reg:SI PR_REG))
9876               (clobber (reg:SI T_REG))
9877               (clobber (reg:SI R4_REG))
9878               (clobber (reg:SI R5_REG))
9879               (clobber (reg:SI R6_REG))
9880               (clobber (reg:SI R0_REG))
9881               (clobber (reg:SI R1_REG))
9882               (clobber (reg:SI R2_REG))
9883               (clobber (reg:SI R3_REG))])]
9884   "TARGET_HARD_SH4"
9885   "jsr  @%0%#"
9886   [(set_attr "type" "sfunc")
9887    (set_attr "needs_delay_slot" "yes")])
9889 ;; -------------------------------------------------------------------------
9890 ;; Floating point instructions.
9891 ;; -------------------------------------------------------------------------
9893 ;; ??? All patterns should have a type attribute.
9895 (define_expand "movpsi"
9896   [(set (match_operand:PSI 0 "register_operand" "")
9897         (match_operand:PSI 1 "general_movsrc_operand" ""))]
9898   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9899   "")
9901 ;; The c / m alternative is a fake to guide reload to load directly into
9902 ;; fpscr, since reload doesn't know how to use post-increment.
9903 ;; TARGET_LEGITIMATE_ADDRESS_P guards about bogus addresses before reload,
9904 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
9905 ;; predicate after reload.
9906 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
9907 ;; like a mac -> gpr move.
9908 (define_insn "fpu_switch"
9909   [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
9910         (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
9911   "TARGET_SH2E
9912    && (! reload_completed
9913        || true_regnum (operands[0]) != FPSCR_REG
9914        || !MEM_P (operands[1])
9915        || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
9916   "@
9917         ! precision stays the same
9918         lds.l   %1,fpscr
9919         mov.l   %1,%0
9920         #
9921         lds     %1,fpscr
9922         mov     %1,%0
9923         mov.l   %1,%0
9924         sts     fpscr,%0
9925         sts.l   fpscr,%0"
9926   [(set_attr "length" "0,2,2,4,2,2,2,2,2")
9927    (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,fstore")])
9929 (define_peephole2
9930   [(set (reg:PSI FPSCR_REG)
9931         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
9932   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
9933   [(const_int 0)]
9935   rtx fpscr, mem, new_insn;
9937   fpscr = SET_DEST (PATTERN (curr_insn));
9938   mem = SET_SRC (PATTERN (curr_insn));
9939   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
9941   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
9942   add_reg_note (new_insn, REG_INC, operands[0]);
9943   DONE;
9946 (define_split
9947   [(set (reg:PSI FPSCR_REG)
9948         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
9949   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
9950    && (flag_peephole2 ? epilogue_completed : reload_completed)"
9951   [(const_int 0)]
9953   rtx fpscr, mem, new_insn;
9955   fpscr = SET_DEST (PATTERN (curr_insn));
9956   mem = SET_SRC (PATTERN (curr_insn));
9957   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
9959   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
9960   add_reg_note (new_insn, REG_INC, operands[0]);
9962   if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
9963     emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
9964   DONE;
9967 ;; ??? This uses the fp unit, but has no type indicating that.
9968 ;; If we did that, this would either give a bogus latency or introduce
9969 ;; a bogus FIFO constraint.
9970 ;; Since this insn is currently only used for prologues/epilogues,
9971 ;; it is probably best to claim no function unit, which matches the
9972 ;; current setting.
9973 (define_insn "toggle_sz"
9974   [(set (reg:PSI FPSCR_REG)
9975         (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
9976   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9977   "fschg"
9978   [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
9980 ;; There's no way we can use it today, since optimize mode switching
9981 ;; doesn't enable us to know from which mode we're switching to the
9982 ;; mode it requests, to tell whether we can use a relative mode switch
9983 ;; (like toggle_pr) or an absolute switch (like loading fpscr from
9984 ;; memory).
9985 (define_insn "toggle_pr"
9986   [(set (reg:PSI FPSCR_REG)
9987         (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
9988   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
9989   "fpchg"
9990   [(set_attr "type" "fpscr_toggle")])
9992 (define_expand "addsf3"
9993   [(set (match_operand:SF 0 "arith_reg_operand" "")
9994         (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
9995                  (match_operand:SF 2 "arith_reg_operand" "")))]
9996   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
9997   "
9999   if (TARGET_SH2E)
10000     {
10001       expand_sf_binop (&gen_addsf3_i, operands);
10002       DONE;
10003     }
10006 (define_insn "*addsf3_media"
10007   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10008         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10009                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10010   "TARGET_SHMEDIA_FPU"
10011   "fadd.s       %1, %2, %0"
10012   [(set_attr "type" "fparith_media")])
10014 (define_insn_and_split "unary_sf_op"
10015   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10016         (vec_select:V2SF
10017          (vec_concat:V2SF
10018           (vec_select:SF
10019            (match_dup 0)
10020            (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
10021           (match_operator:SF 2 "unary_float_operator"
10022             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10023                             (parallel [(match_operand 4
10024                                         "const_int_operand" "n")]))]))
10025          (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
10026   "TARGET_SHMEDIA_FPU"
10027   "#"
10028   "TARGET_SHMEDIA_FPU && reload_completed"
10029   [(set (match_dup 5) (match_dup 6))]
10030   "
10032   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10033   rtx op1 = gen_rtx_REG (SFmode,
10034                          (true_regnum (operands[1])
10035                           + (INTVAL (operands[4]) ^ endian)));
10037   operands[7] = gen_rtx_REG (SFmode,
10038                              (true_regnum (operands[0])
10039                               + (INTVAL (operands[3]) ^ endian)));
10040   operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
10042   [(set_attr "type" "fparith_media")])
10044 (define_insn_and_split "binary_sf_op0"
10045   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10046         (vec_concat:V2SF
10047           (match_operator:SF 3 "binary_float_operator"
10048             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10049                             (parallel [(const_int 0)]))
10050              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
10051                             (parallel [(const_int 0)]))])
10052           (vec_select:SF
10053            (match_dup 0)
10054            (parallel [(const_int 1)]))))]
10055   "TARGET_SHMEDIA_FPU"
10056   "#"
10057   "&& reload_completed"
10058   [(set (match_dup 4) (match_dup 5))]
10059   "
10061   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10062   rtx op1 = gen_rtx_REG (SFmode,
10063                          true_regnum (operands[1]) + endian);
10064   rtx op2 = gen_rtx_REG (SFmode,
10065                          true_regnum (operands[2]) + endian);
10067   operands[4] = gen_rtx_REG (SFmode,
10068                              true_regnum (operands[0]) + endian);
10069   operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
10071   [(set_attr "type" "fparith_media")])
10073 (define_insn_and_split "binary_sf_op1"
10074   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10075         (vec_concat:V2SF
10076           (vec_select:SF
10077            (match_dup 0)
10078            (parallel [(const_int 0)]))
10079           (match_operator:SF 3 "binary_float_operator"
10080             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10081                             (parallel [(const_int 1)]))
10082              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
10083                             (parallel [(const_int 1)]))])))]
10084   "TARGET_SHMEDIA_FPU"
10085   "#"
10086   "&& reload_completed"
10087   [(set (match_dup 4) (match_dup 5))]
10088   "
10090   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10091   rtx op1 = gen_rtx_REG (SFmode,
10092                          true_regnum (operands[1]) + (1 ^ endian));
10093   rtx op2 = gen_rtx_REG (SFmode,
10094                          true_regnum (operands[2]) + (1 ^ endian));
10096   operands[4] = gen_rtx_REG (SFmode,
10097                              true_regnum (operands[0]) + (1 ^ endian));
10098   operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
10100   [(set_attr "type" "fparith_media")])
10102 (define_insn "addsf3_i"
10103   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10104         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10105                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10106    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10107   "TARGET_SH2E"
10108   "fadd %2,%0"
10109   [(set_attr "type" "fp")
10110    (set_attr "fp_mode" "single")])
10112 (define_expand "subsf3"
10113   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10114         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10115                   (match_operand:SF 2 "fp_arith_reg_operand" "")))]
10116   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10117   "
10119   if (TARGET_SH2E)
10120     {
10121       expand_sf_binop (&gen_subsf3_i, operands);
10122       DONE;
10123     }
10126 (define_insn "*subsf3_media"
10127   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10128         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10129                   (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10130   "TARGET_SHMEDIA_FPU"
10131   "fsub.s       %1, %2, %0"
10132   [(set_attr "type" "fparith_media")])
10134 (define_insn "subsf3_i"
10135   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10136         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
10137                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10138    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10139   "TARGET_SH2E"
10140   "fsub %2,%0"
10141   [(set_attr "type" "fp")
10142    (set_attr "fp_mode" "single")])
10144 (define_expand "mulsf3"
10145   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10146         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10147                  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
10148   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10149   "")
10151 (define_insn "*mulsf3_media"
10152   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10153         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10154                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10155   "TARGET_SHMEDIA_FPU"
10156   "fmul.s       %1, %2, %0"
10157   [(set_attr "type" "fparith_media")])
10159 ;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
10160 ;; register in feeding fp instructions.  Thus, in order to generate fmac,
10161 ;; we start out with a mulsf pattern that does not depend on fpscr.
10162 ;; This is split after combine to introduce the dependency, in order to
10163 ;; get mode switching and scheduling right.
10164 (define_insn_and_split "mulsf3_ie"
10165   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10166         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10167                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10168   "TARGET_SH2E"
10169   "fmul %2,%0"
10170   "TARGET_SH4 || TARGET_SH2A_SINGLE"
10171   [(const_int 0)]
10172   "
10174   emit_insn (gen_mulsf3_i4 (operands[0], operands[1], operands[2],
10175              get_fpscr_rtx ()));
10176   DONE;
10178   [(set_attr "type" "fp")])
10180 (define_insn "mulsf3_i4"
10181   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10182         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10183                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10184    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10185   "TARGET_SH2E"
10186   "fmul %2,%0"
10187   [(set_attr "type" "fp")
10188    (set_attr "fp_mode" "single")])
10190 (define_insn "mac_media"
10191   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10192         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10193                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
10194                  (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
10195   "TARGET_SHMEDIA_FPU && TARGET_FMAC"
10196   "fmac.s %1, %2, %0"
10197   [(set_attr "type" "fparith_media")])
10199 (define_insn "*macsf3"
10200   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10201         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
10202                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
10203                  (match_operand:SF 3 "arith_reg_operand" "0")))
10204    (use (match_operand:PSI 4 "fpscr_operand" "c"))]
10205   "TARGET_SH2E && TARGET_FMAC"
10206   "fmac fr0,%2,%0"
10207   [(set_attr "type" "fp")
10208    (set_attr "fp_mode" "single")])
10210 (define_expand "divsf3"
10211   [(set (match_operand:SF 0 "arith_reg_operand" "")
10212         (div:SF (match_operand:SF 1 "arith_reg_operand" "")
10213                 (match_operand:SF 2 "arith_reg_operand" "")))]
10214   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10215   "
10217   if (TARGET_SH2E)
10218     {
10219       expand_sf_binop (&gen_divsf3_i, operands);
10220       DONE;
10221     }
10224 (define_insn "*divsf3_media"
10225   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10226         (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10227                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10228   "TARGET_SHMEDIA_FPU"
10229   "fdiv.s       %1, %2, %0"
10230   [(set_attr "type" "fdiv_media")])
10232 (define_insn "divsf3_i"
10233   [(set (match_operand:SF 0 "arith_reg_dest" "=f")
10234         (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
10235                  (match_operand:SF 2 "arith_reg_operand" "f")))
10236    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10237   "TARGET_SH2E"
10238   "fdiv %2,%0"
10239   [(set_attr "type" "fdiv")
10240    (set_attr "fp_mode" "single")])
10242 (define_insn "floatdisf2"
10243   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10244         (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10245   "TARGET_SHMEDIA_FPU"
10246   "float.qs %1, %0"
10247   [(set_attr "type" "fpconv_media")])
10249 (define_expand "floatsisf2"
10250   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10251         (float:SF (match_operand:SI 1 "fpul_operand" "")))]
10252   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10253   "
10255   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10256     {
10257       emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10258       DONE;
10259     }
10262 (define_insn "*floatsisf2_media"
10263   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10264         (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10265   "TARGET_SHMEDIA_FPU"
10266   "float.ls     %1, %0"
10267   [(set_attr "type" "fpconv_media")])
10269 (define_insn "floatsisf2_i4"
10270   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10271         (float:SF (match_operand:SI 1 "fpul_operand" "y")))
10272    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10273   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10274   "float        %1,%0"
10275   [(set_attr "type" "fp")
10276    (set_attr "fp_mode" "single")])
10278 (define_insn "*floatsisf2_ie"
10279   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10280         (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
10281   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10282   "float        %1,%0"
10283   [(set_attr "type" "fp")])
10285 (define_insn "fix_truncsfdi2"
10286   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10287         (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10288   "TARGET_SHMEDIA_FPU"
10289   "ftrc.sq %1, %0"
10290   [(set_attr "type" "fpconv_media")])
10292 (define_expand "fix_truncsfsi2"
10293   [(set (match_operand:SI 0 "fpul_operand" "=y")
10294         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10295   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10296   "
10298   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10299     {
10300       emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10301       DONE;
10302     }
10305 (define_insn "*fix_truncsfsi2_media"
10306   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10307         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10308   "TARGET_SHMEDIA_FPU"
10309   "ftrc.sl      %1, %0"
10310   [(set_attr "type" "fpconv_media")])
10312 (define_insn "fix_truncsfsi2_i4"
10313   [(set (match_operand:SI 0 "fpul_operand" "=y")
10314         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10315    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10316   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10317   "ftrc %1,%0"
10318   [(set_attr "type" "ftrc_s")
10319    (set_attr "fp_mode" "single")])
10321 ;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
10322 ;; fix_truncsfsi2_i4.
10323 ;; (define_insn "fix_truncsfsi2_i4_2"
10324 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10325 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10326 ;;   (use (reg:PSI FPSCR_REG))
10327 ;;   (clobber (reg:SI FPUL_REG))]
10328 ;;  "TARGET_SH4"
10329 ;;  "#"
10330 ;;  [(set_attr "length" "4")
10331 ;;   (set_attr "fp_mode" "single")])
10333 ;;(define_split
10334 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10335 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10336 ;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
10337 ;;   (clobber (reg:SI FPUL_REG))]
10338 ;;  "TARGET_SH4"
10339 ;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10340 ;;            (use (match_dup 2))])
10341 ;;   (set (match_dup 0) (reg:SI FPUL_REG))])
10343 (define_insn "*fixsfsi"
10344   [(set (match_operand:SI 0 "fpul_operand" "=y")
10345         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10346   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10347   "ftrc %1,%0"
10348   [(set_attr "type" "fp")])
10350 (define_insn "cmpgtsf_t"
10351   [(set (reg:SI T_REG)
10352         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10353                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10354   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10355   "fcmp/gt      %1,%0"
10356   [(set_attr "type" "fp_cmp")
10357    (set_attr "fp_mode" "single")])
10359 (define_insn "cmpeqsf_t"
10360   [(set (reg:SI T_REG)
10361         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10362                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10363   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10364   "fcmp/eq      %1,%0"
10365   [(set_attr "type" "fp_cmp")
10366    (set_attr "fp_mode" "single")])
10368 (define_insn "ieee_ccmpeqsf_t"
10369   [(set (reg:SI T_REG)
10370         (ior:SI (reg:SI T_REG)
10371                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10372                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
10373   "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10374   "* return output_ieee_ccmpeq (insn, operands);"
10375   [(set_attr "length" "4")])
10378 (define_insn "cmpgtsf_t_i4"
10379   [(set (reg:SI T_REG)
10380         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10381                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10382    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10383   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10384   "fcmp/gt      %1,%0"
10385   [(set_attr "type" "fp_cmp")
10386    (set_attr "fp_mode" "single")])
10388 (define_insn "cmpeqsf_t_i4"
10389   [(set (reg:SI T_REG)
10390         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10391                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10392    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10393   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10394   "fcmp/eq      %1,%0"
10395   [(set_attr "type" "fp_cmp")
10396    (set_attr "fp_mode" "single")])
10398 (define_insn "*ieee_ccmpeqsf_t_4"
10399   [(set (reg:SI T_REG)
10400         (ior:SI (reg:SI T_REG)
10401                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10402                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
10403    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10404   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10405   "* return output_ieee_ccmpeq (insn, operands);"
10406   [(set_attr "length" "4")
10407    (set_attr "fp_mode" "single")])
10409 (define_insn "cmpeqsf_media"
10410   [(set (match_operand:SI 0 "register_operand" "=r")
10411         (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10412                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10413   "TARGET_SHMEDIA_FPU"
10414   "fcmpeq.s     %1, %2, %0"
10415   [(set_attr "type" "fcmp_media")])
10417 (define_insn "cmpgtsf_media"
10418   [(set (match_operand:SI 0 "register_operand" "=r")
10419         (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10420                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10421   "TARGET_SHMEDIA_FPU"
10422   "fcmpgt.s     %1, %2, %0"
10423   [(set_attr "type" "fcmp_media")])
10425 (define_insn "cmpgesf_media"
10426   [(set (match_operand:SI 0 "register_operand" "=r")
10427         (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10428                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10429   "TARGET_SHMEDIA_FPU"
10430   "fcmpge.s     %1, %2, %0"
10431   [(set_attr "type" "fcmp_media")])
10433 (define_insn "cmpunsf_media"
10434   [(set (match_operand:SI 0 "register_operand" "=r")
10435         (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10436                       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10437   "TARGET_SHMEDIA_FPU"
10438   "fcmpun.s     %1, %2, %0"
10439   [(set_attr "type" "fcmp_media")])
10441 (define_expand "cbranchsf4"
10442   [(set (pc)
10443         (if_then_else (match_operator 0 "sh_float_comparison_operator"
10444                        [(match_operand:SF 1 "arith_operand" "")
10445                         (match_operand:SF 2 "arith_operand" "")])
10446                       (match_operand 3 "" "")
10447                       (pc)))]
10448   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10449   "
10451   if (TARGET_SHMEDIA)
10452     emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
10453                                           operands[3]));
10454   else
10455     sh_emit_compare_and_branch (operands, SFmode);
10456   DONE;
10459 (define_expand "negsf2"
10460   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10461         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10462   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10463   "
10465   if (TARGET_SH2E)
10466     {
10467       expand_sf_unop (&gen_negsf2_i, operands);
10468       DONE;
10469     }
10472 (define_insn "*negsf2_media"
10473   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10474         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10475   "TARGET_SHMEDIA_FPU"
10476   "fneg.s       %1, %0"
10477   [(set_attr "type" "fmove_media")])
10479 (define_insn "negsf2_i"
10480   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10481         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10482    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10483   "TARGET_SH2E"
10484   "fneg %0"
10485   [(set_attr "type" "fmove")
10486    (set_attr "fp_mode" "single")])
10488 (define_expand "sqrtsf2"
10489   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10490         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10491   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
10492   "
10494   if (TARGET_SH3E)
10495     {
10496       expand_sf_unop (&gen_sqrtsf2_i, operands);
10497       DONE;
10498     }
10501 (define_insn "*sqrtsf2_media"
10502   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10503         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10504   "TARGET_SHMEDIA_FPU"
10505   "fsqrt.s      %1, %0"
10506   [(set_attr "type" "fdiv_media")])
10508 (define_insn "sqrtsf2_i"
10509   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10510         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10511    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10512   "TARGET_SH3E"
10513   "fsqrt        %0"
10514   [(set_attr "type" "fdiv")
10515    (set_attr "fp_mode" "single")])
10517 (define_insn "rsqrtsf2"
10518   [(set (match_operand:SF 0 "register_operand" "=f")
10519         (div:SF (match_operand:SF 1 "immediate_operand" "i")
10520                 (sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
10521    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10522   "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10523    && operands[1] == CONST1_RTX (SFmode)"
10524   "fsrra        %0"
10525   [(set_attr "type" "fsrra")
10526    (set_attr "fp_mode" "single")])
10528 (define_insn "fsca"
10529   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10530         (vec_concat:V2SF
10531          (unspec:SF [(mult:SF
10532                       (float:SF (match_operand:SI 1 "fpul_operand" "y"))
10533                       (match_operand:SF 2 "immediate_operand" "i"))
10534                     ] UNSPEC_FSINA)
10535          (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
10536                     ] UNSPEC_FCOSA)))
10537    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10538   "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10539    && operands[2] == sh_fsca_int2sf ()"
10540   "fsca fpul,%d0"
10541   [(set_attr "type" "fsca")
10542    (set_attr "fp_mode" "single")])
10544 (define_expand "sinsf2"
10545   [(set (match_operand:SF 0 "nonimmediate_operand" "")
10546         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10547                    UNSPEC_FSINA))]
10548   "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10549   "
10551   rtx scaled = gen_reg_rtx (SFmode);
10552   rtx truncated = gen_reg_rtx (SImode);
10553   rtx fsca = gen_reg_rtx (V2SFmode);
10554   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10556   emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10557   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10558   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10559                           get_fpscr_rtx ()));
10560   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 0));
10561   DONE;
10564 (define_expand "cossf2"
10565   [(set (match_operand:SF 0 "nonimmediate_operand" "")
10566         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10567                    UNSPEC_FCOSA))]
10568   "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10569   "
10571   rtx scaled = gen_reg_rtx (SFmode);
10572   rtx truncated = gen_reg_rtx (SImode);
10573   rtx fsca = gen_reg_rtx (V2SFmode);
10574   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10576   emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10577   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10578   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10579                           get_fpscr_rtx ()));
10580   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
10581   DONE;
10584 (define_expand "sindf2"
10585   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10586         (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10587                    UNSPEC_FSINA))]
10588   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10589   "
10591   rtx scaled = gen_reg_rtx (DFmode);
10592   rtx truncated = gen_reg_rtx (SImode);
10593   rtx fsca = gen_reg_rtx (V2SFmode);
10594   rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10595   rtx sfresult = gen_reg_rtx (SFmode);
10597   emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10598   emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10599   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10600                           get_fpscr_rtx ()));
10601   emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 0));
10602   emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10603   DONE;
10606 (define_expand "cosdf2"
10607   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10608         (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10609                    UNSPEC_FCOSA))]
10610   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10611   "
10613   rtx scaled = gen_reg_rtx (DFmode);
10614   rtx truncated = gen_reg_rtx (SImode);
10615   rtx fsca = gen_reg_rtx (V2SFmode);
10616   rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10617   rtx sfresult = gen_reg_rtx (SFmode);
10619   emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10620   emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10621   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10622                           get_fpscr_rtx ()));
10623   emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 4));
10624   emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10625   DONE;
10628 (define_expand "abssf2"
10629   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10630         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10631   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10632   "
10634   if (TARGET_SH2E)
10635     {
10636       expand_sf_unop (&gen_abssf2_i, operands);
10637       DONE;
10638     }
10641 (define_insn "*abssf2_media"
10642   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10643         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10644   "TARGET_SHMEDIA_FPU"
10645   "fabs.s       %1, %0"
10646   [(set_attr "type" "fmove_media")])
10648 (define_insn "abssf2_i"
10649   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10650         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10651    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10652   "TARGET_SH2E"
10653   "fabs %0"
10654   [(set_attr "type" "fmove")
10655    (set_attr "fp_mode" "single")])
10657 (define_expand "adddf3"
10658   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10659         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10660                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10661   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10662   "
10664   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10665     {
10666       expand_df_binop (&gen_adddf3_i, operands);
10667       DONE;
10668     }
10671 (define_insn "*adddf3_media"
10672   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10673         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10674                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10675   "TARGET_SHMEDIA_FPU"
10676   "fadd.d       %1, %2, %0"
10677   [(set_attr "type" "dfparith_media")])
10679 (define_insn "adddf3_i"
10680   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10681         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10682                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10683    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10684   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10685   "fadd %2,%0"
10686   [(set_attr "type" "dfp_arith")
10687    (set_attr "fp_mode" "double")])
10689 (define_expand "subdf3"
10690   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10691         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10692                   (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10693   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10694   "
10696   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10697     {
10698       expand_df_binop (&gen_subdf3_i, operands);
10699       DONE;
10700     }
10703 (define_insn "*subdf3_media"
10704   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10705         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10706                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10707   "TARGET_SHMEDIA_FPU"
10708   "fsub.d       %1, %2, %0"
10709   [(set_attr "type" "dfparith_media")])
10711 (define_insn "subdf3_i"
10712   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10713         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10714                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10715    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10716   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10717   "fsub %2,%0"
10718   [(set_attr "type" "dfp_arith")
10719    (set_attr "fp_mode" "double")])
10721 (define_expand "muldf3"
10722   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10723         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10724                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10725   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10726   "
10728   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10729     {
10730       expand_df_binop (&gen_muldf3_i, operands);
10731       DONE;
10732     }
10735 (define_insn "*muldf3_media"
10736   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10737         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10738                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10739   "TARGET_SHMEDIA_FPU"
10740   "fmul.d       %1, %2, %0"
10741   [(set_attr "type" "dfmul_media")])
10743 (define_insn "muldf3_i"
10744   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10745         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10746                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10747    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10748   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10749   "fmul %2,%0"
10750   [(set_attr "type" "dfp_mul")
10751    (set_attr "fp_mode" "double")])
10753 (define_expand "divdf3"
10754   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10755         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10756                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10757   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10758   "
10760   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10761     {
10762       expand_df_binop (&gen_divdf3_i, operands);
10763       DONE;
10764     }
10767 (define_insn "*divdf3_media"
10768   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10769         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10770                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10771   "TARGET_SHMEDIA_FPU"
10772   "fdiv.d       %1, %2, %0"
10773   [(set_attr "type" "dfdiv_media")])
10775 (define_insn "divdf3_i"
10776   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10777         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10778                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10779    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10780   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10781   "fdiv %2,%0"
10782   [(set_attr "type" "dfdiv")
10783    (set_attr "fp_mode" "double")])
10785 (define_insn "floatdidf2"
10786   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10787         (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10788   "TARGET_SHMEDIA_FPU"
10789   "float.qd     %1, %0"
10790   [(set_attr "type" "dfpconv_media")])
10792 (define_expand "floatsidf2"
10793   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10794         (float:DF (match_operand:SI 1 "fpul_operand" "")))]
10795   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10796   "
10798   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10799     {
10800       emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
10801                                       get_fpscr_rtx ()));
10802       DONE;
10803     }
10806 (define_insn "*floatsidf2_media"
10807   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10808         (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10809   "TARGET_SHMEDIA_FPU"
10810   "float.ld     %1, %0"
10811   [(set_attr "type" "dfpconv_media")])
10813 (define_insn "floatsidf2_i"
10814   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10815         (float:DF (match_operand:SI 1 "fpul_operand" "y")))
10816    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10817   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10818   "float        %1,%0"
10819   [(set_attr "type" "dfp_conv")
10820    (set_attr "fp_mode" "double")])
10822 (define_insn "fix_truncdfdi2"
10823   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10824         (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10825   "TARGET_SHMEDIA_FPU"
10826   "ftrc.dq      %1, %0"
10827   [(set_attr "type" "dfpconv_media")])
10829 (define_expand "fix_truncdfsi2"
10830   [(set (match_operand:SI 0 "fpul_operand" "")
10831         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
10832   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10833   "
10835   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10836     {
10837       emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
10838                                           get_fpscr_rtx ()));
10839       DONE;
10840     }
10843 (define_insn "*fix_truncdfsi2_media"
10844   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10845         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10846   "TARGET_SHMEDIA_FPU"
10847   "ftrc.dl      %1, %0"
10848   [(set_attr "type" "dfpconv_media")])
10850 (define_insn "fix_truncdfsi2_i"
10851   [(set (match_operand:SI 0 "fpul_operand" "=y")
10852         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
10853    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10854   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10855   "ftrc %1,%0"
10856   [(set_attr "type" "dfp_conv")
10857    (set_attr "dfp_comp" "no")
10858    (set_attr "fp_mode" "double")])
10860 ;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
10861 ;; fix_truncdfsi2_i.
10862 ;; (define_insn "fix_truncdfsi2_i4"
10863 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10864 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
10865 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
10866 ;;    (clobber (reg:SI FPUL_REG))]
10867 ;;   "TARGET_SH4"
10868 ;;   "#"
10869 ;;   [(set_attr "length" "4")
10870 ;;    (set_attr "fp_mode" "double")])
10872 ;; (define_split
10873 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10874 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
10875 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
10876 ;;    (clobber (reg:SI FPUL_REG))]
10877 ;;   "TARGET_SH4"
10878 ;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10879 ;;            (use (match_dup 2))])
10880 ;;    (set (match_dup 0) (reg:SI FPUL_REG))])
10882 (define_insn "cmpgtdf_t"
10883   [(set (reg:SI T_REG)
10884         (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
10885                (match_operand:DF 1 "arith_reg_operand" "f")))
10886    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10887   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10888   "fcmp/gt      %1,%0"
10889   [(set_attr "type" "dfp_cmp")
10890    (set_attr "fp_mode" "double")])
10892 (define_insn "cmpeqdf_t"
10893   [(set (reg:SI T_REG)
10894         (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
10895                (match_operand:DF 1 "arith_reg_operand" "f")))
10896    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10897   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10898   "fcmp/eq      %1,%0"
10899   [(set_attr "type" "dfp_cmp")
10900    (set_attr "fp_mode" "double")])
10902 (define_insn "*ieee_ccmpeqdf_t"
10903   [(set (reg:SI T_REG)
10904         (ior:SI (reg:SI T_REG)
10905                 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
10906                        (match_operand:DF 1 "arith_reg_operand" "f"))))
10907    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10908   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10909   "* return output_ieee_ccmpeq (insn, operands);"
10910   [(set_attr "length" "4")
10911    (set_attr "fp_mode" "double")])
10913 (define_insn "cmpeqdf_media"
10914   [(set (match_operand:SI 0 "register_operand" "=r")
10915         (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10916                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10917   "TARGET_SHMEDIA_FPU"
10918   "fcmpeq.d     %1,%2,%0"
10919   [(set_attr "type" "fcmp_media")])
10921 (define_insn "cmpgtdf_media"
10922   [(set (match_operand:SI 0 "register_operand" "=r")
10923         (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10924                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10925   "TARGET_SHMEDIA_FPU"
10926   "fcmpgt.d     %1,%2,%0"
10927   [(set_attr "type" "fcmp_media")])
10929 (define_insn "cmpgedf_media"
10930   [(set (match_operand:SI 0 "register_operand" "=r")
10931         (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10932                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10933   "TARGET_SHMEDIA_FPU"
10934   "fcmpge.d     %1,%2,%0"
10935   [(set_attr "type" "fcmp_media")])
10937 (define_insn "cmpundf_media"
10938   [(set (match_operand:SI 0 "register_operand" "=r")
10939         (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10940                       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10941   "TARGET_SHMEDIA_FPU"
10942   "fcmpun.d     %1,%2,%0"
10943   [(set_attr "type" "fcmp_media")])
10945 (define_expand "cbranchdf4"
10946   [(set (pc)
10947         (if_then_else (match_operator 0 "sh_float_comparison_operator"
10948                        [(match_operand:DF 1 "arith_operand" "")
10949                         (match_operand:DF 2 "arith_operand" "")])
10950                       (match_operand 3 "" "")
10951                       (pc)))]
10952   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10953   "
10955   if (TARGET_SHMEDIA)
10956     emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
10957                                           operands[3]));
10958   else
10959     sh_emit_compare_and_branch (operands, DFmode);
10960   DONE;
10964 (define_expand "negdf2"
10965   [(set (match_operand:DF 0 "arith_reg_operand" "")
10966         (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
10967   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10968   "
10970   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10971     {
10972       expand_df_unop (&gen_negdf2_i, operands);
10973       DONE;
10974     }
10977 (define_insn "*negdf2_media"
10978   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10979         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10980   "TARGET_SHMEDIA_FPU"
10981   "fneg.d       %1, %0"
10982   [(set_attr "type" "fmove_media")])
10984 (define_insn "negdf2_i"
10985   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10986         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
10987    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10988   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10989   "fneg %0"
10990   [(set_attr "type" "fmove")
10991    (set_attr "fp_mode" "double")])
10993 (define_expand "sqrtdf2"
10994   [(set (match_operand:DF 0 "arith_reg_operand" "")
10995         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
10996   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10997   "
10999   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11000     {
11001       expand_df_unop (&gen_sqrtdf2_i, operands);
11002       DONE;
11003     }
11006 (define_insn "*sqrtdf2_media"
11007   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11008         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11009   "TARGET_SHMEDIA_FPU"
11010   "fsqrt.d      %1, %0"
11011   [(set_attr "type" "dfdiv_media")])
11013 (define_insn "sqrtdf2_i"
11014   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11015         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11016    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11017   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11018   "fsqrt        %0"
11019   [(set_attr "type" "dfdiv")
11020    (set_attr "fp_mode" "double")])
11022 (define_expand "absdf2"
11023   [(set (match_operand:DF 0 "arith_reg_operand" "")
11024         (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
11025   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11026   "
11028   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11029     {
11030       expand_df_unop (&gen_absdf2_i, operands);
11031       DONE;
11032     }
11035 (define_insn "*absdf2_media"
11036   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11037         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11038   "TARGET_SHMEDIA_FPU"
11039   "fabs.d       %1, %0"
11040   [(set_attr "type" "fmove_media")])
11042 (define_insn "absdf2_i"
11043   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11044         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11045    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11046   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11047   "fabs %0"
11048   [(set_attr "type" "fmove")
11049    (set_attr "fp_mode" "double")])
11051 (define_expand "extendsfdf2"
11052   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
11053         (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
11054   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11055   "
11057   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11058     {
11059       emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
11060                                         get_fpscr_rtx ()));
11061       DONE;
11062     }
11065 (define_insn "*extendsfdf2_media"
11066   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11067         (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
11068   "TARGET_SHMEDIA_FPU"
11069   "fcnv.sd      %1, %0"
11070   [(set_attr "type" "dfpconv_media")])
11072 (define_insn "extendsfdf2_i4"
11073   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11074         (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
11075    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11076   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11077   "fcnvsd  %1,%0"
11078   [(set_attr "type" "fp")
11079    (set_attr "fp_mode" "double")])
11081 (define_expand "truncdfsf2"
11082   [(set (match_operand:SF 0 "fpul_operand" "")
11083         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
11084   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11085   "
11087   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11088     {
11089       emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
11090                                        get_fpscr_rtx ()));
11091       DONE;
11092     }
11095 (define_insn "*truncdfsf2_media"
11096   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11097         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11098   "TARGET_SHMEDIA_FPU"
11099   "fcnv.ds      %1, %0"
11100   [(set_attr "type" "dfpconv_media")])
11102 (define_insn "truncdfsf2_i4"
11103   [(set (match_operand:SF 0 "fpul_operand" "=y")
11104         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
11105    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11106   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11107   "fcnvds  %1,%0"
11108   [(set_attr "type" "fp")
11109    (set_attr "fp_mode" "double")])
11111 ;; Bit field extract patterns.  These give better code for packed bitfields,
11112 ;; because they allow auto-increment addresses to be generated.
11114 (define_expand "insv"
11115   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
11116                          (match_operand:SI 1 "immediate_operand" "")
11117                          (match_operand:SI 2 "immediate_operand" ""))
11118         (match_operand:SI 3 "general_operand" ""))]
11119   "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
11120   "
11122   rtx addr_target, orig_address, shift_reg, qi_val;
11123   HOST_WIDE_INT bitsize, size, v = 0;
11124   rtx x = operands[3];
11126   if (TARGET_SH2A && TARGET_BITOPS
11127       && (satisfies_constraint_Sbw (operands[0])
11128           || satisfies_constraint_Sbv (operands[0]))
11129       && satisfies_constraint_M (operands[1])
11130       && satisfies_constraint_K03 (operands[2]))
11131     {
11132       if (satisfies_constraint_N (operands[3]))
11133         {
11134           emit_insn (gen_bclr_m2a (operands[0], operands[2]));
11135           DONE;
11136         }
11137       else if (satisfies_constraint_M (operands[3]))
11138         {
11139           emit_insn (gen_bset_m2a (operands[0], operands[2]));
11140           DONE;
11141         }
11142       else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
11143                 && satisfies_constraint_M (operands[1]))
11144         {
11145           emit_insn (gen_bst_m2a (operands[0], operands[2]));
11146           DONE;
11147         }
11148       else if (REG_P (operands[3])
11149                && satisfies_constraint_M (operands[1]))
11150         {
11151           emit_insn (gen_bld_reg (operands[3], const0_rtx));
11152           emit_insn (gen_bst_m2a (operands[0], operands[2]));
11153           DONE;
11154         }
11155     }
11156   /* ??? expmed doesn't care for non-register predicates.  */
11157   if (! memory_operand (operands[0], VOIDmode)
11158       || ! immediate_operand (operands[1], VOIDmode)
11159       || ! immediate_operand (operands[2], VOIDmode)
11160       || ! general_operand (x, VOIDmode))
11161     FAIL;
11162   /* If this isn't a 16 / 24 / 32 bit field, or if
11163      it doesn't start on a byte boundary, then fail.  */
11164   bitsize = INTVAL (operands[1]);
11165   if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
11166       || (INTVAL (operands[2]) % 8) != 0)
11167     FAIL;
11169   size = bitsize / 8;
11170   orig_address = XEXP (operands[0], 0);
11171   shift_reg = gen_reg_rtx (SImode);
11172   if (CONST_INT_P (x))
11173     {
11174       v = INTVAL (x);
11175       qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
11176     }
11177   else
11178     {
11179       emit_insn (gen_movsi (shift_reg, operands[3]));
11180       qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11181     }
11182   addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1));
11184   operands[0] = replace_equiv_address (operands[0], addr_target);
11185   emit_insn (gen_movqi (operands[0], qi_val));
11187   while (size -= 1)
11188     {
11189       if (CONST_INT_P (x))
11190         qi_val
11191           = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
11192       else
11193         {
11194           emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
11195           qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11196         }
11197       emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
11198       emit_insn (gen_movqi (operands[0], qi_val));
11199     }
11201   DONE;
11204 (define_insn "movua"
11205   [(set (match_operand:SI 0 "register_operand" "=z")
11206         (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
11207                    UNSPEC_MOVUA))]
11208   "TARGET_SH4A_ARCH"
11209   "movua.l      %1,%0"
11210   [(set_attr "type" "movua")])
11212 ;; We shouldn't need this, but cse replaces increments with references
11213 ;; to other regs before flow has a chance to create post_inc
11214 ;; addressing modes, and only postreload's cse_move2add brings the
11215 ;; increments back to a usable form.
11216 (define_peephole2
11217   [(set (match_operand:SI 0 "register_operand" "")
11218         (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
11219                          (const_int 32) (const_int 0)))
11220    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11221   "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
11222   [(set (match_operand:SI 0 "register_operand" "")
11223         (sign_extract:SI (mem:SI (post_inc:SI
11224                                   (match_operand:SI 1 "register_operand" "")))
11225                          (const_int 32) (const_int 0)))]
11226   "")
11228 (define_expand "extv"
11229   [(set (match_operand:SI 0 "register_operand" "")
11230         (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11231                          (match_operand 2 "const_int_operand" "")
11232                          (match_operand 3 "const_int_operand" "")))]
11233   "TARGET_SH4A_ARCH || TARGET_SH2A"
11235   if (TARGET_SH2A && TARGET_BITOPS
11236       && (satisfies_constraint_Sbw (operands[1])
11237           || satisfies_constraint_Sbv (operands[1]))
11238       && satisfies_constraint_M (operands[2])
11239       && satisfies_constraint_K03 (operands[3]))
11240    {
11241       emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
11242       if (REGNO (operands[0]) != T_REG)
11243         emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
11244       DONE;
11245    }
11246   if (TARGET_SH4A_ARCH
11247       && INTVAL (operands[2]) == 32
11248       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11249       && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
11250     {
11251       rtx src = adjust_address (operands[1], BLKmode, 0);
11252       set_mem_size (src, 4);
11253       emit_insn (gen_movua (operands[0], src));
11254       DONE;
11255     }
11257   FAIL;
11260 (define_expand "extzv"
11261   [(set (match_operand:SI 0 "register_operand" "")
11262         (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11263                          (match_operand 2 "const_int_operand" "")
11264                          (match_operand 3 "const_int_operand" "")))]
11265   "TARGET_SH4A_ARCH || TARGET_SH2A"
11267   if (TARGET_SH2A && TARGET_BITOPS
11268       && (satisfies_constraint_Sbw (operands[1])
11269           || satisfies_constraint_Sbv (operands[1]))
11270       && satisfies_constraint_M (operands[2])
11271       && satisfies_constraint_K03 (operands[3]))
11272     {
11273       emit_insn (gen_bld_m2a (operands[1], operands[3]));
11274       if (REGNO (operands[0]) != T_REG)
11275         emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
11276       DONE;
11277     }
11278   if (TARGET_SH4A_ARCH
11279       && INTVAL (operands[2]) == 32
11280       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11281       && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
11282     {
11283       rtx src = adjust_address (operands[1], BLKmode, 0);
11284       set_mem_size (src, 4);
11285       emit_insn (gen_movua (operands[0], src));
11286       DONE;
11287     }
11289   FAIL;
11292 ;; SH2A instructions for bitwise operations.
11294 ;; Clear a bit in a memory location.
11295 (define_insn "bclr_m2a"
11296   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11297         (and:QI
11298             (not:QI (ashift:QI (const_int 1)
11299                         (match_operand:QI 1 "const_int_operand" "K03,K03")))
11300             (match_dup 0)))]
11301   "TARGET_SH2A && TARGET_BITOPS"
11302   "@
11303         bclr.b\\t%1,%0
11304         bclr.b\\t%1,@(0,%t0)"
11305 [(set_attr "length" "4,4")])
11307 (define_insn "bclrmem_m2a"
11308   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11309         (and:QI (match_dup 0)
11310                 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
11311   "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
11312   "@
11313         bclr.b\\t%W1,%0
11314         bclr.b\\t%W1,@(0,%t0)"
11315   [(set_attr "length" "4,4")])
11317 ;; Set a bit in a memory location.
11318 (define_insn "bset_m2a"
11319   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11320         (ior:QI
11321             (ashift:QI (const_int 1)
11322                        (match_operand:QI 1 "const_int_operand" "K03,K03"))
11323             (match_dup 0)))]
11324   "TARGET_SH2A && TARGET_BITOPS"
11325   "@
11326         bset.b\\t%1,%0
11327         bset.b\\t%1,@(0,%t0)"
11328   [(set_attr "length" "4,4")])
11330 (define_insn "bsetmem_m2a"
11331   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11332         (ior:QI (match_dup 0)
11333                 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
11334   "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
11335   "@
11336         bset.b\\t%V1,%0
11337         bset.b\\t%V1,@(0,%t0)"
11338   [(set_attr "length" "4,4")])
11340 ;;; Transfer the contents of the T bit to a specified bit of memory.
11341 (define_insn "bst_m2a"
11342   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
11343         (if_then_else (eq (reg:SI T_REG) (const_int 0))
11344             (and:QI
11345                 (not:QI (ashift:QI (const_int 1)
11346                         (match_operand:QI 1 "const_int_operand" "K03,K03")))
11347                 (match_dup 0))
11348             (ior:QI
11349                 (ashift:QI (const_int 1) (match_dup 1))
11350                 (match_dup 0))))]
11351   "TARGET_SH2A && TARGET_BITOPS"
11352   "@
11353         bst.b\\t%1,%0
11354         bst.b\\t%1,@(0,%t0)"
11355   [(set_attr "length" "4")])
11357 ;; Store a specified bit of memory in the T bit.
11358 (define_insn "bld_m2a"
11359   [(set (reg:SI T_REG)
11360         (zero_extract:SI
11361             (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
11362             (const_int 1)
11363             (match_operand 1 "const_int_operand" "K03,K03")))]
11364   "TARGET_SH2A && TARGET_BITOPS"
11365   "@
11366         bld.b\\t%1,%0
11367         bld.b\\t%1,@(0,%t0)"
11368   [(set_attr "length" "4,4")])
11370 ;; Store a specified bit of memory in the T bit.
11371 (define_insn "bldsign_m2a"
11372   [(set (reg:SI T_REG)
11373         (sign_extract:SI
11374             (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11375             (const_int 1)
11376             (match_operand 1 "const_int_operand" "K03,K03")))]
11377   "TARGET_SH2A && TARGET_BITOPS"
11378   "@
11379         bld.b\\t%1,%0
11380         bld.b\\t%1,@(0,%t0)"
11381   [(set_attr "length" "4,4")])
11383 ;; Store a specified bit of the LSB 8 bits of a register in the T bit.
11384 (define_insn "bld_reg"
11385   [(set (reg:SI T_REG)
11386         (zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
11387                          (const_int 1)
11388                          (match_operand 1 "const_int_operand" "K03")))]
11389   "TARGET_SH2A"
11390   "bld\\t%1,%0")
11392 (define_insn "*bld_regqi"
11393   [(set (reg:SI T_REG)
11394         (zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
11395                          (const_int 1)
11396                          (match_operand 1 "const_int_operand" "K03")))]
11397   "TARGET_SH2A"
11398   "bld\\t%1,%0")
11400 ;; Take logical and of a specified bit of memory with the T bit and
11401 ;; store its result in the T bit.
11402 (define_insn "band_m2a"
11403   [(set (reg:SI T_REG)
11404         (and:SI (reg:SI T_REG)
11405                 (zero_extract:SI
11406                     (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11407                     (const_int 1)
11408                     (match_operand 1 "const_int_operand" "K03,K03"))))]
11409   "TARGET_SH2A && TARGET_BITOPS"
11410   "@
11411         band.b\\t%1,%0
11412         band.b\\t%1,@(0,%t0)"
11413   [(set_attr "length" "4,4")])
11415 (define_insn "bandreg_m2a"
11416   [(set (match_operand:SI 0 "register_operand" "=r,r")
11417         (and:SI (zero_extract:SI
11418                     (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11419                     (const_int 1)
11420                     (match_operand 2 "const_int_operand" "K03,K03"))
11421                 (match_operand:SI 3 "register_operand" "r,r")))]
11422   "TARGET_SH2A && TARGET_BITOPS"
11423   "@
11424         band.b\\t%2,%1\;movt\\t%0
11425         band.b\\t%2,@(0,%t1)\;movt\\t%0"
11426   [(set_attr "length" "6,6")])
11428 ;; Take logical or of a specified bit of memory with the T bit and
11429 ;; store its result in the T bit.
11430 (define_insn "bor_m2a"
11431   [(set (reg:SI T_REG)
11432         (ior:SI (reg:SI T_REG)
11433                 (zero_extract:SI
11434                     (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11435                     (const_int 1)
11436                     (match_operand 1 "const_int_operand" "K03,K03"))))]
11437   "TARGET_SH2A && TARGET_BITOPS"
11438   "@
11439         bor.b\\t%1,%0
11440         bor.b\\t%1,@(0,%t0)"
11441   [(set_attr "length" "4,4")])
11443 (define_insn "borreg_m2a"
11444   [(set (match_operand:SI 0 "register_operand" "=r,r")
11445         (ior:SI (zero_extract:SI
11446                     (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11447                     (const_int 1)
11448                     (match_operand 2 "const_int_operand" "K03,K03"))
11449                 (match_operand:SI 3 "register_operand" "=r,r")))]
11450   "TARGET_SH2A && TARGET_BITOPS"
11451   "@
11452         bor.b\\t%2,%1\;movt\\t%0
11453         bor.b\\t%2,@(0,%t1)\;movt\\t%0"
11454   [(set_attr "length" "6,6")])
11456 ;; Take exclusive or of a specified bit of memory with the T bit and
11457 ;; store its result in the T bit.
11458 (define_insn "bxor_m2a"
11459   [(set (reg:SI T_REG)
11460         (xor:SI (reg:SI T_REG)
11461                 (zero_extract:SI
11462                     (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11463                     (const_int 1)
11464                     (match_operand 1 "const_int_operand" "K03,K03"))))]
11465   "TARGET_SH2A && TARGET_BITOPS"
11466   "@
11467         bxor.b\\t%1,%0
11468         bxor.b\\t%1,@(0,%t0)"
11469   [(set_attr "length" "4,4")])
11471 (define_insn "bxorreg_m2a"
11472   [(set (match_operand:SI 0 "register_operand" "=r,r")
11473         (xor:SI (zero_extract:SI
11474                     (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11475                     (const_int 1)
11476                     (match_operand 2 "const_int_operand" "K03,K03"))
11477                 (match_operand:SI 3 "register_operand" "=r,r")))]
11478   "TARGET_SH2A && TARGET_BITOPS"
11479   "@
11480         bxor.b\\t%2,%1\;movt\\t%0
11481         bxor.b\\t%2,@(0,%t1)\;movt\\t%0"
11482   [(set_attr "length" "6,6")])
11485 ;; -------------------------------------------------------------------------
11486 ;; Peepholes
11487 ;; -------------------------------------------------------------------------
11488 ;; This matches cases where the bit in a memory location is set.
11489 (define_peephole2
11490   [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
11491         (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
11492    (set (match_dup 0)
11493         (ior:SI (match_dup 0)
11494         (match_operand:SI 2 "const_int_operand" "Pso,Pso")))
11495    (set (match_dup 1)
11496         (match_operand 3 "arith_reg_operand" "r,r"))]
11497   "TARGET_SH2A && TARGET_BITOPS
11498    && satisfies_constraint_Pso (operands[2])
11499    && REGNO (operands[0]) == REGNO (operands[3])"
11500   [(set (match_dup 1)
11501         (ior:QI (match_dup 1)
11502                 (match_dup 2)))]
11503   "")
11505 ;; This matches cases where the bit in a memory location is cleared.
11506 (define_peephole2
11507   [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
11508         (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
11509    (set (match_dup 0)
11510         (and:SI (match_dup 0)
11511         (match_operand:SI 2 "const_int_operand" "Psz,Psz")))
11512    (set (match_dup 1)
11513         (match_operand 3 "arith_reg_operand" "r,r"))]
11514   "TARGET_SH2A && TARGET_BITOPS
11515    && satisfies_constraint_Psz (operands[2])
11516    && REGNO (operands[0]) == REGNO (operands[3])"
11517   [(set (match_dup 1)
11518         (and:QI (match_dup 1)
11519                 (match_dup 2)))]
11520   "")
11522 ;; This matches cases where a stack pointer increment at the start of the
11523 ;; epilogue combines with a stack slot read loading the return value.
11525 (define_peephole
11526   [(set (match_operand:SI 0 "arith_reg_operand" "")
11527         (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
11528    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11529   "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
11530   "mov.l        @%1+,%0")
11532 ;; See the comment on the dt combiner pattern above.
11534 (define_peephole
11535   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11536         (plus:SI (match_dup 0)
11537                  (const_int -1)))
11538    (set (reg:SI T_REG)
11539         (eq:SI (match_dup 0)
11540                (const_int 0)))]
11541   "TARGET_SH2"
11542   "dt   %0")
11544 ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
11545 ;; to `mov #k,r0; mov.l @(r0,r15),rn'.  These sequences are generated by
11546 ;; reload when the constant is too large for a reg+offset address.
11548 ;; ??? We would get much better code if this was done in reload.  This would
11549 ;; require modifying find_reloads_address to recognize that if the constant
11550 ;; is out-of-range for an immediate add, then we get better code by reloading
11551 ;; the constant into a register than by reloading the sum into a register,
11552 ;; since the former is one instruction shorter if the address does not need
11553 ;; to be offsettable.  Unfortunately this does not work, because there is
11554 ;; only one register, r0, that can be used as an index register.  This register
11555 ;; is also the function return value register.  So, if we try to force reload
11556 ;; to use double-reg addresses, then we end up with some instructions that
11557 ;; need to use r0 twice.  The only way to fix this is to change the calling
11558 ;; convention so that r0 is not used to return values.
11560 (define_peephole
11561   [(set (match_operand:SI 0 "register_operand" "=r")
11562         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11563    (set (mem:SI (match_dup 0))
11564         (match_operand:SI 2 "general_movsrc_operand" ""))]
11565   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11566   "mov.l        %2,@(%0,%1)")
11568 (define_peephole
11569   [(set (match_operand:SI 0 "register_operand" "=r")
11570         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11571    (set (match_operand:SI 2 "general_movdst_operand" "")
11572         (mem:SI (match_dup 0)))]
11573   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11574   "mov.l        @(%0,%1),%2")
11576 (define_peephole
11577   [(set (match_operand:SI 0 "register_operand" "=r")
11578         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11579    (set (mem:HI (match_dup 0))
11580         (match_operand:HI 2 "general_movsrc_operand" ""))]
11581   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11582   "mov.w        %2,@(%0,%1)")
11584 (define_peephole
11585   [(set (match_operand:SI 0 "register_operand" "=r")
11586         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11587    (set (match_operand:HI 2 "general_movdst_operand" "")
11588         (mem:HI (match_dup 0)))]
11589   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11590   "mov.w        @(%0,%1),%2")
11592 (define_peephole
11593   [(set (match_operand:SI 0 "register_operand" "=r")
11594         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11595    (set (mem:QI (match_dup 0))
11596         (match_operand:QI 2 "general_movsrc_operand" ""))]
11597   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11598   "mov.b        %2,@(%0,%1)")
11600 (define_peephole
11601   [(set (match_operand:SI 0 "register_operand" "=r")
11602         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11603    (set (match_operand:QI 2 "general_movdst_operand" "")
11604         (mem:QI (match_dup 0)))]
11605   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11606   "mov.b        @(%0,%1),%2")
11608 (define_peephole
11609   [(set (match_operand:SI 0 "register_operand" "=r")
11610         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11611    (set (mem:SF (match_dup 0))
11612         (match_operand:SF 2 "general_movsrc_operand" ""))]
11613   "TARGET_SH1 && REGNO (operands[0]) == 0
11614    && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
11615        || (GET_CODE (operands[2]) == SUBREG
11616            && REGNO (SUBREG_REG (operands[2])) < 16))
11617    && reg_unused_after (operands[0], insn)"
11618   "mov.l        %2,@(%0,%1)")
11620 (define_peephole
11621   [(set (match_operand:SI 0 "register_operand" "=r")
11622         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11623    (set (match_operand:SF 2 "general_movdst_operand" "")
11625         (mem:SF (match_dup 0)))]
11626   "TARGET_SH1 && REGNO (operands[0]) == 0
11627    && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
11628        || (GET_CODE (operands[2]) == SUBREG
11629            && REGNO (SUBREG_REG (operands[2])) < 16))
11630    && reg_unused_after (operands[0], insn)"
11631   "mov.l        @(%0,%1),%2")
11633 (define_peephole
11634   [(set (match_operand:SI 0 "register_operand" "=r")
11635         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11636    (set (mem:SF (match_dup 0))
11637         (match_operand:SF 2 "general_movsrc_operand" ""))]
11638   "TARGET_SH2E && REGNO (operands[0]) == 0
11639    && ((REG_P (operands[2])
11640         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11641        || (GET_CODE (operands[2]) == SUBREG
11642            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11643    && reg_unused_after (operands[0], insn)"
11644   "fmov{.s|}    %2,@(%0,%1)")
11646 (define_peephole
11647   [(set (match_operand:SI 0 "register_operand" "=r")
11648         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11649    (set (match_operand:SF 2 "general_movdst_operand" "")
11651         (mem:SF (match_dup 0)))]
11652   "TARGET_SH2E && REGNO (operands[0]) == 0
11653    && ((REG_P (operands[2])
11654         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11655        || (GET_CODE (operands[2]) == SUBREG
11656            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11657    && reg_unused_after (operands[0], insn)"
11658   "fmov{.s|}    @(%0,%1),%2")
11660 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).  */
11661 (define_insn "sp_switch_1"
11662   [(const_int 1) (match_operand:SI 0 "symbol_ref_operand" "s")]
11663   "TARGET_SH1"
11664   "*
11666   output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", operands);
11667   output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", operands);
11668   return \"mov r0,r15\";
11670   [(set_attr "length" "10")])
11672 ;; Switch back to the original stack for interrupt functions with the
11673 ;; sp_switch attribute.  */
11674 (define_insn "sp_switch_2"
11675   [(const_int 2)]
11676   "TARGET_SH1"
11677   "mov.l @r15+,r15\;mov.l @r15+,r0"
11678   [(set_attr "length" "4")])
11680 ;; Integer vector moves
11682 (define_expand "movv8qi"
11683   [(set (match_operand:V8QI 0 "general_movdst_operand" "")
11684         (match_operand:V8QI 1 "general_movsrc_operand" ""))]
11685   "TARGET_SHMEDIA"
11686   "{ if (prepare_move_operands (operands, V8QImode)) DONE; }")
11688 (define_insn "movv8qi_i"
11689   [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
11690         (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11691   "TARGET_SHMEDIA
11692    && (register_operand (operands[0], V8QImode)
11693        || sh_register_operand (operands[1], V8QImode))"
11694   "@
11695         add     %1, r63, %0
11696         movi    %1, %0
11697         #
11698         ld%M1.q %m1, %0
11699         st%M0.q %m0, %N1"
11700   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11701    (set_attr "length" "4,4,16,4,4")])
11703 (define_split
11704   [(set (match_operand:V8QI 0 "arith_reg_dest" "")
11705         (subreg:V8QI (const_int 0) 0))]
11706   "TARGET_SHMEDIA"
11707   [(set (match_dup 0)
11708         (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
11709                             (const_int 0) (const_int 0) (const_int 0)
11710                             (const_int 0) (const_int 0)]))])
11712 (define_split
11713   [(set (match_operand 0 "arith_reg_dest" "")
11714         (match_operand 1 "sh_rep_vec" ""))]
11715   "TARGET_SHMEDIA && reload_completed
11716    && GET_MODE (operands[0]) == GET_MODE (operands[1])
11717    && sh_vector_mode_supported_p (GET_MODE (operands[0]))
11718    && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
11719    && (XVECEXP (operands[1], 0, 0) != const0_rtx
11720        || XVECEXP (operands[1], 0, 1) != const0_rtx)
11721    && (XVECEXP (operands[1], 0, 0) != constm1_rtx
11722        || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
11723   [(set (match_dup 0) (match_dup 1))
11724    (match_dup 2)]
11725   "
11727   int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
11728   rtx elt1 = XVECEXP (operands[1], 0, 1);
11730   if (unit_size > 2)
11731     operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
11732   else
11733     {
11734       if (unit_size < 2)
11735         operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
11736       operands[2] = gen_mperm_w0 (operands[0], operands[0]);
11737     }
11738   operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
11739   operands[1] = XVECEXP (operands[1], 0, 0);
11740   if (unit_size < 2)
11741     {
11742       if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
11743         operands[1]
11744           = GEN_INT (TARGET_LITTLE_ENDIAN
11745                      ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
11746                      : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
11747       else
11748         {
11749           operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
11750           operands[1]
11751             = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
11752         }
11753     }
11756 (define_split
11757   [(set (match_operand 0 "arith_reg_dest" "")
11758         (match_operand 1 "sh_const_vec" ""))]
11759   "TARGET_SHMEDIA && reload_completed
11760    && GET_MODE (operands[0]) == GET_MODE (operands[1])
11761    && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
11762   [(set (match_dup 0) (match_dup 1))]
11763   "
11765   rtx v = operands[1];
11766   enum machine_mode new_mode
11767     = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
11769   operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
11770   operands[1]
11771     = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
11774 (define_expand "movv2hi"
11775   [(set (match_operand:V2HI 0 "general_movdst_operand" "")
11776         (match_operand:V2HI 1 "general_movsrc_operand" ""))]
11777   "TARGET_SHMEDIA"
11778   "{ if (prepare_move_operands (operands, V2HImode)) DONE; }")
11780 (define_insn "movv2hi_i"
11781   [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
11782         (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11783   "TARGET_SHMEDIA
11784    && (register_operand (operands[0], V2HImode)
11785        || sh_register_operand (operands[1], V2HImode))"
11786   "@
11787         add.l   %1, r63, %0
11788         movi    %1, %0
11789         #
11790         ld%M1.l %m1, %0
11791         st%M0.l %m0, %N1"
11792   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11793    (set_attr "length" "4,4,16,4,4")
11794    (set (attr "highpart")
11795         (cond [(match_test "sh_contains_memref_p (insn)")
11796                (const_string "user")]
11797               (const_string "ignore")))])
11799 (define_expand "movv4hi"
11800   [(set (match_operand:V4HI 0 "general_movdst_operand" "")
11801         (match_operand:V4HI 1 "general_movsrc_operand" ""))]
11802   "TARGET_SHMEDIA"
11803   "{ if (prepare_move_operands (operands, V4HImode)) DONE; }")
11805 (define_insn "movv4hi_i"
11806   [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
11807         (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11808   "TARGET_SHMEDIA
11809    && (register_operand (operands[0], V4HImode)
11810        || sh_register_operand (operands[1], V4HImode))"
11811   "@
11812         add     %1, r63, %0
11813         movi    %1, %0
11814         #
11815         ld%M1.q %m1, %0
11816         st%M0.q %m0, %N1"
11817   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11818    (set_attr "length" "4,4,16,4,4")
11819    (set_attr "highpart" "depend")])
11821 (define_expand "movv2si"
11822   [(set (match_operand:V2SI 0 "general_movdst_operand" "")
11823         (match_operand:V2SI 1 "general_movsrc_operand" ""))]
11824   "TARGET_SHMEDIA"
11825   "{ if (prepare_move_operands (operands, V2SImode)) DONE; }")
11827 (define_insn "movv2si_i"
11828   [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
11829         (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11830   "TARGET_SHMEDIA
11831    && (register_operand (operands[0], V2SImode)
11832        || sh_register_operand (operands[1], V2SImode))"
11833   "@
11834         add     %1, r63, %0
11835         #
11836         #
11837         ld%M1.q %m1, %0
11838         st%M0.q %m0, %N1"
11839   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11840    (set_attr "length" "4,4,16,4,4")
11841    (set_attr "highpart" "depend")])
11843 ;; Multimedia Intrinsics
11845 (define_insn "absv2si2"
11846   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11847         (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
11848   "TARGET_SHMEDIA"
11849   "mabs.l       %1, %0"
11850   [(set_attr "type" "mcmp_media")
11851    (set_attr "highpart" "depend")])
11853 (define_insn "absv4hi2"
11854   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11855         (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
11856   "TARGET_SHMEDIA"
11857   "mabs.w       %1, %0"
11858   [(set_attr "type" "mcmp_media")
11859    (set_attr "highpart" "depend")])
11861 (define_insn "addv2si3"
11862   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11863         (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
11864                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11865   "TARGET_SHMEDIA"
11866   "madd.l       %1, %2, %0"
11867   [(set_attr "type" "arith_media")
11868    (set_attr "highpart" "depend")])
11870 (define_insn "addv4hi3"
11871   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11872         (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
11873                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11874   "TARGET_SHMEDIA"
11875   "madd.w       %1, %2, %0"
11876   [(set_attr "type" "arith_media")
11877    (set_attr "highpart" "depend")])
11879 (define_insn_and_split "addv2hi3"
11880   [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
11881         (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
11882                    (match_operand:V2HI 2 "extend_reg_operand" "r")))]
11883   "TARGET_SHMEDIA"
11884   "#"
11885   "TARGET_SHMEDIA"
11886   [(const_int 0)]
11887   "
11889   rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
11890   rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
11891   rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
11892   rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
11893   rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
11895   emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
11896   emit_insn (gen_truncdisi2 (si_dst, di_dst));
11897   DONE;
11899   [(set_attr "highpart" "must_split")])
11901 (define_insn "ssaddv2si3"
11902   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11903         (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
11904                       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11905   "TARGET_SHMEDIA"
11906   "madds.l      %1, %2, %0"
11907   [(set_attr "type" "mcmp_media")
11908    (set_attr "highpart" "depend")])
11910 (define_insn "usaddv8qi3"
11911   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11912         (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
11913                       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
11914   "TARGET_SHMEDIA"
11915   "madds.ub     %1, %2, %0"
11916   [(set_attr "type" "mcmp_media")
11917    (set_attr "highpart" "depend")])
11919 (define_insn "ssaddv4hi3"
11920   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11921         (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
11922                       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11923   "TARGET_SHMEDIA"
11924   "madds.w      %1, %2, %0"
11925   [(set_attr "type" "mcmp_media")
11926    (set_attr "highpart" "depend")])
11928 (define_insn "negcmpeqv8qi"
11929   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11930         (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
11931                            (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
11932   "TARGET_SHMEDIA"
11933   "mcmpeq.b     %N1, %N2, %0"
11934   [(set_attr "type" "mcmp_media")
11935    (set_attr "highpart" "depend")])
11937 (define_insn "negcmpeqv2si"
11938   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11939         (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
11940                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11941   "TARGET_SHMEDIA"
11942   "mcmpeq.l     %N1, %N2, %0"
11943   [(set_attr "type" "mcmp_media")
11944    (set_attr "highpart" "depend")])
11946 (define_insn "negcmpeqv4hi"
11947   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11948         (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
11949                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11950   "TARGET_SHMEDIA"
11951   "mcmpeq.w     %N1, %N2, %0"
11952   [(set_attr "type" "mcmp_media")
11953    (set_attr "highpart" "depend")])
11955 (define_insn "negcmpgtuv8qi"
11956   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11957         (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
11958                             (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
11959   "TARGET_SHMEDIA"
11960   "mcmpgt.ub    %N1, %N2, %0"
11961   [(set_attr "type" "mcmp_media")
11962    (set_attr "highpart" "depend")])
11964 (define_insn "negcmpgtv2si"
11965   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11966         (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
11967                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11968   "TARGET_SHMEDIA"
11969   "mcmpgt.l     %N1, %N2, %0"
11970   [(set_attr "type" "mcmp_media")
11971    (set_attr "highpart" "depend")])
11973 (define_insn "negcmpgtv4hi"
11974   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11975         (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
11976                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11977   "TARGET_SHMEDIA"
11978   "mcmpgt.w     %N1, %N2, %0"
11979   [(set_attr "type" "mcmp_media")
11980    (set_attr "highpart" "depend")])
11982 (define_insn "mcmv"
11983   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11984         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11985                         (match_operand:DI 2 "arith_reg_operand" "r"))
11986                 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
11987                         (not:DI (match_dup 2)))))]
11988   "TARGET_SHMEDIA"
11989   "mcmv %N1, %2, %0"
11990   [(set_attr "type" "arith_media")
11991    (set_attr "highpart" "depend")])
11993 (define_insn "mcnvs_lw"
11994   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11995         (vec_concat:V4HI
11996          (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
11997          (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11998   "TARGET_SHMEDIA"
11999   "mcnvs.lw     %N1, %N2, %0"
12000   [(set_attr "type" "mcmp_media")])
12002 (define_insn "mcnvs_wb"
12003   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12004         (vec_concat:V8QI
12005          (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
12006          (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
12007   "TARGET_SHMEDIA"
12008   "mcnvs.wb     %N1, %N2, %0"
12009   [(set_attr "type" "mcmp_media")])
12011 (define_insn "mcnvs_wub"
12012   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12013         (vec_concat:V8QI
12014          (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
12015          (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
12016   "TARGET_SHMEDIA"
12017   "mcnvs.wub    %N1, %N2, %0"
12018   [(set_attr "type" "mcmp_media")])
12020 (define_insn "mextr_rl"
12021   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12022         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12023                              (match_operand:HI 3 "mextr_bit_offset" "i"))
12024                (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12025                           (match_operand:HI 4 "mextr_bit_offset" "i"))))]
12026   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
12027   "*
12029   static char templ[21];
12031   sprintf (templ, \"mextr%d\\t%%N1, %%N2, %%0\",
12032            (int) INTVAL (operands[3]) >> 3);
12033   return templ;
12035   [(set_attr "type" "arith_media")])
12037 (define_insn "*mextr_lr"
12038   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12039         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12040                            (match_operand:HI 3 "mextr_bit_offset" "i"))
12041                (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12042                             (match_operand:HI 4 "mextr_bit_offset" "i"))))]
12043   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
12044   "*
12046   static char templ[21];
12048   sprintf (templ, \"mextr%d\\t%%N2, %%N1, %%0\",
12049            (int) INTVAL (operands[4]) >> 3);
12050   return templ;
12052   [(set_attr "type" "arith_media")])
12054 ; mextrN can be modelled with vec_select / vec_concat, but the selection
12055 ; vector then varies depending on endianness.
12056 (define_expand "mextr1"
12057   [(match_operand:DI 0 "arith_reg_dest" "")
12058    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12059    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12060   "TARGET_SHMEDIA"
12061   "
12063   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12064                            GEN_INT (1 * 8), GEN_INT (7 * 8)));
12065   DONE;
12068 (define_expand "mextr2"
12069   [(match_operand:DI 0 "arith_reg_dest" "")
12070    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12071    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12072   "TARGET_SHMEDIA"
12073   "
12075   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12076                            GEN_INT (2 * 8), GEN_INT (6 * 8)));
12077   DONE;
12080 (define_expand "mextr3"
12081   [(match_operand:DI 0 "arith_reg_dest" "")
12082    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12083    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12084   "TARGET_SHMEDIA"
12085   "
12087   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12088                            GEN_INT (3 * 8), GEN_INT (5 * 8)));
12089   DONE;
12092 (define_expand "mextr4"
12093   [(match_operand:DI 0 "arith_reg_dest" "")
12094    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12095    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12096   "TARGET_SHMEDIA"
12097   "
12099   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12100                            GEN_INT (4 * 8), GEN_INT (4 * 8)));
12101   DONE;
12104 (define_expand "mextr5"
12105   [(match_operand:DI 0 "arith_reg_dest" "")
12106    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12107    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12108   "TARGET_SHMEDIA"
12109   "
12111   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12112                            GEN_INT (5 * 8), GEN_INT (3 * 8)));
12113   DONE;
12116 (define_expand "mextr6"
12117   [(match_operand:DI 0 "arith_reg_dest" "")
12118    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12119    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12120   "TARGET_SHMEDIA"
12121   "
12123   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12124                            GEN_INT (6 * 8), GEN_INT (2 * 8)));
12125   DONE;
12128 (define_expand "mextr7"
12129   [(match_operand:DI 0 "arith_reg_dest" "")
12130    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12131    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12132   "TARGET_SHMEDIA"
12133   "
12135   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12136                            GEN_INT (7 * 8), GEN_INT (1 * 8)));
12137   DONE;
12140 (define_expand "mmacfx_wl"
12141   [(match_operand:V2SI 0 "arith_reg_dest" "")
12142    (match_operand:V2HI 1 "extend_reg_operand" "")
12143    (match_operand:V2HI 2 "extend_reg_operand" "")
12144    (match_operand:V2SI 3 "arith_reg_operand" "")]
12145   "TARGET_SHMEDIA"
12146   "
12148   emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
12149                               operands[1], operands[2]));
12150   DONE;
12153 ;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
12154 ;; is depend
12155 (define_insn "mmacfx_wl_i"
12156   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12157         (ss_plus:V2SI
12158          (match_operand:V2SI 1 "arith_reg_operand" "0")
12159          (ss_truncate:V2SI
12160           (ashift:V2DI
12161            (sign_extend:V2DI
12162             (mult:V2SI
12163              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
12164              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
12165            (const_int 1)))))]
12166   "TARGET_SHMEDIA"
12167   "mmacfx.wl    %2, %3, %0"
12168   [(set_attr "type" "mac_media")
12169    (set_attr "highpart" "depend")])
12171 (define_expand "mmacnfx_wl"
12172   [(match_operand:V2SI 0 "arith_reg_dest" "")
12173    (match_operand:V2HI 1 "extend_reg_operand" "")
12174    (match_operand:V2HI 2 "extend_reg_operand" "")
12175    (match_operand:V2SI 3 "arith_reg_operand" "")]
12176   "TARGET_SHMEDIA"
12177   "
12179   emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
12180                                operands[1], operands[2]));
12181   DONE;
12184 (define_insn "mmacnfx_wl_i"
12185   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12186         (ss_minus:V2SI
12187          (match_operand:V2SI 1 "arith_reg_operand" "0")
12188          (ss_truncate:V2SI
12189           (ashift:V2DI
12190            (sign_extend:V2DI
12191             (mult:V2SI
12192              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
12193              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
12194            (const_int 1)))))]
12195   "TARGET_SHMEDIA"
12196   "mmacnfx.wl   %2, %3, %0"
12197   [(set_attr "type" "mac_media")
12198    (set_attr "highpart" "depend")])
12200 (define_insn "mulv2si3"
12201   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12202         (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12203                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12204   "TARGET_SHMEDIA"
12205   "mmul.l       %1, %2, %0"
12206   [(set_attr "type" "d2mpy_media")
12207    (set_attr "highpart" "depend")])
12209 (define_insn "mulv4hi3"
12210   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12211         (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12212                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12213   "TARGET_SHMEDIA"
12214   "mmul.w       %1, %2, %0"
12215   [(set_attr "type" "dmpy_media")
12216    (set_attr "highpart" "depend")])
12218 (define_insn "mmulfx_l"
12219   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12220         (ss_truncate:V2SI
12221          (ashiftrt:V2DI
12222           (mult:V2DI
12223            (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12224            (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
12225           (const_int 31))))]
12226   "TARGET_SHMEDIA"
12227   "mmulfx.l     %1, %2, %0"
12228   [(set_attr "type" "d2mpy_media")
12229    (set_attr "highpart" "depend")])
12231 (define_insn "mmulfx_w"
12232   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12233         (ss_truncate:V4HI
12234          (ashiftrt:V4SI
12235           (mult:V4SI
12236            (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12237            (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12238           (const_int 15))))]
12239   "TARGET_SHMEDIA"
12240   "mmulfx.w     %1, %2, %0"
12241   [(set_attr "type" "dmpy_media")
12242    (set_attr "highpart" "depend")])
12244 (define_insn "mmulfxrp_w"
12245   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12246         (ss_truncate:V4HI
12247          (ashiftrt:V4SI
12248           (plus:V4SI
12249            (mult:V4SI
12250             (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12251             (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12252            (const_int 16384))
12253           (const_int 15))))]
12254   "TARGET_SHMEDIA"
12255   "mmulfxrp.w   %1, %2, %0"
12256   [(set_attr "type" "dmpy_media")
12257    (set_attr "highpart" "depend")])
12260 (define_expand "mmulhi_wl"
12261   [(match_operand:V2SI 0 "arith_reg_dest" "")
12262    (match_operand:V4HI 1 "arith_reg_operand" "")
12263    (match_operand:V4HI 2 "arith_reg_operand" "")]
12264   "TARGET_SHMEDIA"
12265   "
12267   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
12268              (operands[0], operands[1], operands[2]));
12269   DONE;
12272 (define_expand "mmullo_wl"
12273   [(match_operand:V2SI 0 "arith_reg_dest" "")
12274    (match_operand:V4HI 1 "arith_reg_operand" "")
12275    (match_operand:V4HI 2 "arith_reg_operand" "")]
12276   "TARGET_SHMEDIA"
12277   "
12279   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
12280              (operands[0], operands[1], operands[2]));
12281   DONE;
12284 (define_insn "mmul23_wl"
12285   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12286         (vec_select:V2SI
12287          (mult:V4SI
12288           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12289           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12290          (parallel [(const_int 2) (const_int 3)])))]
12291   "TARGET_SHMEDIA"
12292   "* return (TARGET_LITTLE_ENDIAN
12293              ? \"mmulhi.wl      %1, %2, %0\"
12294              : \"mmullo.wl      %1, %2, %0\");"
12295   [(set_attr "type" "dmpy_media")
12296    (set (attr "highpart")
12297         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12298          (const_string "user")))])
12300 (define_insn "mmul01_wl"
12301   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12302         (vec_select:V2SI
12303          (mult:V4SI
12304           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12305           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12306          (parallel [(const_int 0) (const_int 1)])))]
12307   "TARGET_SHMEDIA"
12308   "* return (TARGET_LITTLE_ENDIAN
12309              ? \"mmullo.wl      %1, %2, %0\"
12310              : \"mmulhi.wl      %1, %2, %0\");"
12311   [(set_attr "type" "dmpy_media")
12312    (set (attr "highpart")
12313         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12314          (const_string "user")))])
12317 (define_expand "mmulsum_wq"
12318   [(match_operand:DI 0 "arith_reg_dest" "")
12319    (match_operand:V4HI 1 "arith_reg_operand" "")
12320    (match_operand:V4HI 2 "arith_reg_operand" "")
12321    (match_operand:DI 3 "arith_reg_operand" "")]
12322   "TARGET_SHMEDIA"
12323   "
12325   emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
12326                                operands[1], operands[2]));
12327   DONE;
12330 (define_insn "mmulsum_wq_i"
12331   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12332         (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
12333          (plus:DI
12334           (plus:DI
12335            (vec_select:DI
12336             (mult:V4DI
12337              (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
12338              (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
12339             (parallel [(const_int 0)]))
12340            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12341                                      (sign_extend:V4DI (match_dup 3)))
12342                           (parallel [(const_int 1)])))
12343           (plus:DI
12344            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12345                                      (sign_extend:V4DI (match_dup 3)))
12346                           (parallel [(const_int 2)]))
12347            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12348                                      (sign_extend:V4DI (match_dup 3)))
12349                           (parallel [(const_int 3)]))))))]
12350   "TARGET_SHMEDIA"
12351   "mmulsum.wq   %2, %3, %0"
12352   [(set_attr "type" "mac_media")])
12354 (define_expand "mperm_w"
12355   [(match_operand:V4HI 0 "arith_reg_dest" "=r")
12356    (match_operand:V4HI 1 "arith_reg_operand" "r")
12357    (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
12358   "TARGET_SHMEDIA"
12359   "
12361   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
12362              (operands[0], operands[1], operands[2]));
12363   DONE;
12366 ; This use of vec_select isn't exactly correct according to rtl.texi
12367 ; (because not constant), but it seems a straightforward extension.
12368 (define_insn "mperm_w_little"
12369   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12370         (vec_select:V4HI
12371          (match_operand:V4HI 1 "arith_reg_operand" "r")
12372          (parallel
12373           [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
12374                             (const_int 2) (const_int 0))
12375            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
12376            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
12377            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
12378   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
12379   "mperm.w      %1, %N2, %0"
12380   [(set_attr "type" "arith_media")])
12382 (define_insn "mperm_w_big"
12383   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12384         (vec_select:V4HI
12385          (match_operand:V4HI 1 "arith_reg_operand" "r")
12386          (parallel
12387           [(zero_extract:QI (not:QI (match_operand:QI 2
12388                                      "extend_reg_or_0_operand" "rZ"))
12389                             (const_int 2) (const_int 0))
12390            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
12391            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
12392            (zero_extract:QI (not:QI (match_dup 2))
12393                             (const_int 2) (const_int 6))])))]
12394   "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
12395   "mperm.w      %1, %N2, %0"
12396   [(set_attr "type" "arith_media")])
12398 (define_insn "mperm_w0"
12399   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12400         (vec_duplicate:V4HI (truncate:HI (match_operand 1
12401                                           "trunc_hi_operand" "r"))))]
12402   "TARGET_SHMEDIA"
12403   "mperm.w      %1, r63, %0"
12404   [(set_attr "type" "arith_media")
12405    (set_attr "highpart" "ignore")])
12407 (define_expand "msad_ubq"
12408   [(match_operand:DI 0 "arith_reg_dest" "")
12409    (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
12410    (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
12411    (match_operand:DI 3 "arith_reg_operand" "")]
12412   "TARGET_SHMEDIA"
12413   "
12415   emit_insn (gen_msad_ubq_i (operands[0], operands[3],
12416                              operands[1], operands[2]));
12417   DONE;
12420 (define_insn "msad_ubq_i"
12421   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12422         (plus:DI
12423          (plus:DI
12424           (plus:DI
12425            (plus:DI
12426             (match_operand:DI 1 "arith_reg_operand" "0")
12427             (abs:DI (vec_select:DI
12428                      (minus:V8DI
12429                       (zero_extend:V8DI
12430                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12431                       (zero_extend:V8DI
12432                        (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
12433                      (parallel [(const_int 0)]))))
12434            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12435                                               (zero_extend:V8DI (match_dup 3)))
12436                                   (parallel [(const_int 1)]))))
12437           (plus:DI
12438            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12439                                               (zero_extend:V8DI (match_dup 3)))
12440                                   (parallel [(const_int 2)])))
12441            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12442                                               (zero_extend:V8DI (match_dup 3)))
12443                                   (parallel [(const_int 3)])))))
12444          (plus:DI
12445           (plus:DI
12446            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12447                                               (zero_extend:V8DI (match_dup 3)))
12448                                   (parallel [(const_int 4)])))
12449            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12450                                               (zero_extend:V8DI (match_dup 3)))
12451                                   (parallel [(const_int 5)]))))
12452           (plus:DI
12453            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12454                                               (zero_extend:V8DI (match_dup 3)))
12455                                   (parallel [(const_int 6)])))
12456            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12457                                               (zero_extend:V8DI (match_dup 3)))
12458                                   (parallel [(const_int 7)])))))))]
12459   "TARGET_SHMEDIA"
12460   "msad.ubq     %N2, %N3, %0"
12461   [(set_attr "type" "mac_media")])
12463 (define_insn "mshalds_l"
12464   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12465         (ss_truncate:V2SI
12466          (ashift:V2DI
12467           (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12468           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12469                   (const_int 31)))))]
12470   "TARGET_SHMEDIA"
12471   "mshalds.l    %1, %2, %0"
12472   [(set_attr "type" "mcmp_media")
12473    (set_attr "highpart" "depend")])
12475 (define_insn "mshalds_w"
12476   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12477         (ss_truncate:V4HI
12478          (ashift:V4SI
12479           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12480           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12481                   (const_int 15)))))]
12482   "TARGET_SHMEDIA"
12483   "mshalds.w    %1, %2, %0"
12484   [(set_attr "type" "mcmp_media")
12485    (set_attr "highpart" "depend")])
12487 (define_insn "ashrv2si3"
12488   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12489         (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12490                        (match_operand:DI 2 "arith_reg_operand" "r")))]
12491   "TARGET_SHMEDIA"
12492   "mshard.l     %1, %2, %0"
12493   [(set_attr "type" "arith_media")
12494    (set_attr "highpart" "depend")])
12496 (define_insn "ashrv4hi3"
12497   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12498         (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12499                        (match_operand:DI 2 "arith_reg_operand" "r")))]
12500   "TARGET_SHMEDIA"
12501   "mshard.w     %1, %2, %0"
12502   [(set_attr "type" "arith_media")
12503    (set_attr "highpart" "depend")])
12505 (define_insn "mshards_q"
12506   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
12507         (ss_truncate:HI
12508          (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
12509                       (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
12510   "TARGET_SHMEDIA"
12511   "mshards.q    %1, %N2, %0"
12512   [(set_attr "type" "mcmp_media")])
12514 (define_expand "mshfhi_b"
12515   [(match_operand:V8QI 0 "arith_reg_dest" "")
12516    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12517    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12518   "TARGET_SHMEDIA"
12519   "
12521   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
12522              (operands[0], operands[1], operands[2]));
12523   DONE;
12526 (define_expand "mshflo_b"
12527   [(match_operand:V8QI 0 "arith_reg_dest" "")
12528    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12529    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12530   "TARGET_SHMEDIA"
12531   "
12533   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
12534              (operands[0], operands[1], operands[2]));
12535   DONE;
12538 (define_insn "mshf4_b"
12539   [(set
12540     (match_operand:V8QI 0 "arith_reg_dest" "=r")
12541     (vec_select:V8QI
12542      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12543                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12544      (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
12545                 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
12546   "TARGET_SHMEDIA"
12547   "* return (TARGET_LITTLE_ENDIAN
12548              ? \"mshfhi.b       %N1, %N2, %0\"
12549              : \"mshflo.b       %N1, %N2, %0\");"
12550   [(set_attr "type" "arith_media")
12551    (set (attr "highpart")
12552         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12553          (const_string "user")))])
12555 (define_insn "mshf0_b"
12556   [(set
12557     (match_operand:V8QI 0 "arith_reg_dest" "=r")
12558     (vec_select:V8QI
12559      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12560                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12561      (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
12562                 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
12563   "TARGET_SHMEDIA"
12564   "* return (TARGET_LITTLE_ENDIAN
12565              ? \"mshflo.b       %N1, %N2, %0\"
12566              : \"mshfhi.b       %N1, %N2, %0\");"
12567   [(set_attr "type" "arith_media")
12568    (set (attr "highpart")
12569         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12570          (const_string "user")))])
12572 (define_expand "mshfhi_l"
12573   [(match_operand:V2SI 0 "arith_reg_dest" "")
12574    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12575    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12576   "TARGET_SHMEDIA"
12577   "
12579   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
12580              (operands[0], operands[1], operands[2]));
12581   DONE;
12584 (define_expand "mshflo_l"
12585   [(match_operand:V2SI 0 "arith_reg_dest" "")
12586    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12587    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12588   "TARGET_SHMEDIA"
12589   "
12591   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
12592              (operands[0], operands[1], operands[2]));
12593   DONE;
12596 (define_insn "mshf4_l"
12597   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12598         (vec_select:V2SI
12599          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12600                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12601          (parallel [(const_int 1) (const_int 3)])))]
12602   "TARGET_SHMEDIA"
12603   "* return (TARGET_LITTLE_ENDIAN
12604              ? \"mshfhi.l       %N1, %N2, %0\"
12605              : \"mshflo.l       %N1, %N2, %0\");"
12606   [(set_attr "type" "arith_media")
12607    (set (attr "highpart")
12608         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12609          (const_string "user")))])
12611 (define_insn "mshf0_l"
12612   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12613         (vec_select:V2SI
12614          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12615                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12616          (parallel [(const_int 0) (const_int 2)])))]
12617   "TARGET_SHMEDIA"
12618   "* return (TARGET_LITTLE_ENDIAN
12619              ? \"mshflo.l       %N1, %N2, %0\"
12620              : \"mshfhi.l       %N1, %N2, %0\");"
12621   [(set_attr "type" "arith_media")
12622    (set (attr "highpart")
12623         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12624          (const_string "user")))])
12626 (define_expand "mshfhi_w"
12627   [(match_operand:V4HI 0 "arith_reg_dest" "")
12628    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12629    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12630   "TARGET_SHMEDIA"
12631   "
12633   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
12634              (operands[0], operands[1], operands[2]));
12635   DONE;
12638 (define_expand "mshflo_w"
12639   [(match_operand:V4HI 0 "arith_reg_dest" "")
12640    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12641    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12642   "TARGET_SHMEDIA"
12643   "
12645   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
12646              (operands[0], operands[1], operands[2]));
12647   DONE;
12650 (define_insn "mshf4_w"
12651   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12652         (vec_select:V4HI
12653          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12654                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12655          (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
12656   "TARGET_SHMEDIA"
12657   "* return (TARGET_LITTLE_ENDIAN
12658              ? \"mshfhi.w       %N1, %N2, %0\"
12659              : \"mshflo.w       %N1, %N2, %0\");"
12660   [(set_attr "type" "arith_media")
12661    (set (attr "highpart")
12662         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12663          (const_string "user")))])
12665 (define_insn "mshf0_w"
12666   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12667         (vec_select:V4HI
12668          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12669                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12670          (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
12671   "TARGET_SHMEDIA"
12672   "* return (TARGET_LITTLE_ENDIAN
12673              ? \"mshflo.w       %N1, %N2, %0\"
12674              : \"mshfhi.w       %N1, %N2, %0\");"
12675   [(set_attr "type" "arith_media")
12676    (set (attr "highpart")
12677         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12678          (const_string "user")))])
12680 (define_insn "mshflo_w_x"
12681   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12682         (vec_select:V4HI
12683          (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
12684                           (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
12685          (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
12686   "TARGET_SHMEDIA"
12687   "mshflo.w     %N1, %N2, %0"
12688   [(set_attr "type" "arith_media")
12689    (set_attr "highpart" "ignore")])
12691 /* These are useful to expand ANDs and as combiner patterns.  */
12692 (define_insn_and_split "mshfhi_l_di"
12693   [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
12694         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
12695                              (const_int 32))
12696                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
12697                         (const_int -4294967296))))]
12698   "TARGET_SHMEDIA"
12699   "@
12700         mshfhi.l        %N1, %N2, %0
12701         #"
12702   "TARGET_SHMEDIA && reload_completed
12703    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12704   [(set (match_dup 3) (match_dup 4))
12705    (set (match_dup 5) (match_dup 6))]
12706   "
12708   operands[3] = gen_lowpart (SImode, operands[0]);
12709   operands[4] = gen_highpart (SImode, operands[1]);
12710   operands[5] = gen_highpart (SImode, operands[0]);
12711   operands[6] = gen_highpart (SImode, operands[2]);
12713   [(set_attr "type" "arith_media")])
12715 (define_insn "*mshfhi_l_di_rev"
12716   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12717         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12718                         (const_int -4294967296))
12719                 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12720                              (const_int 32))))]
12721   "TARGET_SHMEDIA"
12722   "mshfhi.l     %N2, %N1, %0"
12723   [(set_attr "type" "arith_media")])
12725 (define_split
12726   [(set (match_operand:DI 0 "arith_reg_dest" "")
12727         (ior:DI (zero_extend:DI (match_operand:SI 1
12728                                               "extend_reg_or_0_operand" ""))
12729                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
12730                         (const_int -4294967296))))
12731    (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
12732   "TARGET_SHMEDIA"
12733   [(const_int 0)]
12734   "
12736   emit_insn (gen_ashldi3_media (operands[3],
12737                                 simplify_gen_subreg (DImode, operands[1],
12738                                                      SImode, 0),
12739                                 GEN_INT (32)));
12740   emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
12741   DONE;
12744 (define_insn "mshflo_l_di"
12745   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12746         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12747                         (const_int 4294967295))
12748                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12749                            (const_int 32))))]
12751   "TARGET_SHMEDIA"
12752   "mshflo.l     %N1, %N2, %0"
12753   [(set_attr "type" "arith_media")
12754    (set_attr "highpart" "ignore")])
12756 (define_insn "*mshflo_l_di_rev"
12757   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12758         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12759                            (const_int 32))
12760                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12761                         (const_int 4294967295))))]
12763   "TARGET_SHMEDIA"
12764   "mshflo.l     %N2, %N1, %0"
12765   [(set_attr "type" "arith_media")
12766    (set_attr "highpart" "ignore")])
12768 ;; Combiner pattern for trampoline initialization.
12769 (define_insn_and_split "*double_shori"
12770   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12771         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
12772                            (const_int 32))
12773                 (match_operand:DI 2 "const_int_operand" "n")))]
12774   "TARGET_SHMEDIA
12775    && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
12776   "#"
12777   "rtx_equal_p (operands[0], operands[1])"
12778   [(const_int 0)]
12779   "
12781   HOST_WIDE_INT v = INTVAL (operands[2]);
12783   emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
12784   emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
12785   DONE;
12787   [(set_attr "highpart" "ignore")])
12790 (define_insn "*mshflo_l_di_x"
12791   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12792         (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
12793                                  "rZ"))
12794                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12795                            (const_int 32))))]
12797   "TARGET_SHMEDIA"
12798   "mshflo.l     %N1, %N2, %0"
12799   [(set_attr "type" "arith_media")
12800    (set_attr "highpart" "ignore")])
12802 (define_insn_and_split "concat_v2sf"
12803   [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
12804 ;;      (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
12805         (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
12806                          (match_operand:SF 2 "register_operand" "rZ,f,f")))]
12808   "TARGET_SHMEDIA"
12809   "@
12810         mshflo.l        %N1, %N2, %0
12811         #
12812         #"
12813   "TARGET_SHMEDIA && reload_completed
12814    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12815   [(set (match_dup 3) (match_dup 1))
12816    (set (match_dup 4) (match_dup 2))]
12817   "
12819   operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
12820   operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
12822   [(set_attr "type" "arith_media")
12823    (set_attr "highpart" "ignore")])
12825 (define_insn "*mshflo_l_di_x_rev"
12826   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12827         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12828                            (const_int 32))
12829                 (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
12831   "TARGET_SHMEDIA"
12832   "mshflo.l     %N2, %N1, %0"
12833   [(set_attr "type" "arith_media")
12834    (set_attr "highpart" "ignore")])
12836 (define_insn "ashlv2si3"
12837   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12838         (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12839                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12840   "TARGET_SHMEDIA"
12841   "mshlld.l     %1, %2, %0"
12842   [(set_attr "type" "arith_media")
12843    (set_attr "highpart" "depend")])
12845 (define_split
12846   [(set (match_operand 0 "any_register_operand" "")
12847         (match_operator 3 "shift_operator"
12848           [(match_operand 1 "any_register_operand" "")
12849            (match_operand 2 "shift_count_reg_operand" "")]))]
12850   "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
12851   [(set (match_dup 0) (match_dup 3))]
12852   "
12854   rtx count = operands[2];
12855   enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
12857   while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
12858          || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
12859          || GET_CODE (count) == TRUNCATE)
12860     count = XEXP (count, 0);
12861   inner_mode = GET_MODE (count);
12862   count = simplify_gen_subreg (outer_mode, count, inner_mode,
12863                                subreg_lowpart_offset (outer_mode, inner_mode));
12864   operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
12865                                 operands[1], count);
12868 (define_insn "ashlv4hi3"
12869   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12870         (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12871                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12872   "TARGET_SHMEDIA"
12873   "mshlld.w     %1, %2, %0"
12874   [(set_attr "type" "arith_media")
12875    (set_attr "highpart" "depend")])
12877 (define_insn "lshrv2si3"
12878   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12879         (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12880                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12881   "TARGET_SHMEDIA"
12882   "mshlrd.l     %1, %2, %0"
12883   [(set_attr "type" "arith_media")
12884    (set_attr "highpart" "depend")])
12886 (define_insn "lshrv4hi3"
12887   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12888         (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12889                        (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12890   "TARGET_SHMEDIA"
12891   "mshlrd.w     %1, %2, %0"
12892   [(set_attr "type" "arith_media")
12893    (set_attr "highpart" "depend")])
12895 (define_insn "subv2si3"
12896   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12897         (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12898                     (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12899   "TARGET_SHMEDIA"
12900   "msub.l       %N1, %2, %0"
12901   [(set_attr "type" "arith_media")
12902    (set_attr "highpart" "depend")])
12904 (define_insn "subv4hi3"
12905   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12906         (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12907                     (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12908   "TARGET_SHMEDIA"
12909   "msub.w       %N1, %2, %0"
12910   [(set_attr "type" "arith_media")
12911    (set_attr "highpart" "depend")])
12913 (define_insn_and_split "subv2hi3"
12914   [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
12915         (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
12916                    (match_operand:V2HI 2 "arith_reg_operand" "r")))]
12917   "TARGET_SHMEDIA"
12918   "#"
12919   "TARGET_SHMEDIA"
12920   [(const_int 0)]
12921   "
12923   rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
12924   rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
12925   rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
12926   rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
12927   rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
12929   emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
12930   emit_insn (gen_truncdisi2 (si_dst, di_dst));
12931   DONE;
12933   [(set_attr "highpart" "must_split")])
12935 (define_insn "sssubv2si3"
12936   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12937         (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12938                        (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12939   "TARGET_SHMEDIA"
12940   "msubs.l      %N1, %2, %0"
12941   [(set_attr "type" "mcmp_media")
12942    (set_attr "highpart" "depend")])
12944 (define_insn "ussubv8qi3"
12945   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12946         (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12947                        (match_operand:V8QI 2 "arith_reg_operand" "r")))]
12948   "TARGET_SHMEDIA"
12949   "msubs.ub     %N1, %2, %0"
12950   [(set_attr "type" "mcmp_media")
12951    (set_attr "highpart" "depend")])
12953 (define_insn "sssubv4hi3"
12954   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12955         (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12956                        (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12957   "TARGET_SHMEDIA"
12958   "msubs.w      %N1, %2, %0"
12959   [(set_attr "type" "mcmp_media")
12960    (set_attr "highpart" "depend")])
12962 ;; Floating Point Intrinsics
12964 (define_insn "fcosa_s"
12965   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12966         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
12967                    UNSPEC_FCOSA))]
12968   "TARGET_SHMEDIA"
12969   "fcosa.s      %1, %0"
12970   [(set_attr "type" "atrans_media")])
12972 (define_insn "fsina_s"
12973   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12974         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
12975                    UNSPEC_FSINA))]
12976   "TARGET_SHMEDIA"
12977   "fsina.s      %1, %0"
12978   [(set_attr "type" "atrans_media")])
12980 (define_insn "fipr"
12981   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12982         (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
12983                                                     "fp_arith_reg_operand" "f")
12984                                                    (match_operand:V4SF 2
12985                                                     "fp_arith_reg_operand" "f"))
12986                                          (parallel [(const_int 0)]))
12987                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12988                                          (parallel [(const_int 1)])))
12989                  (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12990                                          (parallel [(const_int 2)]))
12991                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12992                                          (parallel [(const_int 3)])))))]
12993   "TARGET_SHMEDIA"
12994   "fipr.s       %1, %2, %0"
12995   [(set_attr "type" "fparith_media")])
12997 (define_insn "fsrra_s"
12998   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12999         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
13000                    UNSPEC_FSRRA))]
13001   "TARGET_SHMEDIA"
13002   "fsrra.s      %1, %0"
13003   [(set_attr "type" "atrans_media")])
13005 (define_insn "ftrv"
13006   [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
13007         (plus:V4SF
13008          (plus:V4SF
13009           (mult:V4SF
13010            (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
13011                             (parallel [(const_int 0) (const_int 5)
13012                                        (const_int 10) (const_int 15)]))
13013            (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
13014           (mult:V4SF
13015            (vec_select:V4SF (match_dup 1)
13016                             (parallel [(const_int 4) (const_int 9)
13017                                        (const_int 14) (const_int 3)]))
13018            (vec_select:V4SF (match_dup 2)
13019                             (parallel [(const_int 1) (const_int 2)
13020                                        (const_int 3) (const_int 0)]))))
13021          (plus:V4SF
13022           (mult:V4SF
13023            (vec_select:V4SF (match_dup 1)
13024                             (parallel [(const_int 8) (const_int 13)
13025                                        (const_int 2) (const_int 7)]))
13026            (vec_select:V4SF (match_dup 2)
13027                             (parallel [(const_int 2) (const_int 3)
13028                                        (const_int 0) (const_int 1)])))
13029           (mult:V4SF
13030            (vec_select:V4SF (match_dup 1)
13031                             (parallel [(const_int 12) (const_int 1)
13032                                        (const_int 6) (const_int 11)]))
13033            (vec_select:V4SF (match_dup 2)
13034                             (parallel [(const_int 3) (const_int 0)
13035                                        (const_int 1) (const_int 2)]))))))]
13036   "TARGET_SHMEDIA"
13037   "ftrv.s %1, %2, %0"
13038   [(set_attr "type" "fparith_media")])
13040 (define_insn "ldhi_l"
13041   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13042         (zero_extract:SI
13043          (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
13044                                   (const_int 3))
13045                           (const_int -3)))
13046          (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
13047          (const_int 0)))]
13048   "TARGET_SHMEDIA32"
13049   "ldhi.l       %U1, %0"
13050   [(set_attr "type" "load_media")])
13052 (define_insn "ldhi_q"
13053   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13054         (zero_extract:DI
13055          (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
13056                                   (const_int 7))
13057                           (const_int -7)))
13058          (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
13059          (const_int 0)))]
13060   "TARGET_SHMEDIA32"
13061   "ldhi.q       %U1, %0"
13062   [(set_attr "type" "load_media")])
13064 (define_insn_and_split "*ldhi_q_comb0"
13065   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13066         (zero_extract:DI
13067          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
13068                                             "register_operand" "r")
13069                                            (match_operand:SI 2
13070                                             "ua_offset" "I06"))
13071                                   (const_int 7))
13072                           (const_int -7)))
13073          (plus:SI (and:SI (match_dup 1) (const_int 7))
13074                   (const_int 1))
13075          (const_int 0)))]
13076   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
13077   "#"
13078   ""
13079   [(pc)]
13080   "emit_insn (gen_ldhi_q (operands[0],
13081                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
13082    DONE;")
13085 (define_insn_and_split "*ldhi_q_comb1"
13086   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13087         (zero_extract:DI
13088          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
13089                                             "register_operand" "r")
13090                                            (match_operand:SI 2
13091                                             "ua_offset" "I06"))
13092                                   (const_int 7))
13093                           (const_int -7)))
13094          (plus:SI (and:SI (plus:SI (match_dup 1)  (match_operand:SI 3
13095                                                    "ua_offset" "I06"))
13096                           (const_int 7))
13097                   (const_int 1))
13098          (const_int 0)))]
13099   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
13100    && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
13101   "#"
13102   ""
13103   [(pc)]
13104   "emit_insn (gen_ldhi_q (operands[0],
13105                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
13106    DONE;")
13109 (define_insn "ldlo_l"
13110   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13111         (zero_extract:SI
13112          (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
13113                          (const_int -4)))
13114          (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
13115          (and:SI (match_dup 1) (const_int 3))))]
13116   "TARGET_SHMEDIA32"
13117   "ldlo.l       %U1, %0"
13118   [(set_attr "type" "load_media")])
13120 (define_insn "ldlo_q"
13121   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13122         (zero_extract:DI
13123          (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
13124                          (const_int -8)))
13125          (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
13126          (and:SI (match_dup 1) (const_int 7))))]
13127   "TARGET_SHMEDIA32"
13128   "ldlo.q       %U1, %0"
13129   [(set_attr "type" "load_media")])
13131 (define_insn_and_split "*ldlo_q_comb0"
13132   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13133         (zero_extract:DI
13134          (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
13135                                   (match_operand:SI 2 "ua_offset" "I06"))
13136                          (const_int -8)))
13137          (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
13138          (and:SI (match_dup 1) (const_int 7))))]
13139   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
13140   "#"
13141   ""
13142   [(pc)]
13143   "emit_insn (gen_ldlo_q (operands[0],
13144                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
13145    DONE;")
13147 (define_insn_and_split "*ldlo_q_comb1"
13148   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13149         (zero_extract:DI
13150          (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
13151                                   (match_operand:SI 2 "ua_offset" "I06"))
13152                          (const_int -8)))
13153          (minus:SI (const_int 8)
13154                    (and:SI (plus:SI (match_dup 1)
13155                                     (match_operand:SI 3 "ua_offset" "I06"))
13156                            (const_int 7)))
13157          (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
13158   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
13159    && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
13160   "#"
13161   ""
13162   [(pc)]
13163   "emit_insn (gen_ldlo_q (operands[0],
13164                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
13165    DONE;")
13167 (define_insn "sthi_l"
13168   [(set (zero_extract:SI
13169          (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
13170                                   (const_int 3))
13171                           (const_int -3)))
13172          (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
13173          (const_int 0))
13174         (match_operand:SI 1 "arith_reg_operand" "r"))]
13175   "TARGET_SHMEDIA32"
13176   "sthi.l       %U0, %1"
13177   [(set_attr "type" "ustore_media")])
13179 ;; All unaligned stores are considered to be 'narrow' because they typically
13180 ;; operate on less that a quadword, and when they operate on a full quadword,
13181 ;; the vanilla store high / store low sequence will cause a stall if not
13182 ;; scheduled apart.
13183 (define_insn "sthi_q"
13184   [(set (zero_extract:DI
13185          (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
13186                                   (const_int 7))
13187                           (const_int -7)))
13188          (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
13189          (const_int 0))
13190         (match_operand:DI 1 "arith_reg_operand" "r"))]
13191   "TARGET_SHMEDIA32"
13192   "sthi.q       %U0, %1"
13193   [(set_attr "type" "ustore_media")])
13195 (define_insn_and_split "*sthi_q_comb0"
13196   [(set (zero_extract:DI
13197          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
13198                                             "register_operand" "r")
13199                                            (match_operand:SI 1 "ua_offset"
13200                                             "I06"))
13201                                   (const_int 7))
13202                           (const_int -7)))
13203          (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
13204          (const_int 0))
13205         (match_operand:DI 2 "arith_reg_operand" "r"))]
13206   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
13207   "#"
13208   ""
13209   [(pc)]
13210   "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13211                           operands[2]));
13212    DONE;")
13214 (define_insn_and_split "*sthi_q_comb1"
13215   [(set (zero_extract:DI
13216          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
13217                                             "register_operand" "r")
13218                                            (match_operand:SI 1 "ua_offset"
13219                                             "I06"))
13220                                   (const_int 7))
13221                           (const_int -7)))
13222          (plus:SI (and:SI (plus:SI (match_dup 0)
13223                                    (match_operand:SI 2 "ua_offset" "I06"))
13224                           (const_int 7))
13225                   (const_int 1))
13226          (const_int 0))
13227         (match_operand:DI 3 "arith_reg_operand" "r"))]
13228   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
13229    && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
13230   "#"
13231   ""
13232   [(pc)]
13233   "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13234                           operands[3]));
13235    DONE;")
13237 ;; This is highpart user because the address is used as full 64 bit.
13238 (define_insn "stlo_l"
13239   [(set (zero_extract:SI
13240          (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
13241                          (const_int -4)))
13242          (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
13243          (and:SI (match_dup 0) (const_int 3)))
13244         (match_operand:SI 1 "arith_reg_operand" "r"))]
13245   "TARGET_SHMEDIA32"
13246   "stlo.l       %U0, %1"
13247   [(set_attr "type" "ustore_media")])
13249 (define_insn "stlo_q"
13250   [(set (zero_extract:DI
13251          (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
13252                          (const_int -8)))
13253          (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
13254          (and:SI (match_dup 0) (const_int 7)))
13255         (match_operand:DI 1 "arith_reg_operand" "r"))]
13256   "TARGET_SHMEDIA32"
13257   "stlo.q       %U0, %1"
13258   [(set_attr "type" "ustore_media")])
13260 (define_insn_and_split "*stlo_q_comb0"
13261   [(set (zero_extract:DI
13262          (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
13263                                   (match_operand:SI 1 "ua_offset" "I06"))
13264                          (const_int -8)))
13265          (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
13266          (and:SI (match_dup 0) (const_int 7)))
13267         (match_operand:DI 2 "arith_reg_operand" "r"))]
13268   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
13269   "#"
13270   ""
13271   [(pc)]
13272   "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13273                           operands[2]));
13274    DONE;")
13276 (define_insn_and_split "*stlo_q_comb1"
13277   [(set (zero_extract:DI
13278          (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
13279                                   (match_operand:SI 1 "ua_offset" "I06"))
13280                          (const_int -8)))
13281          (minus:SI (const_int 8) (and:SI (plus:SI (match_dup 0)
13282                                                   (match_operand:SI 2
13283                                                    "ua_offset" "I06"))
13284                                          (const_int 7)))
13285          (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
13286         (match_operand:DI 3 "arith_reg_operand" "r"))]
13287   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
13288   "#"
13289   ""
13290   [(pc)]
13291   "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13292                           operands[3]));
13293    DONE;")
13295 (define_insn "ldhi_l64"
13296   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13297         (zero_extract:SI
13298          (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13299                                   (const_int 3))
13300                           (const_int -3)))
13301          (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
13302          (const_int 0)))]
13303   "TARGET_SHMEDIA64"
13304   "ldhi.l       %U1, %0"
13305   [(set_attr "type" "load_media")])
13307 (define_insn "ldhi_q64"
13308   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13309         (zero_extract:DI
13310          (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13311                                   (const_int 7))
13312                           (const_int -7)))
13313          (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
13314          (const_int 0)))]
13315   "TARGET_SHMEDIA64"
13316   "ldhi.q       %U1, %0"
13317   [(set_attr "type" "load_media")])
13319 (define_insn "ldlo_l64"
13320   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13321         (zero_extract:SI
13322          (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13323                          (const_int -4)))
13324          (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
13325          (and:DI (match_dup 1) (const_int 3))))]
13326   "TARGET_SHMEDIA64"
13327   "ldlo.l       %U1, %0"
13328   [(set_attr "type" "load_media")])
13330 (define_insn "ldlo_q64"
13331   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13332         (zero_extract:DI
13333          (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13334                          (const_int -8)))
13335          (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
13336          (and:DI (match_dup 1) (const_int 7))))]
13337   "TARGET_SHMEDIA64"
13338   "ldlo.q       %U1, %0"
13339   [(set_attr "type" "load_media")])
13341 (define_insn "sthi_l64"
13342   [(set (zero_extract:SI
13343          (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13344                                   (const_int 3))
13345                           (const_int -3)))
13346          (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
13347          (const_int 0))
13348         (match_operand:SI 1 "arith_reg_operand" "r"))]
13349   "TARGET_SHMEDIA64"
13350   "sthi.l       %U0, %1"
13351   [(set_attr "type" "ustore_media")])
13353 (define_insn "sthi_q64"
13354   [(set (zero_extract:DI
13355          (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13356                                   (const_int 7))
13357                           (const_int -7)))
13358          (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
13359          (const_int 0))
13360         (match_operand:DI 1 "arith_reg_operand" "r"))]
13361   "TARGET_SHMEDIA64"
13362   "sthi.q       %U0, %1"
13363   [(set_attr "type" "ustore_media")])
13365 (define_insn "stlo_l64"
13366   [(set (zero_extract:SI
13367          (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13368                          (const_int -4)))
13369          (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
13370          (and:DI (match_dup 0) (const_int 3)))
13371         (match_operand:SI 1 "arith_reg_operand" "r"))]
13372   "TARGET_SHMEDIA64"
13373   "stlo.l       %U0, %1"
13374   [(set_attr "type" "ustore_media")])
13376 (define_insn "stlo_q64"
13377   [(set (zero_extract:DI
13378          (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13379                          (const_int -8)))
13380          (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
13381          (and:DI (match_dup 0) (const_int 7)))
13382         (match_operand:DI 1 "arith_reg_operand" "r"))]
13383   "TARGET_SHMEDIA64"
13384   "stlo.q       %U0, %1"
13385   [(set_attr "type" "ustore_media")])
13387 (define_insn "nsb"
13388   [(set (match_operand:QI 0 "arith_reg_dest" "=r")
13389         (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13390                    UNSPEC_NSB))]
13391   "TARGET_SHMEDIA"
13392   "nsb  %1, %0"
13393   [(set_attr "type" "arith_media")])
13395 (define_insn "nsbsi"
13396   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13397         (zero_extend:SI
13398          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13399                     UNSPEC_NSB)))]
13400   "TARGET_SHMEDIA"
13401   "nsb  %1, %0"
13402   [(set_attr "type" "arith_media")])
13404 (define_insn "nsbdi"
13405   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13406         (zero_extend:DI
13407          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13408                     UNSPEC_NSB)))]
13409   "TARGET_SHMEDIA"
13410   "nsb  %1, %0"
13411   [(set_attr "type" "arith_media")])
13413 (define_expand "ffsdi2"
13414   [(set (match_operand:DI 0 "arith_reg_dest" "")
13415         (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
13416   "TARGET_SHMEDIA"
13417   "
13419   rtx scratch = gen_reg_rtx (DImode);
13420   rtx last;
13422   emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
13423   emit_insn (gen_xordi3 (scratch, operands[1], scratch));
13424   emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
13425   emit_insn (gen_nsbdi (scratch, scratch));
13426   emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
13427   emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
13428   last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
13429   set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
13431   DONE;
13434 (define_expand "ffssi2"
13435   [(set (match_operand:SI 0 "arith_reg_dest" "")
13436         (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
13437   "TARGET_SHMEDIA"
13438   "
13440   rtx scratch = gen_reg_rtx (SImode);
13441   rtx discratch = gen_reg_rtx (DImode);
13442   rtx last;
13444   emit_insn (gen_adddi3 (discratch,
13445                          simplify_gen_subreg (DImode, operands[1], SImode, 0),
13446                          constm1_rtx));
13447   emit_insn (gen_andcdi3 (discratch,
13448                           simplify_gen_subreg (DImode, operands[1], SImode, 0),
13449                           discratch));
13450   emit_insn (gen_nsbsi (scratch, discratch));
13451   last = emit_insn (gen_subsi3 (operands[0],
13452                                 force_reg (SImode, GEN_INT (63)), scratch));
13453   set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
13455   DONE;
13458 (define_insn "byterev"
13459   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13460         (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
13461                          (parallel [(const_int 7) (const_int 6) (const_int 5)
13462                                     (const_int 4) (const_int 3) (const_int 2)
13463                                     (const_int 1) (const_int 0)])))]
13464   "TARGET_SHMEDIA"
13465   "byterev      %1, %0"
13466   [(set_attr "type" "arith_media")])
13468 (define_insn "*prefetch_media"
13469   [(prefetch (match_operand:QI 0 "address_operand" "p")
13470              (match_operand:SI 1 "const_int_operand" "n")
13471              (match_operand:SI 2 "const_int_operand" "n"))]
13472   "TARGET_SHMEDIA"
13473   "*
13475   operands[0] = gen_rtx_MEM (QImode, operands[0]);
13476   output_asm_insn (\"ld%M0.b    %m0,r63\", operands);
13477   return \"\";
13479   [(set_attr "type" "other")])
13481 (define_insn "*prefetch_i4"
13482   [(prefetch (match_operand:SI 0 "register_operand" "r")
13483              (match_operand:SI 1 "const_int_operand" "n")
13484              (match_operand:SI 2 "const_int_operand" "n"))]
13485   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && !TARGET_VXWORKS_RTP"
13486   "*
13488   return \"pref @%0\";
13490   [(set_attr "type" "other")])
13492 ;; In user mode, the "pref" instruction will raise a RADDERR exception
13493 ;; for accesses to [0x80000000,0xffffffff].  This makes it an unsuitable
13494 ;; implementation of __builtin_prefetch for VxWorks RTPs.
13495 (define_expand "prefetch"
13496   [(prefetch (match_operand 0 "address_operand" "p")
13497              (match_operand:SI 1 "const_int_operand" "n")
13498              (match_operand:SI 2 "const_int_operand" "n"))]
13499   "TARGET_SH2A || ((TARGET_HARD_SH4 || TARGET_SH5)
13500    && (TARGET_SHMEDIA || !TARGET_VXWORKS_RTP))"
13501   "
13503   if (GET_MODE (operands[0]) != Pmode
13504       || !CONST_INT_P (operands[1])
13505       || !CONST_INT_P (operands[2]))
13506     FAIL;
13507   if (! TARGET_SHMEDIA)
13508     operands[0] = force_reg (Pmode, operands[0]);
13511 (define_insn "prefetch_m2a"
13512   [(prefetch (match_operand:SI 0 "register_operand" "r")
13513              (match_operand:SI 1 "const_int_operand" "n")
13514              (match_operand:SI 2 "const_int_operand" "n"))]
13515   "TARGET_SH2A"
13516   "pref\\t@%0"
13517   [(set_attr "type" "other")])
13519 (define_insn "alloco_i"
13520   [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
13521         (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
13522   "TARGET_SHMEDIA32"
13523   "*
13525   rtx xops[2];
13527   if (GET_CODE (operands[0]) == PLUS)
13528     {
13529       xops[0] = XEXP (operands[0], 0);
13530       xops[1] = XEXP (operands[0], 1);
13531     }
13532   else
13533     {
13534       xops[0] = operands[0];
13535       xops[1] = const0_rtx;
13536     }
13537   output_asm_insn (\"alloco   %0, %1\", xops);
13538   return \"\";
13540   [(set_attr "type" "other")])
13542 (define_split
13543   [(set (match_operand 0 "any_register_operand" "")
13544         (match_operand 1 "" ""))]
13545   "TARGET_SHMEDIA && reload_completed"
13546   [(set (match_dup 0) (match_dup 1))]
13547   "
13549   int n_changes = 0;
13551   for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
13552   if (!n_changes)
13553     FAIL;
13556 ; Stack Protector Patterns
13558 (define_expand "stack_protect_set"
13559   [(set (match_operand 0 "memory_operand" "")
13560         (match_operand 1 "memory_operand" ""))]
13561   ""
13563   if (TARGET_SHMEDIA)
13564     {
13565       if (TARGET_SHMEDIA64)
13566         emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
13567       else
13568         emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
13569     }
13570   else
13571     emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
13573   DONE;
13576 (define_insn "stack_protect_set_si"
13577   [(set (match_operand:SI 0 "memory_operand" "=m")
13578         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13579    (set (match_scratch:SI 2 "=&r") (const_int 0))]
13580   "!TARGET_SHMEDIA"
13581   "mov.l\t%1, %2\;mov.l\t%2, %0\;mov\t#0, %2"
13582   [(set_attr "type" "other")
13583    (set_attr "length" "6")])
13585 (define_insn "stack_protect_set_si_media"
13586   [(set (match_operand:SI 0 "memory_operand" "=m")
13587         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13588    (set (match_scratch:SI 2 "=&r") (const_int 0))]
13589   "TARGET_SHMEDIA"
13590   "ld%M1.l\t%m1, %2\;st%M0.l\t%m0, %2\;movi\t0, %2"
13591   [(set_attr "type" "other")
13592    (set_attr "length" "12")])
13594 (define_insn "stack_protect_set_di_media"
13595   [(set (match_operand:DI 0 "memory_operand" "=m")
13596         (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13597    (set (match_scratch:DI 2 "=&r") (const_int 0))]
13598   "TARGET_SHMEDIA64"
13599   "ld%M1.q\t%m1, %2\;st%M0.q\t%m0, %2\;movi\t0, %2"
13600   [(set_attr "type" "other")
13601    (set_attr "length" "12")])
13603 (define_expand "stack_protect_test"
13604   [(match_operand 0 "memory_operand" "")
13605    (match_operand 1 "memory_operand" "")
13606    (match_operand 2 "" "")]
13607   ""
13609   if (TARGET_SHMEDIA)
13610     {
13611       rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
13612       rtx test;
13614       test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
13615       if (TARGET_SHMEDIA64)
13616         {
13617           emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
13618                                                       operands[1]));
13619           emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
13620         }
13621       else
13622         {
13623           emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
13624                                                       operands[1]));
13625           emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
13626         }
13627     }
13628   else
13629     {
13630       emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
13631       emit_jump_insn (gen_branch_true (operands[2]));
13632     }
13634   DONE;
13637 (define_insn "stack_protect_test_si"
13638   [(set (reg:SI T_REG)
13639         (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
13640                     (match_operand:SI 1 "memory_operand" "m")]
13641                    UNSPEC_SP_TEST))
13642   (set (match_scratch:SI 2 "=&r") (const_int 0))
13643   (set (match_scratch:SI 3 "=&r") (const_int 0))]
13644   "!TARGET_SHMEDIA"
13645   "mov.l\t%0, %2\;mov.l\t%1, %3\;cmp/eq\t%2, %3\;mov\t#0, %2\;mov\t#0, %3"
13646   [(set_attr "type" "other")
13647    (set_attr "length" "10")])
13649 (define_insn "stack_protect_test_si_media"
13650   [(set (match_operand:SI 0 "register_operand" "=&r")
13651         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
13652                     (match_operand:SI 2 "memory_operand" "m")]
13653                    UNSPEC_SP_TEST))
13654   (set (match_scratch:SI 3 "=&r") (const_int 0))]
13655   "TARGET_SHMEDIA"
13656   "ld%M1.l\t%m1, %0\;ld%M2.l\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13657   [(set_attr "type" "other")
13658    (set_attr "length" "16")])
13660 (define_insn "stack_protect_test_di_media"
13661   [(set (match_operand:DI 0 "register_operand" "=&r")
13662         (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
13663                     (match_operand:DI 2 "memory_operand" "m")]
13664                    UNSPEC_SP_TEST))
13665   (set (match_scratch:DI 3 "=&r") (const_int 0))]
13666   "TARGET_SHMEDIA64"
13667   "ld%M1.q\t%m1, %0\;ld%M2.q\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13668   [(set_attr "type" "other")
13669    (set_attr "length" "16")])