2013-01-08 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / config / sh / sh.md
blob545806d4478291cbdd8f32d1a5567e40e90fef99
1 ;;- Machine description for Renesas / SuperH SH.
2 ;;  Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3 ;;  2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 ;;  Free Software Foundation, Inc.
5 ;;  Contributed by Steve Chamberlain (sac@cygnus.com).
6 ;;  Improved by Jim Wilson (wilson@cygnus.com).
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)
178   (UNSPECV_GBR          13)
181 ;; -------------------------------------------------------------------------
182 ;; Attributes
183 ;; -------------------------------------------------------------------------
185 ;; Target CPU.
187 (define_attr "cpu"
188  "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
189   (const (symbol_ref "sh_cpu_attr")))
191 (define_attr "endian" "big,little"
192  (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
193                       (const_string "little") (const_string "big"))))
195 ;; Indicate if the default fpu mode is single precision.
196 (define_attr "fpu_single" "yes,no"
197   (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
198                          (const_string "yes") (const_string "no"))))
200 (define_attr "fmovd" "yes,no"
201   (const (if_then_else (symbol_ref "TARGET_FMOVD")
202                        (const_string "yes") (const_string "no"))))
203 ;; pipeline model
204 (define_attr "pipe_model" "sh1,sh4,sh5media"
205   (const
206    (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
207           (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
208          (const_string "sh1"))))
210 ;; cbranch      conditional branch instructions
211 ;; jump         unconditional jumps
212 ;; arith        ordinary arithmetic
213 ;; arith3       a compound insn that behaves similarly to a sequence of
214 ;;              three insns of type arith
215 ;; arith3b      like above, but might end with a redirected branch
216 ;; load         from memory
217 ;; load_si      Likewise, SImode variant for general register.
218 ;; fload        Likewise, but load to fp register.
219 ;; store        to memory
220 ;; fstore       floating point register to memory
221 ;; move         general purpose register to register
222 ;; movi8        8-bit immediate to general purpose register
223 ;; mt_group     other sh4 mt instructions
224 ;; fmove        register to register, floating point
225 ;; smpy         word precision integer multiply
226 ;; dmpy         longword or doublelongword precision integer multiply
227 ;; return       rts
228 ;; pload        load of pr reg, which can't be put into delay slot of rts
229 ;; prset        copy register to pr reg, ditto
230 ;; pstore       store of pr reg, which can't be put into delay slot of jsr
231 ;; prget        copy pr to register, ditto
232 ;; pcload       pc relative load of constant value
233 ;; pcfload      Likewise, but load to fp register.
234 ;; pcload_si    Likewise, SImode variant for general register.
235 ;; rte          return from exception
236 ;; sfunc        special function call with known used registers
237 ;; call         function call
238 ;; fp           floating point
239 ;; fpscr_toggle toggle a bit in the fpscr
240 ;; fdiv         floating point divide (or square root)
241 ;; gp_fpul      move from general purpose register to fpul
242 ;; fpul_gp      move from fpul to general purpose register
243 ;; mac_gp       move from mac[lh] to general purpose register
244 ;; gp_mac       move from general purpose register to mac[lh]
245 ;; mac_mem      move from mac[lh] to memory
246 ;; mem_mac      move from memory to mac[lh]
247 ;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv
248 ;; ftrc_s       fix_truncsfsi2_i4
249 ;; dfdiv        double precision floating point divide (or square root)
250 ;; cwb          ic_invalidate_line_i
251 ;; movua        SH4a unaligned load
252 ;; fsrra        square root reciprocal approximate
253 ;; fsca         sine and cosine approximate
254 ;; tls_load     load TLS related address
255 ;; arith_media  SHmedia arithmetic, logical, and shift instructions
256 ;; cbranch_media SHmedia conditional branch instructions
257 ;; cmp_media    SHmedia compare instructions
258 ;; dfdiv_media  SHmedia double precision divide and square root
259 ;; dfmul_media  SHmedia double precision multiply instruction
260 ;; dfparith_media SHmedia double precision floating point arithmetic
261 ;; dfpconv_media SHmedia double precision floating point conversions
262 ;; dmpy_media   SHmedia longword multiply
263 ;; fcmp_media   SHmedia floating point compare instructions
264 ;; fdiv_media   SHmedia single precision divide and square root
265 ;; fload_media  SHmedia floating point register load instructions
266 ;; fmove_media  SHmedia floating point register moves (inc. fabs and fneg)
267 ;; fparith_media SHmedia single precision floating point arithmetic
268 ;; fpconv_media SHmedia single precision floating point conversions
269 ;; fstore_media SHmedia floating point register store instructions
270 ;; gettr_media  SHmedia gettr instruction
271 ;; invalidate_line_media SHmedia invalidate_line sequence
272 ;; jump_media   SHmedia unconditional branch instructions
273 ;; load_media   SHmedia general register load instructions
274 ;; pt_media     SHmedia pt instruction (expanded by assembler)
275 ;; ptabs_media  SHmedia ptabs instruction
276 ;; store_media  SHmedia general register store instructions
277 ;; mcmp_media   SHmedia multimedia compare, absolute, saturating ops
278 ;; mac_media    SHmedia mac-style fixed point operations
279 ;; d2mpy_media  SHmedia: two 32-bit integer multiplies
280 ;; atrans_media SHmedia approximate transcendental functions
281 ;; ustore_media SHmedia unaligned stores
282 ;; nil          no-op move, will be deleted.
284 (define_attr "type"
285  "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"
286   (const_string "other"))
288 ;; We define a new attribute namely "insn_class".We use
289 ;; this for the DFA based pipeline description.
291 ;; mt_group      SH4 "mt" group instructions.
293 ;; ex_group      SH4 "ex" group instructions.
295 ;; ls_group      SH4 "ls" group instructions.
298 (define_attr "insn_class"
299   "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
300   (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
301          (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group")
302          (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,store,fstore,gp_fpul,fpul_gp") (const_string "ls_group")
303          (eq_attr "type" "cbranch,jump") (const_string "br_group")
304          (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
305            (const_string "fe_group")
306          (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")]
307         (const_string "none")))
308 ;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
309 ;; so these do not belong in an insn group, although they are modeled
310 ;; with their own define_insn_reservations.
312 ;; Indicate what precision must be selected in fpscr for this insn, if any.
314 (define_attr "fp_mode" "single,double,none" (const_string "none"))
316 ;; Indicate if the fpu mode is set by this instruction
317 ;; "unknown" must have the value as "none" in fp_mode, and means
318 ;; that the instruction/abi has left the processor in an unknown
319 ;; state.
320 ;; "none" means that nothing has changed and no mode is set.
321 ;; This attribute is only used for the Renesas ABI.
322 (define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
324 ; If a conditional branch destination is within -252..258 bytes away
325 ; from the instruction it can be 2 bytes long.  Something in the
326 ; range -4090..4100 bytes can be 6 bytes long.  All other conditional
327 ; branches are initially assumed to be 16 bytes long.
328 ; In machine_dependent_reorg, we split all branches that are longer than
329 ; 2 bytes.
331 ;; The maximum range used for SImode constant pool entries is 1018.  A final
332 ;; instruction can add 8 bytes while only being 4 bytes in size, thus we
333 ;; can have a total of 1022 bytes in the pool.  Add 4 bytes for a branch
334 ;; instruction around the pool table, 2 bytes of alignment before the table,
335 ;; and 30 bytes of alignment after the table.  That gives a maximum total
336 ;; pool size of 1058 bytes.
337 ;; Worst case code/pool content size ratio is 1:2 (using asms).
338 ;; Thus, in the worst case, there is one instruction in front of a maximum
339 ;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
340 ;; code.  For the last n bytes of code, there are 2n + 36 bytes of pool.
341 ;; If we have a forward branch, the initial table will be put after the
342 ;; unconditional branch.
344 ;; ??? We could do much better by keeping track of the actual pcloads within
345 ;; the branch range and in the pcload range in front of the branch range.
347 ;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
348 ;; inside an le.
349 (define_attr "short_cbranch_p" "no,yes"
350   (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
351          (const_string "no")
352          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
353          (const_string "yes")
354          (match_test "NEXT_INSN (PREV_INSN (insn)) != insn")
355          (const_string "no")
356          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
357          (const_string "yes")
358          ] (const_string "no")))
360 (define_attr "med_branch_p" "no,yes"
361   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
362               (const_int 1988))
363          (const_string "yes")
364          (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
365          (const_string "no")
366          (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
367               (const_int 8186))
368          (const_string "yes")
369          ] (const_string "no")))
371 (define_attr "med_cbranch_p" "no,yes"
372   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
373               (const_int 1986))
374          (const_string "yes")
375          (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
376          (const_string "no")
377          (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
378                (const_int 8184))
379          (const_string "yes")
380          ] (const_string "no")))
382 (define_attr "braf_branch_p" "no,yes"
383   (cond [(match_test "! TARGET_SH2")
384          (const_string "no")
385          (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
386               (const_int 20660))
387          (const_string "yes")
388          (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
389          (const_string "no")
390          (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
391               (const_int 65530))
392          (const_string "yes")
393          ] (const_string "no")))
395 (define_attr "braf_cbranch_p" "no,yes"
396   (cond [(match_test "! TARGET_SH2")
397          (const_string "no")
398          (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
399               (const_int 20658))
400          (const_string "yes")
401          (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
402          (const_string "no")
403          (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
404               (const_int 65528))
405          (const_string "yes")
406          ] (const_string "no")))
408 ; An unconditional jump in the range -4092..4098 can be 2 bytes long.
409 ; For wider ranges, we need a combination of a code and a data part.
410 ; If we can get a scratch register for a long range jump, the code
411 ; part can be 4 bytes long; otherwise, it must be 8 bytes long.
412 ; If the jump is in the range -32764..32770, the data part can be 2 bytes
413 ; long; otherwise, it must be 6 bytes long.
415 ; All other instructions are two bytes long by default.
417 ;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
418 ;; but getattrtab doesn't understand this.
419 (define_attr "length" ""
420   (cond [(eq_attr "type" "cbranch")
421          (cond [(eq_attr "short_cbranch_p" "yes")
422                 (const_int 2)
423                 (eq_attr "med_cbranch_p" "yes")
424                 (const_int 6)
425                 (eq_attr "braf_cbranch_p" "yes")
426                 (const_int 12)
427 ;; ??? using pc is not computed transitively.
428                 (ne (match_dup 0) (match_dup 0))
429                 (const_int 14)
430                 (match_test "flag_pic")
431                 (const_int 24)
432                 ] (const_int 16))
433          (eq_attr "type" "jump")
434          (cond [(eq_attr "med_branch_p" "yes")
435                 (const_int 2)
436                 (and (match_test "prev_nonnote_insn (insn)")
437                      (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")                              (symbol_ref "INSN"))
438                           (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")                             (symbol_ref "code_for_indirect_jump_scratch"))))
439                 (cond [(eq_attr "braf_branch_p" "yes")
440                        (const_int 6)
441                        (not (match_test "flag_pic"))
442                        (const_int 10)
443                        (match_test "TARGET_SH2")
444                        (const_int 10)] (const_int 18))
445                 (eq_attr "braf_branch_p" "yes")
446                 (const_int 10)
447 ;; ??? using pc is not computed transitively.
448                 (ne (match_dup 0) (match_dup 0))
449                 (const_int 12)
450                 (match_test "flag_pic")
451                 (const_int 22)
452                 ] (const_int 14))
453          (eq_attr "type" "pt_media")
454          (if_then_else (match_test "TARGET_SHMEDIA64")
455                        (const_int 20) (const_int 12))
456          (and (eq_attr "type" "jump_media")
457               (match_test "TARGET_SH5_CUT2_WORKAROUND"))
458          (const_int 8)
459          ] (if_then_else (match_test "TARGET_SHMEDIA")
460                          (const_int 4)
461                          (const_int 2))))
463 ;; DFA descriptions for the pipelines
465 (include "sh1.md")
466 (include "shmedia.md")
467 (include "sh4.md")
469 (include "iterators.md")
470 (include "predicates.md")
471 (include "constraints.md")
473 ;; Definitions for filling delay slots
475 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
477 (define_attr "banked" "yes,no" 
478         (cond [(match_test "sh_loads_bankedreg_p (insn)")
479                (const_string "yes")]
480               (const_string "no")))
482 ;; ??? This should be (nil) instead of (const_int 0)
483 (define_attr "hit_stack" "yes,no"
484         (cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)"))
485                (const_string "no")]
486               (const_string "yes")))
488 (define_attr "interrupt_function" "no,yes"
489   (const (symbol_ref "current_function_interrupt")))
491 (define_attr "in_delay_slot" "yes,no"
492   (cond [(eq_attr "type" "cbranch") (const_string "no")
493          (eq_attr "type" "pcload,pcload_si") (const_string "no")
494          (eq_attr "needs_delay_slot" "yes") (const_string "no")
495          (eq_attr "length" "2") (const_string "yes")
496          ] (const_string "no")))
498 (define_attr "cond_delay_slot" "yes,no"
499   (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
500          ] (const_string "no")))
502 (define_attr "is_sfunc" ""
503   (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
505 (define_attr "is_mac_media" ""
506   (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
508 (define_attr "branch_zero" "yes,no"
509   (cond [(eq_attr "type" "!cbranch") (const_string "no")
510          (ne (symbol_ref "(next_active_insn (insn)\
511                            == (prev_active_insn\
512                                (XEXP (SET_SRC (PATTERN (insn)), 1))))\
513                           && get_attr_length (next_active_insn (insn)) == 2")
514              (const_int 0))
515          (const_string "yes")]
516         (const_string "no")))
518 ;; SH4 Double-precision computation with double-precision result -
519 ;; the two halves are ready at different times.
520 (define_attr "dfp_comp" "yes,no"
521   (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
522         (const_string "no")))
524 ;; Insns for which the latency of a preceding fp insn is decreased by one.
525 (define_attr "late_fp_use" "yes,no" (const_string "no"))
526 ;; And feeding insns for which this relevant.
527 (define_attr "any_fp_comp" "yes,no"
528   (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
529          (const_string "yes")]
530         (const_string "no")))
532 (define_attr "any_int_load" "yes,no"
533   (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
534          (const_string "yes")]
535         (const_string "no")))
537 (define_attr "highpart" "user, ignore, extend, depend, must_split"
538   (const_string "user"))
540 (define_delay
541   (eq_attr "needs_delay_slot" "yes")
542   [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
544 ;; Since a normal return (rts) implicitly uses the PR register,
545 ;; we can't allow PR register loads in an rts delay slot.
546 ;; On the SH1* and SH2*, the rte instruction reads the return pc from the
547 ;; stack, and thus we can't put a pop instruction in its delay slot.
548 ;; On the SH3* and SH4*, the rte instruction does not use the stack, so a
549 ;; pop instruction can go in the delay slot, unless it references a banked
550 ;; register (the register bank is switched by rte).
551 (define_delay
552   (eq_attr "type" "return")
553   [(and (eq_attr "in_delay_slot" "yes")
554         (ior (and (eq_attr "interrupt_function" "no")
555                   (eq_attr "type" "!pload,prset"))
556              (and (eq_attr "interrupt_function" "yes")
557                   (ior (match_test "TARGET_SH3") (eq_attr "hit_stack" "no"))
558                   (eq_attr "banked" "no"))))
559    (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   ;; annulled 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 unnecessary 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 ;; This pattern might be risky because it also tests the upper bits and not
644 ;; only the subreg.  However, it seems that combine will get to this only
645 ;; when testing sign/zero extended values.  In this case the extended upper
646 ;; bits do not matter.
647 (define_insn "*tst<mode>_t_zero"
648   [(set (reg:SI T_REG)
649         (eq:SI
650           (subreg:QIHI
651             (and:SI (match_operand:SI 0 "arith_reg_operand" "%r")
652                     (match_operand:SI 1 "arith_reg_operand" "r")) <lowpart_le>)
653           (const_int 0)))]
654   "TARGET_SH1 && TARGET_LITTLE_ENDIAN"
655   "tst  %0,%1"
656   [(set_attr "type" "mt_group")])
658 (define_insn "*tst<mode>_t_zero"
659   [(set (reg:SI T_REG)
660         (eq:SI
661           (subreg:QIHI
662             (and:SI (match_operand:SI 0 "arith_reg_operand" "%r")
663                     (match_operand:SI 1 "arith_reg_operand" "r")) <lowpart_be>)
664           (const_int 0)))]
665   "TARGET_SH1 && !TARGET_LITTLE_ENDIAN"
666   "tst  %0,%1"
667   [(set_attr "type" "mt_group")])
669 ;; Extract LSB, negate and store in T bit.
671 (define_insn "tstsi_t_and_not"
672   [(set (reg:SI T_REG)
673          (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z"))
674                  (const_int 1)))]
675   "TARGET_SH1"
676   "tst  #1,%0"
677   [(set_attr "type" "mt_group")])
679 ;; Extract contiguous bits and compare them against zero.
681 (define_insn "tstsi_t_zero_extract_eq"
682   [(set (reg:SI T_REG)
683         (eq:SI (zero_extract:SI (match_operand 0 "logical_operand" "z")
684                 (match_operand:SI 1 "const_int_operand")
685                 (match_operand:SI 2 "const_int_operand"))
686          (const_int 0)))]
687   "TARGET_SH1
688    && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))"
690   operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
691   return "tst   %1,%0";
693   [(set_attr "type" "mt_group")])
695 ;; This split is required when testing bits in a QI subreg.
697 (define_split
698   [(set (reg:SI T_REG)
699    (eq:SI (if_then_else:SI (zero_extract:SI
700                             (match_operand 0 "logical_operand" "")
701                             (match_operand 1 "const_int_operand")
702                             (match_operand 2 "const_int_operand"))
703                            (match_operand 3 "const_int_operand")
704                            (const_int 0))
705           (const_int 0)))]
706   "TARGET_SH1
707    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
708    && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
709   [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3))
710                               (const_int 0)))]
712   if (GET_MODE (operands[0]) == QImode)
713     operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
716 ;; Extract single bit, negate and store it in the T bit.
717 ;; Not used for SH4A.
719 (define_insn "tstsi_t_zero_extract_xor"
720   [(set (reg:SI T_REG)
721         (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
722                           (match_operand:SI 3 "const_int_operand"))
723                          (match_operand:SI 1 "const_int_operand")
724                          (match_operand:SI 2 "const_int_operand")))]
725   "TARGET_SH1
726    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
727    && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
728   "tst  %3,%0"
729   [(set_attr "type" "mt_group")])
731 ;; Extract single bit, negate and store it in the T bit.
732 ;; Used for SH4A little endian.
734 (define_insn "tstsi_t_zero_extract_subreg_xor_little"
735   [(set (reg:SI T_REG)
736         (zero_extract:SI
737          (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
738                             (match_operand:SI 3 "const_int_operand")) 0)
739          (match_operand:SI 1 "const_int_operand")
740          (match_operand:SI 2 "const_int_operand")))]
741   "TARGET_SH1 && TARGET_LITTLE_ENDIAN
742    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
743       == (INTVAL (operands[3]) & 255)
744    && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
746   operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
747   return "tst   %3,%0";
749   [(set_attr "type" "mt_group")])
751 ;; Extract single bit, negate and store it in the T bit.
752 ;; Used for SH4A big endian.
754 (define_insn "tstsi_t_zero_extract_subreg_xor_big"
755   [(set (reg:SI T_REG)
756         (zero_extract:SI
757          (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
758                             (match_operand:SI 3 "const_int_operand")) 3)
759          (match_operand:SI 1 "const_int_operand")
760          (match_operand:SI 2 "const_int_operand")))]
761   "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN
762    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
763       == (INTVAL (operands[3]) & 255)
764    && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
766   operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
767   return "tst   %3,%0";
769   [(set_attr "type" "mt_group")])
771 (define_insn "cmpeqsi_t"
772   [(set (reg:SI T_REG)
773         (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
774                (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
775   "TARGET_SH1"
776   "@
777         tst     %0,%0
778         cmp/eq  %1,%0
779         cmp/eq  %1,%0"
780    [(set_attr "type" "mt_group")])
782 ;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this
783 ;; pattern by itself.  What this actually does is:
784 ;;      x == 0: (1 >> 0-0) & 1 = 1
785 ;;      x != 0: (1 >> 0-x) & 1 = 0
786 ;; Without this the test pr51244-8.c fails on SH2A and SH4A.
787 (define_insn_and_split "*cmpeqsi_t"
788   [(set (reg:SI T_REG)
789         (and:SI (lshiftrt:SI
790                   (const_int 1)
791                   (neg:SI (match_operand:SI 0 "arith_reg_operand" "r")))
792                 (const_int 1)))]
793   "TARGET_SH1"
794   "#"
795   "&& 1"
796   [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))])
798 (define_insn "cmpgtsi_t"
799   [(set (reg:SI T_REG)
800         (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
801                (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
802   "TARGET_SH1"
803   "@
804         cmp/pl  %0
805         cmp/gt  %1,%0"
806    [(set_attr "type" "mt_group")])
808 (define_insn "cmpgesi_t"
809   [(set (reg:SI T_REG)
810         (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
811                (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
812   "TARGET_SH1"
813   "@
814         cmp/pz  %0
815         cmp/ge  %1,%0"
816    [(set_attr "type" "mt_group")])
818 ;; FIXME: This is actually wrong.  There is no way to literally move a
819 ;; general reg to t reg.  Luckily, it seems that this pattern will be only
820 ;; used when the general reg is known be either '0' or '1' during combine.
821 ;; What we actually need is reg != 0 -> T, but we have only reg == 0 -> T.
822 ;; Due to interactions with other patterns, combine fails to pick the latter
823 ;; and invert the dependent logic.
824 (define_insn "*negtstsi"
825   [(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))]
826   "TARGET_SH1"
827   "cmp/pl       %0"
828    [(set_attr "type" "mt_group")])
830 ;; Some integer sign comparison patterns can be realized with the div0s insn.
831 ;;      div0s   Rm,Rn           T = (Rm >> 31) ^ (Rn >> 31)
832 (define_insn "cmp_div0s_0"
833   [(set (reg:SI T_REG)
834         (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
835                              (match_operand:SI 1 "arith_reg_operand" "r"))
836                      (const_int 31)))]
837   "TARGET_SH1"
838   "div0s        %0,%1"
839   [(set_attr "type" "arith")])
841 (define_insn "cmp_div0s_1"
842   [(set (reg:SI T_REG)
843         (lt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
844                        (match_operand:SI 1 "arith_reg_operand" "r"))
845                (const_int 0)))]
846   "TARGET_SH1"
847   "div0s        %0,%1"
848   [(set_attr "type" "arith")])
850 (define_insn_and_split "*cmp_div0s_0"
851   [(set (match_operand:SI 0 "arith_reg_dest" "")
852         (lshiftrt:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
853                              (match_operand:SI 2 "arith_reg_operand" ""))
854                      (const_int 31)))
855    (clobber (reg:SI T_REG))]
856   "TARGET_SH1"
857   "#"
858   "&& 1"
859   [(set (reg:SI T_REG)
860         (lshiftrt:SI (xor:SI (match_dup 1) (match_dup 2)) (const_int 31)))
861    (set (match_dup 0) (reg:SI T_REG))])
863 (define_insn_and_split "*cmp_div0s_1"
864   [(set (match_operand:SI 0 "arith_reg_dest" "")
865         (ge:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
866                        (match_operand:SI 2 "arith_reg_operand" ""))
867                (const_int 0)))
868    (clobber (reg:SI T_REG))]
869   "TARGET_SH1"
870   "#"
871   "&& can_create_pseudo_p ()"
872   [(const_int 0)]
873 ;; We have to go through the movnegt expander here which will handle the
874 ;; SH2A vs non-SH2A cases.
876   emit_insn (gen_cmp_div0s_1 (operands[1], operands[2]));
877   emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
878   DONE;
881 (define_insn_and_split "*cmp_div0s_1"
882   [(set (reg:SI T_REG)
883         (ge:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
884                        (match_operand:SI 1 "arith_reg_operand" ""))
885                (const_int 0)))]
886   "TARGET_SH1"
887   "#"
888   "&& can_create_pseudo_p ()"
889   [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 0) (match_dup 1))
890                               (const_int 0)))
891    (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
894 ;; -------------------------------------------------------------------------
895 ;; SImode compare and branch
896 ;; -------------------------------------------------------------------------
898 (define_expand "cbranchsi4"
899   [(set (pc)
900         (if_then_else (match_operator 0 "comparison_operator"
901                         [(match_operand:SI 1 "arith_operand" "")
902                          (match_operand:SI 2 "arith_operand" "")])
903                       (label_ref (match_operand 3 "" ""))
904                       (pc)))
905    (clobber (reg:SI T_REG))]
906   ""
908   if (TARGET_SHMEDIA)
909     emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
910                                            operands[2], operands[3]));
911   else
912     expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
914   DONE;
917 ;; Combine patterns to invert compare and branch operations for which we
918 ;; don't have actual comparison insns.  These patterns are used in cases
919 ;; which appear after the initial cbranchsi expansion, which also does
920 ;; some condition inversion.
922 (define_split
923   [(set (pc)
924         (if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "")
925                           (match_operand:SI 1 "arith_reg_or_0_operand" ""))
926                       (label_ref (match_operand 2))
927                       (pc)))
928    (clobber (reg:SI T_REG))]
929   "TARGET_SH1"
930   [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1)))
931    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
932                            (label_ref (match_dup 2))
933                            (pc)))])
935 ;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A
936 ;; and SH2A combine fails to simplify this pattern by itself.
937 ;; What this actually does is:
938 ;;      x == 0: (1 >> 0-0) & 1 = 1
939 ;;      x != 0: (1 >> 0-x) & 1 = 0
940 ;; Without this the test pr51244-8.c fails on SH2A and SH4A.
941 (define_split
942   [(set (pc)
943         (if_then_else
944           (eq (and:SI (lshiftrt:SI
945                         (const_int 1)
946                         (neg:SI (match_operand:SI 0 "arith_reg_operand" "")))
947                       (const_int 1))
948               (const_int 0))
949           (label_ref (match_operand 2))
950           (pc)))
951    (clobber (reg:SI T_REG))]
952   "TARGET_SH1"
953   [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))
954    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
955                            (label_ref (match_dup 2))
956                            (pc)))])
958 ;; FIXME: These could probably use code iterators for the compare op.
959 (define_split
960   [(set (pc)
961         (if_then_else (le (match_operand:SI 0 "arith_reg_operand" "")
962                           (match_operand:SI 1 "arith_reg_or_0_operand" ""))
963                       (label_ref (match_operand 2))
964                       (pc)))
965    (clobber (reg:SI T_REG))]
966   "TARGET_SH1"
967   [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1)))
968    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
969                            (label_ref (match_dup 2))
970                            (pc)))])
972 (define_split
973   [(set (pc)
974         (if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "")
975                           (match_operand:SI 1 "arith_reg_or_0_operand" ""))
976                       (label_ref (match_operand 2))
977                       (pc)))
978    (clobber (reg:SI T_REG))]
979   "TARGET_SH1"
980   [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1)))
981    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
982                            (label_ref (match_dup 2))
983                            (pc)))])
985 (define_split
986   [(set (pc)
987         (if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "")
988                            (match_operand:SI 1 "arith_reg_operand" ""))
989                       (label_ref (match_operand 2))
990                       (pc)))
991    (clobber (reg:SI T_REG))]
992   "TARGET_SH1"
993   [(set (reg:SI T_REG) (gtu:SI (match_dup 0) (match_dup 1)))
994    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
995                            (label_ref (match_dup 2))
996                            (pc)))])
998 (define_split
999   [(set (pc)
1000         (if_then_else (ltu (match_operand:SI 0 "arith_reg_operand" "")
1001                            (match_operand:SI 1 "arith_reg_operand" ""))
1002                       (label_ref (match_operand 2))
1003                       (pc)))
1004    (clobber (reg:SI T_REG))]
1005   "TARGET_SH1"
1006   [(set (reg:SI T_REG) (geu:SI (match_dup 0) (match_dup 1)))
1007    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1008                            (label_ref (match_dup 2))
1009                            (pc)))])
1011 ;; Compare and branch combine patterns for div0s comparisons.
1012 (define_insn_and_split "*cbranch_div0s"
1013   [(set (pc)
1014         (if_then_else (lt (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
1015                                   (match_operand:SI 1 "arith_reg_operand" ""))
1016                           (const_int 0))
1017                       (label_ref (match_operand 2))
1018                       (pc)))
1019    (clobber (reg:SI T_REG))]
1020   "TARGET_SH1"
1021   "#"
1022   "&& 1"
1023   [(set (reg:SI T_REG)
1024         (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1025    (set (pc)
1026         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1027                       (label_ref (match_dup 2))
1028                       (pc)))])
1030 (define_insn_and_split "*cbranch_div0s"
1031   [(set (pc)
1032         (if_then_else (ge (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
1033                                   (match_operand:SI 1 "arith_reg_operand" ""))
1034                           (const_int 0))
1035                       (label_ref (match_operand 2))
1036                       (pc)))
1037    (clobber (reg:SI T_REG))]
1038   "TARGET_SH1"
1039   "#"
1040   "&& 1"
1041   [(set (reg:SI T_REG)
1042         (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1043    (set (pc)
1044         (if_then_else (eq (reg:SI T_REG) (const_int 0))
1045                       (label_ref (match_dup 2))
1046                       (pc)))])
1048 ;; Conditional move combine pattern for div0s comparisons.
1049 ;; This is used when TARGET_PRETEND_CMOVE is in effect.
1050 (define_insn_and_split "*movsicc_div0s"
1051   [(set (match_operand:SI 0 "arith_reg_dest" "")
1052         (if_then_else:SI (ge (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
1053                                      (match_operand:SI 2 "arith_reg_operand" ""))
1054                              (const_int 0))
1055                          (match_operand:SI 3 "arith_reg_operand" "")
1056                          (match_operand:SI 4 "general_movsrc_operand" "")))
1057    (clobber (reg:SI T_REG))]
1058   "TARGET_PRETEND_CMOVE"
1059   "#"
1060   "&& 1"
1061   [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2))
1062                               (const_int 0)))
1063    (set (match_dup 0)
1064         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1065                       (match_dup 4)
1066                       (match_dup 3)))])
1068 ;; -------------------------------------------------------------------------
1069 ;; SImode unsigned integer comparisons
1070 ;; -------------------------------------------------------------------------
1072 ;; Usually comparisons of 'unsigned int >= 0' are optimized away completely.
1073 ;; However, especially when optimizations are off (e.g. -O0) such comparisons
1074 ;; might remain and we have to handle them.  If the '>= 0' case wasn't
1075 ;; handled here, something else would just load a '0' into the second operand
1076 ;; and do the comparison.  We can do slightly better by just setting the
1077 ;; T bit to '1'.
1078 (define_insn_and_split "cmpgeusi_t"
1079   [(set (reg:SI T_REG)
1080         (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1081                 (match_operand:SI 1 "arith_reg_or_0_operand" "r")))]
1082   "TARGET_SH1"
1083   "cmp/hs       %1,%0"
1084   "&& satisfies_constraint_Z (operands[1])"
1085   [(set (reg:SI T_REG) (const_int 1))]
1086   ""
1087   [(set_attr "type" "mt_group")])
1089 (define_insn "cmpgtusi_t"
1090   [(set (reg:SI T_REG)
1091         (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1092                 (match_operand:SI 1 "arith_reg_operand" "r")))]
1093   "TARGET_SH1"
1094   "cmp/hi       %1,%0"
1095   [(set_attr "type" "mt_group")])
1098 ;; -------------------------------------------------------------------------
1099 ;; DImode compare and branch
1100 ;; -------------------------------------------------------------------------
1103 ;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
1104 ;; Therefore, we aim to have a set of three branches that go straight to the
1105 ;; destination, i.e. only one of them is taken at any one time.
1106 ;; This mechanism should also be slightly better for the sh4-200.
1108 (define_expand "cbranchdi4"
1109   [(set (pc)
1110         (if_then_else (match_operator 0 "comparison_operator"
1111                         [(match_operand:DI 1 "arith_operand" "")
1112                          (match_operand:DI 2 "arith_operand" "")])
1113                       (label_ref (match_operand 3 "" ""))
1114                       (pc)))
1115    (clobber (match_dup 4))
1116    (clobber (reg:SI T_REG))]
1117   "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
1119   enum rtx_code comparison;
1121   if (TARGET_SHMEDIA)
1122     {
1123       emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
1124                                              operands[2], operands[3]));
1125       DONE;
1126     }
1128   else if (!TARGET_CBRANCHDI4)
1129     {
1130       sh_emit_compare_and_branch (operands, DImode);
1131       DONE;
1132     }
1134   else
1135     {
1136       if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
1137         DONE;
1139       comparison = prepare_cbranch_operands (operands, DImode,
1140                                              LAST_AND_UNUSED_RTX_CODE);
1141       if (comparison != GET_CODE (operands[0]))
1142         operands[0]
1143           = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
1144        operands[4] = gen_rtx_SCRATCH (SImode);
1145     }
1148 (define_insn_and_split "cbranchdi4_i"
1149   [(set (pc)
1150         (if_then_else (match_operator 0 "comparison_operator"
1151                         [(match_operand:DI 1 "arith_operand" "r,r")
1152                          (match_operand:DI 2 "arith_operand" "rN,I08")])
1153                       (label_ref (match_operand 3 "" ""))
1154                       (pc)))
1155    (clobber (match_scratch:SI 4 "=X,&r"))
1156    (clobber (reg:SI T_REG))]
1157   "TARGET_CBRANCHDI4"
1158   "#"
1159   "&& reload_completed"
1160   [(pc)]
1162   if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
1163     FAIL;
1164   DONE;
1167 ;; -------------------------------------------------------------------------
1168 ;; DImode signed integer comparisons
1169 ;; -------------------------------------------------------------------------
1171 (define_insn ""
1172   [(set (reg:SI T_REG)
1173         (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
1174                        (match_operand:DI 1 "arith_operand" "r"))
1175                (const_int 0)))]
1176   "TARGET_SH1"
1178   return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0",
1179                               insn, operands);
1181   [(set_attr "length" "6")
1182    (set_attr "type" "arith3b")])
1184 (define_insn "cmpeqdi_t"
1185   [(set (reg:SI T_REG)
1186         (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1187                (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
1188   "TARGET_SH1"
1190   static const char* alt[] =
1191   {
1192        "tst     %S0,%S0"        "\n"
1193     "   bf      0f"             "\n"
1194     "   tst     %R0,%R0"        "\n"
1195     "0:",
1197        "cmp/eq  %S1,%S0"        "\n"
1198     "   bf      0f"             "\n"
1199     "   cmp/eq  %R1,%R0"        "\n"
1200     "0:"
1201   };
1202   return alt[which_alternative];
1204   [(set_attr "length" "6")
1205    (set_attr "type" "arith3b")])
1207 (define_split
1208   [(set (reg:SI T_REG)
1209         (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
1210                (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
1211 ;; If we applied this split when not optimizing, it would only be
1212 ;; applied during the machine-dependent reorg, when no new basic blocks
1213 ;; may be created.
1214   "TARGET_SH1 && reload_completed && optimize"
1215   [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
1216    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1217                            (label_ref (match_dup 6))
1218                            (pc)))
1219    (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
1220    (match_dup 6)]
1222   operands[2] = gen_highpart (SImode, operands[0]);
1223   operands[3] = operands[1] == const0_rtx
1224                 ? const0_rtx
1225                 : gen_highpart (SImode, operands[1]);
1226   operands[4] = gen_lowpart (SImode, operands[0]);
1227   operands[5] = gen_lowpart (SImode, operands[1]);
1228   operands[6] = gen_label_rtx ();
1231 (define_insn "cmpgtdi_t"
1232   [(set (reg:SI T_REG)
1233         (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1234                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1235   "TARGET_SH2"
1237   static const char* alt[] =
1238   {
1239        "cmp/eq  %S1,%S0"        "\n"
1240     "   bf{.|/}s        0f"     "\n"
1241     "   cmp/gt  %S1,%S0"        "\n"
1242     "   cmp/hi  %R1,%R0"        "\n"
1243     "0:",
1245         "tst    %S0,%S0"        "\n"
1246     "   bf{.|/}s        0f"     "\n"
1247     "   cmp/pl  %S0"            "\n"
1248     "   cmp/hi  %S0,%R0"        "\n"
1249     "0:"
1250   };
1251   return alt[which_alternative];
1253   [(set_attr "length" "8")
1254    (set_attr "type" "arith3")])
1256 (define_insn "cmpgedi_t"
1257   [(set (reg:SI T_REG)
1258         (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1259                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1260   "TARGET_SH2"
1262   static const char* alt[] =
1263   {
1264        "cmp/eq  %S1,%S0"        "\n"
1265     "   bf{.|/}s        0f"     "\n"
1266     "   cmp/ge  %S1,%S0"        "\n"
1267     "   cmp/hs  %R1,%R0"        "\n"
1268     "0:",
1270        "cmp/pz  %S0"
1271   };
1272   return alt[which_alternative];
1274   [(set_attr "length" "8,2")
1275    (set_attr "type" "arith3,mt_group")])
1277 ;; -------------------------------------------------------------------------
1278 ;; DImode unsigned integer comparisons
1279 ;; -------------------------------------------------------------------------
1281 (define_insn "cmpgeudi_t"
1282   [(set (reg:SI T_REG)
1283         (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1284                 (match_operand:DI 1 "arith_reg_operand" "r")))]
1285   "TARGET_SH2"
1287   return       "cmp/eq  %S1,%S0"        "\n"
1288          "      bf{.|/}s        0f"     "\n"
1289          "      cmp/hs  %S1,%S0"        "\n"
1290          "      cmp/hs  %R1,%R0"        "\n"
1291          "0:";
1293   [(set_attr "length" "8")
1294    (set_attr "type" "arith3")])
1296 (define_insn "cmpgtudi_t"
1297   [(set (reg:SI T_REG)
1298         (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1299                 (match_operand:DI 1 "arith_reg_operand" "r")))]
1300   "TARGET_SH2"
1302   return       "cmp/eq  %S1,%S0"        "\n"
1303          "      bf{.|/}s        0f"     "\n"
1304          "      cmp/hi  %S1,%S0"        "\n"
1305          "      cmp/hi  %R1,%R0"        "\n"
1306          "0:";
1308   [(set_attr "length" "8")
1309    (set_attr "type" "arith3")])
1311 (define_insn "cmpeqsi_media"
1312   [(set (match_operand:SI 0 "register_operand" "=r")
1313         (eq:SI (match_operand:SI 1 "logical_operand" "%r")
1314                (match_operand:SI 2 "cmp_operand" "Nr")))]
1315   "TARGET_SHMEDIA"
1316   "cmpeq        %1, %N2, %0"
1317   [(set_attr "type" "cmp_media")])
1319 (define_insn "cmpeqdi_media"
1320   [(set (match_operand:SI 0 "register_operand" "=r")
1321         (eq:SI (match_operand:DI 1 "register_operand" "%r")
1322                (match_operand:DI 2 "cmp_operand" "Nr")))]
1323   "TARGET_SHMEDIA"
1324   "cmpeq        %1, %N2, %0"
1325   [(set_attr "type" "cmp_media")])
1327 (define_insn "cmpgtsi_media"
1328   [(set (match_operand:SI 0 "register_operand" "=r")
1329         (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
1330                (match_operand:SI 2 "cmp_operand" "rN")))]
1331   "TARGET_SHMEDIA"
1332   "cmpgt        %N1, %N2, %0"
1333   [(set_attr "type" "cmp_media")])
1335 (define_insn "cmpgtdi_media"
1336   [(set (match_operand:SI 0 "register_operand" "=r")
1337         (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1338                (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1339   "TARGET_SHMEDIA"
1340   "cmpgt        %N1, %N2, %0"
1341   [(set_attr "type" "cmp_media")])
1343 (define_insn "cmpgtusi_media"
1344   [(set (match_operand:SI 0 "register_operand" "=r")
1345         (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
1346                 (match_operand:SI 2 "cmp_operand" "rN")))]
1347   "TARGET_SHMEDIA"
1348   "cmpgtu       %N1, %N2, %0"
1349   [(set_attr "type" "cmp_media")])
1351 (define_insn "cmpgtudi_media"
1352   [(set (match_operand:SI 0 "register_operand" "=r")
1353         (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1354                 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1355   "TARGET_SHMEDIA"
1356   "cmpgtu       %N1, %N2, %0"
1357   [(set_attr "type" "cmp_media")])
1359 ; This pattern is for combine.
1360 (define_insn "*cmpne0sisi_media"
1361   [(set (match_operand:SI 0 "register_operand" "=r")
1362         (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
1363   "TARGET_SHMEDIA"
1364   "cmpgtu       %1,r63,%0"
1365   [(set_attr "type" "cmp_media")])
1367 ;; -------------------------------------------------------------------------
1368 ;; Conditional move instructions
1369 ;; -------------------------------------------------------------------------
1371 ;; The insn names may seem reversed, but note that cmveq performs the move
1372 ;; if op1 == 0, and cmvne does it if op1 != 0.
1374 (define_insn "movdicc_false"
1375   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1376         (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
1377                              (const_int 0))
1378          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1379          (match_operand:DI 3 "arith_reg_operand" "0")))]
1380   "TARGET_SHMEDIA"
1381   "cmveq        %1, %N2, %0"
1382   [(set_attr "type" "arith_media")])
1384 (define_insn "movdicc_true"
1385   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1386         (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
1387                              (const_int 0))
1388          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1389          (match_operand:DI 3 "arith_reg_operand" "0")))]
1390   "TARGET_SHMEDIA"
1391   "cmvne        %1, %N2, %0"
1392   [(set_attr "type" "arith_media")])
1394 (define_peephole2
1395   [(set (match_operand:DI 0 "arith_reg_dest" "")
1396         (if_then_else:DI (match_operator 3 "equality_comparison_operator"
1397                            [(match_operand:DI 1 "arith_reg_operand" "")
1398                             (const_int 0)])
1399          (match_operand:DI 2 "arith_reg_dest" "")
1400          (match_dup 0)))
1401    (set (match_dup 2) (match_dup 0))]
1402   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1403   [(set (match_dup 2)
1404         (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
1406   operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1407                                 VOIDmode, operands[1], CONST0_RTX (DImode));
1410 (define_peephole2
1411   [(set (match_operand:DI 0 "general_movdst_operand" "")
1412         (match_operand:DI 1 "arith_reg_or_0_operand" ""))
1413    (set (match_operand:DI 2 "arith_reg_dest" "")
1414         (if_then_else:DI (match_operator 4 "equality_comparison_operator"
1415                            [(match_operand:DI 3 "arith_reg_operand" "")
1416                             (const_int 0)])
1417          (match_dup 0)
1418          (match_dup 2)))]
1419   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1420   [(set (match_dup 2)
1421         (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
1422   "")
1424 (define_expand "movdicc"
1425   [(set (match_operand:DI 0 "register_operand" "")
1426         (if_then_else:DI (match_operand 1 "comparison_operator" "")
1427                          (match_operand:DI 2 "register_operand" "")
1428                          (match_operand:DI 3 "register_operand" "")))]
1429   "TARGET_SHMEDIA"
1431   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1432       && GET_MODE (XEXP (operands[1], 0)) == DImode
1433       && XEXP (operands[1], 1) == const0_rtx)
1434     ;
1435   else
1436     {
1437       if (!can_create_pseudo_p ())
1438         FAIL;
1440       operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1441                                               GET_CODE (operands[1]),
1442                                               XEXP (operands[1], 0),
1443                                               XEXP (operands[1], 1));
1444       if (!operands[1])
1445         FAIL;
1446     }
1449 ;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1450 ;; SImode to DImode.
1451 (define_insn "movsicc_false"
1452   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1453         (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1454                           (const_int 0))
1455          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1456          (match_operand:SI 3 "arith_reg_operand" "0")))]
1457   "TARGET_SHMEDIA"
1458   "cmveq        %1, %N2, %0"
1459   [(set_attr "type" "arith_media")])
1461 (define_insn "movsicc_true"
1462   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1463         (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1464                           (const_int 0))
1465          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1466          (match_operand:SI 3 "arith_reg_operand" "0")))]
1467   "TARGET_SHMEDIA"
1468   "cmvne        %1, %N2, %0"
1469   [(set_attr "type" "arith_media")])
1471 (define_peephole2
1472   [(set (match_operand:SI 0 "arith_reg_dest" "")
1473         (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1474                            [(match_operand:SI 1 "arith_reg_operand" "")
1475                             (const_int 0)])
1476          (match_operand:SI 2 "arith_reg_dest" "")
1477          (match_dup 0)))
1478    (set (match_dup 2) (match_dup 0))]
1479   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1480   [(set (match_dup 2)
1481         (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1483   operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1484                                 VOIDmode, operands[1], CONST0_RTX (SImode));
1487 (define_peephole2
1488   [(set (match_operand:SI 0 "general_movdst_operand" "")
1489         (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1490    (set (match_operand:SI 2 "arith_reg_dest" "")
1491         (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1492                            [(match_operand:SI 3 "arith_reg_operand" "")
1493                             (const_int 0)])
1494          (match_dup 0)
1495          (match_dup 2)))]
1496   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1497    && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1498   [(set (match_dup 2)
1499         (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1501   replace_rtx (operands[4], operands[0], operands[1]);
1504 (define_peephole2
1505   [(set (match_operand 0 "any_register_operand" "")
1506         (match_operand 1 "any_register_operand" ""))
1507    (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1508    (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1509   "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1510     <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1511    && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1512    && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1513    && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1514    && ! reg_overlap_mentioned_p (operands[0], operands[3])
1515    && ! reg_overlap_mentioned_p (operands[2], operands[0])
1516    && ! reg_overlap_mentioned_p (operands[0], operands[1])
1517    && (REGNO_REG_CLASS (REGNO (operands[0]))
1518        == REGNO_REG_CLASS (REGNO (operands[2])))
1519    && (REGNO_REG_CLASS (REGNO (operands[1]))
1520        == REGNO_REG_CLASS (REGNO (operands[0])))"
1521   [(set (match_dup 0) (match_dup 3))
1522    (set (match_dup 4) (match_dup 5))]
1524   rtx set1, set2, insn2;
1525   rtx replacements[4];
1527   /* We want to replace occurrences of operands[0] with operands[1] and
1528      operands[2] with operands[0] in operands[4]/operands[5].
1529      Doing just two replace_rtx calls naively would result in the second
1530      replacement undoing all that the first did if operands[1] and operands[2]
1531      are identical, so we must do this simultaneously.  */
1532   replacements[0] = operands[0];
1533   replacements[1] = operands[1];
1534   replacements[2] = operands[2];
1535   replacements[3] = operands[0];
1536   if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1537       || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1538       || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1539     FAIL;
1541   operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1542   replace_n_hard_rtx (operands[4], replacements, 2, 1);
1543   operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1544   /* The operands array is aliased to recog_data.operand, which gets
1545      clobbered by extract_insn, so finish with it now.  */
1546   set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1547   set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1548   /* ??? The last insn might be a jump insn, but the generic peephole2 code
1549      always uses emit_insn.  */
1550   /* Check that we don't violate matching constraints or earlyclobbers.  */
1551   extract_insn (emit_insn (set1));
1552   if (! constrain_operands (1))
1553     goto failure;
1554   insn2 = emit (set2);
1555   if (GET_CODE (insn2) == BARRIER)
1556     goto failure;
1557   extract_insn (insn2);
1558   if (! constrain_operands (1))
1559     {
1560       rtx tmp;
1561     failure:
1562       tmp = replacements[0];
1563       replacements[0] = replacements[1];
1564       replacements[1] = tmp;
1565       tmp = replacements[2];
1566       replacements[2] = replacements[3];
1567       replacements[3] = tmp;
1568       replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1569       replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1570       replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1571       FAIL;
1572     }
1573   DONE;
1576 ;; The register allocator is rather clumsy in handling multi-way conditional
1577 ;; moves, so allow the combiner to make them, and we split them up after
1578 ;; reload.  */
1579 (define_insn_and_split "*movsicc_umin"
1580   [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1581         (umin:SI (if_then_else:SI
1582                    (eq (match_operand:SI 1 "arith_reg_operand" "r")
1583                        (const_int 0))
1584                    (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1585                    (match_operand:SI 3 "register_operand" "0"))
1586                  (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1587    (clobber (match_scratch:SI 5 "=&r"))]
1588   "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1589   "#"
1590   "TARGET_SHMEDIA && reload_completed"
1591   [(pc)]
1593   emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1594                                 operands[3]));
1595   emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1596   emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1597                                 operands[0]));
1598   DONE;
1601 (define_insn "*movsicc_t_false"
1602   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1603         (if_then_else (eq (reg:SI T_REG) (const_int 0))
1604                       (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1605                       (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1606   "TARGET_PRETEND_CMOVE
1607    && (arith_reg_operand (operands[1], SImode)
1608        || (immediate_operand (operands[1], SImode)
1609            && satisfies_constraint_I08 (operands[1])))"
1611   return       "bt      0f"     "\n"
1612          "      mov     %1,%0"  "\n"
1613          "0:";
1615   [(set_attr "type" "mt_group,arith") ;; poor approximation
1616    (set_attr "length" "4")])
1618 (define_insn "*movsicc_t_true"
1619   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1620         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1621                       (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1622                       (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1623   "TARGET_PRETEND_CMOVE
1624    && (arith_reg_operand (operands[1], SImode)
1625        || (immediate_operand (operands[1], SImode)
1626            && satisfies_constraint_I08 (operands[1])))"
1628   return       "bf      0f"     "\n"
1629          "      mov     %1,%0"  "\n"
1630          "0:";
1632   [(set_attr "type" "mt_group,arith") ;; poor approximation
1633    (set_attr "length" "4")])
1635 (define_expand "movsicc"
1636   [(set (match_operand:SI 0 "arith_reg_dest" "")
1637         (if_then_else:SI (match_operand 1 "comparison_operator" "")
1638                          (match_operand:SI 2 "arith_reg_or_0_operand" "")
1639                          (match_operand:SI 3 "arith_reg_operand" "")))]
1640   "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1642   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1643       && GET_MODE (XEXP (operands[1], 0)) == SImode
1644       && (TARGET_SHMEDIA
1645           || (REG_P (XEXP (operands[1], 0))
1646               && REGNO (XEXP (operands[1], 0)) == T_REG))
1647       && XEXP (operands[1], 1) == const0_rtx)
1648     ;
1650   else if (TARGET_PRETEND_CMOVE)
1651     {
1652       enum rtx_code code = GET_CODE (operands[1]);
1653       enum rtx_code new_code = code;
1654       rtx op0 = XEXP (operands[1], 0);
1655       rtx op1 = XEXP (operands[1], 1);
1657       if (! currently_expanding_to_rtl)
1658         FAIL;
1659       switch (code)
1660         {
1661         case LT: case LE: case LEU: case LTU:
1662           if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1663             break;
1664         case NE:
1665           new_code = reverse_condition (code);
1666           break;
1667         case EQ: case GT: case GE: case GEU: case GTU:
1668           break;
1669         default:
1670           FAIL;
1671         }
1672       sh_emit_scc_to_t (new_code, op0, op1);
1673       operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1674                                     gen_rtx_REG (SImode, T_REG), const0_rtx);
1675     }
1676   else
1677     {
1678       if (!can_create_pseudo_p ())
1679         FAIL;
1681       operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1682                                               GET_CODE (operands[1]),
1683                                               XEXP (operands[1], 0),
1684                                               XEXP (operands[1], 1));
1685       if (!operands[1])
1686         FAIL;
1687     }
1690 (define_expand "movqicc"
1691   [(set (match_operand:QI 0 "register_operand" "")
1692         (if_then_else:QI (match_operand 1 "comparison_operator" "")
1693                          (match_operand:QI 2 "register_operand" "")
1694                          (match_operand:QI 3 "register_operand" "")))]
1695   "TARGET_SHMEDIA"
1697   operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1698   operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1699   operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1700   emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1701   DONE;
1704 ;; -------------------------------------------------------------------------
1705 ;; Addition instructions
1706 ;; -------------------------------------------------------------------------
1708 (define_expand "adddi3"
1709   [(set (match_operand:DI 0 "arith_reg_operand" "")
1710         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1711                  (match_operand:DI 2 "arith_operand" "")))]
1712   ""
1714   if (TARGET_SH1)
1715     {
1716       if (!can_create_pseudo_p () && ! arith_reg_operand (operands[2], DImode))
1717         FAIL;
1718       operands[2] = force_reg (DImode, operands[2]);
1719       emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1720       DONE;
1721     }
1724 (define_insn "*adddi3_media"
1725   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1726         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1727                  (match_operand:DI 2 "arith_operand" "r,I10")))]
1728   "TARGET_SHMEDIA"
1729   "@
1730         add     %1, %2, %0
1731         addi    %1, %2, %0"
1732   [(set_attr "type" "arith_media")])
1734 (define_insn "*adddisi3_media"
1735   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1736         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1737                  (match_operand:DI 2 "arith_operand" "r,I10")))]
1738   "TARGET_SHMEDIA"
1739   "@
1740         add.l   %1, %2, %0
1741         addi.l  %1, %2, %0"
1742   [(set_attr "type" "arith_media")
1743    (set_attr "highpart" "ignore")])
1745 (define_insn "adddi3z_media"
1746   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1747         (zero_extend:DI
1748          (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1749                   (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1750   "TARGET_SHMEDIA"
1751   "addz.l       %1, %N2, %0"
1752   [(set_attr "type" "arith_media")
1753    (set_attr "highpart" "ignore")])
1755 (define_insn_and_split "adddi3_compact"
1756   [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1757         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1758                  (match_operand:DI 2 "arith_reg_operand" "r")))
1759    (clobber (reg:SI T_REG))]
1760   "TARGET_SH1"
1761   "#"
1762   "&& reload_completed"
1763   [(const_int 0)]
1765   rtx high0 = gen_highpart (SImode, operands[0]);
1766   rtx high2 = gen_highpart (SImode, operands[2]);
1767   rtx low0 = gen_lowpart (SImode, operands[0]);
1769   emit_insn (gen_clrt ());
1770   emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
1771   emit_insn (gen_addc (high0, high0, high2));
1772   DONE;
1775 (define_insn "addc"
1776   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1777         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1778                           (match_operand:SI 2 "arith_reg_operand" "r"))
1779                  (reg:SI T_REG)))
1780    (set (reg:SI T_REG)
1781         (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1782   "TARGET_SH1"
1783   "addc %2,%0"
1784   [(set_attr "type" "arith")])
1786 ;; A simplified version of the addc insn, where the exact value of the
1787 ;; T bit doesn't matter.  This is easier for combine to pick up.
1788 ;; We allow a reg or 0 for one of the operands in order to be able to
1789 ;; do 'reg + T' sequences.  Reload will load the constant 0 into the reg
1790 ;; as needed.
1791 (define_insn "*addc"
1792   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1793         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1794                           (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
1795                  (match_operand:SI 3 "t_reg_operand" "")))
1796    (clobber (reg:SI T_REG))]
1797   "TARGET_SH1"
1798   "addc %2,%0"
1799   [(set_attr "type" "arith")])
1801 ;; Split 'reg + reg + 1' into a sett addc sequence, as it can be scheduled
1802 ;; better, if the sett insn can be done early.
1803 (define_insn_and_split "*addc"
1804   [(set (match_operand:SI 0 "arith_reg_dest" "")
1805         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
1806                           (match_operand:SI 2 "arith_reg_operand" ""))
1807                  (const_int 1)))
1808    (clobber (reg:SI T_REG))]
1809   "TARGET_SH1"
1810   "#"
1811   "&& 1"
1812   [(set (reg:SI T_REG) (const_int 1))
1813    (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
1814                                           (reg:SI T_REG)))
1815               (clobber (reg:SI T_REG))])])
1817 ;; Left shifts by one are usually done with an add insn to avoid T_REG
1818 ;; clobbers.  Thus addc can also be used to do something like '(x << 1) + 1'.
1819 (define_insn_and_split "*addc"
1820   [(set (match_operand:SI 0 "arith_reg_dest")
1821         (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
1822                           (const_int 2))
1823                  (const_int 1)))
1824    (clobber (reg:SI T_REG))]
1825   "TARGET_SH1"
1826   "#"
1827   "&& 1"
1828   [(set (reg:SI T_REG) (const_int 1))
1829    (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 1))
1830                                           (reg:SI T_REG)))
1831               (clobber (reg:SI T_REG))])])
1833 ;; Sometimes combine will try to do 'reg + (0-reg) + 1' if the *addc pattern
1834 ;; matched.  Split this up into a simple sub add sequence, as this will save
1835 ;; us one sett insn.
1836 (define_insn_and_split "*minus_plus_one"
1837   [(set (match_operand:SI 0 "arith_reg_dest" "")
1838         (plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
1839                            (match_operand:SI 2 "arith_reg_operand" ""))
1840                  (const_int 1)))]
1841   "TARGET_SH1"
1842   "#"
1843   "&& 1"
1844   [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1845    (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))])
1847 ;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn.
1848 ;; If the 0 constant can be CSE-ed, this becomes a one instruction
1849 ;; operation, as opposed to sequences such as
1850 ;;      movt    r2
1851 ;;      add     r2,r3
1853 ;; Even if the constant is not CSE-ed, a sequence such as
1854 ;;      mov     #0,r2
1855 ;;      addc    r2,r3
1856 ;; can be scheduled much better since the load of the constant can be
1857 ;; done earlier, before any comparison insns that store the result in
1858 ;; the T bit.
1859 (define_insn_and_split "*addc"
1860   [(set (match_operand:SI 0 "arith_reg_dest" "")
1861         (plus:SI (match_operand:SI 1 "t_reg_operand" "")
1862                  (match_operand:SI 2 "arith_reg_operand" "")))
1863    (clobber (reg:SI T_REG))]
1864   "TARGET_SH1"
1865   "#"
1866   "&& 1"
1867   [(parallel [(set (match_dup 0)
1868                    (plus:SI (plus:SI (match_dup 2) (const_int 0))
1869                             (match_dup 1)))
1870               (clobber (reg:SI T_REG))])])
1872 (define_expand "addsi3"
1873   [(set (match_operand:SI 0 "arith_reg_operand" "")
1874         (plus:SI (match_operand:SI 1 "arith_operand" "")
1875                  (match_operand:SI 2 "arith_operand" "")))]
1876   ""
1878   if (TARGET_SHMEDIA)
1879     operands[1] = force_reg (SImode, operands[1]);
1882 (define_insn "addsi3_media"
1883   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1884         (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1885                  (match_operand:SI 2 "arith_operand" "r,I10")))]
1886   "TARGET_SHMEDIA"
1887   "@
1888         add.l   %1, %2, %0
1889         addi.l  %1, %2, %0"
1890   [(set_attr "type" "arith_media")
1891    (set_attr "highpart" "ignore")])
1893 (define_insn "addsidi3_media"
1894   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1895         (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
1896                                   "%r,r")
1897                                  (match_operand:SI 2 "arith_operand"
1898                                   "r,I10"))))]
1899   "TARGET_SHMEDIA"
1900   "@
1901         add.l   %1, %2, %0
1902         addi.l  %1, %2, %0"
1903   [(set_attr "type" "arith_media")
1904    (set_attr "highpart" "ignore")])
1906 (define_insn "*addsi3_compact"
1907   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1908         (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1909                  (match_operand:SI 2 "arith_operand" "rI08")))]
1910   "TARGET_SH1"
1911   "add  %2,%0"
1912   [(set_attr "type" "arith")])
1914 ;; -------------------------------------------------------------------------
1915 ;; Subtraction instructions
1916 ;; -------------------------------------------------------------------------
1918 (define_expand "subdi3"
1919   [(set (match_operand:DI 0 "arith_reg_operand" "")
1920         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1921                   (match_operand:DI 2 "arith_reg_operand" "")))]
1922   ""
1924   if (TARGET_SH1)
1925     {
1926       operands[1] = force_reg (DImode, operands[1]);
1927       emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1928       DONE;
1929     }
1932 (define_insn "*subdi3_media"
1933   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1934         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1935                   (match_operand:DI 2 "arith_reg_operand" "r")))]
1936   "TARGET_SHMEDIA"
1937   "sub  %N1, %2, %0"
1938   [(set_attr "type" "arith_media")])
1939   
1940 (define_insn "subdisi3_media"
1941   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
1942         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1943                   (match_operand:DI 2 "arith_reg_operand" "r")))]
1944   "TARGET_SHMEDIA"
1945   "sub.l        %N1, %2, %0"
1946   [(set_attr "type" "arith_media")
1947    (set_attr "highpart" "ignore")])
1949 (define_insn_and_split "subdi3_compact"
1950   [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1951         (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1952                  (match_operand:DI 2 "arith_reg_operand" "r")))
1953    (clobber (reg:SI T_REG))]
1954   "TARGET_SH1"
1955   "#"
1956   "&& reload_completed"
1957   [(const_int 0)]
1959   rtx high0 = gen_highpart (SImode, operands[0]);
1960   rtx high2 = gen_highpart (SImode, operands[2]);
1961   rtx low0 = gen_lowpart (SImode, operands[0]);
1963   emit_insn (gen_clrt ());
1964   emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1965   emit_insn (gen_subc (high0, high0, high2));
1966   DONE;
1969 (define_insn "subc"
1970   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1971         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1972                             (match_operand:SI 2 "arith_reg_operand" "r"))
1973                   (reg:SI T_REG)))
1974    (set (reg:SI T_REG)
1975         (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1976                           (reg:SI T_REG))
1977                 (match_dup 1)))]
1978   "TARGET_SH1"
1979   "subc %2,%0"
1980   [(set_attr "type" "arith")])
1982 ;; A simplified version of the subc insn, where the exact value of the
1983 ;; T bit doesn't matter.  This is easier for combine to pick up.
1984 ;; We allow a reg or 0 for one of the operands in order to be able to
1985 ;; do 'reg - T' sequences.  Reload will load the constant 0 into the reg
1986 ;; as needed.
1987 (define_insn "*subc"
1988   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1989         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1990                             (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
1991                   (match_operand:SI 3 "t_reg_operand" "")))
1992    (clobber (reg:SI T_REG))]
1993   "TARGET_SH1"
1994   "subc %2,%0"
1995   [(set_attr "type" "arith")])
1997 ;; Split reg - reg - 1 into a sett subc sequence, as it can be scheduled
1998 ;; better, if the sett insn can be done early.
1999 ;; Notice that combine turns 'a - b - 1' into 'a + (~b)'.
2000 (define_insn_and_split "*subc"
2001   [(set (match_operand:SI 0 "arith_reg_dest" "")
2002         (plus:SI (not:SI (match_operand:SI 1 "arith_reg_operand" ""))
2003                  (match_operand:SI 2 "arith_reg_operand" "")))
2004    (clobber (reg:SI T_REG))]
2005   "TARGET_SH1"
2006   "#"
2007   "&& 1"
2008   [(set (reg:SI T_REG) (const_int 1))
2009    (parallel [(set (match_dup 0)
2010                    (minus:SI (minus:SI (match_dup 2) (match_dup 1))
2011                              (reg:SI T_REG)))
2012               (clobber (reg:SI T_REG))])])
2014 ;; Split 'reg - T' into 'reg - 0 - T' to utilize the subc insn.
2015 ;; If the 0 constant can be CSE-ed, this becomes a one instruction
2016 ;; operation, as opposed to sequences such as
2017 ;;      movt    r2
2018 ;;      sub     r2,r3
2020 ;; Even if the constant is not CSE-ed, a sequence such as
2021 ;;      mov     #0,r2
2022 ;;      subc    r2,r3
2023 ;; can be scheduled much better since the load of the constant can be
2024 ;; done earlier, before any comparison insns that store the result in
2025 ;; the T bit.
2026 (define_insn_and_split "*subc"
2027   [(set (match_operand:SI 0 "arith_reg_dest" "")
2028         (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
2029                   (match_operand:SI 2 "t_reg_operand" "")))
2030    (clobber (reg:SI T_REG))]
2031   "TARGET_SH1"
2032   "#"
2033   "&& 1"
2034   [(parallel [(set (match_dup 0)
2035                    (minus:SI (minus:SI (match_dup 1) (const_int 0))
2036                              (match_dup 2)))
2037               (clobber (reg:SI T_REG))])])
2039 (define_insn "*subsi3_internal"
2040   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2041         (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2042                   (match_operand:SI 2 "arith_reg_operand" "r")))]
2043   "TARGET_SH1"
2044   "sub  %2,%0"
2045   [(set_attr "type" "arith")])
2047 (define_insn_and_split "*subsi3_media"
2048   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2049         (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
2050                   (match_operand:SI 2 "extend_reg_operand" "r")))]
2051   "TARGET_SHMEDIA
2052    && (operands[1] != constm1_rtx
2053        || (GET_CODE (operands[2]) != TRUNCATE
2054            && GET_CODE (operands[2]) != SUBREG))"
2055   "sub.l        %N1, %2, %0"
2056   "operands[1] == constm1_rtx"
2057   [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
2058   ""
2059   [(set_attr "type" "arith_media")
2060    (set_attr "highpart" "ignore")])
2062 (define_split
2063   [(set (match_operand:SI 0 "arith_reg_dest" "")
2064         (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2065                                                        "general_extend_operand"
2066                                                        "") 0)) 0)))]
2067   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
2068   [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2069    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2070   "")
2072 (define_split
2073   [(set (match_operand:SI 0 "arith_reg_dest" "")
2074         (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2075                                                        "general_extend_operand"
2076                                                        "") 0)) 3)))]
2077   "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
2078   [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2079    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2080   "")
2081 ;; Convert `constant - reg' to `neg rX; add rX, #const' since this
2082 ;; will sometimes save one instruction.  Otherwise we might get
2083 ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
2084 ;; are the same.
2086 (define_expand "subsi3"
2087   [(set (match_operand:SI 0 "arith_reg_operand" "")
2088         (minus:SI (match_operand:SI 1 "arith_operand" "")
2089                   (match_operand:SI 2 "arith_reg_operand" "")))]
2090   ""
2092   if (TARGET_SH1 && CONST_INT_P (operands[1]))
2093     {
2094       emit_insn (gen_negsi2 (operands[0], operands[2]));
2095       emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
2096       DONE;
2097     }
2098   if (TARGET_SHMEDIA)
2099     {
2100       if (!can_create_pseudo_p ()
2101           && ! arith_reg_or_0_operand (operands[1], SImode))
2102         FAIL;
2103       if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
2104         operands[1] = force_reg (SImode, operands[1]);
2105     }
2108 ;; -------------------------------------------------------------------------
2109 ;; Division instructions
2110 ;; -------------------------------------------------------------------------
2112 ;; We take advantage of the library routines which don't clobber as many
2113 ;; registers as a normal function call would.
2115 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
2116 ;; also has an effect on the register that holds the address of the sfunc.
2117 ;; To make this work, we have an extra dummy insn that shows the use
2118 ;; of this register for reorg.
2120 (define_insn "use_sfunc_addr"
2121   [(set (reg:SI PR_REG)
2122         (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
2123   "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
2124   ""
2125   [(set_attr "length" "0")])
2127 (define_insn "udivsi3_sh2a"
2128   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2129         (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
2130                 (match_operand:SI 2 "arith_reg_operand" "z")))]
2131   "TARGET_SH2A"
2132   "divu %2,%1"
2133   [(set_attr "type" "arith")
2134    (set_attr "in_delay_slot" "no")])
2136 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
2137 ;; hard register 0.  If we used hard register 0, then the next instruction
2138 ;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
2139 ;; gets allocated to a stack slot that needs its address reloaded, then
2140 ;; there is nothing to prevent reload from using r0 to reload the address.
2141 ;; This reload would clobber the value in r0 we are trying to store.
2142 ;; If we let reload allocate r0, then this problem can never happen.
2144 (define_insn "udivsi3_i1"
2145   [(set (match_operand:SI 0 "register_operand" "=z")
2146         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2147    (clobber (reg:SI T_REG))
2148    (clobber (reg:SI PR_REG))
2149    (clobber (reg:SI R4_REG))
2150    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2151   "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
2152   "jsr  @%1%#"
2153   [(set_attr "type" "sfunc")
2154    (set_attr "needs_delay_slot" "yes")])
2156 ; Since shmedia-nofpu code could be linked against shcompact code, and
2157 ; the udivsi3 libcall has the same name, we must consider all registers
2158 ; clobbered that are in the union of the registers clobbered by the
2159 ; shmedia and the shcompact implementation.  Note, if the shcompact
2160 ; implementation actually used shcompact code, we'd need to clobber
2161 ; also r23 and fr23.
2162 (define_insn "udivsi3_i1_media"
2163   [(set (match_operand:SI 0 "register_operand" "=z")
2164         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2165    (clobber (reg:SI T_MEDIA_REG))
2166    (clobber (reg:SI PR_MEDIA_REG))
2167    (clobber (reg:SI R20_REG))
2168    (clobber (reg:SI R21_REG))
2169    (clobber (reg:SI R22_REG))
2170    (clobber (reg:DI TR0_REG))
2171    (clobber (reg:DI TR1_REG))
2172    (clobber (reg:DI TR2_REG))
2173    (use (match_operand 1 "target_reg_operand" "b"))]
2174   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2175   "blink        %1, r18"
2176   [(set_attr "type" "sfunc")
2177    (set_attr "needs_delay_slot" "yes")])
2179 (define_expand "udivsi3_i4_media"
2180   [(set (match_dup 3)
2181         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
2182    (set (match_dup 4)
2183         (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
2184    (set (match_dup 5) (float:DF (match_dup 3)))
2185    (set (match_dup 6) (float:DF (match_dup 4)))
2186    (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
2187    (set (match_dup 8) (fix:DI (match_dup 7)))
2188    (set (match_operand:SI 0 "register_operand" "")
2189         (truncate:SI (match_dup 8)))]
2190   "TARGET_SHMEDIA_FPU"
2192   operands[3] = gen_reg_rtx (DImode);
2193   operands[4] = gen_reg_rtx (DImode);
2194   operands[5] = gen_reg_rtx (DFmode);
2195   operands[6] = gen_reg_rtx (DFmode);
2196   operands[7] = gen_reg_rtx (DFmode);
2197   operands[8] = gen_reg_rtx (DImode);
2200 (define_insn "udivsi3_i4"
2201   [(set (match_operand:SI 0 "register_operand" "=y")
2202         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2203    (clobber (reg:SI T_REG))
2204    (clobber (reg:SI PR_REG))
2205    (clobber (reg:DF DR0_REG))
2206    (clobber (reg:DF DR2_REG))
2207    (clobber (reg:DF DR4_REG))
2208    (clobber (reg:SI R0_REG))
2209    (clobber (reg:SI R1_REG))
2210    (clobber (reg:SI R4_REG))
2211    (clobber (reg:SI R5_REG))
2212    (use (reg:PSI FPSCR_REG))
2213    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2214   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
2215   "jsr  @%1%#"
2216   [(set_attr "type" "sfunc")
2217    (set_attr "fp_mode" "double")
2218    (set_attr "needs_delay_slot" "yes")])
2220 (define_insn "udivsi3_i4_single"
2221   [(set (match_operand:SI 0 "register_operand" "=y")
2222         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2223    (clobber (reg:SI T_REG))
2224    (clobber (reg:SI PR_REG))
2225    (clobber (reg:DF DR0_REG))
2226    (clobber (reg:DF DR2_REG))
2227    (clobber (reg:DF DR4_REG))
2228    (clobber (reg:SI R0_REG))
2229    (clobber (reg:SI R1_REG))
2230    (clobber (reg:SI R4_REG))
2231    (clobber (reg:SI R5_REG))
2232    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2233   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
2234   "jsr  @%1%#"
2235   [(set_attr "type" "sfunc")
2236    (set_attr "needs_delay_slot" "yes")])
2238 (define_insn "udivsi3_i4_int"
2239   [(set (match_operand:SI 0 "register_operand" "=z")
2240         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2241    (clobber (reg:SI T_REG))
2242    (clobber (reg:SI R1_REG))
2243    (clobber (reg:SI PR_REG))
2244    (clobber (reg:SI MACH_REG))
2245    (clobber (reg:SI MACL_REG))
2246    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2247   "TARGET_SH1"
2248   "jsr  @%1%#"
2249   [(set_attr "type" "sfunc")
2250    (set_attr "needs_delay_slot" "yes")])
2253 (define_expand "udivsi3"
2254   [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
2255    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2256    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2257    (parallel [(set (match_operand:SI 0 "register_operand" "")
2258                    (udiv:SI (reg:SI R4_REG)
2259                             (reg:SI R5_REG)))
2260               (clobber (reg:SI T_REG))
2261               (clobber (reg:SI PR_REG))
2262               (clobber (reg:SI R4_REG))
2263               (use (match_dup 3))])]
2264   ""
2266   rtx last;
2268   operands[3] = gen_reg_rtx (Pmode);
2269   /* Emit the move of the address to a pseudo outside of the libcall.  */
2270   if (TARGET_DIVIDE_CALL_TABLE)
2271     {
2272       /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
2273          that causes problems when the divide code is supposed to come from a
2274          separate library.  Division by zero is undefined, so dividing 1 can be
2275          implemented by comparing with the divisor.  */
2276       if (operands[1] == const1_rtx && currently_expanding_to_rtl)
2277         {
2278           rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
2279           emit_insn (gen_cstoresi4 (operands[0], test,
2280                                     operands[1], operands[2]));
2281           DONE;
2282         }
2283       else if (operands[2] == const0_rtx)
2284         {
2285           emit_move_insn (operands[0], operands[2]);
2286           DONE;
2287         }
2288       function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT);
2289       last = gen_udivsi3_i4_int (operands[0], operands[3]);
2290     }
2291   else if (TARGET_DIVIDE_CALL_FP)
2292     {
2293       function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC);
2294       if (TARGET_FPU_SINGLE)
2295         last = gen_udivsi3_i4_single (operands[0], operands[3]);
2296       else
2297         last = gen_udivsi3_i4 (operands[0], operands[3]);
2298     }
2299   else if (TARGET_SHMEDIA_FPU)
2300     {
2301       operands[1] = force_reg (SImode, operands[1]);
2302       operands[2] = force_reg (SImode, operands[2]);
2303       emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
2304       DONE;
2305     }
2306   else if (TARGET_SH2A)
2307     {
2308       operands[1] = force_reg (SImode, operands[1]);
2309       operands[2] = force_reg (SImode, operands[2]);
2310       emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
2311       DONE;
2312     }
2313   else if (TARGET_SH5)
2314     {
2315       function_symbol (operands[3],
2316                        TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3",
2317                        SFUNC_STATIC);
2319       if (TARGET_SHMEDIA)
2320         last = gen_udivsi3_i1_media (operands[0], operands[3]);
2321       else if (TARGET_FPU_ANY)
2322         last = gen_udivsi3_i4_single (operands[0], operands[3]);
2323       else
2324         last = gen_udivsi3_i1 (operands[0], operands[3]);
2325     }
2326   else
2327     {
2328       function_symbol (operands[3], "__udivsi3", SFUNC_STATIC);
2329       last = gen_udivsi3_i1 (operands[0], operands[3]);
2330     }
2331   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2332   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2333   emit_insn (last);
2334   DONE;
2337 (define_insn "divsi3_sh2a"
2338   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2339         (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
2340                 (match_operand:SI 2 "arith_reg_operand" "z")))]
2341   "TARGET_SH2A"
2342   "divs %2,%1"
2343   [(set_attr "type" "arith")
2344    (set_attr "in_delay_slot" "no")])
2346 (define_insn "divsi3_i1"
2347   [(set (match_operand:SI 0 "register_operand" "=z")
2348         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2349    (clobber (reg:SI T_REG))
2350    (clobber (reg:SI PR_REG))
2351    (clobber (reg:SI R1_REG))
2352    (clobber (reg:SI R2_REG))
2353    (clobber (reg:SI R3_REG))
2354    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2355   "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
2356   "jsr  @%1%#"
2357   [(set_attr "type" "sfunc")
2358    (set_attr "needs_delay_slot" "yes")])
2360 (define_insn "divsi3_i1_media"
2361   [(set (match_operand:SI 0 "register_operand" "=z")
2362         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2363    (clobber (reg:SI T_MEDIA_REG))
2364    (clobber (reg:SI PR_MEDIA_REG))
2365    (clobber (reg:SI R1_REG))
2366    (clobber (reg:SI R20_REG))
2367    (clobber (reg:SI R21_REG))
2368    (clobber (reg:SI TR0_REG))
2369    (use (match_operand 1 "target_reg_operand" "b"))]
2370   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2371   "blink        %1, r18"
2372   [(set_attr "type" "sfunc")])
2374 (define_insn "divsi3_media_2"
2375   [(set (match_operand:SI 0 "register_operand" "=z")
2376         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2377    (clobber (reg:SI T_MEDIA_REG))
2378    (clobber (reg:SI PR_MEDIA_REG))
2379    (clobber (reg:SI R1_REG))
2380    (clobber (reg:SI R21_REG))
2381    (clobber (reg:SI TR0_REG))
2382    (use (reg:SI R20_REG))
2383    (use (match_operand 1 "target_reg_operand" "b"))]
2384   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2385   "blink        %1, r18"
2386   [(set_attr "type" "sfunc")])
2388 ;; This pattern acts as a placeholder for -mdiv=inv:call to carry
2389 ;; hard reg clobbers and data dependencies that we need when we want
2390 ;; to rematerialize the division into a call.
2391 (define_insn_and_split "divsi_inv_call"
2392   [(set (match_operand:SI 0 "register_operand" "=r")
2393         (div:SI (match_operand:SI 1 "register_operand" "r")
2394                 (match_operand:SI 2 "register_operand" "r")))
2395    (clobber (reg:SI R4_REG))
2396    (clobber (reg:SI R5_REG))
2397    (clobber (reg:SI T_MEDIA_REG))
2398    (clobber (reg:SI PR_MEDIA_REG))
2399    (clobber (reg:SI R1_REG))
2400    (clobber (reg:SI R21_REG))
2401    (clobber (reg:SI TR0_REG))
2402    (clobber (reg:SI R20_REG))
2403    (use (match_operand:SI 3 "register_operand" "r"))]
2404   "TARGET_SHMEDIA"
2405   "#"
2406   "&& (reload_in_progress || reload_completed)"
2407   [(set (match_dup 0) (match_dup 3))]
2408   ""
2409   [(set_attr "highpart" "must_split")])
2411 ;; This is the combiner pattern for -mdiv=inv:call .
2412 (define_insn_and_split "*divsi_inv_call_combine"
2413   [(set (match_operand:SI 0 "register_operand" "=z")
2414         (div:SI (match_operand:SI 1 "register_operand" "r")
2415                 (match_operand:SI 2 "register_operand" "r")))
2416    (clobber (reg:SI R4_REG))
2417    (clobber (reg:SI R5_REG))
2418    (clobber (reg:SI T_MEDIA_REG))
2419    (clobber (reg:SI PR_MEDIA_REG))
2420    (clobber (reg:SI R1_REG))
2421    (clobber (reg:SI R21_REG))
2422    (clobber (reg:SI TR0_REG))
2423    (clobber (reg:SI R20_REG))
2424    (use (unspec:SI [(match_dup 1)
2425                     (match_operand:SI 3 "" "")
2426                     (unspec:SI [(match_operand:SI 4 "" "")
2427                                 (match_dup 3)
2428                                 (match_operand:DI 5 "" "")]
2429                      UNSPEC_DIV_INV_M2)
2430                     (match_operand:DI 6 "" "")
2431                     (const_int 0)
2432                     (const_int 0)]
2433          UNSPEC_DIV_INV_M3))]
2434   "TARGET_SHMEDIA"
2435   "#"
2436   "&& (reload_in_progress || reload_completed)"
2437   [(pc)]
2439   const char *name = sh_divsi3_libfunc;
2440   enum sh_function_kind kind = SFUNC_GOT;
2441   rtx sym;
2443   emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2444   emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2445   while (TARGET_DIVIDE_INV_CALL2)
2446     {
2447       rtx x = operands[3];
2449       if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2450         break;
2451       x = XVECEXP (x, 0, 0);
2452       name = "__sdivsi3_2";
2453       kind = SFUNC_STATIC;
2454       emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2455       break;
2456     }
2457   sym = function_symbol (NULL, name, kind);
2458   emit_insn (gen_divsi3_media_2 (operands[0], sym));
2459   DONE;
2461   [(set_attr "highpart" "must_split")])
2463 (define_expand "divsi3_i4_media"
2464   [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2465    (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2466    (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2467    (set (match_operand:SI 0 "register_operand" "=r")
2468         (fix:SI (match_dup 5)))]
2469   "TARGET_SHMEDIA_FPU"
2471   operands[3] = gen_reg_rtx (DFmode);
2472   operands[4] = gen_reg_rtx (DFmode);
2473   operands[5] = gen_reg_rtx (DFmode);
2476 (define_insn "divsi3_i4"
2477   [(set (match_operand:SI 0 "register_operand" "=y")
2478         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2479    (clobber (reg:SI PR_REG))
2480    (clobber (reg:DF DR0_REG))
2481    (clobber (reg:DF DR2_REG))
2482    (use (reg:PSI FPSCR_REG))
2483    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2484   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
2485   "jsr  @%1%#"
2486   [(set_attr "type" "sfunc")
2487    (set_attr "fp_mode" "double")
2488    (set_attr "needs_delay_slot" "yes")])
2490 (define_insn "divsi3_i4_single"
2491   [(set (match_operand:SI 0 "register_operand" "=y")
2492         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2493    (clobber (reg:SI PR_REG))
2494    (clobber (reg:DF DR0_REG))
2495    (clobber (reg:DF DR2_REG))
2496    (clobber (reg:SI R2_REG))
2497    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2498   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
2499   "jsr  @%1%#"
2500   [(set_attr "type" "sfunc")
2501    (set_attr "needs_delay_slot" "yes")])
2503 (define_insn "divsi3_i4_int"
2504   [(set (match_operand:SI 0 "register_operand" "=z")
2505         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2506    (clobber (reg:SI T_REG))
2507    (clobber (reg:SI PR_REG))
2508    (clobber (reg:SI R1_REG))
2509    (clobber (reg:SI MACH_REG))
2510    (clobber (reg:SI MACL_REG))
2511    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2512   "TARGET_SH1"
2513   "jsr  @%1%#"
2514   [(set_attr "type" "sfunc")
2515    (set_attr "needs_delay_slot" "yes")])
2517 (define_expand "divsi3"
2518   [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2519    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2520    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2521    (parallel [(set (match_operand:SI 0 "register_operand" "")
2522                    (div:SI (reg:SI R4_REG)
2523                            (reg:SI R5_REG)))
2524               (clobber (reg:SI T_REG))
2525               (clobber (reg:SI PR_REG))
2526               (clobber (reg:SI R1_REG))
2527               (clobber (reg:SI R2_REG))
2528               (clobber (reg:SI R3_REG))
2529               (use (match_dup 3))])]
2530   ""
2532   rtx last;
2534   operands[3] = gen_reg_rtx (Pmode);
2535   /* Emit the move of the address to a pseudo outside of the libcall.  */
2536   if (TARGET_DIVIDE_CALL_TABLE)
2537     {
2538       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2539       last = gen_divsi3_i4_int (operands[0], operands[3]);
2540     }
2541   else if (TARGET_DIVIDE_CALL_FP)
2542     {
2543       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2544       if (TARGET_FPU_SINGLE)
2545         last = gen_divsi3_i4_single (operands[0], operands[3]);
2546       else
2547         last = gen_divsi3_i4 (operands[0], operands[3]);
2548     }
2549   else if (TARGET_SH2A)
2550     {
2551       operands[1] = force_reg (SImode, operands[1]);
2552       operands[2] = force_reg (SImode, operands[2]);
2553       emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2554       DONE;
2555     }
2556   else if (TARGET_DIVIDE_INV)
2557     {
2558       rtx dividend = operands[1];
2559       rtx divisor = operands[2];
2560       rtx tab_base;
2561       rtx nsb_res = gen_reg_rtx (DImode);
2562       rtx norm64 = gen_reg_rtx (DImode);
2563       rtx tab_ix = gen_reg_rtx (DImode);
2564       rtx norm32 = gen_reg_rtx (SImode);
2565       rtx i92 = force_reg (DImode, GEN_INT (92));
2566       rtx scratch0a = gen_reg_rtx (DImode);
2567       rtx scratch0b = gen_reg_rtx (DImode);
2568       rtx inv0 = gen_reg_rtx (SImode);
2569       rtx scratch1a = gen_reg_rtx (DImode);
2570       rtx scratch1b = gen_reg_rtx (DImode);
2571       rtx shift = gen_reg_rtx (DImode);
2572       rtx i2p27, i43;
2573       rtx inv1 = gen_reg_rtx (SImode);
2574       rtx scratch2a = gen_reg_rtx (DImode);
2575       rtx scratch2b = gen_reg_rtx (SImode);
2576       rtx inv2 = gen_reg_rtx (SImode);
2577       rtx scratch3a = gen_reg_rtx (DImode);
2578       rtx scratch3b = gen_reg_rtx (DImode);
2579       rtx scratch3c = gen_reg_rtx (DImode);
2580       rtx scratch3d = gen_reg_rtx (SImode);
2581       rtx scratch3e = gen_reg_rtx (DImode);
2582       rtx result = gen_reg_rtx (SImode);
2584       if (! arith_reg_or_0_operand (dividend, SImode))
2585         dividend = force_reg (SImode, dividend);
2586       if (! arith_reg_operand (divisor, SImode))
2587         divisor = force_reg (SImode, divisor);
2588       if (flag_pic && Pmode != DImode)
2589         {
2590           tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2591           tab_base = gen_datalabel_ref (tab_base);
2592           tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2593         }
2594       else
2595         {
2596           tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table");
2597           tab_base = gen_datalabel_ref (tab_base);
2598           tab_base = force_reg (DImode, tab_base);
2599         }
2600       if (TARGET_DIVIDE_INV20U)
2601         i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2602       else
2603         i2p27 = GEN_INT (0);
2604       if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2605         i43 = force_reg (DImode, GEN_INT (43));
2606       else
2607         i43 = GEN_INT (0);
2608       emit_insn (gen_nsbdi (nsb_res,
2609                             simplify_gen_subreg (DImode, divisor, SImode, 0)));
2610       emit_insn (gen_ashldi3_media (norm64,
2611                                     gen_rtx_SUBREG (DImode, divisor, 0),
2612                                     nsb_res));
2613       emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2614       emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2615       emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2616                                    inv0, scratch0a, scratch0b,
2617                                    scratch1a, scratch1b));
2618       emit_insn (gen_subdi3 (shift, i92, nsb_res));
2619       emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2620                                    scratch2a));
2621       emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2622                                    i2p27, i43,
2623                                    scratch3a, scratch3b, scratch3c,
2624                                    scratch2a, scratch2b, scratch3d, scratch3e));
2625       if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2626         emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2627       else if (TARGET_DIVIDE_INV_FP)
2628         emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2629                                      gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2630                                      gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2631                                      gen_reg_rtx (DFmode)));
2632       else
2633         emit_move_insn (operands[0], result);
2634       DONE;
2635     }
2636   else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2637     {
2638       operands[1] = force_reg (SImode, operands[1]);
2639       operands[2] = force_reg (SImode, operands[2]);
2640       emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2641       DONE;
2642     }
2643   else if (TARGET_SH5)
2644     {
2645       if (TARGET_DIVIDE_CALL2)
2646         {
2647           rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2648           tab_base = gen_datalabel_ref (tab_base);
2649           emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2650         }
2651       if (TARGET_FPU_ANY && TARGET_SH1)
2652         function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2653       else if (TARGET_DIVIDE_CALL2)
2654         function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC);
2655       else
2656         function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2658       if (TARGET_SHMEDIA)
2659         last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2660                 (operands[0], operands[3]));
2661       else if (TARGET_FPU_ANY)
2662         last = gen_divsi3_i4_single (operands[0], operands[3]);
2663       else
2664         last = gen_divsi3_i1 (operands[0], operands[3]);
2665     }
2666   else
2667     {
2668       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2669       last = gen_divsi3_i1 (operands[0], operands[3]);
2670     }
2671   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2672   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2673   emit_insn (last);
2674   DONE;
2677 ;; operands: scratch, tab_base, tab_ix
2678 ;; These are unspecs because we could generate an indexed addressing mode
2679 ;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2680 ;; confuse reload.  See PR27117.
2682 (define_insn "divsi_inv_qitable"
2683   [(set (match_operand:DI 0 "register_operand" "=r")
2684         (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2685                                     (match_operand:DI 2 "register_operand" "r")]
2686                          UNSPEC_DIV_INV_TABLE)))]
2687   "TARGET_SHMEDIA"
2688   "ldx.ub       %1, %2, %0"
2689   [(set_attr "type" "load_media")
2690    (set_attr "highpart" "user")])
2692 ;; operands: scratch, tab_base, tab_ix
2693 (define_insn "divsi_inv_hitable"
2694   [(set (match_operand:DI 0 "register_operand" "=r")
2695         (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2696                                     (match_operand:DI 2 "register_operand" "r")]
2697                          UNSPEC_DIV_INV_TABLE)))]
2698   "TARGET_SHMEDIA"
2699   "ldx.w        %1, %2, %0"
2700   [(set_attr "type" "load_media")
2701    (set_attr "highpart" "user")])
2703 ;; operands: inv0, tab_base, tab_ix, norm32
2704 ;; scratch equiv in sdivsi3_2: r19, r21
2705 (define_expand "divsi_inv_m0"
2706   [(set (match_operand:SI 0 "register_operand" "=r")
2707         (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2708                     (match_operand:DI 2 "register_operand" "r")
2709                     (match_operand:SI 3 "register_operand" "r")]
2710          UNSPEC_DIV_INV_M0))
2711    (clobber (match_operand:DI 4 "register_operand" "=r"))
2712    (clobber (match_operand:DI 5 "register_operand" "=r"))]
2713   "TARGET_SHMEDIA"
2716 tab_base: r20
2717 tab_ix: r21
2718 norm32: r25
2719  ldx.ub r20, r21, r19 // u0.8
2720  shlli r21, 1, r21
2721  muls.l r25, r19, r19 // s2.38
2722  ldx.w r20, r21, r21  // s2.14
2723  shari r19, 24, r19   // truncate to s2.14
2724  sub r21, r19, r19    // some 11 bit inverse in s1.14
2727   rtx inv0 = operands[0];
2728   rtx tab_base = operands[1];
2729   rtx tab_ix = operands[2];
2730   rtx norm32 = operands[3];
2731   rtx scratch0 = operands[4];
2732   rtx scratch0_si = gen_lowpart (SImode, scratch0);
2733   rtx scratch1 = operands[5];
2735   emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2736   emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2737   emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2738   emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2739   emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2740   emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2741   DONE;
2744 ;; operands: inv1, tab_base, tab_ix, norm32
2745 (define_insn_and_split "divsi_inv_m1"
2746   [(set (match_operand:SI 0 "register_operand" "=r")
2747         (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2748                     (match_operand:DI 2 "register_operand" "r")
2749                     (match_operand:SI 3 "register_operand" "r")]
2750          UNSPEC_DIV_INV_M1))
2751    (clobber (match_operand:SI 4 "register_operand" "=r"))
2752    (clobber (match_operand:DI 5 "register_operand" "=r"))
2753    (clobber (match_operand:DI 6 "register_operand" "=r"))
2754    (clobber (match_operand:DI 7 "register_operand" "=r"))
2755    (clobber (match_operand:DI 8 "register_operand" "=r"))]
2756   "TARGET_SHMEDIA"
2757   "#"
2758   "&& !can_create_pseudo_p ()"
2759   [(pc)]
2761 /* inv0: r19
2762  muls.l r19, r19, r18 // u0.28
2763  muls.l r25, r18, r18 // s2.58
2764  shlli r19, 45, r0    // multiply by two and convert to s2.58
2765  sub r0, r18, r18
2766  shari r18, 28, r18   // some 18 bit inverse in s1.30
2769   rtx inv1 = operands[0];
2770   rtx tab_base = operands[1];
2771   rtx tab_ix = operands[2];
2772   rtx norm32 = operands[3];
2773   rtx inv0 = operands[4];
2774   rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2775   rtx scratch0a = operands[5];
2776   rtx scratch0b = operands[6];
2777   rtx scratch0 = operands[7];
2778   rtx scratch1 = operands[8];
2779   rtx scratch1_si = gen_lowpart (SImode, scratch1);
2781   emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2782                                scratch0a, scratch0b));
2783   emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2784   emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2785   emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2786   emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2787   emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2788   DONE;
2791 ;; operands: inv2, norm32, inv1, i92
2792 (define_insn_and_split "divsi_inv_m2"
2793   [(set (match_operand:SI 0 "register_operand" "=r")
2794         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2795                     (match_operand:SI 2 "register_operand" "r")
2796                     (match_operand:DI 3 "register_operand" "r")]
2797          UNSPEC_DIV_INV_M2))
2798    (clobber (match_operand:DI 4 "register_operand" "=r"))]
2799   "TARGET_SHMEDIA"
2800   "#"
2801   "&& !can_create_pseudo_p ()"
2802   [(pc)]
2805  muls.l r18, r25, r0  // s2.60
2806  shari r0, 16, r0     // s-16.44
2807   sub
2808  muls.l r0, r18, r19  // s-16.74
2809  shari r19, 30, r19   // s-16.44
2811   rtx inv2 = operands[0];
2812   rtx norm32 = operands[1];
2813   rtx inv1 = operands[2];
2814   rtx i92 = operands[3];
2815   rtx scratch0 = operands[4];
2816   rtx scratch0_si = gen_lowpart (SImode, scratch0);
2818   emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2819   emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2820   emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2821   emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2822   emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2823   DONE;
2826 (define_insn_and_split "divsi_inv_m3"
2827   [(set (match_operand:SI 0 "register_operand" "=r")
2828         (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2829                     (match_operand:SI 2 "register_operand" "r")
2830                     (match_operand:SI 3 "register_operand" "r")
2831                     (match_operand:DI 4 "register_operand" "r")
2832                     (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
2833                     (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
2834          UNSPEC_DIV_INV_M3))
2835    (clobber (match_operand:DI 7 "register_operand" "=r"))
2836    (clobber (match_operand:DI 8 "register_operand" "=r"))
2837    (clobber (match_operand:DI 9 "register_operand" "=r"))
2838    (clobber (match_operand:DI 10 "register_operand" "=r"))
2839    (clobber (match_operand:SI 11 "register_operand" "=r"))
2840    (clobber (match_operand:SI 12 "register_operand" "=r"))
2841    (clobber (match_operand:DI 13 "register_operand" "=r"))]
2842   "TARGET_SHMEDIA"
2843   "#"
2844   "&& !can_create_pseudo_p ()"
2845   [(pc)]
2848   r0: result  r1: shift  r4: dividend  r18: inv1  r19: inv2
2849   r0: scratch0  r19: scratch1 r21: scratch2
2851   muls.l r18, r4, r25 // s32.30
2852  muls.l r19, r4, r19  // s15.30
2853  shari r25, 63, r21
2854   shari r19, 14, r19  // s18.-14
2855  sub r25, r19, r0
2856  shard r0, r1, r0
2857  sub r0, r21, r0
2860   rtx result = operands[0];
2861   rtx dividend = operands[1];
2862   rtx inv1 = operands[2];
2863   rtx inv2 = operands[3];
2864   rtx shift = operands[4];
2865   rtx scratch0 = operands[7];
2866   rtx scratch1 = operands[8];
2867   rtx scratch2 = operands[9];
2869   if (satisfies_constraint_N (dividend))
2870     {
2871       emit_move_insn (result, dividend);
2872       DONE;
2873     }
2875   emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
2876   emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
2877   emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
2878   emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
2879   emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
2880   emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
2881   emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
2882   DONE;
2885 ;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
2886 ;; inv1: tab_base, tab_ix, norm32
2887 ;; inv2: norm32, inv1, i92
2888 (define_insn_and_split "divsi_inv_m1_3"
2889   [(set (match_operand:SI 0 "register_operand" "=r")
2890         (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2891                     (unspec:SI [(match_operand:DI 2 "register_operand" "r")
2892                                 (match_operand:DI 3 "register_operand" "r")
2893                                 (match_operand:SI 4 "register_operand" "r")]
2894                      UNSPEC_DIV_INV_M1)
2895                     (unspec:SI [(match_dup 4)
2896                                 (unspec:SI [(match_dup 2)
2897                                             (match_dup 3)
2898                                             (match_dup 4)] UNSPEC_DIV_INV_M1)
2899                                 (match_operand:SI 5 "" "")]
2900                      UNSPEC_DIV_INV_M2)
2901                     (match_operand:DI 6 "register_operand" "r")
2902                     (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
2903                     (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
2904          UNSPEC_DIV_INV_M3))
2905    (clobber (match_operand:DI 9 "register_operand" "=r"))
2906    (clobber (match_operand:DI 10 "register_operand" "=r"))
2907    (clobber (match_operand:DI 11 "register_operand" "=r"))
2908    (clobber (match_operand:DI 12 "register_operand" "=r"))
2909    (clobber (match_operand:SI 13 "register_operand" "=r"))
2910    (clobber (match_operand:SI 14 "register_operand" "=r"))
2911    (clobber (match_operand:DI 15 "register_operand" "=r"))]
2912   "TARGET_SHMEDIA
2913    && (TARGET_DIVIDE_INV_MINLAT
2914        || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2915   "#"
2916   "&& !can_create_pseudo_p ()"
2917   [(pc)]
2919   rtx result = operands[0];
2920   rtx dividend = operands[1];
2921   rtx tab_base = operands[2];
2922   rtx tab_ix = operands[3];
2923   rtx norm32 = operands[4];
2924   /* rtx i92 = operands[5]; */
2925   rtx shift = operands[6];
2926   rtx i2p27 = operands[7];
2927   rtx i43 = operands[8];
2928   rtx scratch0 = operands[9];
2929   rtx scratch0_si = gen_lowpart (SImode, scratch0);
2930   rtx scratch1 = operands[10];
2931   rtx scratch1_si = gen_lowpart (SImode, scratch1);
2932   rtx scratch2 = operands[11];
2933   rtx scratch3 = operands[12];
2934   rtx scratch4 = operands[13];
2935   rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
2936   rtx scratch5 = operands[14];
2937   rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
2938   rtx scratch6 = operands[15];
2940   emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
2941                                scratch0, scratch1));
2942   /* inv0 == scratch4 */
2943   if (! TARGET_DIVIDE_INV20U)
2944     {
2945       emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
2946       i2p27 = scratch0;
2947       emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
2948     }
2949   else
2950     {
2951       emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
2952       emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2953     }
2954   emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
2955   emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
2956   emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
2957   /* inv1 == scratch4 */
2959   if (TARGET_DIVIDE_INV_MINLAT)
2960     {
2961       emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
2962       emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
2963       emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
2964       emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
2965       emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
2966       emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
2967       emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
2968       emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
2969       emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
2970       emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
2971       emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
2972     }
2973   else
2974     {
2975       rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
2976       /* Use separate scratch regs for nsb and sign to allow scheduling.  */
2977       emit_insn (gen_nsbdi (scratch6,
2978                             simplify_gen_subreg (DImode, dividend, SImode, 0)));
2979       emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
2980       emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
2981       emit_insn (gen_divsi_inv20 (scratch2,
2982                                   norm32, scratch4, dividend,
2983                                   scratch6, scratch3, i43,
2984                                   /* scratch0 may be shared with i2p27.  */
2985                                   scratch0, scratch1, scratch5,
2986                                   label, label, i2p27));
2987     }
2988   emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
2989   emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
2990   DONE;
2993 (define_insn "divsi_inv20"
2994   [(set (match_operand:DI 0 "register_operand" "=&r")
2995         (unspec:DI [(match_operand:SI 1 "register_operand" "r")
2996                     (match_operand:SI 2 "register_operand" "r")
2997                     (match_operand:SI 3 "register_operand" "r")
2998                     (match_operand:DI 4 "register_operand" "r")
2999                     (match_operand:DI 5 "register_operand" "r")
3000                     (match_operand:DI 6 "register_operand" "r")
3001                     (match_operand:DI 12 "register_operand" "r")
3002                     (match_operand 10 "target_operand" "b")
3003                     (match_operand 11 "immediate_operand" "i")]
3004          UNSPEC_DIV_INV20))
3005    (clobber (match_operand:DI 7 "register_operand" "=&r"))
3006    (clobber (match_operand:DI 8 "register_operand" "=&r"))
3007    (clobber (match_operand:SI 9 "register_operand" "=r"))]
3008   "TARGET_SHMEDIA
3009    && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
3011 /* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
3012              %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
3013              %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
3014              %10 label (tr), %11 label (imm)
3016  muls.l inv1, norm32, scratch0  // s2.60
3017   muls.l inv1, dividend, result // s32.30
3018   xor i2p27, result_sign, round_scratch
3019  bge/u dividend_nsb, i43, tr.. (label)
3020  shari scratch0, 16, scratch0   // s-16.44
3021  muls.l sratch0_si, inv1, scratch0 // s-16.74
3022   sub result, round_scratch, result
3023   shari dividend, 14, scratch1   // s19.-14
3024  shari scratch0, 30, scratch0   // s-16.44
3025  muls.l scratch0, scratch1, round_scratch // s15.30
3026 label:
3027  sub result, round_scratch, result */
3029   const bool likely = TARGET_DIVIDE_INV20L;
3030   if (likely)
3031     return
3032                "muls.l  %2, %3, %0"     "\n"
3033         "       xor     %12, %5, %7"    "\n"
3034         "       bge/l   %4, %6, %10"    "\n"
3035         "       muls.l  %2, %1, %8"     "\n"
3036         "       shari   %8, 16, %8"     "\n"
3037         "       muls.l  %8, %2, %8"     "\n"
3038         "       shari   %3, 14, %9"     "\n"
3039         "       shari   %8, 30, %8"     "\n"
3040         "       muls.l  %8, %9, %8"     "\n"
3041         "       sub     %0, %8, %0"     "\n"
3042         "%11:   add     %0, %7, %0";
3043   else
3044     return
3045                "muls.l  %2, %1, %8"     "\n"
3046         "       muls.l  %2, %3, %0"     "\n"
3047         "       xor     %12, %5, %7"    "\n"
3048         "       bge/u   %4, %6, %10"    "\n"
3049         "       shari   %8, 16, %8"     "\n"
3050         "       muls.l  %8, %2, %8"     "\n"
3051         "       sub     %0, %7, %0"     "\n"
3052         "       shari   %3, 14, %9"     "\n"
3053         "       shari   %8, 30, %8"     "\n"
3054         "       muls.l  %8, %9, %7"     "\n"
3055         "%11:   sub     %0, %7, %0";
3058 (define_insn_and_split "divsi_inv_fp"
3059   [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
3060         (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
3061                 (match_operand:SI 2 "register_operand" "rf")))
3062    (use (match_operand:SI 3 "general_movsrc_operand" "r"))
3063    (clobber (match_operand:SI 4 "register_operand" "=r"))
3064    (clobber (match_operand:SI 5 "register_operand" "=r"))
3065    (clobber (match_operand:DF 6 "register_operand" "=r"))
3066    (clobber (match_operand:DF 7 "register_operand" "=r"))
3067    (clobber (match_operand:DF 8 "register_operand" "=r"))]
3068   "TARGET_SHMEDIA_FPU"
3069   "#"
3070   "&& (reload_in_progress || reload_completed)"
3071   [(set (match_dup 0) (match_dup 3))]
3072   ""
3073   [(set_attr "highpart" "must_split")])
3075 ;; If a matching group of divide-by-inverse instructions is in the same
3076 ;; basic block after gcse & loop optimizations, we want to transform them
3077 ;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
3078 (define_insn_and_split "*divsi_inv_fp_combine"
3079   [(set (match_operand:SI 0 "register_operand" "=f")
3080         (div:SI (match_operand:SI 1 "register_operand" "f")
3081                 (match_operand:SI 2 "register_operand" "f")))
3082    (use (unspec:SI [(match_dup 1)
3083                     (match_operand:SI 3 "" "")
3084                     (unspec:SI [(match_operand:SI 4 "" "")
3085                                 (match_dup 3)
3086                                 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
3087                     (match_operand:DI 6 "" "")
3088                     (const_int 0)
3089                     (const_int 0)] UNSPEC_DIV_INV_M3))
3090    (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
3091    (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
3092    (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
3093    (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
3094    (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
3095   "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
3096   "#"
3097   "&& 1"
3098   [(set (match_dup 9) (float:DF (match_dup 1)))
3099    (set (match_dup 10) (float:DF (match_dup 2)))
3100    (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
3101    (set (match_dup 8)
3102         (fix:SI (match_dup 11)))
3103    (set (match_dup 0) (match_dup 8))]
3105   if (! fp_arith_reg_operand (operands[1], SImode))
3106     {
3107       emit_move_insn (operands[7], operands[1]);
3108       operands[1] = operands[7];
3109     }
3110   if (! fp_arith_reg_operand (operands[2], SImode))
3111     {
3112       emit_move_insn (operands[8], operands[2]);
3113       operands[2] = operands[8];
3114     }
3116   [(set_attr "highpart" "must_split")])
3118 ;; -------------------------------------------------------------------------
3119 ;; Multiplication instructions
3120 ;; -------------------------------------------------------------------------
3122 (define_insn "umulhisi3_i"
3123   [(set (reg:SI MACL_REG)
3124         (mult:SI (zero_extend:SI
3125                   (match_operand:HI 0 "arith_reg_operand" "r"))
3126                  (zero_extend:SI
3127                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
3128   "TARGET_SH1"
3129   "mulu.w       %1,%0"
3130   [(set_attr "type" "smpy")])
3132 (define_insn "mulhisi3_i"
3133   [(set (reg:SI MACL_REG)
3134         (mult:SI (sign_extend:SI
3135                   (match_operand:HI 0 "arith_reg_operand" "r"))
3136                  (sign_extend:SI
3137                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
3138   "TARGET_SH1"
3139   "muls.w       %1,%0"
3140   [(set_attr "type" "smpy")])
3142 (define_expand "mulhisi3"
3143   [(set (reg:SI MACL_REG)
3144         (mult:SI (sign_extend:SI
3145                   (match_operand:HI 1 "arith_reg_operand" ""))
3146                  (sign_extend:SI
3147                   (match_operand:HI 2 "arith_reg_operand" ""))))
3148    (set (match_operand:SI 0 "arith_reg_operand" "")
3149         (reg:SI MACL_REG))]
3150   "TARGET_SH1"
3152   rtx insn, macl;
3154   macl = gen_rtx_REG (SImode, MACL_REG);
3155   start_sequence ();
3156   emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
3157   insn = get_insns ();  
3158   end_sequence ();
3159   /* expand_binop can't find a suitable code in umul_widen_optab to
3160      make a REG_EQUAL note from, so make one here.
3161      See also smulsi3_highpart.
3162      ??? Alternatively, we could put this at the calling site of expand_binop,
3163      i.e. expand_expr.  */
3164   /* Use emit_libcall_block for loop invariant code motion and to make
3165      a REG_EQUAL note.  */
3166   emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3168   DONE;
3171 (define_expand "umulhisi3"
3172   [(set (reg:SI MACL_REG)
3173         (mult:SI (zero_extend:SI
3174                   (match_operand:HI 1 "arith_reg_operand" ""))
3175                  (zero_extend:SI
3176                   (match_operand:HI 2 "arith_reg_operand" ""))))
3177    (set (match_operand:SI 0 "arith_reg_operand" "")
3178         (reg:SI MACL_REG))]
3179   "TARGET_SH1"
3181   rtx insn, macl;
3183   macl = gen_rtx_REG (SImode, MACL_REG);
3184   start_sequence ();
3185   emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
3186   insn = get_insns ();  
3187   end_sequence ();
3188   /* expand_binop can't find a suitable code in umul_widen_optab to
3189      make a REG_EQUAL note from, so make one here.
3190      See also smulsi3_highpart.
3191      ??? Alternatively, we could put this at the calling site of expand_binop,
3192      i.e. expand_expr.  */
3193   /* Use emit_libcall_block for loop invariant code motion and to make
3194      a REG_EQUAL note.  */
3195   emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3197   DONE;
3200 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
3201 ;; a call to a routine which clobbers known registers.
3203 (define_insn ""
3204   [(set (match_operand:SI 1 "register_operand" "=z")
3205         (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
3206    (clobber (reg:SI MACL_REG))
3207    (clobber (reg:SI T_REG))
3208    (clobber (reg:SI PR_REG))
3209    (clobber (reg:SI R3_REG))
3210    (clobber (reg:SI R2_REG))
3211    (clobber (reg:SI R1_REG))
3212    (use (match_operand:SI 0 "arith_reg_operand" "r"))]
3213   "TARGET_SH1"
3214   "jsr  @%0%#"
3215   [(set_attr "type" "sfunc")
3216    (set_attr "needs_delay_slot" "yes")])
3218 (define_expand "mulsi3_call"
3219   [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
3220    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
3221    (parallel[(set (match_operand:SI 0 "register_operand" "")
3222                   (mult:SI (reg:SI R4_REG)
3223                            (reg:SI R5_REG)))
3224              (clobber (reg:SI MACL_REG))
3225              (clobber (reg:SI T_REG))
3226              (clobber (reg:SI PR_REG))
3227              (clobber (reg:SI R3_REG))
3228              (clobber (reg:SI R2_REG))
3229              (clobber (reg:SI R1_REG))
3230              (use (match_operand:SI 3 "register_operand" ""))])]
3231   "TARGET_SH1"
3232   "")
3234 (define_insn "mul_r"
3235   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3236         (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
3237                  (match_operand:SI 2 "arith_reg_operand" "z")))]
3238   "TARGET_SH2A"
3239   "mulr %2,%0"
3240   [(set_attr "type" "dmpy")])
3242 (define_insn "mul_l"
3243   [(set (reg:SI MACL_REG)
3244         (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
3245                  (match_operand:SI 1 "arith_reg_operand" "r")))]
3246   "TARGET_SH2"
3247   "mul.l        %1,%0"
3248   [(set_attr "type" "dmpy")])
3250 (define_expand "mulsi3"
3251   [(set (reg:SI MACL_REG)
3252         (mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
3253                   (match_operand:SI 2 "arith_reg_operand" "")))
3254    (set (match_operand:SI 0 "arith_reg_operand" "")
3255         (reg:SI MACL_REG))]
3256   "TARGET_SH1"
3258   if (!TARGET_SH2)
3259     {
3260       /* The address must be set outside the libcall,
3261          since it goes into a pseudo.  */
3262       rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC);
3263       rtx addr = force_reg (SImode, sym);
3264       rtx insns = gen_mulsi3_call (operands[0], operands[1],
3265                                    operands[2], addr);
3266       emit_insn (insns);
3267     }
3268   else
3269     {
3270       rtx macl = gen_rtx_REG (SImode, MACL_REG);
3272       emit_insn (gen_mul_l (operands[1], operands[2]));
3273       /* consec_sets_giv can only recognize the first insn that sets a
3274          giv as the giv insn.  So we must tag this also with a REG_EQUAL
3275          note.  */
3276       emit_insn (gen_movsi_i ((operands[0]), macl));
3277     }
3278   DONE;
3281 (define_insn "mulsidi3_i"
3282   [(set (reg:SI MACH_REG)
3283         (truncate:SI
3284          (lshiftrt:DI
3285           (mult:DI
3286            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3287            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3288           (const_int 32))))
3289    (set (reg:SI MACL_REG)
3290         (mult:SI (match_dup 0)
3291                  (match_dup 1)))]
3292   "TARGET_SH2"
3293   "dmuls.l      %1,%0"
3294   [(set_attr "type" "dmpy")])
3296 (define_expand "mulsidi3"
3297   [(set (match_operand:DI 0 "arith_reg_dest" "")
3298         (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3299                  (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3300   "TARGET_SH2 || TARGET_SHMEDIA"
3302   if (TARGET_SH2)
3303     {
3304       emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2]));
3305       DONE;
3306     }
3309 (define_insn "mulsidi3_media"
3310   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3311         (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3312                  (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3313   "TARGET_SHMEDIA"
3314   "muls.l       %1, %2, %0"
3315   [(set_attr "type" "dmpy_media")
3316    (set_attr "highpart" "ignore")])
3318 (define_insn_and_split "mulsidi3_compact"
3319   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3320         (mult:DI
3321          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3322          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3323    (clobber (reg:SI MACH_REG))
3324    (clobber (reg:SI MACL_REG))]
3325   "TARGET_SH2"
3326   "#"
3327   "&& 1"
3328   [(const_int 0)]
3330   rtx low_dst = gen_lowpart (SImode, operands[0]);
3331   rtx high_dst = gen_highpart (SImode, operands[0]);
3333   emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
3335   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3336   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3337   /* We need something to tag the possible REG_EQUAL notes on to.  */
3338   emit_move_insn (operands[0], operands[0]);
3339   DONE;
3342 (define_insn "umulsidi3_i"
3343   [(set (reg:SI MACH_REG)
3344         (truncate:SI
3345          (lshiftrt:DI
3346           (mult:DI
3347            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3348            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3349           (const_int 32))))
3350    (set (reg:SI MACL_REG)
3351         (mult:SI (match_dup 0)
3352                  (match_dup 1)))]
3353   "TARGET_SH2"
3354   "dmulu.l      %1,%0"
3355   [(set_attr "type" "dmpy")])
3357 (define_expand "umulsidi3"
3358   [(set (match_operand:DI 0 "arith_reg_dest" "")
3359         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3360                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3361   "TARGET_SH2 || TARGET_SHMEDIA"
3363   if (TARGET_SH2)
3364     {
3365       emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2]));
3366       DONE;
3367     }
3370 (define_insn "umulsidi3_media"
3371   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3372         (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3373                  (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3374   "TARGET_SHMEDIA"
3375   "mulu.l       %1, %2, %0"
3376   [(set_attr "type" "dmpy_media")
3377    (set_attr "highpart" "ignore")])
3379 (define_insn_and_split "umulsidi3_compact"
3380   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3381         (mult:DI
3382          (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3383          (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3384    (clobber (reg:SI MACH_REG))
3385    (clobber (reg:SI MACL_REG))]
3386   "TARGET_SH2"
3387   "#"
3388   "&& 1"
3389   [(const_int 0)]
3391   rtx low_dst = gen_lowpart (SImode, operands[0]);
3392   rtx high_dst = gen_highpart (SImode, operands[0]);
3394   emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
3396   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3397   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3398   /* We need something to tag the possible REG_EQUAL notes on to.  */
3399   emit_move_insn (operands[0], operands[0]);
3400   DONE;
3403 (define_insn "smulsi3_highpart_i"
3404   [(set (reg:SI MACH_REG)
3405         (truncate:SI
3406          (lshiftrt:DI
3407           (mult:DI
3408            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3409            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3410           (const_int 32))))
3411    (clobber (reg:SI MACL_REG))]
3412   "TARGET_SH2"
3413   "dmuls.l      %1,%0"
3414   [(set_attr "type" "dmpy")])
3416 (define_expand "smulsi3_highpart"
3417   [(parallel
3418     [(set (reg:SI MACH_REG)
3419           (truncate:SI
3420            (lshiftrt:DI
3421             (mult:DI
3422              (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3423              (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3424             (const_int 32))))
3425     (clobber (reg:SI MACL_REG))])
3426    (set (match_operand:SI 0 "arith_reg_operand" "")
3427         (reg:SI MACH_REG))]
3428   "TARGET_SH2"
3430   rtx insn, mach;
3432   mach = gen_rtx_REG (SImode, MACH_REG);
3433   start_sequence ();
3434   emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3435   insn = get_insns ();  
3436   end_sequence ();
3437   /* expand_binop can't find a suitable code in mul_highpart_optab to
3438      make a REG_EQUAL note from, so make one here.
3439      See also {,u}mulhisi.
3440      ??? Alternatively, we could put this at the calling site of expand_binop,
3441      i.e. expand_mult_highpart.  */
3442   /* Use emit_libcall_block for loop invariant code motion and to make
3443      a REG_EQUAL note.  */
3444   emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3446   DONE;
3449 (define_insn "umulsi3_highpart_i"
3450   [(set (reg:SI MACH_REG)
3451         (truncate:SI
3452          (lshiftrt:DI
3453           (mult:DI
3454            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3455            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3456           (const_int 32))))
3457    (clobber (reg:SI MACL_REG))]
3458   "TARGET_SH2"
3459   "dmulu.l      %1,%0"
3460   [(set_attr "type" "dmpy")])
3462 (define_expand "umulsi3_highpart"
3463   [(parallel
3464     [(set (reg:SI MACH_REG)
3465           (truncate:SI
3466            (lshiftrt:DI
3467             (mult:DI
3468              (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3469              (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3470             (const_int 32))))
3471     (clobber (reg:SI MACL_REG))])
3472    (set (match_operand:SI 0 "arith_reg_operand" "")
3473         (reg:SI MACH_REG))]
3474   "TARGET_SH2"
3476   rtx insn, mach;
3478   mach = gen_rtx_REG (SImode, MACH_REG);
3479   start_sequence ();
3480   emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3481   insn = get_insns ();  
3482   end_sequence ();
3483   /* Use emit_libcall_block for loop invariant code motion and to make
3484      a REG_EQUAL note.  */
3485   emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3487   DONE;
3490 (define_insn_and_split "muldi3"
3491   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3492         (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3493                  (match_operand:DI 2 "arith_reg_operand" "r")))
3494    (clobber (match_scratch:DI 3 "=&r"))
3495    (clobber (match_scratch:DI 4 "=r"))]
3496   "TARGET_SHMEDIA"
3497   "#"
3498   "reload_completed"
3499   [(const_int 0)]
3501   rtx op3_v2si, op2_v2si;
3503   op3_v2si = operands[3];
3504   if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3505     {
3506       op3_v2si = XEXP (op3_v2si, 0);
3507       op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3508     }
3509   op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3510   op2_v2si = operands[2];
3511   if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3512     {
3513       op2_v2si = XEXP (op2_v2si, 0);
3514       op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3515     }
3516   op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3517   emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3518   emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3519   emit_insn (gen_umulsidi3_media (operands[4],
3520                                  sh_gen_truncate (SImode, operands[1], 0),
3521                                  sh_gen_truncate (SImode, operands[2], 0)));
3522   emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3523   emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3524   emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3525   emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3526   DONE;
3530 ;; -------------------------------------------------------------------------
3531 ;; Logical operations
3532 ;; -------------------------------------------------------------------------
3534 (define_expand "andsi3"
3535   [(set (match_operand:SI 0 "arith_reg_operand" "")
3536         (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3537                 (match_operand:SI 2 "logical_and_operand" "")))]
3538   ""
3540   /* If it is possible to turn the and insn into a zero extension
3541      already, redundant zero extensions will be folded, which results
3542      in better code.  
3543      Ideally the splitter of *andsi_compact would be enough, if redundant
3544      zero extensions were detected after the combine pass, which does not
3545      happen at the moment.  */
3546   if (TARGET_SH1)
3547     {
3548       if (satisfies_constraint_Jmb (operands[2]))
3549         {
3550           emit_insn (gen_zero_extendqisi2 (operands[0],
3551                                            gen_lowpart (QImode, operands[1])));
3552           DONE;
3553         }
3554       else if (satisfies_constraint_Jmw (operands[2]))
3555         {
3556           emit_insn (gen_zero_extendhisi2 (operands[0],
3557                                            gen_lowpart (HImode, operands[1])));
3558           DONE;
3559         }
3560     }
3563 (define_insn_and_split "*andsi_compact"
3564   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r")
3565         (and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0")
3566                 (match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))]
3567   "TARGET_SH1"
3568   "@
3569         extu.b  %1,%0
3570         extu.w  %1,%0
3571         and     %2,%0
3572         and     %2,%0"
3573   "&& 1"
3574  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
3576   if (satisfies_constraint_Jmb (operands[2]))
3577     operands[1] = gen_lowpart (QImode, operands[1]);
3578   else if (satisfies_constraint_Jmw (operands[2]))
3579     operands[1] = gen_lowpart (HImode, operands[1]);
3580   else
3581     FAIL;
3583   [(set_attr "type" "arith")])
3585 (define_insn "*andsi3_media"
3586   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3587         (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3588                 (match_operand:SI 2 "logical_operand" "r,I10")))]
3589   "TARGET_SHMEDIA"
3590   "@
3591         and     %1, %2, %0
3592         andi    %1, %2, %0"
3593   [(set_attr "type" "arith_media")])
3595 (define_insn "*andsi3_bclr"
3596   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3597         (and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3598                 (match_operand:SI 2 "const_int_operand" "Psz")))]
3599   "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
3600   "bclr %W2,%0"
3601   [(set_attr "type" "arith")])
3603 (define_insn_and_split "anddi3"
3604   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3605         (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3606                 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
3607   "TARGET_SHMEDIA"
3608   "@
3609         and     %1, %2, %0
3610         andi    %1, %2, %0
3611         #"
3612   "reload_completed
3613    && ! logical_operand (operands[2], DImode)"
3614   [(const_int 0)]
3616   if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3617     emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3618   else
3619     emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3620   DONE;
3622   [(set_attr "type" "arith_media")])
3624 (define_insn "andcsi3"
3625   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3626         (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3627                 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3628   "TARGET_SHMEDIA"
3629   "andc %1,%2,%0"
3630   [(set_attr "type" "arith_media")])
3632 (define_insn "andcdi3"
3633   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3634         (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3635                 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3636   "TARGET_SHMEDIA"
3637   "andc %1,%2,%0"
3638   [(set_attr "type" "arith_media")])
3640 (define_expand "iorsi3"
3641   [(set (match_operand:SI 0 "arith_reg_operand" "")
3642         (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3643                 (match_operand:SI 2 "logical_operand" "")))]
3644   ""
3645   "")
3647 (define_insn "*iorsi3_compact"
3648   [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3649         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3650                 (match_operand:SI 2 "logical_operand" "r,K08")))]
3651   "TARGET_SH1
3652    && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
3653   "or   %2,%0"
3654   [(set_attr "type" "arith")])
3656 (define_insn "*iorsi3_media"
3657   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3658         (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3659                 (match_operand:SI 2 "logical_operand" "r,I10")))]
3660   "TARGET_SHMEDIA"
3661   "@
3662         or      %1, %2, %0
3663         ori     %1, %2, %0"
3664   [(set_attr "type" "arith_media")])
3666 (define_insn "*iorsi3_bset"
3667   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3668         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3669         (match_operand:SI 2 "const_int_operand" "Pso")))]
3670   "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
3671   "bset %V2,%0"
3672   [(set_attr "type" "arith")])
3674 (define_insn "iordi3"
3675   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3676         (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3677                 (match_operand:DI 2 "logical_operand" "r,I10")))]
3678   "TARGET_SHMEDIA"
3679   "@
3680         or      %1, %2, %0
3681         ori     %1, %2, %0"
3682   [(set_attr "type" "arith_media")])
3684 (define_insn_and_split "*logical_sidi3"
3685   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3686         (sign_extend:DI (match_operator:SI 3 "logical_operator"
3687                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3688                            (match_operand:SI 2 "logical_operand" "r,I10")])))]
3689   "TARGET_SHMEDIA"
3690   "#"
3691   "&& reload_completed"
3692   [(set (match_dup 0) (match_dup 3))]
3694   operands[3]
3695     = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3696                       simplify_gen_subreg (DImode, operands[1], SImode, 0),
3697                       simplify_gen_subreg (DImode, operands[2], SImode, 0));
3700 (define_insn_and_split "*logical_sidisi3"
3701   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3702         (truncate:SI (sign_extend:DI
3703                         (match_operator:SI 3 "logical_operator"
3704                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3705                            (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3706   "TARGET_SHMEDIA"
3707   "#"
3708   "&& 1"
3709   [(set (match_dup 0) (match_dup 3))])
3711 (define_insn_and_split "*logical_sidi3_2"
3712   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3713         (sign_extend:DI (truncate:SI (sign_extend:DI
3714                         (match_operator:SI 3 "logical_operator"
3715                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3716                            (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3717   "TARGET_SHMEDIA"
3718   "#"
3719   "&& 1"
3720   [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3722 (define_expand "xorsi3"
3723   [(set (match_operand:SI 0 "arith_reg_operand" "")
3724         (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3725                 (match_operand:SI 2 "xor_operand" "")))]
3726   ""
3727   "")
3729 (define_insn "*xorsi3_compact"
3730   [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3731         (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3732                 (match_operand:SI 2 "logical_operand" "K08,r")))]
3733   "TARGET_SH1"
3734   "xor  %2,%0"
3735   [(set_attr "type" "arith")])
3737 ;; The *logical_op_t pattern helps combine eliminating sign/zero extensions
3738 ;; of results where one of the inputs is a T bit store.  Notice that this
3739 ;; pattern must not match during reload.  If reload picks this pattern it
3740 ;; will be impossible to split it afterwards.
3741 (define_insn_and_split "*logical_op_t"
3742   [(set (match_operand:SI 0 "arith_reg_dest")
3743         (match_operator:SI 3 "logical_operator"
3744           [(match_operand:SI 1 "arith_reg_operand")
3745            (match_operand:SI 2 "t_reg_operand")]))]
3746   "TARGET_SH1 && can_create_pseudo_p ()"
3747   "#"
3748   "&& 1"
3749   [(set (match_dup 4) (reg:SI T_REG))
3750    (set (match_dup 0) (match_dup 3))]
3752   operands[4] = gen_reg_rtx (SImode);
3753   operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
3754                                 operands[1], operands[4]);
3757 (define_insn "*xorsi3_media"
3758   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3759         (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3760                 (match_operand:SI 2 "xor_operand" "r,I06")))]
3761   "TARGET_SHMEDIA"
3762   "@
3763         xor     %1, %2, %0
3764         xori    %1, %2, %0"
3765   [(set_attr "type" "arith_media")])
3767 (define_insn "xordi3"
3768   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3769         (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3770                 (match_operand:DI 2 "xor_operand" "r,I06")))]
3771   "TARGET_SHMEDIA"
3772   "@
3773         xor     %1, %2, %0
3774         xori    %1, %2, %0"
3775   [(set_attr "type" "arith_media")])
3777 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3778 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
3779 (define_split
3780   [(set (match_operand:DI 0 "arith_reg_dest" "")
3781         (sign_extend:DI (match_operator 4 "binary_logical_operator"
3782                           [(match_operand 1 "any_register_operand" "")
3783                            (match_operand 2 "any_register_operand" "")])))]
3784   "TARGET_SHMEDIA"
3785   [(set (match_dup 5) (match_dup 4))
3786    (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3788   enum machine_mode inmode = GET_MODE (operands[1]);
3789   int offset = 0;
3791   if (GET_CODE (operands[0]) == SUBREG)
3792     {
3793       offset = SUBREG_BYTE (operands[0]);
3794       operands[0] = SUBREG_REG (operands[0]);
3795     }
3796   gcc_assert (REG_P (operands[0]));
3797   if (! TARGET_LITTLE_ENDIAN)
3798     offset += 8 - GET_MODE_SIZE (inmode);
3799   operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3802 ;; -------------------------------------------------------------------------
3803 ;; Shifts and rotates
3804 ;; -------------------------------------------------------------------------
3806 (define_expand "rotldi3"
3807   [(set (match_operand:DI 0 "arith_reg_dest" "")
3808         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "")
3809                    (match_operand:HI 2 "mextr_bit_offset" "")))]
3810   "TARGET_SHMEDIA"
3812   if (! mextr_bit_offset (operands[2], HImode))
3813     FAIL;
3816 (define_insn "rotldi3_mextr"
3817   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3818         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3819                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
3820   "TARGET_SHMEDIA"
3822   static char templ[16];
3823   sprintf (templ, "mextr%d      %%1,%%1,%%0",
3824            8 - (int) (INTVAL (operands[2]) >> 3));
3825   return templ;
3827   [(set_attr "type" "arith_media")])
3829 (define_expand "rotrdi3"
3830   [(set (match_operand:DI 0 "arith_reg_dest" "")
3831         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "")
3832                      (match_operand:HI 2 "mextr_bit_offset" "")))]
3833   "TARGET_SHMEDIA"
3835   if (! mextr_bit_offset (operands[2], HImode))
3836     FAIL;
3839 (define_insn "rotrdi3_mextr"
3840   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3841         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3842                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
3843   "TARGET_SHMEDIA"
3845   static char templ[16];
3846   sprintf (templ, "mextr%d      %%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3);
3847   return templ;
3849   [(set_attr "type" "arith_media")])
3851 (define_split
3852   [(set (match_operand:DI 0 "arith_reg_dest" "")
3853         (ior:DI (zero_extend:DI (mem:QI (match_operand 1
3854                                          "ua_address_operand" "")))
3855                 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
3856                            (const_int 8))))
3857    (clobber (match_operand:DI 3 "register_operand" ""))]
3858   "TARGET_SHMEDIA"
3859   [(match_dup 4) (match_dup 5)]
3861   operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
3862                  (operands[3], operands[1]));
3863   operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
3864                               GEN_INT (56), GEN_INT (8));
3867 (define_expand "rotrsi3"
3868   [(set (match_operand:SI 0 "arith_reg_dest")
3869         (rotatert:SI (match_operand:SI 1 "arith_reg_operand")
3870                      (match_operand:SI 2 "const_int_operand")))]
3871   "TARGET_SH1"
3873   HOST_WIDE_INT ival = INTVAL (operands[2]);
3874   if (ival == 1)
3875     {
3876       emit_insn (gen_rotrsi3_1 (operands[0], operands[1]));
3877       DONE;
3878     }
3880   FAIL;
3883 (define_insn "rotrsi3_1"
3884   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3885         (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
3886                      (const_int 1)))
3887    (set (reg:SI T_REG)
3888         (and:SI (match_dup 1) (const_int 1)))]
3889   "TARGET_SH1"
3890   "rotr %0"
3891   [(set_attr "type" "arith")])
3893 ;; A slimplified version of rotr for combine.
3894 (define_insn "*rotrsi3_1"
3895   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3896         (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
3897                      (const_int 1)))
3898    (clobber (reg:SI T_REG))]
3899   "TARGET_SH1"
3900   "rotr %0"
3901   [(set_attr "type" "arith")])
3903 (define_insn "rotlsi3_1"
3904   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3905         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3906                    (const_int 1)))
3907    (set (reg:SI T_REG)
3908         (lshiftrt:SI (match_dup 1) (const_int 31)))]
3909   "TARGET_SH1"
3910   "rotl %0"
3911   [(set_attr "type" "arith")])
3913 ;; A simplified version of rotl for combine.
3914 (define_insn "*rotlsi3_1"
3915   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3916         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3917                    (const_int 1)))
3918    (clobber (reg:SI T_REG))]
3919   "TARGET_SH1"
3920   "rotl %0"
3921   [(set_attr "type" "arith")])
3923 (define_insn "rotlsi3_31"
3924   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3925         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3926                    (const_int 31)))
3927    (clobber (reg:SI T_REG))]
3928   "TARGET_SH1"
3929   "rotr %0"
3930   [(set_attr "type" "arith")])
3932 (define_insn "rotlsi3_16"
3933   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3934         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
3935                    (const_int 16)))]
3936   "TARGET_SH1"
3937   "swap.w       %1,%0"
3938   [(set_attr "type" "arith")])
3940 (define_expand "rotlsi3"
3941   [(set (match_operand:SI 0 "arith_reg_dest")
3942         (rotate:SI (match_operand:SI 1 "arith_reg_operand")
3943                    (match_operand:SI 2 "const_int_operand")))]
3944   "TARGET_SH1"
3946   static const char rot_tab[] = {
3947     000, 000, 000, 000, 000, 000, 010, 001,
3948     001, 001, 011, 013, 003, 003, 003, 003,
3949     003, 003, 003, 003, 003, 013, 012, 002,
3950     002, 002, 010, 000, 000, 000, 000, 000,
3951   };
3953   int count = INTVAL (operands[2]);
3954   int choice = rot_tab[count];
3955   if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
3956     FAIL;
3957   choice &= 7;
3958   switch (choice)
3959     {
3960     case 0:
3961       emit_move_insn (operands[0], operands[1]);
3962       count -= (count & 16) * 2;
3963       break;
3964     case 3:
3965      emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
3966      count -= 16;
3967      break;
3968     case 1:
3969     case 2:
3970       {
3971         rtx parts[2];
3972         parts[0] = gen_reg_rtx (SImode);
3973         parts[1] = gen_reg_rtx (SImode);
3974         emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
3975         emit_move_insn (parts[choice-1], operands[1]);
3976         emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
3977         emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
3978         emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
3979         count = (count & ~16) - 8;
3980       }
3981     }
3983   for (; count > 0; count--)
3984     emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
3985   for (; count < 0; count++)
3986     emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
3988   DONE;
3991 (define_insn "*rotlhi3_8"
3992   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3993         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
3994                    (const_int 8)))]
3995   "TARGET_SH1"
3996   "swap.b       %1,%0"
3997   [(set_attr "type" "arith")])
3999 (define_expand "rotlhi3"
4000   [(set (match_operand:HI 0 "arith_reg_operand")
4001         (rotate:HI (match_operand:HI 1 "arith_reg_operand")
4002                    (match_operand:HI 2 "const_int_operand")))]
4003   "TARGET_SH1"
4005   if (INTVAL (operands[2]) != 8)
4006     FAIL;
4009 ;; The rotcr and rotcl insns are used primarily in DImode shifts by one.
4010 ;; They can also be used to implement things like
4011 ;;      bool t = a == b;
4012 ;;      int x0 = (y >> 1) | (t << 31);  // rotcr
4013 ;;      int x1 = (y << 1) | t;          // rotcl
4014 (define_insn "rotcr"
4015   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4016         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4017                              (const_int 1))
4018                 (ashift:SI (match_operand:SI 2 "t_reg_operand")
4019                            (const_int 31))))
4020    (set (reg:SI T_REG)
4021         (and:SI (match_dup 1) (const_int 1)))]
4022   "TARGET_SH1"
4023   "rotcr        %0"
4024   [(set_attr "type" "arith")])
4026 (define_insn "rotcl"
4027   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4028         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4029                            (const_int 1))
4030                 (match_operand:SI 2 "t_reg_operand")))
4031    (set (reg:SI T_REG)
4032         (lshiftrt:SI (match_dup 1) (const_int 31)))]
4033   "TARGET_SH1"
4034   "rotcl        %0"
4035   [(set_attr "type" "arith")])
4037 ;; Simplified rotcr version for combine, which allows arbitrary shift
4038 ;; amounts for the reg.  If the shift amount is '1' rotcr can be used
4039 ;; directly.  Otherwise we have to insert a shift in between.
4040 (define_insn_and_split "*rotcr"
4041   [(set (match_operand:SI 0 "arith_reg_dest")
4042         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4043                              (match_operand:SI 2 "const_int_operand"))
4044                 (ashift:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4045                            (const_int 31))))
4046    (clobber (reg:SI T_REG))]
4047   "TARGET_SH1"
4048   "#"
4049   "&& can_create_pseudo_p ()"
4050   [(const_int 0)]
4052   if (INTVAL (operands[2]) > 1)
4053     {
4054       const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4055       rtx prev_set_t_insn = NULL_RTX;
4056       rtx tmp_t_reg = NULL_RTX;
4058       /* If we're going to emit a shift sequence that clobbers the T_REG,
4059          try to find the previous insn that sets the T_REG and emit the 
4060          shift insn before that insn, to remove the T_REG dependency.
4061          If the insn that sets the T_REG cannot be found, store the T_REG
4062          in a temporary reg and restore it after the shift.  */
4063       if (sh_lshrsi_clobbers_t_reg_p (shift_count)
4064           && ! sh_dynamicalize_shift_p (shift_count))
4065         {
4066           prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4068           /* Skip the nott insn, which was probably inserted by the splitter
4069              of *rotcr_neg_t.  Don't use one of the recog functions
4070              here during insn splitting, since that causes problems in later
4071              passes.  */
4072           if (prev_set_t_insn != NULL_RTX)
4073             {
4074               rtx pat = PATTERN (prev_set_t_insn);
4075               if (GET_CODE (pat) == SET
4076                   && t_reg_operand (XEXP (pat, 0), SImode)
4077                   && negt_reg_operand (XEXP (pat, 1), SImode))
4078               prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4079             }
4081           if (! (prev_set_t_insn != NULL_RTX
4082                  && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4083                  && ! reg_referenced_p (get_t_reg_rtx (),
4084                                         PATTERN (prev_set_t_insn))))
4085             {
4086               prev_set_t_insn = NULL_RTX;
4087               tmp_t_reg = gen_reg_rtx (SImode);
4088               emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4089             } 
4090         }
4092       rtx shift_result = gen_reg_rtx (SImode);
4093       rtx shift_insn = gen_lshrsi3 (shift_result, operands[1], shift_count);
4094       operands[1] = shift_result;
4096       /* Emit the shift insn before the insn that sets T_REG, if possible.  */
4097       if (prev_set_t_insn != NULL_RTX)
4098         emit_insn_before (shift_insn, prev_set_t_insn);
4099       else
4100         emit_insn (shift_insn);
4102       /* Restore T_REG if it has been saved before.  */
4103       if (tmp_t_reg != NULL_RTX)
4104         emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4105     }
4107   /* For the rotcr insn to work, operands[3] must be in T_REG.
4108      If it is not we can get it there by shifting it right one bit.
4109      In this case T_REG is not an input for this insn, thus we don't have to
4110      pay attention as of where to insert the shlr insn.  */
4111   if (! t_reg_operand (operands[3], SImode))
4112     {
4113       /* We don't care about the shifted result here, only the T_REG.  */
4114       emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4115       operands[3] = get_t_reg_rtx ();
4116     }
4118   emit_insn (gen_rotcr (operands[0], operands[1], operands[3]));
4119   DONE;
4122 ;; If combine tries the same as above but with swapped operands, split
4123 ;; it so that it will try the pattern above.
4124 (define_split
4125   [(set (match_operand:SI 0 "arith_reg_dest")
4126         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4127                            (const_int 31))
4128                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4129                              (match_operand:SI 3 "const_int_operand"))))]
4130   "TARGET_SH1 && can_create_pseudo_p ()"
4131   [(parallel [(set (match_dup 0)
4132                    (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4133                            (ashift:SI (match_dup 1) (const_int 31))))
4134               (clobber (reg:SI T_REG))])])
4136 ;; Basically the same as the rotcr pattern above, but for rotcl.
4137 ;; FIXME: Fold copy pasted split code for rotcr and rotcl.
4138 (define_insn_and_split "*rotcl"
4139   [(set (match_operand:SI 0 "arith_reg_dest")
4140         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4141                            (match_operand:SI 2 "const_int_operand"))
4142                 (and:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4143                         (const_int 1))))
4144    (clobber (reg:SI T_REG))]
4145   "TARGET_SH1"
4146   "#"
4147   "&& can_create_pseudo_p ()"
4148   [(const_int 0)]
4150   gcc_assert (INTVAL (operands[2]) > 0);
4152   if (INTVAL (operands[2]) > 1)
4153     {
4154       const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4155       rtx prev_set_t_insn = NULL_RTX;
4156       rtx tmp_t_reg = NULL_RTX;
4158       /* If we're going to emit a shift sequence that clobbers the T_REG,
4159          try to find the previous insn that sets the T_REG and emit the 
4160          shift insn before that insn, to remove the T_REG dependency.
4161          If the insn that sets the T_REG cannot be found, store the T_REG
4162          in a temporary reg and restore it after the shift.  */
4163       if (sh_ashlsi_clobbers_t_reg_p (shift_count)
4164           && ! sh_dynamicalize_shift_p (shift_count))
4165         {
4166           prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4168           /* Skip the nott insn, which was probably inserted by the splitter
4169              of *rotcl_neg_t.  Don't use one of the recog functions
4170              here during insn splitting, since that causes problems in later
4171              passes.  */
4172           if (prev_set_t_insn != NULL_RTX)
4173             {
4174               rtx pat = PATTERN (prev_set_t_insn);
4175               if (GET_CODE (pat) == SET
4176                   && t_reg_operand (XEXP (pat, 0), SImode)
4177                   && negt_reg_operand (XEXP (pat, 1), SImode))
4178               prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4179             }
4181           if (! (prev_set_t_insn != NULL_RTX
4182                  && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4183                  && ! reg_referenced_p (get_t_reg_rtx (),
4184                                         PATTERN (prev_set_t_insn))))
4185             {
4186               prev_set_t_insn = NULL_RTX;
4187               tmp_t_reg = gen_reg_rtx (SImode);
4188               emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4189             } 
4190         }
4192       rtx shift_result = gen_reg_rtx (SImode);
4193       rtx shift_insn = gen_ashlsi3 (shift_result, operands[1], shift_count);
4194       operands[1] = shift_result;
4196       /* Emit the shift insn before the insn that sets T_REG, if possible.  */
4197       if (prev_set_t_insn != NULL_RTX)
4198         emit_insn_before (shift_insn, prev_set_t_insn);
4199       else
4200         emit_insn (shift_insn);
4202       /* Restore T_REG if it has been saved before.  */
4203       if (tmp_t_reg != NULL_RTX)
4204         emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4205     }
4207   /* For the rotcl insn to work, operands[3] must be in T_REG.
4208      If it is not we can get it there by shifting it right one bit.
4209      In this case T_REG is not an input for this insn, thus we don't have to
4210      pay attention as of where to insert the shlr insn.  */
4211   if (! t_reg_operand (operands[3], SImode))
4212     {
4213       /* We don't care about the shifted result here, only the T_REG.  */
4214       emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4215       operands[3] = get_t_reg_rtx ();
4216     }
4218   emit_insn (gen_rotcl (operands[0], operands[1], operands[3]));
4219   DONE;
4222 ;; rotcl combine pattern variations
4223 (define_insn_and_split "*rotcl"
4224   [(set (match_operand:SI 0 "arith_reg_dest")
4225         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4226                            (match_operand:SI 2 "const_int_operand"))
4227                 (match_operand:SI 3 "t_reg_operand")))
4228    (clobber (reg:SI T_REG))]
4229   "TARGET_SH1"
4230   "#"
4231   "&& can_create_pseudo_p ()"
4232   [(parallel [(set (match_dup 0)
4233                    (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4234                            (and:SI (match_dup 3) (const_int 1))))
4235               (clobber (reg:SI T_REG))])])
4237 (define_insn_and_split "*rotcl"
4238   [(set (match_operand:SI 0 "arith_reg_dest")
4239         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4240                         (const_int 1))
4241                 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4242                            (match_operand:SI 3 "const_int_operand"))))
4243    (clobber (reg:SI T_REG))]
4244   "TARGET_SH1"
4245   "#"
4246   "&& can_create_pseudo_p ()"
4247   [(parallel [(set (match_dup 0)
4248                    (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4249                            (and:SI (match_dup 1) (const_int 1))))
4250               (clobber (reg:SI T_REG))])])
4252 (define_insn_and_split "*rotcl"
4253   [(set (match_operand:SI 0 "arith_reg_dest")
4254         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4255                            (match_operand:SI 2 "const_int_operand"))
4256                 (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4257                              (const_int 31))))
4258    (clobber (reg:SI T_REG))]
4259   "TARGET_SH1"
4260   "#"
4261   "&& can_create_pseudo_p ()"
4262   [(parallel [(set (match_dup 0)
4263                    (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4264                            (and:SI (reg:SI T_REG) (const_int 1))))
4265               (clobber (reg:SI T_REG))])]
4267   /* We don't care about the result of the left shift, only the T_REG.  */
4268   emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4271 (define_insn_and_split "*rotcl"
4272   [(set (match_operand:SI 0 "arith_reg_dest")
4273         (ior:SI (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4274                              (const_int 31))
4275                 (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4276                            (match_operand:SI 2 "const_int_operand"))))
4277    (clobber (reg:SI T_REG))]
4278   "TARGET_SH1"
4279   "#"
4280   "&& can_create_pseudo_p ()"
4281   [(parallel [(set (match_dup 0)
4282                    (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4283                            (and:SI (reg:SI T_REG) (const_int 1))))
4284               (clobber (reg:SI T_REG))])]
4286   /* We don't care about the result of the left shift, only the T_REG.  */
4287   emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4290 ;; rotcr combine bridge pattern which will make combine try out more
4291 ;; complex patterns.
4292 (define_insn_and_split "*rotcr"
4293   [(set (match_operand:SI 0 "arith_reg_dest")
4294         (ashift:SI (match_operand:SI 1 "t_reg_operand") (const_int 31)))]
4295   "TARGET_SH1"
4296   "#"
4297   "&& 1"
4298   [(set (match_dup 0) (match_dup 1))
4299    (parallel [(set (match_dup 0)
4300                    (ior:SI (lshiftrt:SI (match_dup 0) (const_int 1))
4301                            (ashift:SI (match_dup 1) (const_int 31))))
4302               (set (reg:SI T_REG)
4303                    (and:SI (match_dup 0) (const_int 1)))])])
4305 (define_insn_and_split "*rotcr"
4306   [(set (match_operand:SI 0 "arith_reg_dest")
4307         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
4308                         (const_int -2147483648)) ;; 0xffffffff80000000
4309                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4310                              (const_int 1))))
4311    (clobber (reg:SI T_REG))]
4312   "TARGET_SH1"
4313   "#"
4314   "&& can_create_pseudo_p ()"
4315   [(const_int 0)]
4317   rtx tmp = gen_reg_rtx (SImode);
4318   emit_insn (gen_shll (tmp, operands[1]));
4319   emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ()));
4320   DONE;
4323 ;; rotcr combine patterns for rotating in the negated T_REG value.
4324 (define_insn_and_split "*rotcr_neg_t"
4325   [(set (match_operand:SI 0 "arith_reg_dest")
4326         (ior:SI (match_operand:SI 1 "negt_reg_shl31_operand")
4327                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4328                              (match_operand:SI 3 "const_int_operand"))))
4329    (clobber (reg:SI T_REG))]
4330   "TARGET_SH1"
4331   "#"
4332   "&& can_create_pseudo_p ()"
4333   [(parallel [(set (match_dup 0)
4334                    (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4335                            (ashift:SI (reg:SI T_REG) (const_int 31))))
4336               (clobber (reg:SI T_REG))])]
4338   emit_insn (gen_nott (get_t_reg_rtx ()));
4341 (define_insn_and_split "*rotcr_neg_t"
4342   [(set (match_operand:SI 0 "arith_reg_dest")
4343         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4344                              (match_operand:SI 2 "const_int_operand"))
4345                 (match_operand:SI 3 "negt_reg_shl31_operand")))
4346    (clobber (reg:SI T_REG))]
4347   "TARGET_SH1"
4348   "#"
4349   "&& can_create_pseudo_p ()"
4350   [(parallel [(set (match_dup 0)
4351                    (ior:SI (lshiftrt:SI (match_dup 1) (match_dup 2))
4352                            (ashift:SI (reg:SI T_REG) (const_int 31))))
4353               (clobber (reg:SI T_REG))])]
4355   emit_insn (gen_nott (get_t_reg_rtx ()));
4358 ;; rotcl combine patterns for rotating in the negated T_REG value.
4359 ;; For some strange reason these have to be specified as splits which combine
4360 ;; will pick up.  If they are specified as insn_and_split like the
4361 ;; *rotcr_neg_t patterns above, combine would recognize them successfully
4362 ;; but not emit them on non-SH2A targets.
4363 (define_split
4364   [(set (match_operand:SI 0 "arith_reg_dest")
4365         (ior:SI (match_operand:SI 1 "negt_reg_operand")
4366                 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4367                            (match_operand:SI 3 "const_int_operand"))))]
4368   "TARGET_SH1"
4369   [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4370    (parallel [(set (match_dup 0)
4371                    (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4372                            (and:SI (reg:SI T_REG) (const_int 1))))
4373               (clobber (reg:SI T_REG))])])
4375 (define_split
4376   [(set (match_operand:SI 0 "arith_reg_dest")
4377         (ior:SI (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4378                            (match_operand:SI 3 "const_int_operand"))
4379                 (match_operand:SI 1 "negt_reg_operand")))]
4380   "TARGET_SH1"
4381   [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4382    (parallel [(set (match_dup 0)
4383                    (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4384                            (and:SI (reg:SI T_REG) (const_int 1))))
4385               (clobber (reg:SI T_REG))])])
4387 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4388 ;; SImode shift left
4390 (define_expand "ashlsi3"
4391   [(set (match_operand:SI 0 "arith_reg_operand" "")
4392         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
4393                    (match_operand:SI 2 "shift_count_operand" "")))]
4394   ""
4396   if (TARGET_SHMEDIA)
4397     {
4398       emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
4399       DONE;
4400     }
4401   if (TARGET_DYNSHIFT
4402       && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
4403       operands[2] = force_reg (SImode, operands[2]);
4405   /*  If the ashlsi3_* insn is going to clobber the T_REG it must be
4406       expanded here.  */
4407   if (CONST_INT_P (operands[2])
4408       && sh_ashlsi_clobbers_t_reg_p (operands[2])
4409       && ! sh_dynamicalize_shift_p (operands[2]))
4410     {
4411       emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1],
4412                                            operands[2]));
4413       DONE;
4414     }
4416   /* Expand a library call for the dynamic shift.  */
4417   if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
4418     {
4419       emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
4420       rtx funcaddr = gen_reg_rtx (Pmode);
4421       function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC);
4422       emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr));
4424       DONE;
4425     }
4428 (define_insn "ashlsi3_k"
4429   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4430         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
4431                    (match_operand:SI 2 "p27_shift_count_operand" "M,P27")))]
4432   "TARGET_SH1"
4433   "@
4434         add     %0,%0
4435         shll%O2 %0"
4436   [(set_attr "type" "arith")])
4438 (define_insn_and_split "ashlsi3_d"
4439   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4440         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4441                    (match_operand:SI 2 "shift_count_operand" "r")))]
4442   "TARGET_DYNSHIFT"
4443   "shld %2,%0"
4444   "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
4445    && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4446   [(const_int 0)]
4448   if (satisfies_constraint_P27 (operands[2]))
4449     {
4450       emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2]));
4451       DONE;
4452     }
4453   else if (! satisfies_constraint_P27 (operands[2]))
4454     {
4455       /* This must happen before reload, otherwise the constant will be moved
4456          into a register due to the "r" constraint, after which this split
4457          cannot be done anymore.
4458          Unfortunately the move insn will not always be eliminated.
4459          Also, here we must not create a shift sequence that clobbers the
4460          T_REG.  */
4461       emit_move_insn (operands[0], operands[1]);
4462       gen_shifty_op (ASHIFT, operands);
4463       DONE;
4464     }
4466   FAIL;
4468   [(set_attr "type" "dyn_shift")])
4470 ;; If dynamic shifts are not available use a library function.
4471 ;; By specifying the pattern we reduce the number of call clobbered regs.
4472 ;; In order to make combine understand the truncation of the shift amount
4473 ;; operand we have to allow it to use pseudo regs for the shift operands.
4474 (define_insn "ashlsi3_d_call"
4475   [(set (match_operand:SI 0 "arith_reg_dest" "=z")
4476         (ashift:SI (reg:SI R4_REG)
4477                    (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
4478                            (const_int 31))))
4479    (use (match_operand:SI 2 "arith_reg_operand" "r"))
4480    (clobber (reg:SI T_REG))
4481    (clobber (reg:SI PR_REG))]
4482   "TARGET_SH1 && !TARGET_DYNSHIFT"
4483   "jsr  @%2%#"
4484   [(set_attr "type" "sfunc")
4485    (set_attr "needs_delay_slot" "yes")])
4487 (define_insn_and_split "ashlsi3_n"
4488   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4489         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4490                    (match_operand:SI 2 "not_p27_shift_count_operand" "")))]
4491   "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4492   "#"
4493   "&& (reload_completed
4494        || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4495   [(const_int 0)]
4497   if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4498     {
4499       /* If this pattern was picked and dynamic shifts are supported, switch
4500          to dynamic shift pattern before reload.  */
4501       operands[2] = force_reg (SImode, operands[2]);
4502       emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4503     }
4504   else
4505     gen_shifty_op (ASHIFT, operands);
4507   DONE;
4510 (define_insn_and_split "ashlsi3_n_clobbers_t"
4511   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4512         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4513                    (match_operand:SI 2 "not_p27_shift_count_operand" "")))
4514    (clobber (reg:SI T_REG))]
4515   "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])"
4516   "#"
4517   "&& (reload_completed || INTVAL (operands[2]) == 31
4518        || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4519   [(const_int 0)]
4521   if (INTVAL (operands[2]) == 31)
4522     {
4523       /* If the shift amount is 31 we split into a different sequence before
4524          reload so that it gets a chance to allocate R0 for the sequence.
4525          If it fails to do so (due to pressure on R0), it will take one insn
4526          more for the and.  */
4527       emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx));
4528       emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4529     }
4530   else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4531     {
4532       /* If this pattern was picked and dynamic shifts are supported, switch
4533          to dynamic shift pattern before reload.  */
4534       operands[2] = force_reg (SImode, operands[2]);
4535       emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4536     }
4537   else
4538     gen_shifty_op (ASHIFT, operands);
4540   DONE;
4543 (define_insn "shll"
4544   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4545         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
4546    (set (reg:SI T_REG)
4547         (lt:SI (match_dup 1) (const_int 0)))]
4548   "TARGET_SH1"
4549   "shll %0"
4550   [(set_attr "type" "arith")])
4552 (define_insn "*ashlsi_c_void"
4553   [(set (reg:SI T_REG)
4554         (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
4555    (clobber (match_scratch:SI 1 "=0"))]
4556   "TARGET_SH1 && cse_not_expected"
4557   "shll %0"
4558   [(set_attr "type" "arith")])
4560 (define_peephole2
4561   [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
4562    (set (reg:SI T_REG)
4563         (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
4564   "TARGET_SH1
4565    && peep2_reg_dead_p (2, operands[0])
4566    && peep2_reg_dead_p (2, operands[1])"
4567   [(const_int 0)]
4569   emit_insn (gen_shll (operands[1], operands[1]));
4570   DONE;
4573 (define_insn "ashlsi3_media"
4574   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4575         (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
4576                    (match_operand:SI 2 "shift_count_operand" "r,n")))]
4577   "TARGET_SHMEDIA"
4578   "@
4579         shlld.l %1, %2, %0
4580         shlli.l %1, %2, %0"
4581   [(set_attr "type" "arith_media")
4582    (set_attr "highpart" "ignore")])
4584 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4585 ;; HImode shift left
4587 (define_expand "ashlhi3"
4588   [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
4589                    (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
4590                               (match_operand:SI 2 "nonmemory_operand" "")))
4591               (clobber (reg:SI T_REG))])]
4592   "TARGET_SH1"
4594   if (!CONST_INT_P (operands[2]))
4595     FAIL;
4596   /* It may be possible to call gen_ashlhi3 directly with more generic
4597      operands.  Make sure operands[1] is a HImode register here.  */
4598   if (!arith_reg_operand (operands[1], HImode))
4599     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4602 (define_insn "ashlhi3_k"
4603   [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4604         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
4605                    (match_operand:HI 2 "const_int_operand" "M,P27")))]
4606   "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
4607   "@
4608         add     %0,%0
4609         shll%O2 %0"
4610   [(set_attr "type" "arith")])
4612 (define_insn_and_split "*ashlhi3_n"
4613   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4614         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
4615                    (match_operand:HI 2 "const_int_operand" "n")))
4616    (clobber (reg:SI T_REG))]
4617   "TARGET_SH1"
4618   "#"
4619   "&& reload_completed"
4620   [(use (reg:SI R0_REG))]
4622   gen_shifty_hi_op (ASHIFT, operands);
4623   DONE;
4626 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4627 ;; DImode shift left
4629 (define_expand "ashldi3"
4630   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4631                    (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
4632                               (match_operand:DI 2 "immediate_operand" "")))
4633               (clobber (reg:SI T_REG))])]
4634   ""
4636   if (TARGET_SHMEDIA)
4637     {
4638       emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
4639       DONE;
4640     }
4641   if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
4642     {
4643       emit_insn (gen_ashldi3_k (operands[0], operands[1]));
4644       DONE;
4645     }
4646   else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32)
4647     {
4648       emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
4649       DONE;
4650     }
4651   else
4652     FAIL;
4655 ;; Expander for DImode shift left with SImode operations.
4656 (define_expand "ashldi3_std"
4657   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4658         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4659                    (match_operand:DI 2 "const_int_operand" "n")))]
4660   "TARGET_SH1 && INTVAL (operands[2]) < 32"
4662   rtx low_src = gen_lowpart (SImode, operands[1]);
4663   rtx high_src = gen_highpart (SImode, operands[1]);
4664   rtx dst = gen_reg_rtx (DImode);
4665   rtx low_dst = gen_lowpart (SImode, dst);
4666   rtx high_dst = gen_highpart (SImode, dst);
4667   rtx tmp0 = gen_reg_rtx (SImode);
4668   rtx tmp1 = gen_reg_rtx (SImode);
4670   emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
4671   emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));  
4672   emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));  
4673   emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
4674   emit_move_insn (operands[0], dst);
4675   DONE;
4678 (define_insn_and_split "ashldi3_k"
4679   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4680         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
4681                    (const_int 1)))
4682    (clobber (reg:SI T_REG))]
4683   "TARGET_SH1"
4684   "#"
4685   "&& reload_completed"
4686   [(const_int 0)]
4688   rtx high = gen_highpart (SImode, operands[0]);
4689   rtx low = gen_lowpart (SImode, operands[0]);
4690   emit_insn (gen_shll (low, low));
4691   emit_insn (gen_rotcl (high, high, get_t_reg_rtx ()));
4692   DONE;
4695 (define_insn "ashldi3_media"
4696   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4697         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4698                    (match_operand:DI 2 "shift_count_operand" "r,n")))]
4699   "TARGET_SHMEDIA"
4700   "@
4701         shlld   %1, %2, %0
4702         shlli   %1, %2, %0"
4703   [(set_attr "type" "arith_media")])
4705 (define_insn "*ashldisi3_media"
4706   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4707         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4708                    (match_operand:DI 2 "const_int_operand" "n")))]
4709   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4710   "shlli.l      %1, %2, %0"
4711   [(set_attr "type" "arith_media")
4712    (set_attr "highpart" "ignore")])
4714 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4715 ;; SImode arithmetic shift right
4717 ;; We can't do HImode right shifts correctly unless we start out with an
4718 ;; explicit zero / sign extension; doing that would result in worse overall
4719 ;; code, so just let the machine independent code widen the mode.
4720 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
4722 (define_expand "ashrsi3"
4723   [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
4724                    (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
4725                                 (match_operand:SI 2 "nonmemory_operand" "")))
4726               (clobber (reg:SI T_REG))])]
4727   ""
4729   if (TARGET_SHMEDIA)
4730     {
4731       emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
4732       DONE;
4733     }
4734   if (expand_ashiftrt (operands))
4735     DONE;
4736   else
4737     FAIL;
4740 (define_insn "shar"
4741   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4742         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4743                      (const_int 1)))
4744    (set (reg:SI T_REG)
4745         (and:SI (match_dup 1) (const_int 1)))]
4746   "TARGET_SH1"
4747   "shar %0"
4748   [(set_attr "type" "arith")])
4750 (define_insn "ashrsi3_k"
4751   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4752         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4753                      (match_operand:SI 2 "const_int_operand" "M")))
4754    (clobber (reg:SI T_REG))]
4755   "TARGET_SH1 && INTVAL (operands[2]) == 1"
4756   "shar %0"
4757   [(set_attr "type" "arith")])
4759 (define_insn_and_split "ashrsi2_16"
4760   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4761         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
4762                      (const_int 16)))]
4763   "TARGET_SH1"
4764   "#"
4765   "&& 1"
4766   [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
4767    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
4769   operands[2] = gen_lowpart (HImode, operands[0]);
4772 (define_insn_and_split "ashrsi2_31"
4773   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4774         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4775                      (const_int 31)))
4776    (clobber (reg:SI T_REG))]
4777   "TARGET_SH1"
4778   "#"
4779   "&& 1"
4780   [(const_int 0)]
4782   emit_insn (gen_shll (operands[0], operands[1]));
4783   emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
4784   DONE;
4787 (define_insn "ashrsi3_d"
4788   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4789         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4790                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4791   "TARGET_DYNSHIFT"
4792   "shad %2,%0"
4793   [(set_attr "type" "dyn_shift")])
4795 (define_insn "ashrsi3_n"
4796   [(set (reg:SI R4_REG)
4797         (ashiftrt:SI (reg:SI R4_REG)
4798                      (match_operand:SI 0 "const_int_operand" "i")))
4799    (clobber (reg:SI T_REG))
4800    (clobber (reg:SI PR_REG))
4801    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
4802   "TARGET_SH1"
4803   "jsr  @%1%#"
4804   [(set_attr "type" "sfunc")
4805    (set_attr "needs_delay_slot" "yes")])
4807 (define_insn "ashrsi3_media"
4808   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4809         (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
4810                      (match_operand:SI 2 "shift_count_operand" "r,n")))]
4811   "TARGET_SHMEDIA"
4812   "@
4813         shard.l %1, %2, %0
4814         shari.l %1, %2, %0"
4815   [(set_attr "type" "arith_media")
4816    (set_attr "highpart" "ignore")])
4818 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4819 ;; DImode arithmetic shift right
4821 (define_expand "ashrdi3"
4822   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4823                    (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4824                                 (match_operand:DI 2 "immediate_operand" "")))
4825               (clobber (reg:SI T_REG))])]
4826   ""
4828   if (TARGET_SHMEDIA)
4829     {
4830       emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4831       DONE;
4832     }
4833   if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
4834     FAIL;
4837 (define_insn_and_split "ashrdi3_k"
4838   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4839         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4840                      (const_int 1)))
4841    (clobber (reg:SI T_REG))]
4842   "TARGET_SH1"
4843   "#"
4844   "&& reload_completed"
4845   [(const_int 0)]
4847   rtx high = gen_highpart (SImode, operands[0]);
4848   rtx low = gen_lowpart (SImode, operands[0]);
4849   emit_insn (gen_shar (high, high));
4850   emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
4851   DONE;
4854 (define_insn "ashrdi3_media"
4855   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4856         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4857                      (match_operand:DI 2 "shift_count_operand" "r,n")))]
4858   "TARGET_SHMEDIA
4859    && (arith_reg_dest (operands[0], DImode)
4860        || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
4861   "@
4862         shard   %1, %2, %0
4863         shari   %1, %2, %0"
4864   [(set_attr "type" "arith_media")])
4866 (define_insn "*ashrdisi3_media"
4867   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4868         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4869                      (match_operand:DI 2 "const_int_operand" "n")))]
4870   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4871   "shari.l      %1, %2, %0"
4872   [(set_attr "type" "arith_media")
4873    (set_attr "highpart" "ignore")])
4875 (define_insn "ashrdisi3_media_high"
4876   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4877         (truncate:SI
4878            (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4879                         (match_operand:DI 2 "const_int_operand" "n"))))]
4880   "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
4881   "shari        %1, %2, %0"
4882   [(set_attr "type" "arith_media")])
4884 (define_insn "ashrdisi3_media_opaque"
4885   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4886         (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
4887                     (match_operand:DI 2 "const_int_operand" "n")]
4888          UNSPEC_ASHIFTRT))]
4889   "TARGET_SHMEDIA"
4890   "shari        %1, %2, %0"
4891   [(set_attr "type" "arith_media")])
4893 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4894 ;; SImode logical shift right
4896 (define_expand "lshrsi3"
4897   [(set (match_operand:SI 0 "arith_reg_dest" "")
4898         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
4899                      (match_operand:SI 2 "shift_count_operand" "")))]
4900   ""
4902   if (TARGET_SHMEDIA)
4903     {
4904       emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
4905       DONE;
4906     }
4908   /* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn
4909      here, otherwise the pattern will never match due to the shift amount reg
4910      negation.  */
4911   if (TARGET_DYNSHIFT
4912       && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
4913     {
4914       rtx neg_count = force_reg (SImode,
4915                                  gen_int_mode (- INTVAL (operands[2]), SImode));
4916       emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
4917       DONE;
4918     }
4920   if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2]))
4921     {
4922       rtx neg_count = gen_reg_rtx (SImode);
4923       emit_insn (gen_negsi2 (neg_count, operands[2]));
4924       emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
4925       DONE;
4926     }
4928   /* If the lshrsi3_* insn is going to clobber the T_REG it must be
4929      expanded here.  */
4930   if (CONST_INT_P (operands[2])
4931       && sh_lshrsi_clobbers_t_reg_p (operands[2])
4932       && ! sh_dynamicalize_shift_p (operands[2]))
4933     {
4934       emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1],
4935                  operands[2]));
4936       DONE;
4937     }
4939   /* Expand a library call for the dynamic shift.  */
4940   if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
4941     {
4942       emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
4943       rtx funcaddr = gen_reg_rtx (Pmode);
4944       function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC);
4945       emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr));
4946       DONE;
4947     }
4950 (define_insn "lshrsi3_k"
4951   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4952         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4953                      (match_operand:SI 2 "p27_rshift_count_operand" "P27")))]
4954   "TARGET_SH1"
4955   "shlr%O2      %0"
4956   [(set_attr "type" "arith")])
4958 (define_insn_and_split "lshrsi3_d"
4959   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4960         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4961                      (neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))]
4962   "TARGET_DYNSHIFT"
4963   "shld %2,%0"
4964   "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
4965    && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
4966   [(const_int 0)]
4968   if (satisfies_constraint_P27 (operands[2]))
4969     {
4970       /* This will not be done for a shift amount of 1, because it would
4971          clobber the T_REG.  */
4972       emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2]));
4973       DONE;
4974     }
4975   else if (! satisfies_constraint_P27 (operands[2]))
4976     {
4977       /* This must happen before reload, otherwise the constant will be moved
4978          into a register due to the "r" constraint, after which this split
4979          cannot be done anymore.
4980          Unfortunately the move insn will not always be eliminated.
4981          Also, here we must not create a shift sequence that clobbers the
4982          T_REG.  */
4983       emit_move_insn (operands[0], operands[1]);
4984       gen_shifty_op (LSHIFTRT, operands);
4985       DONE;
4986     }
4988   FAIL;
4990   [(set_attr "type" "dyn_shift")])
4992 ;; If dynamic shifts are not available use a library function.
4993 ;; By specifying the pattern we reduce the number of call clobbered regs.
4994 ;; In order to make combine understand the truncation of the shift amount
4995 ;; operand we have to allow it to use pseudo regs for the shift operands.
4996 (define_insn "lshrsi3_d_call"
4997   [(set (match_operand:SI 0 "arith_reg_dest" "=z")
4998         (lshiftrt:SI (reg:SI R4_REG)
4999                      (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
5000                              (const_int 31))))
5001    (use (match_operand:SI 2 "arith_reg_operand" "r"))
5002    (clobber (reg:SI T_REG))
5003    (clobber (reg:SI PR_REG))]
5004   "TARGET_SH1 && !TARGET_DYNSHIFT"
5005   "jsr  @%2%#"
5006   [(set_attr "type" "sfunc")
5007    (set_attr "needs_delay_slot" "yes")])
5009 (define_insn_and_split "lshrsi3_n"
5010   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5011         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5012                      (match_operand:SI 2 "not_p27_rshift_count_operand")))]
5013   "TARGET_SH1 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5014   "#"
5015   "&& (reload_completed
5016        || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5017   [(const_int 0)]
5019   if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5020     {
5021       /* If this pattern was picked and dynamic shifts are supported, switch
5022          to dynamic shift pattern before reload.  */
5023       operands[2] = force_reg (SImode,
5024                                gen_int_mode (- INTVAL (operands[2]), SImode));
5025       emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5026     }
5027   else
5028     gen_shifty_op (LSHIFTRT, operands);
5030   DONE;
5033 ;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of
5034 ;; the shlr pattern.
5035 (define_insn_and_split "lshrsi3_n_clobbers_t"
5036   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5037         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5038                      (match_operand:SI 2 "not_p27_rshift_count_operand")))
5039    (clobber (reg:SI T_REG))]
5040   "TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])"
5041   "#"
5042   "&& (reload_completed || INTVAL (operands[2]) == 31
5043        || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5044   [(const_int 0)]
5046   if (INTVAL (operands[2]) == 31)
5047     {
5048       emit_insn (gen_shll (operands[0], operands[1]));
5049       emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
5050     }
5051   else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5052     {
5053       /* If this pattern was picked and dynamic shifts are supported, switch
5054          to dynamic shift pattern before reload.  */
5055       operands[2] = force_reg (SImode,
5056                                gen_int_mode (- INTVAL (operands[2]), SImode));
5057       emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5058     }
5059   else
5060     gen_shifty_op (LSHIFTRT, operands);
5062   DONE;
5065 (define_insn "shlr"
5066   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5067         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5068                      (const_int 1)))
5069    (set (reg:SI T_REG)
5070         (and:SI (match_dup 1) (const_int 1)))]
5071   "TARGET_SH1"
5072   "shlr %0"
5073   [(set_attr "type" "arith")])
5075 (define_insn "lshrsi3_media"
5076   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5077         (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5078                      (match_operand:SI 2 "shift_count_operand" "r,n")))]
5079   "TARGET_SHMEDIA"
5080   "@
5081         shlrd.l %1, %2, %0
5082         shlri.l %1, %2, %0"
5083   [(set_attr "type" "arith_media")
5084    (set_attr "highpart" "ignore")])
5086 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5087 ;; DImode logical shift right
5089 (define_expand "lshrdi3"
5090   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5091                    (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
5092                                (match_operand:DI 2 "immediate_operand" "")))
5093              (clobber (reg:SI T_REG))])]
5094   ""
5096   if (TARGET_SHMEDIA)
5097     {
5098       emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
5099       DONE;
5100     }
5101   if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5102     FAIL;
5105 (define_insn_and_split "lshrdi3_k"
5106   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5107         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5108                      (const_int 1)))
5109    (clobber (reg:SI T_REG))]
5110   "TARGET_SH1"
5111   "#"
5112   "&& reload_completed"
5113   [(const_int 0)]
5115   rtx high = gen_highpart (SImode, operands[0]);
5116   rtx low = gen_lowpart (SImode, operands[0]);
5117   emit_insn (gen_shlr (high, high));
5118   emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5119   DONE;
5122 (define_insn "lshrdi3_media"
5123   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5124         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5125                      (match_operand:DI 2 "shift_count_operand" "r,n")))]
5126   "TARGET_SHMEDIA
5127    && (arith_reg_dest (operands[0], DImode)
5128        || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
5129   "@
5130         shlrd   %1, %2, %0
5131         shlri   %1, %2, %0"
5132   [(set_attr "type" "arith_media")])
5134 (define_insn "*lshrdisi3_media"
5135   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5136         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5137                      (match_operand:DI 2 "const_int_operand" "n")))]
5138   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5139   "shlri.l      %1, %2, %0"
5140   [(set_attr "type" "arith_media")
5141    (set_attr "highpart" "ignore")])
5143 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5144 ;; Combined left/right shifts
5146 (define_split
5147   [(set (match_operand:SI 0 "register_operand" "")
5148         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5149                            (match_operand:SI 2 "const_int_operand" ""))
5150                 (match_operand:SI 3 "const_int_operand" "")))]
5151   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5152   [(use (reg:SI R0_REG))]
5154   if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5155     FAIL;
5156   DONE;
5159 (define_split
5160   [(set (match_operand:SI 0 "register_operand" "")
5161         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5162                            (match_operand:SI 2 "const_int_operand" ""))
5163                 (match_operand:SI 3 "const_int_operand" "")))
5164    (clobber (reg:SI T_REG))]
5165   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5166   [(use (reg:SI R0_REG))]
5168   if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5169     FAIL;
5170   DONE;
5173 (define_insn ""
5174   [(set (match_operand:SI 0 "register_operand" "=r")
5175         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5176                            (match_operand:SI 2 "const_int_operand" "n"))
5177                 (match_operand:SI 3 "const_int_operand" "n")))
5178    (clobber (reg:SI T_REG))]
5179   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
5180   "#"
5181   [(set (attr "length")
5182         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5183                (const_string "4")
5184                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5185                (const_string "6")
5186                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5187                (const_string "8")
5188                (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
5189                (const_string "10")
5190                (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
5191                (const_string "12")
5192                (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
5193                (const_string "14")
5194                (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
5195                (const_string "16")]
5196               (const_string "18")))
5197    (set_attr "type" "arith")])
5199 (define_insn ""
5200   [(set (match_operand:SI 0 "register_operand" "=z")
5201         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5202                            (match_operand:SI 2 "const_int_operand" "n"))
5203                 (match_operand:SI 3 "const_int_operand" "n")))
5204    (clobber (reg:SI T_REG))]
5205   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
5206   "#"
5207   [(set (attr "length")
5208         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5209                (const_string "4")
5210                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5211                (const_string "6")
5212                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5213                (const_string "8")]
5214               (const_string "10")))
5215    (set_attr "type" "arith")])
5217 ;; shift left / and combination with a scratch register: The combine pass
5218 ;; does not accept the individual instructions, even though they are
5219 ;; cheap.  But it needs a precise description so that it is usable after
5220 ;; reload.
5221 (define_insn "and_shl_scratch"
5222   [(set (match_operand:SI 0 "register_operand" "=r,&r")
5223         (lshiftrt:SI
5224          (ashift:SI
5225           (and:SI
5226            (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
5227                         (match_operand:SI 2 "const_int_operand" "N,n"))
5228            (match_operand:SI 3 "" "0,r"))
5229           (match_operand:SI 4 "const_int_operand" "n,n"))
5230          (match_operand:SI 5 "const_int_operand" "n,n")))
5231    (clobber (reg:SI T_REG))]
5232   "TARGET_SH1"
5233   "#"
5234   [(set (attr "length")
5235         (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
5236                (const_string "4")
5237                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
5238                (const_string "6")
5239                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
5240                (const_string "8")
5241                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
5242                (const_string "10")]
5243               (const_string "12")))
5244    (set_attr "type" "arith")])
5246 (define_split
5247   [(set (match_operand:SI 0 "register_operand" "")
5248         (lshiftrt:SI
5249          (ashift:SI
5250           (and:SI
5251            (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
5252                         (match_operand:SI 2 "const_int_operand" ""))
5253            (match_operand:SI 3 "register_operand" ""))
5254           (match_operand:SI 4 "const_int_operand" ""))
5255          (match_operand:SI 5 "const_int_operand" "")))
5256    (clobber (reg:SI T_REG))]
5257   "TARGET_SH1"
5258   [(use (reg:SI R0_REG))]
5260   rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
5262   if (INTVAL (operands[2]))
5263     {
5264       gen_shifty_op (LSHIFTRT, operands);
5265     }
5266   emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
5267   operands[2] = operands[4];
5268   gen_shifty_op (ASHIFT, operands);
5269   if (INTVAL (operands[5]))
5270     {
5271       operands[2] = operands[5];
5272       gen_shifty_op (LSHIFTRT, operands);
5273     }
5274   DONE;
5277 ;; signed left/right shift combination.
5278 (define_split
5279   [(set (match_operand:SI 0 "register_operand" "")
5280         (sign_extract:SI
5281          (ashift:SI (match_operand:SI 1 "register_operand" "")
5282                     (match_operand:SI 2 "const_int_operand" ""))
5283          (match_operand:SI 3 "const_int_operand" "")
5284          (const_int 0)))
5285    (clobber (reg:SI T_REG))]
5286   "TARGET_SH1"
5287   [(use (reg:SI R0_REG))]
5289   if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1]))
5290     FAIL;
5291   DONE;
5294 (define_insn "shl_sext_ext"
5295   [(set (match_operand:SI 0 "register_operand" "=r")
5296         (sign_extract:SI
5297          (ashift:SI (match_operand:SI 1 "register_operand" "0")
5298                     (match_operand:SI 2 "const_int_operand" "n"))
5299          (match_operand:SI 3 "const_int_operand" "n")
5300          (const_int 0)))
5301    (clobber (reg:SI T_REG))]
5302   "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
5303   "#"
5304   [(set (attr "length")
5305         (cond [(match_test "shl_sext_length (insn)")
5306                (const_string "2")
5307                (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
5308                (const_string "4")
5309                (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5310                (const_string "6")
5311                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5312                (const_string "8")
5313                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5314                (const_string "10")
5315                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5316                (const_string "12")
5317                (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
5318                (const_string "14")
5319                (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
5320                (const_string "16")]
5321               (const_string "18")))
5322     (set_attr "type" "arith")])
5324 (define_insn "shl_sext_sub"
5325   [(set (match_operand:SI 0 "register_operand" "=z")
5326         (sign_extract:SI
5327          (ashift:SI (match_operand:SI 1 "register_operand" "0")
5328                     (match_operand:SI 2 "const_int_operand" "n"))
5329          (match_operand:SI 3 "const_int_operand" "n")
5330          (const_int 0)))
5331    (clobber (reg:SI T_REG))]
5332   "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
5333   "#"
5334   [(set (attr "length")
5335         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5336                (const_string "6")
5337                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5338                (const_string "8")
5339                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5340                (const_string "10")
5341                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5342                (const_string "12")]
5343               (const_string "14")))
5344     (set_attr "type" "arith")])
5346 ;; These patterns are found in expansions of DImode shifts by 16, and
5347 ;; allow the xtrct instruction to be generated from C source.
5349 (define_insn "xtrct_left"
5350   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5351         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5352                            (const_int 16))
5353                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
5354                              (const_int 16))))]
5355   "TARGET_SH1"
5356   "xtrct        %1,%0"
5357   [(set_attr "type" "arith")])
5359 (define_insn "xtrct_right"
5360   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5361         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5362                              (const_int 16))
5363                 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
5364                            (const_int 16))))]
5365   "TARGET_SH1"
5366   "xtrct        %2,%0"
5367   [(set_attr "type" "arith")])
5369 ;; -------------------------------------------------------------------------
5370 ;; Unary arithmetic
5371 ;; -------------------------------------------------------------------------
5373 (define_insn "negc"
5374   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5375         (neg:SI (plus:SI (reg:SI T_REG)
5376                          (match_operand:SI 1 "arith_reg_operand" "r"))))
5377    (set (reg:SI T_REG)
5378         (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
5379                (const_int 0)))]
5380   "TARGET_SH1"
5381   "negc %1,%0"
5382   [(set_attr "type" "arith")])
5384 ;; A simplified version of the negc insn, where the exact value of the
5385 ;; T bit doesn't matter.  This is easier for combine to pick up.
5386 ;; Notice that '0 - x - 1' is the same as '~x', thus we don't specify
5387 ;; extra patterns for this case.
5388 (define_insn "*negc"
5389   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5390         (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5391                   (match_operand:SI 2 "t_reg_operand" "")))
5392    (clobber (reg:SI T_REG))]
5393   "TARGET_SH1"
5394   "negc %1,%0"
5395   [(set_attr "type" "arith")])
5397 (define_insn "*negdi_media"
5398   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5399         (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
5400   "TARGET_SHMEDIA"
5401   "sub  r63, %1, %0"
5402   [(set_attr "type" "arith_media")])
5404 ;; Don't expand immediately because otherwise neg:DI (abs:DI) will not be
5405 ;; combined.
5406 (define_expand "negdi2"
5407   [(parallel [(set (match_operand:DI 0 "arith_reg_dest")
5408                    (neg:DI (match_operand:DI 1 "arith_reg_operand")))
5409               (clobber (reg:SI T_REG))])]
5410   "TARGET_SH1")
5412 (define_insn_and_split "*negdi2"
5413   [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
5414         (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))
5415    (clobber (reg:SI T_REG))]
5416   "TARGET_SH1"
5417   "#"
5418   "&& reload_completed"
5419   [(const_int 0)]
5421   emit_insn (gen_clrt ());
5422   emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
5423                        gen_lowpart (SImode, operands[1])));
5424   emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
5425                        gen_highpart (SImode, operands[1])));
5426   DONE;
5429 (define_insn "negsi2"
5430   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5431         (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5432   "TARGET_SH1"
5433   "neg  %1,%0"
5434   [(set_attr "type" "arith")])
5436 (define_insn_and_split "one_cmplsi2"
5437   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5438         (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5439   "TARGET_SH1"
5440   "not  %1,%0"
5441   "&& can_create_pseudo_p ()"
5442   [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0)))
5443    (set (match_dup 0) (reg:SI T_REG))]
5445 /* PR 54685
5446    If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following
5447    sequence:
5449      (set (reg0) (not:SI (reg0) (reg1)))
5450      (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31)))
5451                 (clobber (reg:SI T_REG))])
5453    ... match and combine the sequence manually in the split pass after the
5454    combine pass.  Notice that combine does try the target pattern of this
5455    split, but if the pattern is added it interferes with other patterns, in
5456    particular with the div0s comparisons.
5457    This could also be done with a peephole but doing it here before register
5458    allocation can save one temporary.
5459    When we're here, the not:SI pattern obviously has been matched already
5460    and we only have to see whether the following insn is the left shift.  */
5462   rtx i = next_nonnote_insn_bb (curr_insn);
5463   if (i == NULL_RTX || !NONJUMP_INSN_P (i))
5464     FAIL;
5466   rtx p = PATTERN (i);
5467   if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2)
5468     FAIL;
5470   rtx p0 = XVECEXP (p, 0, 0);
5471   rtx p1 = XVECEXP (p, 0, 1);
5473   if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31)))  */
5474       GET_CODE (p0) == SET
5475       && GET_CODE (XEXP (p0, 1)) == LSHIFTRT
5476       && REG_P (XEXP (XEXP (p0, 1), 0))
5477       && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0])
5478       && CONST_INT_P (XEXP (XEXP (p0, 1), 1))
5479       && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31
5481       /* (clobber (reg:SI T_REG))  */
5482       && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0))
5483       && REGNO (XEXP (p1, 0)) == T_REG)
5484     {
5485       operands[0] = XEXP (p0, 0);
5486       set_insn_deleted (i);
5487     }
5488   else
5489     FAIL;
5491   [(set_attr "type" "arith")])
5493 (define_expand "one_cmpldi2"
5494   [(set (match_operand:DI 0 "arith_reg_dest" "")
5495         (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
5496                 (const_int -1)))]
5497   "TARGET_SHMEDIA" "")
5499 (define_expand "abs<mode>2"
5500   [(parallel [(set (match_operand:SIDI 0 "arith_reg_dest")
5501                    (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
5502               (clobber (reg:SI T_REG))])]
5503   "TARGET_SH1")
5505 (define_insn_and_split "*abs<mode>2"
5506   [(set (match_operand:SIDI 0 "arith_reg_dest")
5507         (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
5508    (clobber (reg:SI T_REG))]
5509   "TARGET_SH1"
5510   "#"
5511   "&& can_create_pseudo_p ()"
5512   [(const_int 0)]
5514   if (<MODE>mode == SImode)
5515     emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5516   else
5517     {
5518       rtx high_src = gen_highpart (SImode, operands[1]);
5519       emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5520     }
5522   emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
5523                                  const1_rtx));
5524   DONE;
5527 (define_insn_and_split "*negabs<mode>2"
5528   [(set (match_operand:SIDI 0 "arith_reg_dest")
5529         (neg:SIDI (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))))
5530    (clobber (reg:SI T_REG))]
5531   "TARGET_SH1"
5532   "#"
5533   "&& can_create_pseudo_p ()"
5534   [(const_int 0)]
5536   if (<MODE>mode == SImode)
5537     emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5538   else
5539     {
5540       rtx high_src = gen_highpart (SImode, operands[1]);
5541       emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5542     }
5544   emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
5545                                  const0_rtx));
5546   DONE;
5549 ;; The SH4 202 can do zero-offset branches without pipeline stalls.
5550 ;; This can be used as some kind of conditional execution, which is useful
5551 ;; for abs.
5552 ;; Actually the instruction scheduling should decide whether to use a
5553 ;; zero-offset branch or not for any generic case involving a single
5554 ;; instruction on SH4 202.
5556 (define_insn_and_split "negsi_cond"
5557   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5558         (if_then_else
5559           (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand" "M,N"))
5560           (match_operand:SI 1 "arith_reg_operand" "0,0")
5561           (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
5562   "TARGET_SH1 && TARGET_ZDCBRANCH"
5564   static const char* alt[] =
5565   {
5566        "bt      0f"     "\n"
5567     "   neg     %2,%0"  "\n"
5568     "0:",
5570        "bf      0f"     "\n"
5571     "   neg     %2,%0"  "\n"
5572     "0:"
5573   };
5574   return alt[which_alternative];
5576   "TARGET_SH1 && ! TARGET_ZDCBRANCH"
5577   [(const_int 0)]
5579   rtx skip_neg_label = gen_label_rtx ();
5581   emit_move_insn (operands[0], operands[1]);
5583   emit_jump_insn (INTVAL (operands[3])
5584                   ? gen_branch_true (skip_neg_label)
5585                   : gen_branch_false (skip_neg_label));
5587   emit_label_after (skip_neg_label,
5588                     emit_insn (gen_negsi2 (operands[0], operands[1])));
5589   DONE;
5591   [(set_attr "type" "arith") ;; poor approximation
5592    (set_attr "length" "4")])
5594 (define_insn_and_split "negdi_cond"
5595   [(set (match_operand:DI 0 "arith_reg_dest")
5596         (if_then_else
5597           (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand"))
5598           (match_operand:DI 1 "arith_reg_operand")
5599           (neg:DI (match_operand:DI 2 "arith_reg_operand"))))
5600    (clobber (reg:SI T_REG))]
5601   "TARGET_SH1"
5602   "#"
5603   "&& can_create_pseudo_p ()"
5604   [(const_int 0)]
5606   rtx skip_neg_label = gen_label_rtx ();
5608   emit_move_insn (operands[0], operands[1]);
5610   emit_jump_insn (INTVAL (operands[3]) 
5611                   ? gen_branch_true (skip_neg_label)
5612                   : gen_branch_false (skip_neg_label));
5614   if (!INTVAL (operands[3]))
5615     emit_insn (gen_clrt ());
5617   emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
5618                        gen_lowpart (SImode, operands[1])));
5619   emit_label_after (skip_neg_label,
5620                     emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
5621                                          gen_highpart (SImode, operands[1]))));
5622   DONE;
5625 (define_expand "bswapsi2"
5626   [(set (match_operand:SI 0 "arith_reg_dest" "")
5627         (bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))]
5628   "TARGET_SH1"
5630   if (! can_create_pseudo_p ())
5631     FAIL;
5632   else
5633     {
5634       rtx tmp0 = gen_reg_rtx (SImode);
5635       rtx tmp1 = gen_reg_rtx (SImode);
5637       emit_insn (gen_swapbsi2 (tmp0, operands[1]));
5638       emit_insn (gen_rotlsi3_16 (tmp1, tmp0));
5639       emit_insn (gen_swapbsi2 (operands[0], tmp1));
5640       DONE;
5641     }
5644 (define_insn "swapbsi2"
5645   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5646         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
5647                         (const_int 4294901760))
5648                 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5649                                 (const_int 65280))
5650                         (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5651                                 (const_int 255)))))]
5652   "TARGET_SH1"
5653   "swap.b       %1,%0"
5654   [(set_attr "type" "arith")])
5656 ;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying
5657 ;; partial byte swap expressions such as...
5658 ;;   ((x & 0xFF) << 8) | ((x >> 8) & 0xFF).
5659 ;; ...which are currently not handled by the tree optimizers.
5660 ;; The combine pass will not initially try to combine the full expression,
5661 ;; but only some sub-expressions.  In such a case the *swapbisi2_and_shl8
5662 ;; pattern acts as an intermediate pattern that will eventually lead combine
5663 ;; to the swapbsi2 pattern above.
5664 ;; As a side effect this also improves code that does (x & 0xFF) << 8
5665 ;; or (x << 8) & 0xFF00.
5666 (define_insn_and_split "*swapbisi2_and_shl8"
5667   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5668         (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5669                                    (const_int 8))
5670                         (const_int 65280))
5671                 (match_operand:SI 2 "arith_reg_operand" "r")))]
5672   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5673   "#"
5674   "&& can_create_pseudo_p ()"
5675   [(const_int 0)]
5677   rtx tmp0 = gen_reg_rtx (SImode);
5678   rtx tmp1 = gen_reg_rtx (SImode);
5680   emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1])));
5681   emit_insn (gen_swapbsi2 (tmp1, tmp0));
5682   emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2]));
5683   DONE;
5686 ;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another
5687 ;; intermediate pattern that will help the combine pass arriving at swapbsi2.
5688 (define_insn_and_split "*swapbhisi2"
5689   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5690         (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5691                                    (const_int 8))
5692                         (const_int 65280))
5693                 (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))]
5694   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5695   "#"
5696   "&& can_create_pseudo_p ()"
5697   [(const_int 0)]
5699   rtx tmp = gen_reg_rtx (SImode);
5701   emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1])));
5702   emit_insn (gen_swapbsi2 (operands[0], tmp));
5703   DONE;
5706 ;; In some cases the swapbsi2 pattern might leave a sequence such as...
5707 ;;   swap.b  r4,r4
5708 ;;   mov     r4,r0
5710 ;; which can be simplified to...
5711 ;;   swap.b  r4,r0
5712 (define_peephole2
5713   [(set (match_operand:SI 0 "arith_reg_dest" "")
5714         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5715                         (const_int 4294901760))
5716                 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5717                                 (const_int 65280))
5718                         (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5719                                 (const_int 255)))))
5720    (set (match_operand:SI 2 "arith_reg_dest" "")
5721         (match_dup 0))]
5722   "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
5723   [(set (match_dup 2)
5724         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5725                         (const_int 4294901760))
5726                 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5727                                 (const_int 65280))
5728                         (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5729                                 (const_int 255)))))])
5732 ;; -------------------------------------------------------------------------
5733 ;; Zero extension instructions
5734 ;; -------------------------------------------------------------------------
5736 (define_insn "zero_extendsidi2"
5737   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5738         (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
5739   "TARGET_SHMEDIA"
5740   "addz.l       %1, r63, %0"
5741   [(set_attr "type" "arith_media")
5742    (set_attr "highpart" "extend")])
5744 (define_insn "zero_extendhidi2"
5745   [(set (match_operand:DI 0 "register_operand" "=r,r")
5746         (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5747   "TARGET_SHMEDIA"
5748   "@
5749         #
5750         ld%M1.uw        %m1, %0"
5751   [(set_attr "type" "*,load_media")
5752    (set (attr "highpart")
5753         (cond [(match_test "sh_contains_memref_p (insn)")
5754                (const_string "user")]
5755               (const_string "ignore")))])
5757 (define_split
5758   [(set (match_operand:DI 0 "register_operand" "")
5759         (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
5760   "TARGET_SHMEDIA && reload_completed"
5761   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
5762    (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
5764   if (GET_CODE (operands[1]) == TRUNCATE)
5765     operands[1] = XEXP (operands[1], 0);
5768 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
5769 ;; reload the entire truncate expression.
5770 (define_insn_and_split "*loaddi_trunc"
5771   [(set (match_operand 0 "any_register_operand" "=r")
5772         (truncate (match_operand:DI 1 "memory_operand" "m")))]
5773   "TARGET_SHMEDIA && reload_completed"
5774   "#"
5775   "TARGET_SHMEDIA && reload_completed"
5776   [(set (match_dup 0) (match_dup 1))]
5778   operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
5781 (define_insn "zero_extendqidi2"
5782   [(set (match_operand:DI 0 "register_operand" "=r,r")
5783         (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5784   "TARGET_SHMEDIA"
5785   "@
5786         andi    %1, 255, %0
5787         ld%M1.ub        %m1, %0"
5788   [(set_attr "type" "arith_media,load_media")
5789    (set (attr "highpart")
5790         (cond [(match_test "sh_contains_memref_p (insn)")
5791                (const_string "user")]
5792               (const_string "ignore")))])
5794 (define_expand "zero_extend<mode>si2"
5795   [(set (match_operand:SI 0 "arith_reg_dest")
5796         (zero_extend:SI (match_operand:QIHI 1 "zero_extend_operand")))])
5798 (define_insn_and_split "*zero_extend<mode>si2_compact"
5799   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5800         (zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
5801   "TARGET_SH1"
5802   "extu.<bw>    %1,%0"
5803   "&& can_create_pseudo_p ()"
5804   [(set (match_dup 0) (match_dup 2))]
5806   /* Sometimes combine fails to combine a T bit or negated T bit store to a
5807      reg with a following zero extension.  In the split pass after combine,
5808      try to figure the extended reg was set.  If it originated from the T
5809      bit we can replace the zero extension with a reg move, which will be
5810      eliminated.  Notice that this also helps the *cbranch_t splitter when
5811      it tries to post-combine tests and conditional branches, as it does not
5812      check for zero extensions.  */
5813   operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
5814   if (operands[2] == NULL_RTX)
5815     FAIL;
5817   [(set_attr "type" "arith")])
5819 (define_insn "*zero_extendhisi2_media"
5820   [(set (match_operand:SI 0 "register_operand" "=r,r")
5821         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5822   "TARGET_SHMEDIA"
5823   "@
5824         #
5825         ld%M1.uw        %m1, %0"
5826   [(set_attr "type" "arith_media,load_media")
5827    (set (attr "highpart")
5828         (cond [(match_test "sh_contains_memref_p (insn)")
5829                (const_string "user")]
5830               (const_string "ignore")))])
5832 (define_split
5833   [(set (match_operand:SI 0 "register_operand" "")
5834         (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
5835   "TARGET_SHMEDIA && reload_completed"
5836   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5837    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5839   rtx op1 = operands[1];
5841   if (GET_CODE (op1) == TRUNCATE)
5842     op1 = XEXP (op1, 0);
5843   operands[2]
5844     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
5845                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
5848 (define_insn "*zero_extendqisi2_media"
5849   [(set (match_operand:SI 0 "register_operand" "=r,r")
5850         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5851   "TARGET_SHMEDIA"
5852   "@
5853         andi    %1, 255, %0
5854         ld%M1.ub        %m1, %0"
5855   [(set_attr "type" "arith_media,load_media")
5856    (set (attr "highpart")
5857         (cond [(match_test "sh_contains_memref_p (insn)")
5858                (const_string "user")]
5859               (const_string "ignore")))])
5861 (define_insn "zero_extendqihi2"
5862   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
5863         (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
5864   "TARGET_SH1"
5865   "extu.b       %1,%0"
5866   [(set_attr "type" "arith")])
5868 ;; SH2A supports two zero extending load instructions: movu.b and movu.w.
5869 ;; They could also be used for simple memory addresses like @Rn by setting
5870 ;; the displacement value to zero.  However, doing so too early results in
5871 ;; missed opportunities for other optimizations such as post-inc or index
5872 ;; addressing loads.
5873 ;; Although the 'zero_extend_movu_operand' predicate does not allow simple
5874 ;; register addresses (an address without a displacement, index, post-inc),
5875 ;; zero-displacement addresses might be generated during reload, wich are
5876 ;; simplified to simple register addresses in turn.  Thus, we have to
5877 ;; provide the Sdd and Sra alternatives in the patterns.
5878 (define_insn "*zero_extend<mode>si2_disp_mem"
5879   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5880         (zero_extend:SI
5881           (match_operand:QIHI 1 "zero_extend_movu_operand" "Sdd,Sra")))]
5882   "TARGET_SH2A"
5883   "@
5884         movu.<bw>       %1,%0
5885         movu.<bw>       @(0,%t1),%0"
5886   [(set_attr "type" "load")
5887    (set_attr "length" "4")])
5889 ;; Convert the zero extending loads in sequences such as:
5890 ;;      movu.b  @(1,r5),r0      movu.w  @(2,r5),r0
5891 ;;      mov.b   r0,@(1,r4)      mov.b   r0,@(1,r4)
5893 ;; back to sign extending loads like:
5894 ;;      mov.b   @(1,r5),r0      mov.w   @(2,r5),r0
5895 ;;      mov.b   r0,@(1,r4)      mov.b   r0,@(1,r4)
5897 ;; if the extension type is irrelevant.  The sign extending mov.{b|w} insn
5898 ;; is only 2 bytes in size if the displacement is {K04|K05}.
5899 ;; If the displacement is greater it doesn't matter, so we convert anyways.
5900 (define_peephole2
5901   [(set (match_operand:SI 0 "arith_reg_dest" "")
5902         (zero_extend:SI (match_operand 1 "displacement_mem_operand" "")))
5903    (set (match_operand 2 "general_operand" "")
5904         (match_operand 3 "arith_reg_operand" ""))]
5905   "TARGET_SH2A
5906    && REGNO (operands[0]) == REGNO (operands[3])
5907    && peep2_reg_dead_p (2, operands[0])
5908    && GET_MODE_SIZE (GET_MODE (operands[2]))
5909       <= GET_MODE_SIZE (GET_MODE (operands[1]))"
5910   [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
5911    (set (match_dup 2) (match_dup 3))])
5913 ;; Fold sequences such as
5914 ;;      mov.b   @r3,r7
5915 ;;      extu.b  r7,r7
5916 ;; into
5917 ;;      movu.b  @(0,r3),r7
5918 ;; This does not reduce the code size but the number of instructions is
5919 ;; halved, which results in faster code.
5920 (define_peephole2
5921   [(set (match_operand:SI 0 "arith_reg_dest" "")
5922         (sign_extend:SI (match_operand 1 "simple_mem_operand" "")))
5923    (set (match_operand:SI 2 "arith_reg_dest" "")
5924         (zero_extend:SI (match_operand 3 "arith_reg_operand" "")))]
5925   "TARGET_SH2A
5926    && GET_MODE (operands[1]) == GET_MODE (operands[3])
5927    && (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode)
5928    && REGNO (operands[0]) == REGNO (operands[3])
5929    && (REGNO (operands[2]) == REGNO (operands[0])
5930        || peep2_reg_dead_p (2, operands[0]))"
5931   [(set (match_dup 2) (zero_extend:SI (match_dup 4)))]
5933   operands[4]
5934     = replace_equiv_address (operands[1],
5935                              gen_rtx_PLUS (SImode, XEXP (operands[1], 0),
5936                                            const0_rtx));
5939 ;; -------------------------------------------------------------------------
5940 ;; Sign extension instructions
5941 ;; -------------------------------------------------------------------------
5943 ;; ??? This should be a define expand.
5944 ;; ??? Or perhaps it should be dropped?
5946 ;; convert_move generates good code for SH[1-4].
5947 (define_insn "extendsidi2"
5948   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
5949         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
5950   "TARGET_SHMEDIA"
5951   "@
5952         add.l   %1, r63, %0
5953         ld%M1.l %m1, %0
5954         fmov.sl %1, %0"
5955   [(set_attr "type" "arith_media,load_media,fpconv_media")
5956    (set (attr "highpart")
5957         (cond [(match_test "sh_contains_memref_p (insn)")
5958                (const_string "user")]
5959               (const_string "extend")))])
5961 (define_insn "extendhidi2"
5962   [(set (match_operand:DI 0 "register_operand" "=r,r")
5963         (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5964   "TARGET_SHMEDIA"
5965   "@
5966         #
5967         ld%M1.w %m1, %0"
5968   [(set_attr "type" "*,load_media")
5969    (set (attr "highpart")
5970         (cond [(match_test "sh_contains_memref_p (insn)")
5971                (const_string "user")]
5972               (const_string "ignore")))])
5974 (define_split
5975   [(set (match_operand:DI 0 "register_operand" "")
5976         (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
5977   "TARGET_SHMEDIA && reload_completed"
5978   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
5979    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
5981   if (GET_CODE (operands[1]) == TRUNCATE)
5982     operands[1] = XEXP (operands[1], 0);
5985 (define_insn "extendqidi2"
5986   [(set (match_operand:DI 0 "register_operand" "=r,r")
5987         (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5988   "TARGET_SHMEDIA"
5989   "@
5990         #
5991         ld%M1.b %m1, %0"
5992   [(set_attr "type" "*,load_media")
5993    (set (attr "highpart")
5994         (cond [(match_test "sh_contains_memref_p (insn)")
5995                (const_string "user")]
5996               (const_string "ignore")))])
5998 (define_split
5999   [(set (match_operand:DI 0 "register_operand" "")
6000         (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
6001   "TARGET_SHMEDIA && reload_completed"
6002   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
6003    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
6005   if (GET_CODE (operands[1]) == TRUNCATE)
6006     operands[1] = XEXP (operands[1], 0);
6009 (define_expand "extend<mode>si2"
6010   [(set (match_operand:SI 0 "arith_reg_dest")
6011         (sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))])
6013 (define_insn "*extendhisi2_media"
6014   [(set (match_operand:SI 0 "register_operand" "=r,r")
6015         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6016   "TARGET_SHMEDIA"
6017   "@
6018         #
6019         ld%M1.w %m1, %0"
6020   [(set_attr "type" "arith_media,load_media")
6021    (set (attr "highpart")
6022         (cond [(match_test "sh_contains_memref_p (insn)")
6023                (const_string "user")]
6024               (const_string "ignore")))])
6026 (define_split
6027   [(set (match_operand:SI 0 "register_operand" "")
6028         (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6029   "TARGET_SHMEDIA && reload_completed"
6030   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6031    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
6033   rtx op1 = operands[1];
6034   if (GET_CODE (op1) == TRUNCATE)
6035     op1 = XEXP (op1, 0);
6036   operands[2]
6037     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6038                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
6041 (define_insn_and_split "*extend<mode>si2_compact_reg"
6042   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6043         (sign_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
6044   "TARGET_SH1"
6045   "exts.<bw>    %1,%0"
6046   "&& can_create_pseudo_p ()"
6047   [(set (match_dup 0) (match_dup 2))]
6049   /* Sometimes combine fails to combine a T bit or negated T bit store to a
6050      reg with a following sign extension.  In the split pass after combine,
6051      try to figure the extended reg was set.  If it originated from the T
6052      bit we can replace the sign extension with a reg move, which will be
6053      eliminated.  */
6054   operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
6055   if (operands[2] == NULL_RTX)
6056     FAIL;
6058   [(set_attr "type" "arith")])
6060 ;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute.
6061 ;; See movqi insns.
6062 (define_insn "*extend<mode>si2_compact_mem_disp"
6063   [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
6064         (sign_extend:SI
6065           (mem:QIHI
6066             (plus:SI
6067               (match_operand:SI 1 "arith_reg_operand" "%r,r")
6068               (match_operand:SI 2 "const_int_operand" "<disp04>,N")))))]
6069   "TARGET_SH1 && ! TARGET_SH2A
6070    && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
6071   "@
6072         mov.<bw>        @(%O2,%1),%0
6073         mov.<bw>        @%1,%0"
6074   [(set_attr "type" "load")])
6076 (define_insn "*extend<mode>si2_compact_mem_disp"
6077   [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
6078         (sign_extend:SI
6079           (mem:QIHI
6080             (plus:SI
6081               (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6082               (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>")))))]
6083   "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
6084   "@
6085         mov.<bw>        @(%O2,%1),%0
6086         mov.<bw>        @%1,%0
6087         mov.<bw>        @(%O2,%1),%0"
6088   [(set_attr "type" "load")
6089    (set_attr "length" "2,2,4")])
6091 ;; The *_snd patterns will take care of other QImode/HImode addressing
6092 ;; modes than displacement addressing.  They must be defined _after_ the
6093 ;; displacement addressing patterns.  Otherwise the displacement addressing
6094 ;; patterns will not be picked.
6095 (define_insn "*extend<mode>si2_compact_snd"
6096   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6097         (sign_extend:SI
6098           (match_operand:QIHI 1 "movsrc_no_disp_mem_operand" "Snd")))]
6099   "TARGET_SH1"
6100   "mov.<bw>     %1,%0"
6101   [(set_attr "type" "load")])
6103 (define_insn "*extendqisi2_media"
6104   [(set (match_operand:SI 0 "register_operand" "=r,r")
6105         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6106   "TARGET_SHMEDIA"
6107   "@
6108         #
6109         ld%M1.b %m1, %0"
6110   [(set_attr "type" "arith_media,load_media")
6111    (set (attr "highpart")
6112         (cond [(match_test "sh_contains_memref_p (insn)")
6113                (const_string "user")]
6114               (const_string "ignore")))])
6116 (define_split
6117   [(set (match_operand:SI 0 "register_operand" "")
6118         (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
6119   "TARGET_SHMEDIA && reload_completed"
6120   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
6121    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
6123   rtx op1 = operands[1];
6124   if (GET_CODE (op1) == TRUNCATE)
6125     op1 = XEXP (op1, 0);
6126   operands[2]
6127     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6128                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
6131 (define_expand "extendqihi2"
6132   [(set (match_operand:HI 0 "arith_reg_dest" "")
6133         (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "")))]
6134   ""
6135   "")
6137 (define_insn "*extendqihi2_compact_reg"
6138   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6139         (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6140   "TARGET_SH1"
6141   "exts.b       %1,%0"
6142   [(set_attr "type" "arith")])
6144 ;; It would seem useful to combine the truncXi patterns into the movXi
6145 ;; patterns, but unary operators are ignored when matching constraints,
6146 ;; so we need separate patterns.
6147 (define_insn "truncdisi2"
6148   [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
6149         (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
6150   "TARGET_SHMEDIA"
6151   "@
6152         add.l   %1, r63, %0
6153         st%M0.l %m0, %1
6154         fst%M0.s        %m0, %T1
6155         fmov.ls %1, %0
6156         fmov.sl %T1, %0
6157         fmov.s  %T1, %0"
6158   [(set_attr "type"   "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")
6159    (set (attr "highpart")
6160         (cond [(match_test "sh_contains_memref_p (insn)")
6161                (const_string "user")]
6162               (const_string "extend")))])
6164 (define_insn "truncdihi2"
6165   [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
6166         (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
6167   "TARGET_SHMEDIA"
6169   static const char* alt[] =
6170   {
6171        "shlli   %1,48,%0"       "\n"
6172     "   shlri   %0,48,%0",
6174        "st%M0.w %m0, %1"
6175   };
6176   return alt[which_alternative];
6178   [(set_attr "type"   "arith_media,store_media")
6179    (set_attr "length" "8,4")
6180    (set (attr "highpart")
6181         (cond [(match_test "sh_contains_memref_p (insn)")
6182                (const_string "user")]
6183               (const_string "extend")))])
6185 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
6186 ; Because we use zero extension, we can't provide signed QImode compares
6187 ; using a simple compare or conditional branch insn.
6188 (define_insn "truncdiqi2"
6189   [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
6190         (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
6191   "TARGET_SHMEDIA"
6192   "@
6193         andi    %1, 255, %0
6194         st%M0.b %m0, %1"
6195   [(set_attr "type"   "arith_media,store")
6196    (set (attr "highpart")
6197         (cond [(match_test "sh_contains_memref_p (insn)")
6198                (const_string "user")]
6199               (const_string "extend")))])
6200 ;; -------------------------------------------------------------------------
6201 ;; Move instructions
6202 ;; -------------------------------------------------------------------------
6204 ;; define push and pop so it is easy for sh.c
6205 ;; We can't use push and pop on SHcompact because the stack must always
6206 ;; be 8-byte aligned.
6208 (define_expand "push"
6209   [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
6210         (match_operand:SI 0 "register_operand" "r,l,x"))]
6211   "TARGET_SH1 && ! TARGET_SH5"
6212   "")
6214 (define_expand "pop"
6215   [(set (match_operand:SI 0 "register_operand" "=r,l,x")
6216         (mem:SI (post_inc:SI (reg:SI SP_REG))))]
6217   "TARGET_SH1 && ! TARGET_SH5"
6218   "")
6220 (define_expand "push_e"
6221   [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
6222                    (match_operand:SF 0 "" ""))
6223               (use (reg:PSI FPSCR_REG))
6224               (clobber (scratch:SI))])]
6225   "TARGET_SH1 && ! TARGET_SH5"
6226   "")
6228 (define_insn "push_fpul"
6229   [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
6230   "TARGET_SH2E && ! TARGET_SH5"
6231   "sts.l        fpul,@-r15"
6232   [(set_attr "type" "fstore")
6233    (set_attr "late_fp_use" "yes")
6234    (set_attr "hit_stack" "yes")])
6236 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
6237 ;; so use that.
6238 (define_expand "push_4"
6239   [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
6240                    (match_operand:DF 0 "" ""))
6241               (use (reg:PSI FPSCR_REG))
6242               (clobber (scratch:SI))])]
6243   "TARGET_SH1 && ! TARGET_SH5"
6244   "")
6246 (define_expand "pop_e"
6247   [(parallel [(set (match_operand:SF 0 "" "")
6248               (mem:SF (post_inc:SI (reg:SI SP_REG))))
6249               (use (reg:PSI FPSCR_REG))
6250               (clobber (scratch:SI))])]
6251   "TARGET_SH1 && ! TARGET_SH5"
6252   "")
6254 (define_insn "pop_fpul"
6255   [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
6256   "TARGET_SH2E && ! TARGET_SH5"
6257   "lds.l        @r15+,fpul"
6258   [(set_attr "type" "load")
6259    (set_attr "hit_stack" "yes")])
6261 (define_expand "pop_4"
6262   [(parallel [(set (match_operand:DF 0 "" "")
6263                    (mem:DF (post_inc:SI (reg:SI SP_REG))))
6264               (use (reg:PSI FPSCR_REG))
6265               (clobber (scratch:SI))])]
6266   "TARGET_SH1 && ! TARGET_SH5"
6267   "")
6269 (define_expand "push_fpscr"
6270   [(const_int 0)]
6271   "TARGET_SH2E"
6273   rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
6274                                                  gen_rtx_PRE_DEC (Pmode,
6275                                                           stack_pointer_rtx)),
6276                                         get_fpscr_rtx ()));
6277   add_reg_note (insn, REG_INC, stack_pointer_rtx);
6278   DONE;
6281 (define_expand "pop_fpscr"
6282   [(const_int 0)]
6283   "TARGET_SH2E"
6285   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
6286                                         gen_frame_mem (PSImode,
6287                                                  gen_rtx_POST_INC (Pmode,
6288                                                           stack_pointer_rtx))));
6289   add_reg_note (insn, REG_INC, stack_pointer_rtx);
6290   DONE;
6293 ;; The clrt and sett patterns can happen as the result of optimization and
6294 ;; insn expansion.
6295 ;; Comparisons might get simplified to a move of zero or 1 into the T reg.
6296 ;; In this case they might not disappear completely, because the T reg is
6297 ;; a fixed hard reg.
6298 ;; When DImode operations that use the T reg as carry/borrow are split into
6299 ;; individual SImode operations, the T reg is usually cleared before the
6300 ;; first SImode insn.
6302 (define_insn "clrt"
6303   [(set (reg:SI T_REG) (const_int 0))]
6304   "TARGET_SH1"
6305   "clrt"
6306   [(set_attr "type" "mt_group")])
6308 (define_insn "sett"
6309   [(set (reg:SI T_REG) (const_int 1))]
6310   "TARGET_SH1"
6311   "sett"
6312   [(set_attr "type" "mt_group")])
6314 ;; Use the combine pass to transform sequences such as
6315 ;;      mov     r5,r0
6316 ;;      add     #1,r0
6317 ;;      shll2   r0
6318 ;;      mov.l   @(r0,r4),r0
6319 ;; into
6320 ;;      shll2   r5
6321 ;;      add     r4,r5
6322 ;;      mov.l   @(4,r5),r0
6324 ;; See also PR 39423.
6325 ;; Notice that these patterns have a T_REG clobber, because the shift
6326 ;; sequence that will be split out might clobber the T_REG.  Ideally, the
6327 ;; clobber would be added conditionally, depending on the result of
6328 ;; sh_ashlsi_clobbers_t_reg_p.  When splitting out the shifts we must go
6329 ;; through the ashlsi3 expander in order to get the right shift insn --
6330 ;; a T_REG clobbering or non-clobbering shift sequence or dynamic shift.
6331 ;; FIXME: Combine never tries this kind of patterns for DImode.
6332 (define_insn_and_split "*movsi_index_disp_load"
6333   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6334         (match_operand:SI 1 "mem_index_disp_operand" "m"))
6335    (clobber (reg:SI T_REG))]
6336   "TARGET_SH1"
6337   "#"
6338   "&& can_create_pseudo_p ()"
6339   [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6340    (set (match_dup 0) (match_dup 7))]
6342   rtx mem = operands[1];
6343   rtx plus0_rtx = XEXP (mem, 0);
6344   rtx plus1_rtx = XEXP (plus0_rtx, 0);
6345   rtx mult_rtx = XEXP (plus1_rtx, 0);
6347   operands[1] = XEXP (mult_rtx, 0);
6348   operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6349   operands[3] = XEXP (plus1_rtx, 1);
6350   operands[4] = XEXP (plus0_rtx, 1);
6351   operands[5] = gen_reg_rtx (SImode);
6352   operands[6] = gen_reg_rtx (SImode);
6353   operands[7] =
6354     replace_equiv_address (mem,
6355                            gen_rtx_PLUS (SImode, operands[6], operands[4]));
6357   emit_insn (gen_ashlsi3 (operands[5], operands[1], operands[2]));
6360 (define_insn_and_split "*movhi_index_disp_load"
6361   [(set (match_operand:SI 0 "arith_reg_dest")
6362         (SZ_EXTEND:SI (match_operand:HI 1 "mem_index_disp_operand")))
6363    (clobber (reg:SI T_REG))]
6364   "TARGET_SH1"
6365   "#"
6366   "&& can_create_pseudo_p ()"
6367   [(const_int 0)]
6369   rtx mem = operands[1];
6370   rtx plus0_rtx = XEXP (mem, 0);
6371   rtx plus1_rtx = XEXP (plus0_rtx, 0);
6372   rtx mult_rtx = XEXP (plus1_rtx, 0);
6374   rtx op_1 = XEXP (mult_rtx, 0);
6375   rtx op_2 = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6376   rtx op_3 = XEXP (plus1_rtx, 1);
6377   rtx op_4 = XEXP (plus0_rtx, 1);
6378   rtx op_5 = gen_reg_rtx (SImode);
6379   rtx op_6 = gen_reg_rtx (SImode);
6380   rtx op_7 = replace_equiv_address (mem, gen_rtx_PLUS (SImode, op_6, op_4));
6382   emit_insn (gen_ashlsi3 (op_5, op_1, op_2));
6383   emit_insn (gen_addsi3 (op_6, op_5, op_3));
6385   if (<CODE> == SIGN_EXTEND)
6386     {
6387       emit_insn (gen_extendhisi2 (operands[0], op_7));
6388       DONE;
6389     }
6390   else if (<CODE> == ZERO_EXTEND)
6391     {
6392       /* On SH2A the movu.w insn can be used for zero extending loads.  */
6393       if (TARGET_SH2A)
6394         emit_insn (gen_zero_extendhisi2 (operands[0], op_7));
6395       else
6396         {
6397           emit_insn (gen_extendhisi2 (operands[0], op_7));
6398           emit_insn (gen_zero_extendhisi2 (operands[0],
6399                                            gen_lowpart (HImode, operands[0])));
6400         }
6401       DONE;
6402     }
6403   else
6404     FAIL;
6407 (define_insn_and_split "*mov<mode>_index_disp_store"
6408   [(set (match_operand:HISI 0 "mem_index_disp_operand" "=m")
6409         (match_operand:HISI 1 "arith_reg_operand" "r"))
6410    (clobber (reg:SI T_REG))]
6411   "TARGET_SH1"
6412   "#"
6413   "&& can_create_pseudo_p ()"
6414   [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6415    (set (match_dup 7) (match_dup 1))]
6417   rtx mem = operands[0];
6418   rtx plus0_rtx = XEXP (mem, 0);
6419   rtx plus1_rtx = XEXP (plus0_rtx, 0);
6420   rtx mult_rtx = XEXP (plus1_rtx, 0);
6422   operands[0] = XEXP (mult_rtx, 0);
6423   operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6424   operands[3] = XEXP (plus1_rtx, 1);
6425   operands[4] = XEXP (plus0_rtx, 1);
6426   operands[5] = gen_reg_rtx (SImode);
6427   operands[6] = gen_reg_rtx (SImode);
6428   operands[7] =
6429     replace_equiv_address (mem,
6430                            gen_rtx_PLUS (SImode, operands[6], operands[4]));
6432   emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2]));
6435 ;; t/r must come after r/r, lest reload will try to reload stuff like
6436 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
6437 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
6438 (define_insn "movsi_i"
6439   [(set (match_operand:SI 0 "general_movdst_operand"
6440             "=r,r,r,r,r,r,m,<,<,x,l,x,l,r")
6441         (match_operand:SI 1 "general_movsrc_operand"
6442          "Q,r,I08,mr,x,l,r,x,l,r,r,>,>,i"))]
6443   "TARGET_SH1
6444    && ! TARGET_SH2E
6445    && ! TARGET_SH2A
6446    && (register_operand (operands[0], SImode)
6447        || register_operand (operands[1], SImode))"
6448   "@
6449         mov.l   %1,%0
6450         mov     %1,%0
6451         mov     %1,%0
6452         mov.l   %1,%0
6453         sts     %1,%0
6454         sts     %1,%0
6455         mov.l   %1,%0
6456         sts.l   %1,%0
6457         sts.l   %1,%0
6458         lds     %1,%0
6459         lds     %1,%0
6460         lds.l   %1,%0
6461         lds.l   %1,%0
6462         fake    %1,%0"
6463   [(set_attr "type" "pcload_si,move,movi8,load_si,mac_gp,prget,store,mac_mem,pstore,gp_mac,prset,mem_mac,pload,pcload_si")
6464    (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
6466 ;; t/r must come after r/r, lest reload will try to reload stuff like
6467 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
6468 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
6469 ;; will require a reload.
6470 ;; ??? We can't include f/f because we need the proper FPSCR setting when
6471 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
6472 (define_insn "movsi_ie"
6473   [(set (match_operand:SI 0 "general_movdst_operand"
6474             "=r,r,r,r,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
6475         (match_operand:SI 1 "general_movsrc_operand"
6476          "Q,r,I08,I20,I28,mr,x,l,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
6477   "(TARGET_SH2E || TARGET_SH2A)
6478    && (register_operand (operands[0], SImode)
6479        || register_operand (operands[1], SImode))"
6480   "@
6481         mov.l   %1,%0
6482         mov     %1,%0
6483         mov     %1,%0
6484         movi20  %1,%0
6485         movi20s %1,%0
6486         mov.l   %1,%0
6487         sts     %1,%0
6488         sts     %1,%0
6489         mov.l   %1,%0
6490         sts.l   %1,%0
6491         sts.l   %1,%0
6492         lds     %1,%0
6493         lds     %1,%0
6494         lds.l   %1,%0
6495         lds.l   %1,%0
6496         lds.l   %1,%0
6497         sts.l   %1,%0
6498         fake    %1,%0
6499         lds     %1,%0
6500         sts     %1,%0
6501         fsts    fpul,%0
6502         flds    %1,fpul
6503         fmov    %1,%0
6504         ! move optimized away"
6505   [(set_attr "type" "pcload_si,move,movi8,move,move,load_si,mac_gp,prget,store,mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore,pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
6506    (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
6507    (set_attr_alternative "length"
6508      [(const_int 2)
6509       (const_int 2)
6510       (const_int 2)
6511       (const_int 4)
6512       (const_int 4)
6513       (if_then_else
6514         (match_test "TARGET_SH2A")
6515         (const_int 4) (const_int 2))
6516       (const_int 2)
6517       (const_int 2)
6518       (if_then_else
6519         (match_test "TARGET_SH2A")
6520         (const_int 4) (const_int 2))
6521       (const_int 2)
6522       (const_int 2)
6523       (const_int 2)
6524       (const_int 2)
6525       (const_int 2)
6526       (const_int 2)
6527       (const_int 2)
6528       (const_int 2)
6529       (const_int 2)
6530       (const_int 2)
6531       (const_int 2)
6532       (const_int 2)
6533       (const_int 2)
6534       (const_int 2)
6535       (const_int 0)])])
6537 (define_insn "movsi_i_lowpart"
6538   [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
6539         (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,r,i"))]
6540    "TARGET_SH1
6541     && (register_operand (operands[0], SImode)
6542         || register_operand (operands[1], SImode))"
6543   "@
6544         mov.l   %1,%0
6545         mov     %1,%0
6546         mov     %1,%0
6547         mov.l   %1,%0
6548         sts     %1,%0
6549         sts     %1,%0
6550         mov.l   %1,%0
6551         fake    %1,%0"
6552   [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,store,pcload")])
6554 (define_insn_and_split "load_ra"
6555   [(set (match_operand:SI 0 "general_movdst_operand" "")
6556         (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
6557   "TARGET_SH1"
6558   "#"
6559   "&& ! currently_expanding_to_rtl"
6560   [(set (match_dup 0) (match_dup 1))]
6562   if (TARGET_SHCOMPACT && crtl->saves_all_registers)
6563     operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
6566 ;; The '?'s in the following constraints may not reflect the time taken
6567 ;; to perform the move. They are there to discourage the use of floating-
6568 ;; point registers for storing integer values.
6569 (define_insn "*movsi_media"
6570   [(set (match_operand:SI 0 "general_movdst_operand"
6571                 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
6572         (match_operand:SI 1 "general_movsrc_operand"
6573          "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
6574   "TARGET_SHMEDIA_FPU
6575    && (register_operand (operands[0], SImode)
6576        || sh_register_operand (operands[1], SImode)
6577        || GET_CODE (operands[1]) == TRUNCATE)"
6578   "@
6579         add.l   %1, r63, %0
6580         movi    %1, %0
6581         #
6582         ld%M1.l %m1, %0
6583         st%M0.l %m0, %N1
6584         fld%M1.s        %m1, %0
6585         fst%M0.s        %m0, %1
6586         fmov.ls %N1, %0
6587         fmov.sl %1, %0
6588         fmov.s  %1, %0
6589         ptabs   %1, %0
6590         gettr   %1, %0
6591         pt      %1, %0"
6592   [(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")
6593    (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
6594    (set (attr "highpart")
6595         (cond [(match_test "sh_contains_memref_p (insn)")
6596                (const_string "user")]
6597               (const_string "ignore")))])
6599 (define_insn "*movsi_media_nofpu"
6600   [(set (match_operand:SI 0 "general_movdst_operand"
6601                 "=r,r,r,r,m,*b,r,*b")
6602         (match_operand:SI 1 "general_movsrc_operand"
6603          "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
6604   "TARGET_SHMEDIA
6605    && (register_operand (operands[0], SImode)
6606        || sh_register_operand (operands[1], SImode)
6607        || GET_CODE (operands[1]) == TRUNCATE)"
6608   "@
6609         add.l   %1, r63, %0
6610         movi    %1, %0
6611         #
6612         ld%M1.l %m1, %0
6613         st%M0.l %m0, %N1
6614         ptabs   %1, %0
6615         gettr   %1, %0
6616         pt      %1, %0"
6617   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
6618    (set_attr "length" "4,4,8,4,4,4,4,12")
6619    (set (attr "highpart")
6620         (cond [(match_test "sh_contains_memref_p (insn)")
6621                (const_string "user")]
6622               (const_string "ignore")))])
6624 (define_expand "movsi_const"
6625   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6626         (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6627                               (const_int 16)] UNSPEC_EXTRACT_S16)))
6628    (set (match_dup 0)
6629         (ior:SI (ashift:SI (match_dup 0) (const_int 16))
6630                 (const:SI (unspec:SI [(match_dup 1)
6631                                       (const_int 0)] UNSPEC_EXTRACT_U16))))]
6632   "TARGET_SHMEDIA && reload_completed
6633    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6635   if (GET_CODE (operands[1]) == LABEL_REF
6636       && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
6637     LABEL_NUSES (XEXP (operands[1], 0)) += 2;
6638   else if (GOTOFF_P (operands[1]))
6639     {
6640       rtx unspec = XEXP (operands[1], 0);
6642       if (! UNSPEC_GOTOFF_P (unspec))
6643         {
6644           unspec = XEXP (unspec, 0);
6645           if (! UNSPEC_GOTOFF_P (unspec))
6646             abort ();
6647         }
6648       if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
6649           && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
6650         LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
6651     }
6654 (define_expand "movsi_const_16bit"
6655   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6656         (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6657                               (const_int 0)] UNSPEC_EXTRACT_S16)))]
6658   "TARGET_SHMEDIA && flag_pic && reload_completed
6659    && GET_CODE (operands[1]) == SYMBOL_REF"
6660   "")
6662 (define_split
6663   [(set (match_operand:SI 0 "arith_reg_dest" "")
6664         (match_operand:SI 1 "immediate_operand" ""))]
6665   "TARGET_SHMEDIA && reload_completed
6666    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6667   [(const_int 0)]
6669   rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
6671   set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
6673   DONE;
6676 (define_split
6677   [(set (match_operand:SI 0 "register_operand" "")
6678         (match_operand:SI 1 "immediate_operand" ""))]
6679   "TARGET_SHMEDIA && reload_completed
6680    && ((CONST_INT_P (operands[1])
6681         && ! satisfies_constraint_I16 (operands[1]))
6682        || GET_CODE (operands[1]) == CONST_DOUBLE)"
6683   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
6685 (define_expand "movsi"
6686   [(set (match_operand:SI 0 "general_movdst_operand" "")
6687         (match_operand:SI 1 "general_movsrc_operand" ""))]
6688   ""
6690   prepare_move_operands (operands, SImode);
6693 (define_expand "ic_invalidate_line"
6694   [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
6695                                 (match_dup 1)] UNSPEC_ICACHE)
6696               (clobber (scratch:SI))])]
6697   "TARGET_HARD_SH4 || TARGET_SH5"
6699   if (TARGET_SHMEDIA)
6700     {
6701       emit_insn (gen_ic_invalidate_line_media (operands[0]));
6702       DONE;
6703     }
6704   else if (TARGET_SHCOMPACT)
6705     {
6706       operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC);
6707       operands[1] = force_reg (Pmode, operands[1]);
6708       emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
6709       DONE;
6710     }
6711   else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
6712     {
6713       emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
6714       DONE;
6715     }
6716   operands[0] = force_reg (Pmode, operands[0]);
6717   operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
6718                                                                Pmode)));
6721 ;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
6722 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
6723 ;; the requirement *1*00 for associative address writes.  The alignment of
6724 ;; %0 implies that its least significant bit is cleared,
6725 ;; thus we clear the V bit of a matching entry if there is one.
6726 (define_insn "ic_invalidate_line_i"
6727   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
6728                      (match_operand:SI 1 "register_operand" "r")]
6729                      UNSPEC_ICACHE)
6730    (clobber (match_scratch:SI 2 "=&r"))]
6731   "TARGET_HARD_SH4"
6733   return       "ocbwb   @%0"    "\n"
6734          "      extu.w  %0,%2"  "\n"
6735          "      or      %1,%2"  "\n"
6736          "      mov.l   %0,@%2";
6738   [(set_attr "length" "8")
6739    (set_attr "type" "cwb")])
6741 (define_insn "ic_invalidate_line_sh4a"
6742   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
6743                     UNSPEC_ICACHE)]
6744   "TARGET_SH4A_ARCH || TARGET_SH4_300"
6746   return       "ocbwb   @%0"    "\n"
6747          "      synco"          "\n"
6748          "      icbi    @%0";
6750   [(set_attr "length" "16")     ;; FIXME: Why 16 and not 6?  Looks like typo.
6751    (set_attr "type" "cwb")])
6753 ;; ??? could make arg 0 an offsettable memory operand to allow to save
6754 ;; an add in the code that calculates the address.
6755 (define_insn "ic_invalidate_line_media"
6756   [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
6757                     UNSPEC_ICACHE)]
6758   "TARGET_SHMEDIA"
6760   return       "ocbwb   %0,0"   "\n"
6761          "      synco"          "\n"
6762          "      icbi    %0,0"   "\n"
6763          "      synci";
6765   [(set_attr "length" "16")
6766    (set_attr "type" "invalidate_line_media")])
6768 (define_insn "ic_invalidate_line_compact"
6769   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
6770                      (match_operand:SI 1 "register_operand" "r")]
6771                     UNSPEC_ICACHE)
6772    (clobber (reg:SI PR_REG))]
6773   "TARGET_SHCOMPACT"
6774   "jsr @%1%#"
6775   [(set_attr "type" "sfunc")
6776    (set_attr "needs_delay_slot" "yes")])
6778 (define_expand "initialize_trampoline"
6779   [(match_operand:SI 0 "" "")
6780    (match_operand:SI 1 "" "")
6781    (match_operand:SI 2 "" "")]
6782   "TARGET_SHCOMPACT"
6784   rtx sfun, tramp;
6786   tramp = force_reg (Pmode, operands[0]);
6787   sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline",
6788                                             SFUNC_STATIC));
6789   emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
6790   emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
6792   emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
6793   DONE;
6796 (define_insn "initialize_trampoline_compact"
6797   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
6798                      (match_operand:SI 1 "register_operand" "r")
6799                      (reg:SI R2_REG) (reg:SI R3_REG)]
6800                     UNSPEC_INIT_TRAMP)
6802    (clobber (reg:SI PR_REG))]
6803   "TARGET_SHCOMPACT"
6804   "jsr @%1%#"
6805   [(set_attr "type" "sfunc")
6806    (set_attr "needs_delay_slot" "yes")])
6808 (define_expand "movhi"
6809   [(set (match_operand:HI 0 "general_movdst_operand" "")
6810         (match_operand:HI 1 "general_movsrc_operand" ""))]
6811   ""
6813   prepare_move_operands (operands, HImode);
6816 (define_expand "movqi"
6817   [(set (match_operand:QI 0 "general_operand" "")
6818         (match_operand:QI 1 "general_operand" ""))]
6819   ""
6821   prepare_move_operands (operands, QImode);
6824 ;; If movqi_reg_reg is specified as an alternative of movqi, movqi will be
6825 ;; selected to copy QImode regs.  If one of them happens to be allocated
6826 ;; on the stack, reload will stick to movqi insn and generate wrong
6827 ;; displacement addressing because of the generic m alternatives.  
6828 ;; With the movqi_reg_reg being specified before movqi it will be initially 
6829 ;; picked to load/store regs.  If the regs regs are on the stack reload will
6830 ;; try other insns and not stick to movqi_reg_reg.
6831 ;; The same applies to the movhi variants.
6833 ;; Notice, that T bit is not allowed as a mov src operand here.  This is to
6834 ;; avoid things like (set (reg:QI) (subreg:QI (reg:SI T_REG) 0)), which
6835 ;; introduces zero extensions after T bit stores and redundant reg copies.
6837 ;; FIXME: We can't use 'arith_reg_operand' (which disallows T_REG) as a
6838 ;; predicate for the mov src operand because reload will have trouble
6839 ;; reloading MAC subregs otherwise.  For that probably special patterns
6840 ;; would be required.
6841 (define_insn "*mov<mode>_reg_reg"
6842   [(set (match_operand:QIHI 0 "arith_reg_dest" "=r")
6843         (match_operand:QIHI 1 "register_operand" "r"))]
6844   "TARGET_SH1 && !t_reg_operand (operands[1], VOIDmode)"
6845   "mov  %1,%0"
6846   [(set_attr "type" "move")])
6848 ;; FIXME: The non-SH2A and SH2A variants should be combined by adding
6849 ;; "enabled" attribute as it is done in other targets.
6850 (define_insn "*mov<mode>_store_mem_disp04"
6851   [(set (mem:QIHI
6852           (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
6853                    (match_operand:SI 1 "const_int_operand" "<disp04>,N")))
6854         (match_operand:QIHI 2 "arith_reg_operand" "z,r"))]
6855   "TARGET_SH1 && sh_legitimate_index_p (<MODE>mode, operands[1], false, true)"
6856   "@
6857         mov.<bw>        %2,@(%O1,%0)
6858         mov.<bw>        %2,@%0"
6859   [(set_attr "type" "store")])
6861 (define_insn "*mov<mode>_store_mem_disp12"
6862   [(set (mem:QIHI
6863           (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
6864                    (match_operand:SI 1 "const_int_operand" "<disp12>")))
6865         (match_operand:QIHI 2 "arith_reg_operand" "r"))]
6866   "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[1], true, true)"
6867   "mov.<bw>     %2,@(%O1,%0)"
6868   [(set_attr "type" "store")
6869    (set_attr "length" "4")])
6871 (define_insn "*mov<mode>_load_mem_disp04"
6872   [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r")
6873         (mem:QIHI
6874           (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
6875                    (match_operand:SI 2 "const_int_operand" "<disp04>,N"))))]
6876   "TARGET_SH1 && ! TARGET_SH2A
6877    && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
6878   "@
6879         mov.<bw>        @(%O2,%1),%0
6880         mov.<bw>        @%1,%0"
6881   [(set_attr "type" "load")])
6883 (define_insn "*mov<mode>_load_mem_disp12"
6884   [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r,r")
6885         (mem:QIHI
6886           (plus:SI
6887             (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6888             (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>"))))]
6889   "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
6890   "@
6891         mov.<bw>        @(%O2,%1),%0
6892         mov.<bw>        @%1,%0
6893         mov.<bw>        @(%O2,%1),%0"
6894   [(set_attr "type" "load")
6895    (set_attr "length" "2,2,4")])
6897 ;; The m constraints basically allow any kind of addresses to be used with any
6898 ;; source/target register as the other operand.  This is not true for 
6899 ;; displacement addressing modes on anything but SH2A.  That's why the
6900 ;; specialized load/store insns are specified above.
6901 (define_insn "*movqi"
6902   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,l")
6903         (match_operand:QI 1 "general_movsrc_operand"  "i,m,r,l,r"))]
6904   "TARGET_SH1
6905    && (arith_reg_operand (operands[0], QImode)
6906        || arith_reg_operand (operands[1], QImode))"
6907   "@
6908         mov     %1,%0
6909         mov.b   %1,%0
6910         mov.b   %1,%0
6911         sts     %1,%0
6912         lds     %1,%0"
6913  [(set_attr "type" "movi8,load,store,prget,prset")])
6915 (define_insn "*movhi"
6916   [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,m,r,l")
6917         (match_operand:HI 1 "general_movsrc_operand"  "Q,i,m,r,l,r"))]
6918   "TARGET_SH1
6919    && (arith_reg_operand (operands[0], HImode)
6920        || arith_reg_operand (operands[1], HImode))"
6921   "@
6922         mov.w   %1,%0
6923         mov     %1,%0
6924         mov.w   %1,%0
6925         mov.w   %1,%0
6926         sts     %1,%0
6927         lds     %1,%0"
6928  [(set_attr "type" "pcload,movi8,load,store,prget,prset")])
6930 (define_insn "*movqi_media"
6931   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
6932         (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
6933   "TARGET_SHMEDIA
6934    && (arith_reg_operand (operands[0], QImode)
6935        || extend_reg_or_0_operand (operands[1], QImode))"
6936   "@
6937         add.l   %1, r63, %0
6938         movi    %1, %0
6939         ld%M1.ub        %m1, %0
6940         st%M0.b %m0, %N1"
6941   [(set_attr "type" "arith_media,arith_media,load_media,store_media")
6942    (set (attr "highpart")
6943         (cond [(match_test "sh_contains_memref_p (insn)")
6944                (const_string "user")]
6945               (const_string "ignore")))])
6947 (define_expand "reload_inqi"
6948   [(set (match_operand:SI 2 "" "=&r")
6949         (match_operand:QI 1 "inqhi_operand" ""))
6950    (set (match_operand:QI 0 "arith_reg_operand" "=r")
6951         (truncate:QI (match_dup 3)))]
6952   "TARGET_SHMEDIA"
6954   rtx inner = XEXP (operands[1], 0);
6955   int regno = REGNO (inner);
6957   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
6958   operands[1] = gen_rtx_REG (SImode, regno);
6959   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
6962 (define_insn "*movhi_media"
6963   [(set (match_operand:HI 0 "general_movdst_operand"     "=r,r,r,r,m")
6964         (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
6965   "TARGET_SHMEDIA
6966    && (arith_reg_operand (operands[0], HImode)
6967        || arith_reg_or_0_operand (operands[1], HImode))"
6968   "@
6969         add.l   %1, r63, %0
6970         movi    %1, %0
6971         #
6972         ld%M1.w %m1, %0
6973         st%M0.w %m0, %N1"
6974   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
6975    (set (attr "highpart")
6976         (cond [(match_test "sh_contains_memref_p (insn)")
6977                (const_string "user")]
6978               (const_string "ignore")))])
6980 (define_split
6981   [(set (match_operand:HI 0 "register_operand" "")
6982         (match_operand:HI 1 "immediate_operand" ""))]
6983   "TARGET_SHMEDIA && reload_completed
6984    && ! satisfies_constraint_I16 (operands[1])"
6985   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
6987 (define_expand "reload_inhi"
6988   [(set (match_operand:SI 2 "" "=&r")
6989         (match_operand:HI 1 "inqhi_operand" ""))
6990    (set (match_operand:HI 0 "arith_reg_operand" "=r")
6991         (truncate:HI (match_dup 3)))]
6992   "TARGET_SHMEDIA"
6994   rtx inner = XEXP (operands[1], 0);
6995   int regno = REGNO (inner);
6997   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
6998   operands[1] = gen_rtx_REG (SImode, regno);
6999   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7002 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
7003 ;; compiled with -m2 -ml -O3 -funroll-loops
7004 (define_insn "*movdi_i"
7005   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
7006         (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
7007   "TARGET_SH1
7008    && (arith_reg_operand (operands[0], DImode)
7009        || arith_reg_operand (operands[1], DImode))"
7011   return output_movedouble (insn, operands, DImode);
7013   [(set_attr "length" "4")
7014    (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
7016 ;; If the output is a register and the input is memory or a register, we have
7017 ;; to be careful and see which word needs to be loaded first.
7019 (define_split
7020   [(set (match_operand:DI 0 "general_movdst_operand" "")
7021         (match_operand:DI 1 "general_movsrc_operand" ""))]
7022   "TARGET_SH1 && reload_completed"
7023   [(set (match_dup 2) (match_dup 3))
7024    (set (match_dup 4) (match_dup 5))]
7026   int regno;
7028   if ((MEM_P (operands[0])
7029        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
7030       || (MEM_P (operands[1])
7031           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7032     FAIL;
7034   switch (GET_CODE (operands[0]))
7035     {
7036     case REG:
7037       regno = REGNO (operands[0]);
7038       break;
7039     case SUBREG:
7040       regno = subreg_regno (operands[0]);
7041       break;
7042     case MEM:
7043       regno = -1;
7044       break;
7045     default:
7046       gcc_unreachable ();
7047     }
7049   if (regno == -1
7050       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
7051     {
7052       operands[2] = operand_subword (operands[0], 0, 0, DImode);
7053       operands[3] = operand_subword (operands[1], 0, 0, DImode);
7054       operands[4] = operand_subword (operands[0], 1, 0, DImode);
7055       operands[5] = operand_subword (operands[1], 1, 0, DImode);
7056     }
7057   else
7058     {
7059       operands[2] = operand_subword (operands[0], 1, 0, DImode);
7060       operands[3] = operand_subword (operands[1], 1, 0, DImode);
7061       operands[4] = operand_subword (operands[0], 0, 0, DImode);
7062       operands[5] = operand_subword (operands[1], 0, 0, DImode);
7063     }
7065   if (operands[2] == 0 || operands[3] == 0
7066       || operands[4] == 0 || operands[5] == 0)
7067     FAIL;
7070 ;; The '?'s in the following constraints may not reflect the time taken
7071 ;; to perform the move. They are there to discourage the use of floating-
7072 ;; point registers for storing integer values.
7073 (define_insn "*movdi_media"
7074   [(set (match_operand:DI 0 "general_movdst_operand"
7075                  "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
7076         (match_operand:DI 1 "general_movsrc_operand"
7077          "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
7078   "TARGET_SHMEDIA_FPU
7079    && (register_operand (operands[0], DImode)
7080        || sh_register_operand (operands[1], DImode))"
7081   "@
7082         add     %1, r63, %0
7083         movi    %1, %0
7084         #
7085         ld%M1.q %m1, %0
7086         st%M0.q %m0, %N1
7087         fld%M1.d        %m1, %0
7088         fst%M0.d        %m0, %1
7089         fmov.qd %N1, %0
7090         fmov.dq %1, %0
7091         fmov.d  %1, %0
7092         ptabs   %1, %0
7093         gettr   %1, %0
7094         pt      %1, %0"
7095   [(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")
7096    (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
7098 (define_insn "*movdi_media_nofpu"
7099   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
7100         (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
7101   "TARGET_SHMEDIA
7102    && (register_operand (operands[0], DImode)
7103        || sh_register_operand (operands[1], DImode))"
7104   "@
7105         add     %1, r63, %0
7106         movi    %1, %0
7107         #
7108         ld%M1.q %m1, %0
7109         st%M0.q %m0, %N1
7110         ptabs   %1, %0
7111         gettr   %1, %0
7112         pt      %1, %0"
7113   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
7114    (set_attr "length" "4,4,16,4,4,4,4,*")])
7116 (define_insn "*movdi_media_I16"
7117   [(set (match_operand:DI 0 "ext_dest_operand" "=r")
7118         (match_operand:DI 1 "const_int_operand" "I16"))]
7119   "TARGET_SHMEDIA && reload_completed"
7120   "movi %1, %0"
7121   [(set_attr "type" "arith_media")
7122    (set_attr "length" "4")])
7124 (define_split
7125   [(set (match_operand:DI 0 "arith_reg_dest" "")
7126         (match_operand:DI 1 "immediate_operand" ""))]
7127   "TARGET_SHMEDIA && reload_completed
7128    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7129   [(set (match_dup 0) (match_dup 1))]
7131   rtx insn;
7133   if (TARGET_SHMEDIA64)
7134     insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
7135   else
7136     insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
7138   set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
7140   DONE;
7143 (define_expand "movdi_const"
7144   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7145         (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7146                               (const_int 48)] UNSPEC_EXTRACT_S16)))
7147    (set (match_dup 0)
7148         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7149                 (const:DI (unspec:DI [(match_dup 1)
7150                                       (const_int 32)] UNSPEC_EXTRACT_U16))))
7151    (set (match_dup 0)
7152         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7153                 (const:DI (unspec:DI [(match_dup 1)
7154                                       (const_int 16)] UNSPEC_EXTRACT_U16))))
7155    (set (match_dup 0)
7156         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7157                 (const:DI (unspec:DI [(match_dup 1)
7158                                       (const_int 0)] UNSPEC_EXTRACT_U16))))]
7159   "TARGET_SHMEDIA64 && reload_completed
7160    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7162   sh_mark_label (operands[1], 4);
7165 (define_expand "movdi_const_32bit"
7166   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7167         (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7168                               (const_int 16)] UNSPEC_EXTRACT_S16)))
7169    (set (match_dup 0)
7170         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7171                 (const:DI (unspec:DI [(match_dup 1)
7172                                       (const_int 0)] UNSPEC_EXTRACT_U16))))]
7173   "TARGET_SHMEDIA32 && reload_completed
7174    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7176   sh_mark_label (operands[1], 2);
7179 (define_expand "movdi_const_16bit"
7180   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7181         (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7182                               (const_int 0)] UNSPEC_EXTRACT_S16)))]
7183   "TARGET_SHMEDIA && flag_pic && reload_completed
7184    && GET_CODE (operands[1]) == SYMBOL_REF"
7185   "")
7187 (define_split
7188   [(set (match_operand:DI 0 "ext_dest_operand" "")
7189         (match_operand:DI 1 "immediate_operand" ""))]
7190   "TARGET_SHMEDIA && reload_completed
7191    && CONST_INT_P (operands[1])
7192    && ! satisfies_constraint_I16 (operands[1])"
7193   [(set (match_dup 0) (match_dup 2))
7194    (match_dup 1)]
7196   unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
7197   unsigned HOST_WIDE_INT low = val;
7198   unsigned HOST_WIDE_INT high = val;
7199   unsigned HOST_WIDE_INT sign;
7200   unsigned HOST_WIDE_INT val2 = val ^ (val-1);
7202   /* Zero-extend the 16 least-significant bits.  */
7203   low &= 0xffff;
7205   /* Arithmetic shift right the word by 16 bits.  */
7206   high >>= 16;
7207   if (GET_CODE (operands[0]) == SUBREG
7208       && GET_MODE (SUBREG_REG (operands[0])) == SImode)
7209     {
7210       high &= 0xffff;
7211       high ^= 0x8000;
7212       high -= 0x8000;
7213     }
7214   else
7215     {
7216       sign = 1;
7217       sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7218       high ^= sign;
7219       high -= sign;
7220     }
7221   do
7222     {
7223       /* If we can't generate the constant with a two-insn movi / shori
7224          sequence, try some other strategies.  */
7225       if (! CONST_OK_FOR_I16 (high))
7226         {
7227           /* Try constant load / left shift.  We know VAL != 0.  */
7228           val2 = val ^ (val-1);
7229           if (val2 > 0x1ffff)
7230             {
7231               int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
7233               if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
7234                   || (! CONST_OK_FOR_I16 (high >> 16)
7235                       && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
7236                 {
7237                   val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
7238                   operands[1] = gen_ashldi3_media (operands[0], operands[0],
7239                                                    GEN_INT (trailing_zeroes));
7240                   break;
7241                 }
7242             }
7243           /* Try constant load / right shift.  */
7244           val2 = (val >> 15) + 1;
7245           if (val2 == (val2 & -val2))
7246             {
7247               int shift = 49 - exact_log2 (val2);
7249               val2 = trunc_int_for_mode (val << shift, DImode);
7250               if (CONST_OK_FOR_I16 (val2))
7251                 {
7252                   operands[1] = gen_lshrdi3_media (operands[0], operands[0],
7253                                                    GEN_INT (shift));
7254                   break;
7255                 }
7256             }
7257           /* Try mperm.w .  */
7258           val2 = val & 0xffff;
7259           if ((val >> 16 & 0xffff) == val2
7260               && (val >> 32 & 0xffff) == val2
7261               && (val >> 48 & 0xffff) == val2)
7262             {
7263               val2 = (HOST_WIDE_INT) val >> 48;
7264               operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
7265               operands[1] = gen_mperm_w0 (operands[1], operands[1]);
7266               break;
7267             }
7268           /* Try movi / mshflo.l  */
7269           val2 = (HOST_WIDE_INT) val >> 32;
7270           if (val2 == ((unsigned HOST_WIDE_INT)
7271                         trunc_int_for_mode (val, SImode)))
7272             {
7273               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7274                                              operands[0]);
7275               break;
7276             }
7277           /* Try movi / mshflo.l w/ r63.  */
7278           val2 = val + ((HOST_WIDE_INT) -1 << 32);
7279           if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
7280             {
7281               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7282                                              const0_rtx);
7283               break;
7284             }
7285         }
7286       val2 = high;
7287       operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
7288     }
7289   while (0);
7290   operands[2] = GEN_INT (val2);
7293 (define_split
7294   [(set (match_operand:DI 0 "ext_dest_operand" "")
7295         (match_operand:DI 1 "immediate_operand" ""))]
7296   "TARGET_SHMEDIA && reload_completed
7297    && GET_CODE (operands[1]) == CONST_DOUBLE"
7298   [(set (match_dup 0) (match_dup 2))
7299   (set (match_dup 0)
7300        (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
7302   unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
7303   unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
7304   unsigned HOST_WIDE_INT val = low;
7305   unsigned HOST_WIDE_INT sign;
7307   /* Zero-extend the 16 least-significant bits.  */
7308   val &= 0xffff;
7309   operands[1] = GEN_INT (val);
7311   /* Arithmetic shift right the double-word by 16 bits.  */
7312   low >>= 16;
7313   low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
7314   high >>= 16;
7315   sign = 1;
7316   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7317   high ^= sign;
7318   high -= sign;
7320   /* This will only be true if high is a sign-extension of low, i.e.,
7321      it must be either 0 or (unsigned)-1, and be zero iff the
7322      most-significant bit of low is set.  */
7323   if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
7324     operands[2] = GEN_INT (low);
7325   else
7326     operands[2] = immed_double_const (low, high, DImode);
7329 (define_insn "shori_media"
7330   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
7331         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
7332                            (const_int 16))
7333                 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
7334   "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
7335   "@
7336         shori   %u2, %0
7337         #"
7338   [(set_attr "type" "arith_media,*")])
7340 (define_insn "*shori_media_si"
7341   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
7342         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
7343                            (const_int 16))
7344                 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
7345   "TARGET_SHMEDIA"
7346   "shori        %u2, %0")
7348 (define_expand "movdi"
7349   [(set (match_operand:DI 0 "general_movdst_operand" "")
7350         (match_operand:DI 1 "general_movsrc_operand" ""))]
7351   ""
7353   prepare_move_operands (operands, DImode);
7356 (define_insn "movdf_media"
7357   [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
7358         (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
7359   "TARGET_SHMEDIA_FPU
7360    && (register_operand (operands[0], DFmode)
7361        || sh_register_operand (operands[1], DFmode))"
7362   "@
7363         fmov.d  %1, %0
7364         fmov.qd %N1, %0
7365         fmov.dq %1, %0
7366         add     %1, r63, %0
7367         #
7368         fld%M1.d        %m1, %0
7369         fst%M0.d        %m0, %1
7370         ld%M1.q %m1, %0
7371         st%M0.q %m0, %N1"
7372   [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
7374 (define_insn "movdf_media_nofpu"
7375   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7376         (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
7377   "TARGET_SHMEDIA
7378    && (register_operand (operands[0], DFmode)
7379        || sh_register_operand (operands[1], DFmode))"
7380   "@
7381         add     %1, r63, %0
7382         #
7383         ld%M1.q %m1, %0
7384         st%M0.q %m0, %N1"
7385   [(set_attr "type" "arith_media,*,load_media,store_media")])
7387 (define_split
7388   [(set (match_operand:DF 0 "arith_reg_dest" "")
7389         (match_operand:DF 1 "immediate_operand" ""))]
7390   "TARGET_SHMEDIA && reload_completed"
7391   [(set (match_dup 3) (match_dup 2))]
7393   int endian = WORDS_BIG_ENDIAN ? 1 : 0;
7394   long values[2];
7395   REAL_VALUE_TYPE value;
7397   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
7398   REAL_VALUE_TO_TARGET_DOUBLE (value, values);
7400   if (HOST_BITS_PER_WIDE_INT >= 64)
7401     operands[2] = immed_double_const ((unsigned long) values[endian]
7402                                       | ((HOST_WIDE_INT) values[1 - endian]
7403                                          << 32), 0, DImode);
7404   else
7405     {
7406       gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
7407       operands[2] = immed_double_const (values[endian], values[1 - endian],
7408                                         DImode);
7409     }
7411   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
7414 ;; ??? This should be a define expand.
7416 (define_insn "movdf_k"
7417   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7418         (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
7419   "TARGET_SH1
7420    && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
7421        /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
7422        || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
7423        || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
7424    && (arith_reg_operand (operands[0], DFmode)
7425        || arith_reg_operand (operands[1], DFmode))"
7427   return output_movedouble (insn, operands, DFmode);
7429   [(set_attr "length" "4")
7430    (set_attr "type" "move,pcload,load,store")])
7432 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
7433 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
7434 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
7435 ;; the d/m/c/X alternative, which is split later into single-precision
7436 ;; instructions.  And when not optimizing, no splits are done before fixing
7437 ;; up pcloads, so we need usable length information for that.
7438 (define_insn "movdf_i4"
7439   [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
7440         (match_operand:DF 1 "general_movsrc_operand"  "d,r,F,m,d,FQ,m,r,d,r"))
7441    (use (match_operand:PSI 2 "fpscr_operand"          "c,c,c,c,c,c,c,c,c,c"))
7442    (clobber (match_scratch:SI 3                      "=X,X,&z,X,X,X,X,X,X,X"))]
7443   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
7444    && (arith_reg_operand (operands[0], DFmode)
7445        || arith_reg_operand (operands[1], DFmode))"
7446   {
7447     switch (which_alternative)
7448     {
7449     case 0:
7450       if (TARGET_FMOVD)
7451         return "fmov    %1,%0";
7452       else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
7453         return         "fmov    %R1,%R0"        "\n"
7454                "        fmov    %S1,%S0";
7455       else
7456         return         "fmov    %S1,%S0"        "\n"
7457                "        fmov    %R1,%R0";
7458     case 3:
7459     case 4:
7460       return "fmov.d    %1,%0";
7461     default:
7462       return "#";
7463     }
7464   }
7465   [(set_attr_alternative "length"
7466      [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
7467       (const_int 4)
7468       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7469       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7470       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7471       (const_int 4)
7472       (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
7473       ;; We can't use 4-byte push/pop on SHcompact, so we have to
7474       ;; increment or decrement r15 explicitly.
7475       (if_then_else
7476        (match_test "TARGET_SHCOMPACT")
7477        (const_int 10) (const_int 8))
7478       (if_then_else
7479        (match_test "TARGET_SHCOMPACT")
7480        (const_int 10) (const_int 8))])
7481    (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
7482    (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
7483    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
7484                                            (const_string "double")
7485                                            (const_string "none")))])
7487 ;; Moving DFmode between fp/general registers through memory
7488 ;; (the top of the stack) is faster than moving through fpul even for
7489 ;; little endian.  Because the type of an instruction is important for its
7490 ;; scheduling,  it is beneficial to split these operations, rather than
7491 ;; emitting them in one single chunk, even if this will expose a stack
7492 ;; use that will prevent scheduling of other stack accesses beyond this
7493 ;; instruction.
7494 (define_split
7495   [(set (match_operand:DF 0 "register_operand" "")
7496         (match_operand:DF 1 "register_operand" ""))
7497    (use (match_operand:PSI 2 "fpscr_operand" ""))
7498    (clobber (match_scratch:SI 3 "=X"))]
7499   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
7500    && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
7501   [(const_int 0)]
7503   rtx insn, tos;
7505   if (TARGET_SH5 && true_regnum (operands[1]) < 16)
7506     {
7507       emit_move_insn (stack_pointer_rtx,
7508                       plus_constant (Pmode, stack_pointer_rtx, -8));
7509       tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
7510     }
7511   else
7512     tos = gen_tmp_stack_mem (DFmode,
7513                              gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
7514   insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
7515   if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
7516     add_reg_note (insn, REG_INC, stack_pointer_rtx);
7517   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
7518     tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
7519   else
7520     tos = gen_tmp_stack_mem (DFmode,
7521                              gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
7522   insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
7523   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
7524     emit_move_insn (stack_pointer_rtx,
7525                     plus_constant (Pmode, stack_pointer_rtx, 8));
7526   else
7527     add_reg_note (insn, REG_INC, stack_pointer_rtx);
7528   DONE;
7531 ;; local-alloc sometimes allocates scratch registers even when not required,
7532 ;; so we must be prepared to handle these.
7534 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
7535 (define_split
7536   [(set (match_operand:DF 0 "general_movdst_operand" "")
7537         (match_operand:DF 1 "general_movsrc_operand"  ""))
7538    (use (match_operand:PSI 2 "fpscr_operand" ""))
7539    (clobber (match_scratch:SI 3 ""))]
7540   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
7541    && reload_completed
7542    && true_regnum (operands[0]) < 16
7543    && true_regnum (operands[1]) < 16"
7544   [(set (match_dup 0) (match_dup 1))]
7546   /* If this was a reg <-> mem operation with base + index reg addressing,
7547      we have to handle this in a special way.  */
7548   rtx mem = operands[0];
7549   int store_p = 1;
7550   if (! memory_operand (mem, DFmode))
7551     {
7552       mem = operands[1];
7553       store_p = 0;
7554     }
7555   if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
7556     mem = SUBREG_REG (mem);
7557   if (MEM_P (mem))
7558     {
7559       rtx addr = XEXP (mem, 0);
7560       if (GET_CODE (addr) == PLUS
7561           && REG_P (XEXP (addr, 0))
7562           && REG_P (XEXP (addr, 1)))
7563         {
7564           int offset;
7565           rtx reg0 = gen_rtx_REG (Pmode, 0);
7566           rtx regop = operands[store_p], word0 ,word1;
7568           if (GET_CODE (regop) == SUBREG)
7569             alter_subreg (&regop, true);
7570           if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
7571             offset = 2;
7572           else
7573             offset = 4;
7574           mem = copy_rtx (mem);
7575           PUT_MODE (mem, SImode);
7576           word0 = gen_rtx_SUBREG (SImode, regop, 0);
7577           alter_subreg (&word0, true);
7578           word1 = gen_rtx_SUBREG (SImode, regop, 4);
7579           alter_subreg (&word1, true);
7580           if (store_p || ! refers_to_regno_p (REGNO (word0),
7581                                               REGNO (word0) + 1, addr, 0))
7582             {
7583               emit_insn (store_p
7584                          ? gen_movsi_ie (mem, word0)
7585                          : gen_movsi_ie (word0, mem));
7586               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7587               mem = copy_rtx (mem);
7588               emit_insn (store_p
7589                          ? gen_movsi_ie (mem, word1)
7590                          : gen_movsi_ie (word1, mem));
7591               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7592             }
7593           else
7594             {
7595               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7596               emit_insn (gen_movsi_ie (word1, mem));
7597               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7598               mem = copy_rtx (mem);
7599               emit_insn (gen_movsi_ie (word0, mem));
7600             }
7601           DONE;
7602         }
7603     }
7606 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
7607 (define_split
7608   [(set (match_operand:DF 0 "register_operand" "")
7609         (match_operand:DF 1 "memory_operand"  ""))
7610    (use (match_operand:PSI 2 "fpscr_operand" ""))
7611    (clobber (reg:SI R0_REG))]
7612   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
7613   [(parallel [(set (match_dup 0) (match_dup 1))
7614               (use (match_dup 2))
7615               (clobber (scratch:SI))])]
7616   "")
7618 (define_expand "reload_indf__frn"
7619   [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
7620                    (match_operand:DF 1 "immediate_operand" "FQ"))
7621               (use (reg:PSI FPSCR_REG))
7622               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
7623   "TARGET_SH1"
7624   "")
7626 (define_expand "reload_outdf__RnFRm"
7627   [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
7628                    (match_operand:DF 1 "register_operand" "af,r"))
7629               (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
7630   "TARGET_SH1"
7631   "")
7633 ;; Simplify no-op moves.
7634 (define_split
7635   [(set (match_operand:SF 0 "register_operand" "")
7636         (match_operand:SF 1 "register_operand" ""))
7637    (use (match_operand:PSI 2 "fpscr_operand" ""))
7638    (clobber (match_scratch:SI 3 ""))]
7639   "TARGET_SH2E && reload_completed
7640    && true_regnum (operands[0]) == true_regnum (operands[1])"
7641   [(set (match_dup 0) (match_dup 0))]
7642   "")
7644 ;; fmovd substitute post-reload splits
7645 (define_split
7646   [(set (match_operand:DF 0 "register_operand" "")
7647         (match_operand:DF 1 "register_operand" ""))
7648    (use (match_operand:PSI 2 "fpscr_operand" ""))
7649    (clobber (match_scratch:SI 3 ""))]
7650   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
7651    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7652    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
7653   [(const_int 0)]
7655   int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
7656   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
7657                            gen_rtx_REG (SFmode, src), operands[2]));
7658   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
7659                            gen_rtx_REG (SFmode, src + 1), operands[2]));
7660   DONE;
7663 (define_split
7664   [(set (match_operand:DF 0 "register_operand" "")
7665         (mem:DF (match_operand:SI 1 "register_operand" "")))
7666    (use (match_operand:PSI 2 "fpscr_operand" ""))
7667    (clobber (match_scratch:SI 3 ""))]
7668   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7669    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7670    && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
7671   [(const_int 0)]
7673   int regno = true_regnum (operands[0]);
7674   rtx insn;
7675   rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
7676   rtx mem2
7677     = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
7678   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
7679                                            regno + !! TARGET_LITTLE_ENDIAN),
7680                                   mem2, operands[2]));
7681   add_reg_note (insn, REG_INC, operands[1]);
7682   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
7683                                                regno + ! TARGET_LITTLE_ENDIAN),
7684                                   change_address (mem, SFmode, NULL_RTX),
7685                                   operands[2]));
7686   DONE;
7689 (define_split
7690   [(set (match_operand:DF 0 "register_operand" "")
7691         (match_operand:DF 1 "memory_operand" ""))
7692    (use (match_operand:PSI 2 "fpscr_operand" ""))
7693    (clobber (match_scratch:SI 3 ""))]
7694   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7695    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
7696   [(const_int 0)]
7698   int regno = true_regnum (operands[0]);
7699   rtx addr, insn;
7700   rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
7701   rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
7702   rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
7704   operands[1] = copy_rtx (mem2);
7705   addr = XEXP (mem2, 0);
7707   switch (GET_CODE (addr))
7708     {
7709     case REG:
7710       /* This is complicated.  If the register is an arithmetic register
7711          we can just fall through to the REG+DISP case below.  Otherwise
7712          we have to use a combination of POST_INC and REG addressing...  */
7713       if (! arith_reg_operand (operands[1], SFmode))
7714         {
7715           XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
7716           insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
7717           add_reg_note (insn, REG_INC, XEXP (addr, 0));
7718           
7719           emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7721           /* If we have modified the stack pointer, the value that we have
7722              read with post-increment might be modified by an interrupt,
7723              so write it back.  */
7724           if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
7725             emit_insn (gen_push_e (reg0));
7726           else
7727             emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0), GEN_INT (-4)));
7728           break;
7729         }
7730       /* Fall through.  */
7731          
7732     case PLUS:
7733       emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
7734       operands[1] = copy_rtx (operands[1]);
7735       XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4);
7736       emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7737       break;
7738       
7739     case POST_INC:
7740       insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
7741       add_reg_note (insn, REG_INC, XEXP (addr, 0));
7742     
7743       insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7744       add_reg_note (insn, REG_INC, XEXP (addr, 0));
7745       break;
7747     default:
7748       debug_rtx (addr);
7749       gcc_unreachable ();
7750     }
7752   DONE;
7755 (define_split
7756   [(set (match_operand:DF 0 "memory_operand" "")
7757         (match_operand:DF 1 "register_operand" ""))
7758    (use (match_operand:PSI 2 "fpscr_operand" ""))
7759    (clobber (match_scratch:SI 3 ""))]
7760   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7761    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
7762   [(const_int 0)]
7764   int regno = true_regnum (operands[1]);
7765   rtx insn, addr;
7766   rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
7767   rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
7769   operands[0] = copy_rtx (operands[0]);
7770   PUT_MODE (operands[0], SFmode);
7771   addr = XEXP (operands[0], 0);
7773   switch (GET_CODE (addr))
7774     {
7775     case REG:
7776       /* This is complicated.  If the register is an arithmetic register
7777          we can just fall through to the REG+DISP case below.  Otherwise
7778          we have to use a combination of REG and PRE_DEC addressing...  */
7779       if (! arith_reg_operand (operands[0], SFmode))
7780         {
7781           emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
7782           emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7784           operands[0] = copy_rtx (operands[0]);
7785           XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
7786           
7787           insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7788           add_reg_note (insn, REG_INC, XEXP (addr, 0));
7789           break;
7790         }
7791       /* Fall through.  */
7792       
7793     case PLUS:
7794       /* Since REG+DISP addressing has already been decided upon by gcc
7795          we can rely upon it having chosen an arithmetic register as the
7796          register component of the address.  Just emit the lower numbered
7797          register first, to the lower address, then the higher numbered
7798          register to the higher address.  */
7799       emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7801       operands[0] = copy_rtx (operands[0]);
7802       XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4);
7804       emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));         
7805       break;
7806       
7807     case PRE_DEC:
7808       /* This is easy.  Output the word to go to the higher address
7809          first (ie the word in the higher numbered register) then the
7810          word to go to the lower address.  */
7812       insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7813       add_reg_note (insn, REG_INC, XEXP (addr, 0));
7815       insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7816       add_reg_note (insn, REG_INC, XEXP (addr, 0));
7817       break;
7818       
7819     default:
7820       /* FAIL; */
7821       debug_rtx (addr);
7822       gcc_unreachable ();
7823     }
7825   DONE;
7828 ;; If the output is a register and the input is memory or a register, we have
7829 ;; to be careful and see which word needs to be loaded first.
7831 (define_split
7832   [(set (match_operand:DF 0 "general_movdst_operand" "")
7833         (match_operand:DF 1 "general_movsrc_operand" ""))]
7834   "TARGET_SH1 && reload_completed"
7835   [(set (match_dup 2) (match_dup 3))
7836    (set (match_dup 4) (match_dup 5))]
7838   int regno;
7840   if ((MEM_P (operands[0])
7841        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
7842       || (MEM_P (operands[1])
7843           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7844     FAIL;
7846   switch (GET_CODE (operands[0]))
7847     {
7848     case REG:
7849       regno = REGNO (operands[0]);
7850       break;
7851     case SUBREG:
7852       regno = subreg_regno (operands[0]);
7853       break;
7854     case MEM:
7855       regno = -1;
7856       break;
7857     default:
7858       gcc_unreachable ();
7859     }
7861   if (regno == -1
7862       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
7863     {
7864       operands[2] = operand_subword (operands[0], 0, 0, DFmode);
7865       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
7866       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
7867       operands[5] = operand_subword (operands[1], 1, 0, DFmode);
7868     }
7869   else
7870     {
7871       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
7872       operands[3] = operand_subword (operands[1], 1, 0, DFmode);
7873       operands[4] = operand_subword (operands[0], 0, 0, DFmode);
7874       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
7875     }
7877   if (operands[2] == 0 || operands[3] == 0
7878       || operands[4] == 0 || operands[5] == 0)
7879     FAIL;
7882 (define_expand "movdf"
7883   [(set (match_operand:DF 0 "general_movdst_operand" "")
7884         (match_operand:DF 1 "general_movsrc_operand" ""))]
7885   ""
7887   prepare_move_operands (operands, DFmode);
7888   if (TARGET_SHMEDIA)
7889     {
7890       if (TARGET_SHMEDIA_FPU)
7891         emit_insn (gen_movdf_media (operands[0], operands[1]));
7892       else
7893         emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
7894       DONE;
7895     }
7896   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
7897     {
7898       emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
7899       DONE;
7900     }
7903 ;;This is incompatible with the way gcc uses subregs.
7904 ;;(define_insn "movv2sf_i"
7905 ;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
7906 ;;      (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
7907 ;;  "TARGET_SHMEDIA_FPU
7908 ;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
7909 ;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
7910 ;;  "@
7911 ;;      #
7912 ;;      fld%M1.p        %m1, %0
7913 ;;      fst%M0.p        %m0, %1"
7914 ;;  [(set_attr "type" "*,fload_media,fstore_media")])
7916 (define_insn_and_split "movv2sf_i"
7917   [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
7918         (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
7919   "TARGET_SHMEDIA_FPU"
7920   "#"
7921   "TARGET_SHMEDIA_FPU && reload_completed"
7922   [(set (match_dup 0) (match_dup 1))]
7924   operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
7925   operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
7928 (define_expand "movv2sf"
7929   [(set (match_operand:V2SF 0 "general_movdst_operand" "")
7930         (match_operand:V2SF 1 "nonimmediate_operand" ""))]
7931   "TARGET_SHMEDIA_FPU"
7933   prepare_move_operands (operands, V2SFmode);
7936 (define_expand "addv2sf3"
7937   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7938    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7939    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7940   "TARGET_SHMEDIA_FPU"
7942   sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
7943   DONE;
7946 (define_expand "subv2sf3"
7947   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7948    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7949    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7950   "TARGET_SHMEDIA_FPU"
7952   sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
7953   DONE;
7956 (define_expand "mulv2sf3"
7957   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7958    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7959    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7960   "TARGET_SHMEDIA_FPU"
7962   sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
7963   DONE;
7966 (define_expand "divv2sf3"
7967   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7968    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7969    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7970   "TARGET_SHMEDIA_FPU"
7972   sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
7973   DONE;
7976 (define_insn_and_split "*movv4sf_i"
7977   [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
7978         (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
7979   "TARGET_SHMEDIA_FPU"
7980   "#"
7981   "&& reload_completed"
7982   [(const_int 0)]
7984   int i;
7986   for (i = 0; i < 4/2; i++)
7987     {
7988       rtx x, y;
7990       if (MEM_P (operands[0]))
7991         x = adjust_address (operands[0], V2SFmode,
7992                             i * GET_MODE_SIZE (V2SFmode));
7993       else
7994         x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
7996       if (MEM_P (operands[1]))
7997         y = adjust_address (operands[1], V2SFmode,
7998                             i * GET_MODE_SIZE (V2SFmode));
7999       else
8000         y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
8002       emit_insn (gen_movv2sf_i (x, y));
8003     }
8005   DONE;
8007   [(set_attr "length" "8")])
8009 (define_expand "movv4sf"
8010   [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
8011         (match_operand:V4SF 1 "general_operand" ""))]
8012   "TARGET_SHMEDIA_FPU"
8014   prepare_move_operands (operands, V4SFmode);
8017 (define_insn_and_split "*movv16sf_i"
8018   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8019         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8020   "TARGET_SHMEDIA_FPU"
8021   "#"
8022   "&& reload_completed"
8023   [(const_int 0)]
8025   int i;
8027   for (i = 0; i < 16/2; i++)
8028     {
8029       rtx x,y;
8031       if (MEM_P (operands[0]))
8032         x = adjust_address (operands[0], V2SFmode,
8033                             i * GET_MODE_SIZE (V2SFmode));
8034       else
8035         {
8036           x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
8037           alter_subreg (&x, true);
8038         }
8040       if (MEM_P (operands[1]))
8041         y = adjust_address (operands[1], V2SFmode,
8042                             i * GET_MODE_SIZE (V2SFmode));
8043       else
8044         {
8045           y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
8046           alter_subreg (&y, true);
8047         }
8049       emit_insn (gen_movv2sf_i (x, y));
8050     }
8052   DONE;
8054   [(set_attr "length" "32")])
8056 (define_expand "movv16sf"
8057   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8058         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8059   "TARGET_SHMEDIA_FPU"
8061   prepare_move_operands (operands, V16SFmode);
8064 (define_insn "movsf_media"
8065   [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
8066         (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
8067   "TARGET_SHMEDIA_FPU
8068    && (register_operand (operands[0], SFmode)
8069        || sh_register_operand (operands[1], SFmode))"
8070   "@
8071         fmov.s  %1, %0
8072         fmov.ls %N1, %0
8073         fmov.sl %1, %0
8074         add.l   %1, r63, %0
8075         #
8076         fld%M1.s        %m1, %0
8077         fst%M0.s        %m0, %1
8078         ld%M1.l %m1, %0
8079         st%M0.l %m0, %N1"
8080   [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
8081    (set (attr "highpart")
8082         (cond [(match_test "sh_contains_memref_p (insn)")
8083                (const_string "user")]
8084               (const_string "ignore")))])
8086 (define_insn "movsf_media_nofpu"
8087   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
8088         (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
8089   "TARGET_SHMEDIA
8090    && (register_operand (operands[0], SFmode)
8091        || sh_register_operand (operands[1], SFmode))"
8092   "@
8093         add.l   %1, r63, %0
8094         #
8095         ld%M1.l %m1, %0
8096         st%M0.l %m0, %N1"
8097   [(set_attr "type" "arith_media,*,load_media,store_media")
8098    (set (attr "highpart")
8099         (cond [(match_test "sh_contains_memref_p (insn)")
8100                (const_string "user")]
8101               (const_string "ignore")))])
8103 (define_split
8104   [(set (match_operand:SF 0 "arith_reg_dest" "")
8105         (match_operand:SF 1 "immediate_operand" ""))]
8106   "TARGET_SHMEDIA && reload_completed
8107    && ! FP_REGISTER_P (true_regnum (operands[0]))"
8108   [(set (match_dup 3) (match_dup 2))]
8110   long values;
8111   REAL_VALUE_TYPE value;
8113   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
8114   REAL_VALUE_TO_TARGET_SINGLE (value, values);
8115   operands[2] = GEN_INT (values);
8117   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
8120 (define_insn "movsf_i"
8121   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
8122         (match_operand:SF 1 "general_movsrc_operand"  "r,G,FQ,mr,r,r,l"))]
8123   "TARGET_SH1
8124    && (! TARGET_SH2E
8125        /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
8126        || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
8127        || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
8128    && (arith_reg_operand (operands[0], SFmode)
8129        || arith_reg_operand (operands[1], SFmode))"
8130   "@
8131         mov     %1,%0
8132         mov     #0,%0
8133         mov.l   %1,%0
8134         mov.l   %1,%0
8135         mov.l   %1,%0
8136         lds     %1,%0
8137         sts     %1,%0"
8138   [(set_attr "type" "move,move,pcload,load,store,move,move")])
8140 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
8141 ;; update_flow_info would not know where to put REG_EQUAL notes
8142 ;; when the destination changes mode.
8143 (define_insn "movsf_ie"
8144   [(set (match_operand:SF 0 "general_movdst_operand"
8145          "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
8146         (match_operand:SF 1 "general_movsrc_operand"
8147           "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
8148    (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"))
8149    (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
8150   "TARGET_SH2E
8151    && (arith_reg_operand (operands[0], SFmode)
8152        || arith_reg_operand (operands[1], SFmode)
8153        || arith_reg_operand (operands[3], SImode)
8154        || (fpul_operand (operands[0], SFmode)
8155            && memory_operand (operands[1], SFmode)
8156            && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
8157        || (fpul_operand (operands[1], SFmode)
8158            && memory_operand (operands[0], SFmode)
8159            && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
8160   "@
8161         fmov    %1,%0
8162         mov     %1,%0
8163         fldi0   %0
8164         fldi1   %0
8165         #
8166         fmov.s  %1,%0
8167         fmov.s  %1,%0
8168         mov.l   %1,%0
8169         mov.l   %1,%0
8170         mov.l   %1,%0
8171         fsts    fpul,%0
8172         flds    %1,fpul
8173         lds.l   %1,%0
8174         #
8175         sts     %1,%0
8176         lds     %1,%0
8177         sts.l   %1,%0
8178         lds.l   %1,%0
8179         ! move optimized away"
8180   [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
8181    (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
8182    (set_attr_alternative "length"
8183      [(const_int 2)
8184       (const_int 2)
8185       (const_int 2)
8186       (const_int 2)
8187       (const_int 4)
8188       (if_then_else
8189         (match_test "TARGET_SH2A")
8190         (const_int 4) (const_int 2))
8191       (if_then_else
8192         (match_test "TARGET_SH2A")
8193         (const_int 4) (const_int 2))
8194       (const_int 2)
8195       (if_then_else
8196         (match_test "TARGET_SH2A")
8197         (const_int 4) (const_int 2))
8198       (if_then_else
8199         (match_test "TARGET_SH2A")
8200         (const_int 4) (const_int 2))
8201       (const_int 2)
8202       (const_int 2)
8203       (const_int 2)
8204       (const_int 4)
8205       (const_int 2)
8206       (const_int 2)
8207       (const_int 2)
8208       (const_int 2)
8209       (const_int 0)])
8210    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
8211                                            (const_string "single")
8212                                            (const_string "single")))])
8214 (define_split
8215   [(set (match_operand:SF 0 "register_operand" "")
8216         (match_operand:SF 1 "register_operand" ""))
8217    (use (match_operand:PSI 2 "fpscr_operand" ""))
8218    (clobber (reg:SI FPUL_REG))]
8219   "TARGET_SH1"
8220   [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
8221               (use (match_dup 2))
8222               (clobber (scratch:SI))])
8223    (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
8224               (use (match_dup 2))
8225               (clobber (scratch:SI))])]
8226   "")
8228 (define_expand "movsf"
8229   [(set (match_operand:SF 0 "general_movdst_operand" "")
8230         (match_operand:SF 1 "general_movsrc_operand" ""))]
8231   ""
8233   prepare_move_operands (operands, SFmode);
8234   if (TARGET_SHMEDIA)
8235     {
8236       if (TARGET_SHMEDIA_FPU)
8237         emit_insn (gen_movsf_media (operands[0], operands[1]));
8238       else
8239         emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
8240       DONE;
8241     }
8242   if (TARGET_SH2E)
8243     {
8244       emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
8245       DONE;
8246     }
8249 (define_insn "mov_nop"
8250   [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
8251   "TARGET_SH2E"
8252   ""
8253   [(set_attr "length" "0")
8254    (set_attr "type" "nil")])
8256 (define_expand "reload_insf__frn"
8257   [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
8258                    (match_operand:SF 1 "immediate_operand" "FQ"))
8259               (use (reg:PSI FPSCR_REG))
8260               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8261   "TARGET_SH1"
8262   "")
8264 (define_expand "reload_insi__i_fpul"
8265   [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
8266                    (match_operand:SI 1 "immediate_operand" "i"))
8267               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8268   "TARGET_SH1"
8269   "")
8271 (define_expand "ptabs"
8272   [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
8273   "TARGET_SHMEDIA"
8275   if (!TARGET_PT_FIXED)
8276     {
8277       rtx eq = operands[1];
8279       /* ??? For canonical RTL we really should remove any CONST from EQ
8280          before wrapping it in the AND, and finally wrap the EQ into a
8281          const if is constant.  However, for reload we must expose the
8282          input register or symbolic constant, and we can't have
8283          different insn structures outside of the operands for different
8284          alternatives of the same pattern.  */
8285       eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
8286                        GEN_INT (3));
8287       operands[1]
8288         = (gen_rtx_IF_THEN_ELSE
8289             (PDImode,
8290              eq,
8291              gen_rtx_MEM (PDImode, operands[1]),
8292              gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
8293                             PDImode, operands[1])));
8294     }
8297 ;; expanded by ptabs expander.
8298 (define_insn "*extendsipdi_media"
8299   [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8300         (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
8301                                                           "r,Csy")
8302                                       (const_int 3))
8303                               (const_int 3))
8304                           (mem:PDI (match_dup 1))
8305                           (sign_extend:PDI (match_dup 1))))]
8306   "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8307   "@
8308         ptabs   %1, %0
8309         pt      %1, %0"
8310   [(set_attr "type"   "ptabs_media,pt_media")
8311    (set_attr "length" "4,*")])
8313 (define_insn "*truncdipdi_media"
8314   [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8315         (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
8316                                                           "r,Csy")
8317                                       (const_int 3))
8318                               (const_int 3))
8319                           (mem:PDI (match_dup 1))
8320                           (truncate:PDI (match_dup 1))))]
8321   "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8322   "@
8323         ptabs   %1, %0
8324         pt      %1, %0"
8325   [(set_attr "type"   "ptabs_media,pt_media")
8326    (set_attr "length" "4,*")])
8328 (define_insn "*movsi_y"
8329   [(set (match_operand:SI 0 "register_operand" "=y,y")
8330         (match_operand:SI 1 "immediate_operand" "Qi,I08"))
8331    (clobber (match_scratch:SI 2 "=&z,r"))]
8332   "TARGET_SH2E
8333    && (reload_in_progress || reload_completed)"
8334   "#"
8335   [(set_attr "length" "4")
8336    (set_attr "type" "pcload,move")])
8338 (define_split
8339   [(set (match_operand:SI 0 "register_operand" "")
8340         (match_operand:SI 1 "immediate_operand" ""))
8341    (clobber (match_operand:SI 2 "register_operand" ""))]
8342   "TARGET_SH1"
8343   [(set (match_dup 2) (match_dup 1))
8344    (set (match_dup 0) (match_dup 2))]
8345   "")
8347 ;; ------------------------------------------------------------------------
8348 ;; Define the real conditional branch instructions.
8349 ;; ------------------------------------------------------------------------
8351 (define_expand "branch_true"
8352   [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
8353                            (label_ref (match_operand 0))
8354                            (pc)))]
8355   "TARGET_SH1")
8357 (define_expand "branch_false"
8358   [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8359                            (label_ref (match_operand 0))
8360                            (pc)))]
8361   "TARGET_SH1")
8363 (define_insn_and_split "*cbranch_t"
8364   [(set (pc) (if_then_else (match_operand 1 "cbranch_treg_value")
8365                            (label_ref (match_operand 0))
8366                            (pc)))]
8367   "TARGET_SH1"
8369   return output_branch (sh_eval_treg_value (operands[1]), insn, operands);
8371   "&& 1"
8372   [(set (pc) (if_then_else (eq (reg:SI T_REG) (match_dup 2))
8373                            (label_ref (match_dup 0))
8374                            (pc)))]
8376   /* Try to find missed test and branch combine opportunities which result
8377      in redundant T bit tests before conditional branches.
8378      This is done not only after combine (and before reload) but in every
8379      split pass, because some opportunities are formed also after combine.
8380      FIXME: Probably this would not be needed if CCmode was used
8381      together with TARGET_FIXED_CONDITION_CODE_REGS.  */
8383   const int treg_value = sh_eval_treg_value (operands[1]);
8384   operands[2] = NULL_RTX;
8386   /* Scan the insns backwards for an insn that sets the T bit by testing a
8387      reg against zero like:
8388         (set (reg T_REG) (eq (reg) (const_int 0)))  */
8389   rtx testing_insn = NULL_RTX;
8390   rtx tested_reg = NULL_RTX;
8392   set_of_reg s0 = sh_find_set_of_reg (get_t_reg_rtx (), curr_insn,
8393                                       prev_nonnote_insn_bb);
8394   if (s0.set_src != NULL_RTX
8395       && GET_CODE (s0.set_src) == EQ
8396       && REG_P (XEXP (s0.set_src, 0))
8397       && satisfies_constraint_Z (XEXP (s0.set_src, 1)))
8398     {
8399       testing_insn = s0.insn;
8400       tested_reg = XEXP (s0.set_src, 0);
8401     }
8402   else
8403     FAIL;
8405   /* Continue scanning the insns backwards and try to find the insn that
8406      sets the tested reg which we found above.  If the reg is set by storing
8407      the T bit or the negated T bit we can eliminate the test insn before
8408      the branch.  Notice that the branch condition has to be inverted if the
8409      test is eliminated.  */
8411   /* If the T bit is used between the testing insn and the brach insn
8412      leave it alone.  */
8413   if (reg_used_between_p (get_t_reg_rtx (), testing_insn, curr_insn))
8414     FAIL;
8416   while (true)
8417     {
8418       /* It's not safe to go beyond the current basic block after reload.  */
8419       set_of_reg s1 = sh_find_set_of_reg (tested_reg, s0.insn,
8420                                           reload_completed
8421                                           ? prev_nonnote_insn_bb
8422                                           : prev_nonnote_insn);
8423       if (s1.set_src == NULL_RTX)
8424         break;
8426       if (t_reg_operand (s1.set_src, VOIDmode))
8427         operands[2] = GEN_INT (treg_value ^ 1);
8428       else if (negt_reg_operand (s1.set_src, VOIDmode))
8429         operands[2] = GEN_INT (treg_value);
8430       else if (REG_P (s1.set_src))
8431         {
8432            /* If it's a reg-reg copy follow the copied reg.  This can
8433               happen e.g. when T bit store zero-extensions are
8434               eliminated.  */
8435           tested_reg = s1.set_src;
8436           s0.insn = s1.insn;
8437           continue;
8438         }
8440         /* It's only safe to remove the testing insn if the T bit is not
8441            modified between the testing insn and the insn that stores the
8442            T bit.  Notice that some T bit stores such as negc also modify
8443            the T bit.  */
8444         if (modified_between_p (get_t_reg_rtx (), s1.insn, testing_insn)
8445             || modified_in_p (get_t_reg_rtx (), s1.insn))
8446           operands[2] = NULL_RTX;
8448         break;
8449       }
8451   if (operands[2] == NULL_RTX)
8452     FAIL;
8454   set_insn_deleted (testing_insn);
8456   [(set_attr "type" "cbranch")])
8458 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
8459 ;; which destination is too far away.
8460 ;; The const_int_operand is distinct for each branch target; it avoids
8461 ;; unwanted matches with redundant_insn.
8462 (define_insn "block_branch_redirect"
8463   [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
8464   "TARGET_SH1"
8465   ""
8466   [(set_attr "length" "0")])
8468 ;; This one has the additional purpose to record a possible scratch register
8469 ;; for the following branch.
8470 ;; ??? Unfortunately, just setting the scratch register is not good enough,
8471 ;; because the insn then might be deemed dead and deleted.  And we can't
8472 ;; make the use in the jump insn explicit because that would disable
8473 ;; delay slot scheduling from the target.
8474 (define_insn "indirect_jump_scratch"
8475   [(set (match_operand:SI 0 "register_operand" "=r")
8476         (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
8477    (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
8478   "TARGET_SH1"
8479   ""
8480   [(set_attr "length" "0")])
8482 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
8483 ;; being pulled into the delay slot of a condbranch that has been made to
8484 ;; jump around the unconditional jump because it was out of range.
8485 (define_insn "stuff_delay_slot"
8486   [(set (pc)
8487         (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
8488                  (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
8489   "TARGET_SH1"
8490   ""
8491   [(set_attr "length" "0")
8492    (set_attr "cond_delay_slot" "yes")])
8494 ;; Conditional branch insns
8496 (define_expand "cbranchint4_media"
8497   [(set (pc)
8498         (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
8499                        [(match_operand 1 "" "")
8500                         (match_operand 2 "" "")])
8501                       (match_operand 3 "" "")
8502                       (pc)))]
8503   "TARGET_SHMEDIA"
8505   enum machine_mode mode = GET_MODE (operands[1]);
8506   if (mode == VOIDmode)
8507     mode = GET_MODE (operands[2]);
8508   if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
8509     {
8510       operands[1] = force_reg (mode, operands[1]);
8511       if (CONSTANT_P (operands[2])
8512           && (! satisfies_constraint_I06 (operands[2])))
8513         operands[2] = force_reg (mode, operands[2]);
8514     }
8515   else
8516     {
8517       if (operands[1] != const0_rtx)
8518         operands[1] = force_reg (mode, operands[1]);
8519       if (operands[2] != const0_rtx)
8520         operands[2] = force_reg (mode, operands[2]);
8521     }
8522   switch (GET_CODE (operands[0]))
8523     {
8524     case LEU:
8525     case LE:
8526     case LTU:
8527     case LT:
8528       operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
8529                                     VOIDmode, operands[2], operands[1]);
8530       operands[1] = XEXP (operands[0], 0);
8531       operands[2] = XEXP (operands[0], 1);
8532       break;
8533     default:
8534       operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
8535                                     VOIDmode, operands[1], operands[2]);
8536       break;
8537     }
8538   operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
8541 (define_expand "cbranchfp4_media"
8542   [(set (pc)
8543         (if_then_else (match_operator 0 "sh_float_comparison_operator"
8544                        [(match_operand 1 "" "")
8545                         (match_operand 2 "" "")])
8546                       (match_operand 3 "" "")
8547                       (pc)))]
8548   "TARGET_SHMEDIA"
8550   rtx tmp = gen_reg_rtx (SImode);
8551   rtx cmp;
8552   if (GET_CODE (operands[0]) == NE)
8553     cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
8554   else
8555     cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
8556                           operands[1], operands[2]);
8558   emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
8560   if (GET_CODE (cmp) == GET_CODE (operands[0]))
8561     operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
8562   else
8563     operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
8564   operands[1] = tmp;
8565   operands[2] = const0_rtx;
8566   operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
8569 (define_insn "*beq_media_i"
8570   [(set (pc)
8571         (if_then_else (match_operator 3 "equality_comparison_operator"
8572                         [(match_operand:DI 1 "arith_reg_operand" "r,r")
8573                          (match_operand:DI 2 "arith_operand" "r,I06")])
8574                       (match_operand 0 "target_operand" "b,b")
8575                       (pc)))]
8576   "TARGET_SHMEDIA"
8577   "@
8578         b%o3%'  %1, %2, %0%>
8579         b%o3i%' %1, %2, %0%>"
8580   [(set_attr "type" "cbranch_media")])
8582 (define_insn "*beq_media_i32"
8583   [(set (pc)
8584         (if_then_else (match_operator 3 "equality_comparison_operator"
8585                         [(match_operand:SI 1 "arith_reg_operand" "r,r")
8586                          (match_operand:SI 2 "arith_operand" "r,I06")])
8587                       (match_operand 0 "target_operand" "b,b")
8588                       (pc)))]
8589   "TARGET_SHMEDIA"
8590   "@
8591         b%o3%'  %1, %2, %0%>
8592         b%o3i%' %1, %2, %0%>"
8593   [(set_attr "type" "cbranch_media")])
8595 (define_insn "*bgt_media_i"
8596   [(set (pc)
8597         (if_then_else (match_operator 3 "greater_comparison_operator"
8598                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8599                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
8600                       (match_operand 0 "target_operand" "b")
8601                       (pc)))]
8602   "TARGET_SHMEDIA"
8603   "b%o3%'       %N1, %N2, %0%>"
8604   [(set_attr "type" "cbranch_media")])
8606 (define_insn "*bgt_media_i32"
8607   [(set (pc)
8608         (if_then_else (match_operator 3 "greater_comparison_operator"
8609                         [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8610                          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8611                       (match_operand 0 "target_operand" "b")
8612                       (pc)))]
8613   "TARGET_SHMEDIA"
8614   "b%o3%'       %N1, %N2, %0%>"
8615   [(set_attr "type" "cbranch_media")])
8617 ;; These are only needed to make invert_jump() happy - otherwise, jump
8618 ;; optimization will be silently disabled.
8619 (define_insn "*blt_media_i"
8620   [(set (pc)
8621         (if_then_else (match_operator 3 "less_comparison_operator"
8622                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8623                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
8624                       (match_operand 0 "target_operand" "b")
8625                       (pc)))]
8626   "TARGET_SHMEDIA"
8627   "b%o3%'       %N2, %N1, %0%>"
8628   [(set_attr "type" "cbranch_media")])
8630 (define_insn "*blt_media_i32"
8631   [(set (pc)
8632         (if_then_else (match_operator 3 "less_comparison_operator"
8633                         [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8634                          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8635                       (match_operand 0 "target_operand" "b")
8636                       (pc)))]
8637   "TARGET_SHMEDIA"
8638   "b%o3%'       %N2, %N1, %0%>"
8639   [(set_attr "type" "cbranch_media")])
8641 ;; combiner splitter for test-and-branch on single bit in register.  This
8642 ;; is endian dependent because the non-paradoxical subreg looks different
8643 ;; on big endian.
8644 (define_split
8645   [(set (pc)
8646         (if_then_else
8647           (match_operator 3 "equality_comparison_operator"
8648             [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1
8649                                                       "extend_reg_operand" "")
8650                                                     0)
8651                                          (const_int 1)
8652                                          (match_operand 2
8653                                           "const_int_operand" "")) 0)
8654              (const_int 0)])
8655           (match_operand 0 "target_operand" "")
8656           (pc)))
8657    (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
8658   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
8659   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
8660    (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
8662   operands[5] = GEN_INT (31 - INTVAL (operands[2]));
8663   operands[6] = (GET_CODE (operands[3]) == EQ
8664                  ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
8665                  : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
8668 ; operand 0 is the loop count pseudo register
8669 ; operand 1 is the number of loop iterations or 0 if it is unknown
8670 ; operand 2 is the maximum number of loop iterations
8671 ; operand 3 is the number of levels of enclosed loops
8672 ; operand 4 is the label to jump to at the top of the loop
8674 (define_expand "doloop_end"
8675   [(parallel [(set (pc) (if_then_else
8676                           (ne:SI (match_operand:SI 0 "" "")
8677                               (const_int 1))
8678                           (label_ref (match_operand 4 "" ""))
8679                           (pc)))
8680               (set (match_dup 0)
8681                    (plus:SI (match_dup 0) (const_int -1)))
8682               (clobber (reg:SI T_REG))])
8683    (match_operand 5 "" "")]
8684   "TARGET_SH2"
8686   if (GET_MODE (operands[0]) != SImode)
8687     FAIL;
8688   emit_jump_insn (gen_doloop_end_split (operands[0], operands[4], operands[0]));
8689   DONE;
8692 (define_insn_and_split "doloop_end_split"
8693   [(set (pc)
8694         (if_then_else (ne:SI  (match_operand:SI 2 "arith_reg_dest" "0")
8695                           (const_int 1))
8696                       (label_ref (match_operand 1 "" ""))
8697                       (pc)))
8698    (set (match_operand:SI 0 "arith_reg_dest" "=r")
8699         (plus (match_dup 2) (const_int -1)))
8700    (clobber (reg:SI T_REG))]
8701   "TARGET_SH2"
8702   "#"
8703   ""
8704   [(parallel [(set (reg:SI T_REG)
8705                    (eq:SI (match_dup 2) (const_int 1)))
8706               (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
8707    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8708                            (label_ref (match_dup 1))
8709                            (pc)))]
8710   ""
8711    [(set_attr "type" "cbranch")])
8714 ;; ------------------------------------------------------------------------
8715 ;; Jump and linkage insns
8716 ;; ------------------------------------------------------------------------
8718 (define_insn "jump_compact"
8719   [(set (pc)
8720         (label_ref (match_operand 0 "" "")))]
8721   "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
8723   /* The length is 16 if the delay slot is unfilled.  */
8724   if (get_attr_length(insn) > 4)
8725     return output_far_jump(insn, operands[0]);
8726   else
8727     return "bra %l0%#";
8729   [(set_attr "type" "jump")
8730    (set_attr "needs_delay_slot" "yes")])
8732 ;; ??? It would be much saner to explicitly use the scratch register
8733 ;; in the jump insn, and have indirect_jump_scratch only set it,
8734 ;; but fill_simple_delay_slots would refuse to do delay slot filling
8735 ;; from the target then, as it uses simplejump_p.
8736 ;;(define_insn "jump_compact_far"
8737 ;;  [(set (pc)
8738 ;;      (label_ref (match_operand 0 "" "")))
8739 ;;   (use (match_operand 1 "register_operand" "r")]
8740 ;;  "TARGET_SH1"
8741 ;;  "* return output_far_jump(insn, operands[0], operands[1]);"
8742 ;;  [(set_attr "type" "jump")
8743 ;;   (set_attr "needs_delay_slot" "yes")])
8745 (define_insn "jump_media"
8746   [(set (pc)
8747         (match_operand 0 "target_operand" "b"))]
8748   "TARGET_SHMEDIA"
8749   "blink        %0, r63%>"
8750   [(set_attr "type" "jump_media")])
8752 (define_expand "jump"
8753   [(set (pc)
8754         (label_ref (match_operand 0 "" "")))]
8755   ""
8757   if (TARGET_SH1)
8758     emit_jump_insn (gen_jump_compact (operands[0]));
8759   else if (TARGET_SHMEDIA)
8760     {
8761       if (reload_in_progress || reload_completed)
8762         FAIL;
8763       emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode,
8764                                                          operands[0])));
8765     }
8766   DONE;
8769 (define_insn "force_mode_for_call"
8770   [(use (reg:PSI FPSCR_REG))]
8771   "TARGET_SHCOMPACT"
8772   ""
8773   [(set_attr "length" "0")
8774    (set (attr "fp_mode")
8775         (if_then_else (eq_attr "fpu_single" "yes")
8776                       (const_string "single") (const_string "double")))])
8778 (define_insn "calli"
8779   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8780          (match_operand 1 "" ""))
8781    (use (reg:PSI FPSCR_REG))
8782    (clobber (reg:SI PR_REG))]
8783   "TARGET_SH1"
8785   if (TARGET_SH2A && (dbr_sequence_length () == 0))
8786     return "jsr/n       @%0";
8787   else
8788     return "jsr @%0%#";
8790   [(set_attr "type" "call")
8791    (set (attr "fp_mode")
8792         (if_then_else (eq_attr "fpu_single" "yes")
8793                       (const_string "single") (const_string "double")))
8794    (set_attr "needs_delay_slot" "yes")
8795    (set_attr "fp_set" "unknown")])
8797 ;; This is TBR relative jump instruction for SH2A architecture.
8798 ;; Its use is enabled assigning an attribute "function_vector"
8799 ;; and the vector number to a function during its declaration.
8801 (define_insn "calli_tbr_rel"
8802   [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
8803          (match_operand 1 "" ""))
8804    (use (reg:PSI FPSCR_REG))
8805    (clobber (reg:SI PR_REG))]
8806   "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
8808   unsigned HOST_WIDE_INT vect_num;
8809   vect_num = sh2a_get_function_vector_number (operands[0]);
8810   operands[2] = GEN_INT (vect_num * 4);
8812   return "jsr/n @@(%O2,tbr)";
8814   [(set_attr "type" "call")
8815    (set (attr "fp_mode")
8816         (if_then_else (eq_attr "fpu_single" "yes")
8817                       (const_string "single") (const_string "double")))
8818    (set_attr "needs_delay_slot" "no")
8819    (set_attr "fp_set" "unknown")])
8821 ;; This is a pc-rel call, using bsrf, for use with PIC.
8823 (define_insn "calli_pcrel"
8824   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8825          (match_operand 1 "" ""))
8826    (use (reg:PSI FPSCR_REG))
8827    (use (reg:SI PIC_REG))
8828    (use (match_operand 2 "" ""))
8829    (clobber (reg:SI PR_REG))]
8830   "TARGET_SH2"
8832   return       "bsrf    %0"     "\n"
8833          "%O2:%#";
8835   [(set_attr "type" "call")
8836    (set (attr "fp_mode")
8837         (if_then_else (eq_attr "fpu_single" "yes")
8838                       (const_string "single") (const_string "double")))
8839    (set_attr "needs_delay_slot" "yes")
8840    (set_attr "fp_set" "unknown")])
8842 (define_insn_and_split "call_pcrel"
8843   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
8844          (match_operand 1 "" ""))
8845    (use (reg:PSI FPSCR_REG))
8846    (use (reg:SI PIC_REG))
8847    (clobber (reg:SI PR_REG))
8848    (clobber (match_scratch:SI 2 "=r"))]
8849   "TARGET_SH2"
8850   "#"
8851   "reload_completed"
8852   [(const_int 0)]
8854   rtx lab = PATTERN (gen_call_site ());
8856   if (SYMBOL_REF_LOCAL_P (operands[0]))
8857     emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
8858   else
8859     emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
8860   emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
8861   DONE;
8863   [(set_attr "type" "call")
8864    (set (attr "fp_mode")
8865         (if_then_else (eq_attr "fpu_single" "yes")
8866                       (const_string "single") (const_string "double")))
8867    (set_attr "needs_delay_slot" "yes")
8868    (set_attr "fp_set" "unknown")])
8870 (define_insn "call_compact"
8871   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8872          (match_operand 1 "" ""))
8873    (match_operand 2 "immediate_operand" "n")
8874    (use (reg:SI R0_REG))
8875    (use (reg:SI R1_REG))
8876    (use (reg:PSI FPSCR_REG))
8877    (clobber (reg:SI PR_REG))]
8878   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8879   "jsr  @%0%#"
8880   [(set_attr "type" "call")
8881    (set (attr "fp_mode")
8882         (if_then_else (eq_attr "fpu_single" "yes")
8883                       (const_string "single") (const_string "double")))
8884    (set_attr "needs_delay_slot" "yes")])
8886 (define_insn "call_compact_rettramp"
8887   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8888          (match_operand 1 "" ""))
8889    (match_operand 2 "immediate_operand" "n")
8890    (use (reg:SI R0_REG))
8891    (use (reg:SI R1_REG))
8892    (use (reg:PSI FPSCR_REG))
8893    (clobber (reg:SI R10_REG))
8894    (clobber (reg:SI PR_REG))]
8895   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8896   "jsr  @%0%#"
8897   [(set_attr "type" "call")
8898    (set (attr "fp_mode")
8899         (if_then_else (eq_attr "fpu_single" "yes")
8900                       (const_string "single") (const_string "double")))
8901    (set_attr "needs_delay_slot" "yes")])
8903 (define_insn "call_media"
8904   [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
8905          (match_operand 1 "" ""))
8906    (clobber (reg:DI PR_MEDIA_REG))]
8907   "TARGET_SHMEDIA"
8908   "blink        %0, r18"
8909   [(set_attr "type" "jump_media")])
8911 (define_insn "call_valuei"
8912   [(set (match_operand 0 "" "=rf")
8913         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8914               (match_operand 2 "" "")))
8915    (use (reg:PSI FPSCR_REG))
8916    (clobber (reg:SI PR_REG))]
8917   "TARGET_SH1"
8919   if (TARGET_SH2A && (dbr_sequence_length () == 0))
8920     return "jsr/n       @%1";
8921   else
8922     return "jsr @%1%#";
8924   [(set_attr "type" "call")
8925    (set (attr "fp_mode")
8926         (if_then_else (eq_attr "fpu_single" "yes")
8927                       (const_string "single") (const_string "double")))
8928    (set_attr "needs_delay_slot" "yes")
8929    (set_attr "fp_set" "unknown")])
8931 ;; This is TBR relative jump instruction for SH2A architecture.
8932 ;; Its use is enabled by assigning an attribute "function_vector"
8933 ;; and the vector number to a function during its declaration.
8935 (define_insn "call_valuei_tbr_rel"
8936   [(set (match_operand 0 "" "=rf")
8937         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
8938               (match_operand 2 "" "")))
8939    (use (reg:PSI FPSCR_REG))
8940    (clobber (reg:SI PR_REG))]
8941   "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
8943   unsigned HOST_WIDE_INT vect_num;
8944   vect_num = sh2a_get_function_vector_number (operands[1]);
8945   operands[3] = GEN_INT (vect_num * 4);
8947   return "jsr/n @@(%O3,tbr)";
8949   [(set_attr "type" "call")
8950    (set (attr "fp_mode")
8951         (if_then_else (eq_attr "fpu_single" "yes")
8952                       (const_string "single") (const_string "double")))
8953    (set_attr "needs_delay_slot" "no")
8954    (set_attr "fp_set" "unknown")])
8956 (define_insn "call_valuei_pcrel"
8957   [(set (match_operand 0 "" "=rf")
8958         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8959               (match_operand 2 "" "")))
8960    (use (reg:PSI FPSCR_REG))
8961    (use (reg:SI PIC_REG))
8962    (use (match_operand 3 "" ""))
8963    (clobber (reg:SI PR_REG))]
8964   "TARGET_SH2"
8966   return       "bsrf    %1"     "\n"
8967          "%O3:%#";
8969   [(set_attr "type" "call")
8970    (set (attr "fp_mode")
8971         (if_then_else (eq_attr "fpu_single" "yes")
8972                       (const_string "single") (const_string "double")))
8973    (set_attr "needs_delay_slot" "yes")
8974    (set_attr "fp_set" "unknown")])
8976 (define_insn_and_split "call_value_pcrel"
8977   [(set (match_operand 0 "" "=rf")
8978         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
8979               (match_operand 2 "" "")))
8980    (use (reg:PSI FPSCR_REG))
8981    (use (reg:SI PIC_REG))
8982    (clobber (reg:SI PR_REG))
8983    (clobber (match_scratch:SI 3 "=r"))]
8984   "TARGET_SH2"
8985   "#"
8986   "reload_completed"
8987   [(const_int 0)]
8989   rtx lab = PATTERN (gen_call_site ());
8991   if (SYMBOL_REF_LOCAL_P (operands[1]))
8992     emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
8993   else
8994     emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
8995   emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
8996                                          operands[2], copy_rtx (lab)));
8997   DONE;
8999   [(set_attr "type" "call")
9000    (set (attr "fp_mode")
9001         (if_then_else (eq_attr "fpu_single" "yes")
9002                       (const_string "single") (const_string "double")))
9003    (set_attr "needs_delay_slot" "yes")
9004    (set_attr "fp_set" "unknown")])
9006 (define_insn "call_value_compact"
9007   [(set (match_operand 0 "" "=rf")
9008         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9009               (match_operand 2 "" "")))
9010    (match_operand 3 "immediate_operand" "n")
9011    (use (reg:SI R0_REG))
9012    (use (reg:SI R1_REG))
9013    (use (reg:PSI FPSCR_REG))
9014    (clobber (reg:SI PR_REG))]
9015   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9016   "jsr  @%1%#"
9017   [(set_attr "type" "call")
9018    (set (attr "fp_mode")
9019         (if_then_else (eq_attr "fpu_single" "yes")
9020                       (const_string "single") (const_string "double")))
9021    (set_attr "needs_delay_slot" "yes")])
9023 (define_insn "call_value_compact_rettramp"
9024   [(set (match_operand 0 "" "=rf")
9025         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9026               (match_operand 2 "" "")))
9027    (match_operand 3 "immediate_operand" "n")
9028    (use (reg:SI R0_REG))
9029    (use (reg:SI R1_REG))
9030    (use (reg:PSI FPSCR_REG))
9031    (clobber (reg:SI R10_REG))
9032    (clobber (reg:SI PR_REG))]
9033   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9034   "jsr  @%1%#"
9035   [(set_attr "type" "call")
9036    (set (attr "fp_mode")
9037         (if_then_else (eq_attr "fpu_single" "yes")
9038                       (const_string "single") (const_string "double")))
9039    (set_attr "needs_delay_slot" "yes")])
9041 (define_insn "call_value_media"
9042   [(set (match_operand 0 "" "=rf")
9043         (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
9044               (match_operand 2 "" "")))
9045    (clobber (reg:DI PR_MEDIA_REG))]
9046   "TARGET_SHMEDIA"
9047   "blink        %1, r18"
9048   [(set_attr "type" "jump_media")])
9050 (define_expand "call"
9051   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9052                             (match_operand 1 "" ""))
9053               (match_operand 2 "" "")
9054               (use (reg:PSI FPSCR_REG))
9055               (clobber (reg:SI PR_REG))])]
9056   ""
9058   if (TARGET_SHMEDIA)
9059     {
9060       operands[0] = shmedia_prepare_call_address (operands[0], 0);
9061       emit_call_insn (gen_call_media (operands[0], operands[1]));
9062       DONE;
9063     }
9064   else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
9065     {
9066       rtx cookie_rtx = operands[2];
9067       long cookie = INTVAL (cookie_rtx);
9068       rtx func = XEXP (operands[0], 0);
9069       rtx r0, r1;
9071       if (flag_pic)
9072         {
9073           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9074             {
9075               rtx reg = gen_reg_rtx (Pmode);
9077               emit_insn (gen_symGOTPLT2reg (reg, func));
9078               func = reg;
9079             }
9080           else
9081             func = legitimize_pic_address (func, Pmode, 0);
9082         }
9084       r0 = gen_rtx_REG (SImode, R0_REG);
9085       r1 = gen_rtx_REG (SImode, R1_REG);
9087       /* Since such a call function may use all call-clobbered
9088          registers, we force a mode switch earlier, so that we don't
9089          run out of registers when adjusting fpscr for the call.  */
9090       emit_insn (gen_force_mode_for_call ());
9092       operands[0]
9093         = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9094       operands[0] = force_reg (SImode, operands[0]);
9096       emit_move_insn (r0, func);
9097       emit_move_insn (r1, cookie_rtx);
9099       if (cookie & CALL_COOKIE_RET_TRAMP (1))
9100         emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
9101                                                    operands[2]));
9102       else
9103         emit_call_insn (gen_call_compact (operands[0], operands[1],
9104                                           operands[2]));
9106       DONE;
9107     }
9108   else if (TARGET_SHCOMPACT && flag_pic
9109            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9110            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9111     {
9112       rtx reg = gen_reg_rtx (Pmode);
9114       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
9115       XEXP (operands[0], 0) = reg;
9116     }
9117   if (!flag_pic && TARGET_SH2A
9118       && MEM_P (operands[0])
9119       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9120     {
9121       if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
9122         {
9123           emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
9124                                              operands[1]));
9125           DONE;
9126         }
9127     }
9128   if (flag_pic && TARGET_SH2
9129       && MEM_P (operands[0])
9130       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9131     {
9132       emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
9133       DONE;
9134     }
9135   else
9136   {
9137     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9138     operands[1] = operands[2];
9139   }
9141   emit_call_insn (gen_calli (operands[0], operands[1]));
9142   DONE;
9145 (define_insn "call_pop_compact"
9146   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9147          (match_operand 1 "" ""))
9148    (match_operand 2 "immediate_operand" "n")
9149    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9150                                  (match_operand 3 "immediate_operand" "n")))
9151    (use (reg:SI R0_REG))
9152    (use (reg:SI R1_REG))
9153    (use (reg:PSI FPSCR_REG))
9154    (clobber (reg:SI PR_REG))]
9155   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9156   "jsr  @%0%#"
9157   [(set_attr "type" "call")
9158    (set (attr "fp_mode")
9159         (if_then_else (eq_attr "fpu_single" "yes")
9160                       (const_string "single") (const_string "double")))
9161    (set_attr "needs_delay_slot" "yes")])
9163 (define_insn "call_pop_compact_rettramp"
9164   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9165          (match_operand 1 "" ""))
9166    (match_operand 2 "immediate_operand" "n")
9167    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9168                                  (match_operand 3 "immediate_operand" "n")))
9169    (use (reg:SI R0_REG))
9170    (use (reg:SI R1_REG))
9171    (use (reg:PSI FPSCR_REG))
9172    (clobber (reg:SI R10_REG))
9173    (clobber (reg:SI PR_REG))]
9174   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9175   "jsr  @%0%#"
9176   [(set_attr "type" "call")
9177    (set (attr "fp_mode")
9178         (if_then_else (eq_attr "fpu_single" "yes")
9179                       (const_string "single") (const_string "double")))
9180    (set_attr "needs_delay_slot" "yes")])
9182 (define_expand "call_pop"
9183   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9184                     (match_operand 1 "" ""))
9185              (match_operand 2 "" "")
9186              (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9187                                            (match_operand 3 "" "")))])]
9188   "TARGET_SHCOMPACT"
9190   rtx cookie_rtx;
9191   long cookie;
9192   rtx func;
9193   rtx r0, r1;
9195   gcc_assert (operands[2] && INTVAL (operands[2]));
9196   cookie_rtx = operands[2];
9197   cookie = INTVAL (cookie_rtx);
9198   func = XEXP (operands[0], 0);
9200   if (flag_pic)
9201     {
9202       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9203         {
9204           rtx reg = gen_reg_rtx (Pmode);
9205           emit_insn (gen_symGOTPLT2reg (reg, func));
9206           func = reg;
9207         }
9208       else
9209         func = legitimize_pic_address (func, Pmode, 0);
9210     }
9212   r0 = gen_rtx_REG (SImode, R0_REG);
9213   r1 = gen_rtx_REG (SImode, R1_REG);
9215   /* Since such a call function may use all call-clobbered
9216      registers, we force a mode switch earlier, so that we don't
9217      run out of registers when adjusting fpscr for the call.  */
9218   emit_insn (gen_force_mode_for_call ());
9220   operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9221                                  SFUNC_GOT);
9222   operands[0] = force_reg (SImode, operands[0]);
9224   emit_move_insn (r0, func);
9225   emit_move_insn (r1, cookie_rtx);
9227   if (cookie & CALL_COOKIE_RET_TRAMP (1))
9228     emit_call_insn (gen_call_pop_compact_rettramp
9229                      (operands[0], operands[1], operands[2], operands[3]));
9230   else
9231     emit_call_insn (gen_call_pop_compact
9232                      (operands[0], operands[1], operands[2], operands[3]));
9234   DONE;
9237 (define_expand "call_value"
9238   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9239                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9240                                  (match_operand 2 "" "")))
9241               (match_operand 3 "" "")
9242               (use (reg:PSI FPSCR_REG))
9243               (clobber (reg:SI PR_REG))])]
9244   ""
9246   if (TARGET_SHMEDIA)
9247     {
9248       operands[1] = shmedia_prepare_call_address (operands[1], 0);
9249       emit_call_insn (gen_call_value_media (operands[0], operands[1],
9250                                             operands[2]));
9251       DONE;
9252     }
9253   else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
9254     {
9255       rtx cookie_rtx = operands[3];
9256       long cookie = INTVAL (cookie_rtx);
9257       rtx func = XEXP (operands[1], 0);
9258       rtx r0, r1;
9260       if (flag_pic)
9261         {
9262           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9263             {
9264               rtx reg = gen_reg_rtx (Pmode);
9266               emit_insn (gen_symGOTPLT2reg (reg, func));
9267               func = reg;
9268             }
9269           else
9270             func = legitimize_pic_address (func, Pmode, 0);
9271         }
9273       r0 = gen_rtx_REG (SImode, R0_REG);
9274       r1 = gen_rtx_REG (SImode, R1_REG);
9276       /* Since such a call function may use all call-clobbered
9277          registers, we force a mode switch earlier, so that we don't
9278          run out of registers when adjusting fpscr for the call.  */
9279       emit_insn (gen_force_mode_for_call ());
9281       operands[1]
9282         = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9283       operands[1] = force_reg (SImode, operands[1]);
9285       emit_move_insn (r0, func);
9286       emit_move_insn (r1, cookie_rtx);
9288       if (cookie & CALL_COOKIE_RET_TRAMP (1))
9289         emit_call_insn (gen_call_value_compact_rettramp (operands[0],
9290                                                          operands[1],
9291                                                          operands[2],
9292                                                          operands[3]));
9293       else
9294         emit_call_insn (gen_call_value_compact (operands[0], operands[1],
9295                                                 operands[2], operands[3]));
9297       DONE;
9298     }
9299   else if (TARGET_SHCOMPACT && flag_pic
9300            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9301            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9302     {
9303       rtx reg = gen_reg_rtx (Pmode);
9305       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
9306       XEXP (operands[1], 0) = reg;
9307     }
9308   if (!flag_pic && TARGET_SH2A
9309       && MEM_P (operands[1])
9310       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9311     {
9312       if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
9313         {
9314           emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
9315                                  XEXP (operands[1], 0), operands[2]));
9316           DONE;
9317         }
9318     }
9319   if (flag_pic && TARGET_SH2
9320       && MEM_P (operands[1])
9321       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9322     {
9323       emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
9324                                             operands[2]));
9325       DONE;
9326     }
9327   else
9328     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9330   emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
9331   DONE;
9334 (define_insn "sibcalli"
9335   [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
9336          (match_operand 1 "" ""))
9337    (use (reg:PSI FPSCR_REG))
9338    (return)]
9339   "TARGET_SH1"
9340   "jmp  @%0%#"
9341   [(set_attr "needs_delay_slot" "yes")
9342    (set (attr "fp_mode")
9343         (if_then_else (eq_attr "fpu_single" "yes")
9344                       (const_string "single") (const_string "double")))
9345    (set_attr "type" "jump_ind")])
9347 (define_insn "sibcalli_pcrel"
9348   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
9349          (match_operand 1 "" ""))
9350    (use (match_operand 2 "" ""))
9351    (use (reg:PSI FPSCR_REG))
9352    (return)]
9353   "TARGET_SH2"
9355   return       "braf    %0"     "\n"
9356          "%O2:%#";
9358   [(set_attr "needs_delay_slot" "yes")
9359    (set (attr "fp_mode")
9360         (if_then_else (eq_attr "fpu_single" "yes")
9361                       (const_string "single") (const_string "double")))
9362    (set_attr "type" "jump_ind")])
9364 ;; This uses an unspec to describe that the symbol_ref is very close.
9365 (define_insn "sibcalli_thunk"
9366   [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
9367                              UNSPEC_THUNK))
9368          (match_operand 1 "" ""))
9369    (use (reg:PSI FPSCR_REG))
9370    (return)]
9371   "TARGET_SH1"
9372   "bra  %O0"
9373   [(set_attr "needs_delay_slot" "yes")
9374    (set (attr "fp_mode")
9375         (if_then_else (eq_attr "fpu_single" "yes")
9376                       (const_string "single") (const_string "double")))
9377    (set_attr "type" "jump")
9378    (set_attr "length" "2")])
9380 (define_insn_and_split "sibcall_pcrel"
9381   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
9382          (match_operand 1 "" ""))
9383    (use (reg:PSI FPSCR_REG))
9384    (clobber (match_scratch:SI 2 "=k"))
9385    (return)]
9386   "TARGET_SH2"
9387   "#"
9388   "reload_completed"
9389   [(const_int 0)]
9391   rtx lab = PATTERN (gen_call_site ());
9392   rtx call_insn;
9394   emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
9395   call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
9396                                                   copy_rtx (lab)));
9397   SIBLING_CALL_P (call_insn) = 1;
9398   DONE;
9400   [(set_attr "needs_delay_slot" "yes")
9401    (set (attr "fp_mode")
9402         (if_then_else (eq_attr "fpu_single" "yes")
9403                       (const_string "single") (const_string "double")))
9404    (set_attr "type" "jump_ind")])
9406 (define_insn "sibcall_compact"
9407   [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
9408          (match_operand 1 "" ""))
9409    (return)
9410    (use (match_operand:SI 2 "register_operand" "z,x"))
9411    (use (reg:SI R1_REG))
9412    (use (reg:PSI FPSCR_REG))
9413    ;; We want to make sure the `x' above will only match MACH_REG
9414    ;; because sibcall_epilogue may clobber MACL_REG.
9415    (clobber (reg:SI MACL_REG))]
9416   "TARGET_SHCOMPACT"
9418   static const char* alt[] =
9419   {
9420        "jmp     @%0%#",
9422        "jmp     @%0"    "\n"
9423     "   sts     %2,r0"
9424   };
9425   return alt[which_alternative];
9427   [(set_attr "needs_delay_slot" "yes,no")
9428    (set_attr "length" "2,4")
9429    (set (attr "fp_mode") (const_string "single"))
9430    (set_attr "type" "jump_ind")])
9432 (define_insn "sibcall_media"
9433   [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
9434          (match_operand 1 "" ""))
9435    (use (reg:SI PR_MEDIA_REG))
9436    (return)]
9437   "TARGET_SHMEDIA"
9438   "blink        %0, r63"
9439   [(set_attr "type" "jump_media")])
9441 (define_expand "sibcall"
9442   [(parallel
9443     [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9444            (match_operand 1 "" ""))
9445      (match_operand 2 "" "")
9446      (use (reg:PSI FPSCR_REG))
9447      (return)])]
9448   ""
9450   if (TARGET_SHMEDIA)
9451     {
9452       operands[0] = shmedia_prepare_call_address (operands[0], 1);
9453       emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
9454       DONE;
9455     }
9456   else if (TARGET_SHCOMPACT && operands[2]
9457            && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9458     {
9459       rtx cookie_rtx = operands[2];
9460       long cookie = INTVAL (cookie_rtx);
9461       rtx func = XEXP (operands[0], 0);
9462       rtx mach, r1;
9464       if (flag_pic)
9465         {
9466           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9467             {
9468               rtx reg = gen_reg_rtx (Pmode);
9470               emit_insn (gen_symGOT2reg (reg, func));
9471               func = reg;
9472             }
9473           else
9474             func = legitimize_pic_address (func, Pmode, 0);
9475         }
9477       /* FIXME: if we could tell whether all argument registers are
9478          already taken, we could decide whether to force the use of
9479          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
9480          simple way to tell.  We could use the CALL_COOKIE, but we
9481          can't currently tell a register used for regular argument
9482          passing from one that is unused.  If we leave it up to reload
9483          to decide which register to use, it seems to always choose
9484          R0_REG, which leaves no available registers in SIBCALL_REGS
9485          to hold the address of the trampoline.  */
9486       mach = gen_rtx_REG (SImode, MACH_REG);
9487       r1 = gen_rtx_REG (SImode, R1_REG);
9489       /* Since such a call function may use all call-clobbered
9490          registers, we force a mode switch earlier, so that we don't
9491          run out of registers when adjusting fpscr for the call.  */
9492       emit_insn (gen_force_mode_for_call ());
9494       operands[0]
9495         = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9496       operands[0] = force_reg (SImode, operands[0]);
9498       /* We don't need a return trampoline, since the callee will
9499          return directly to the upper caller.  */
9500       if (cookie & CALL_COOKIE_RET_TRAMP (1))
9501         {
9502           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9503           cookie_rtx = GEN_INT (cookie);
9504         }
9506       emit_move_insn (mach, func);
9507       emit_move_insn (r1, cookie_rtx);
9509       emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
9510       DONE;
9511     }
9512   else if (TARGET_SHCOMPACT && flag_pic
9513            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9514            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9515     {
9516       rtx reg = gen_reg_rtx (Pmode);
9518       emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
9519       XEXP (operands[0], 0) = reg;
9520     }
9521   if (flag_pic && TARGET_SH2
9522       && MEM_P (operands[0])
9523       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9524       /* The PLT needs the PIC register, but the epilogue would have
9525          to restore it, so we can only use PC-relative PIC calls for
9526          static functions.  */
9527       && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9528     {
9529       emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
9530       DONE;
9531     }
9532   else
9533     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9535   emit_call_insn (gen_sibcalli (operands[0], operands[1]));
9536   DONE;
9539 (define_insn "sibcall_valuei"
9540   [(set (match_operand 0 "" "=rf")
9541         (call (mem:SI (match_operand:SI 1 "register_operand" "k"))
9542               (match_operand 2 "" "")))
9543    (use (reg:PSI FPSCR_REG))
9544    (return)]
9545   "TARGET_SH1"
9546   "jmp  @%1%#"
9547   [(set_attr "needs_delay_slot" "yes")
9548    (set (attr "fp_mode")
9549         (if_then_else (eq_attr "fpu_single" "yes")
9550                       (const_string "single") (const_string "double")))
9551    (set_attr "type" "jump_ind")])
9553 (define_insn "sibcall_valuei_pcrel"
9554   [(set (match_operand 0 "" "=rf")
9555         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
9556               (match_operand 2 "" "")))
9557    (use (match_operand 3 "" ""))
9558    (use (reg:PSI FPSCR_REG))
9559    (return)]
9560   "TARGET_SH2"
9562   return       "braf    %1"     "\n"
9563          "%O3:%#";
9565   [(set_attr "needs_delay_slot" "yes")
9566    (set (attr "fp_mode")
9567         (if_then_else (eq_attr "fpu_single" "yes")
9568                       (const_string "single") (const_string "double")))
9569    (set_attr "type" "jump_ind")])
9571 (define_insn_and_split "sibcall_value_pcrel"
9572   [(set (match_operand 0 "" "=rf")
9573         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9574               (match_operand 2 "" "")))
9575    (use (reg:PSI FPSCR_REG))
9576    (clobber (match_scratch:SI 3 "=k"))
9577    (return)]
9578   "TARGET_SH2"
9579   "#"
9580   "reload_completed"
9581   [(const_int 0)]
9583   rtx lab = PATTERN (gen_call_site ());
9584   rtx call_insn;
9586   emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
9587   call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
9588                                                         operands[3],
9589                                                         operands[2],
9590                                                         copy_rtx (lab)));
9591   SIBLING_CALL_P (call_insn) = 1;
9592   DONE;
9594   [(set_attr "needs_delay_slot" "yes")
9595    (set (attr "fp_mode")
9596         (if_then_else (eq_attr "fpu_single" "yes")
9597                       (const_string "single") (const_string "double")))
9598    (set_attr "type" "jump_ind")])
9600 (define_insn "sibcall_value_compact"
9601   [(set (match_operand 0 "" "=rf,rf")
9602         (call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
9603               (match_operand 2 "" "")))
9604    (return)
9605    (use (match_operand:SI 3 "register_operand" "z,x"))
9606    (use (reg:SI R1_REG))
9607    (use (reg:PSI FPSCR_REG))
9608    ;; We want to make sure the `x' above will only match MACH_REG
9609    ;; because sibcall_epilogue may clobber MACL_REG.
9610    (clobber (reg:SI MACL_REG))]
9611   "TARGET_SHCOMPACT"
9613   static const char* alt[] =
9614   {
9615        "jmp     @%1%#",
9617        "jmp     @%1"    "\n"
9618     "   sts     %3,r0"
9619   };
9620   return alt[which_alternative];
9622   [(set_attr "needs_delay_slot" "yes,no")
9623    (set_attr "length" "2,4")
9624    (set (attr "fp_mode") (const_string "single"))
9625    (set_attr "type" "jump_ind")])
9627 (define_insn "sibcall_value_media"
9628   [(set (match_operand 0 "" "=rf")
9629         (call (mem:DI (match_operand 1 "target_reg_operand" "k"))
9630               (match_operand 2 "" "")))
9631    (use (reg:SI PR_MEDIA_REG))
9632    (return)]
9633   "TARGET_SHMEDIA"
9634   "blink        %1, r63"
9635   [(set_attr "type" "jump_media")])
9637 (define_expand "sibcall_value"
9638   [(parallel
9639     [(set (match_operand 0 "arith_reg_operand" "")
9640           (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9641                 (match_operand 2 "" "")))
9642      (match_operand 3 "" "")
9643      (use (reg:PSI FPSCR_REG))
9644      (return)])]
9645   ""
9647   if (TARGET_SHMEDIA)
9648     {
9649       operands[1] = shmedia_prepare_call_address (operands[1], 1);
9650       emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
9651                                                operands[2]));
9652       DONE;
9653     }
9654   else if (TARGET_SHCOMPACT && operands[3]
9655            && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9656     {
9657       rtx cookie_rtx = operands[3];
9658       long cookie = INTVAL (cookie_rtx);
9659       rtx func = XEXP (operands[1], 0);
9660       rtx mach, r1;
9662       if (flag_pic)
9663         {
9664           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9665             {
9666               rtx reg = gen_reg_rtx (Pmode);
9668               emit_insn (gen_symGOT2reg (reg, func));
9669               func = reg;
9670             }
9671           else
9672             func = legitimize_pic_address (func, Pmode, 0);
9673         }
9675       /* FIXME: if we could tell whether all argument registers are
9676          already taken, we could decide whether to force the use of
9677          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
9678          simple way to tell.  We could use the CALL_COOKIE, but we
9679          can't currently tell a register used for regular argument
9680          passing from one that is unused.  If we leave it up to reload
9681          to decide which register to use, it seems to always choose
9682          R0_REG, which leaves no available registers in SIBCALL_REGS
9683          to hold the address of the trampoline.  */
9684       mach = gen_rtx_REG (SImode, MACH_REG);
9685       r1 = gen_rtx_REG (SImode, R1_REG);
9687       /* Since such a call function may use all call-clobbered
9688          registers, we force a mode switch earlier, so that we don't
9689          run out of registers when adjusting fpscr for the call.  */
9690       emit_insn (gen_force_mode_for_call ());
9692       operands[1]
9693         = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9694       operands[1] = force_reg (SImode, operands[1]);
9696       /* We don't need a return trampoline, since the callee will
9697          return directly to the upper caller.  */
9698       if (cookie & CALL_COOKIE_RET_TRAMP (1))
9699         {
9700           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9701           cookie_rtx = GEN_INT (cookie);
9702         }
9704       emit_move_insn (mach, func);
9705       emit_move_insn (r1, cookie_rtx);
9707       emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
9708                                                  operands[2], mach));
9709       DONE;
9710     }
9711   else if (TARGET_SHCOMPACT && flag_pic
9712            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9713            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9714     {
9715       rtx reg = gen_reg_rtx (Pmode);
9717       emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
9718       XEXP (operands[1], 0) = reg;
9719     }
9720   if (flag_pic && TARGET_SH2
9721       && MEM_P (operands[1])
9722       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9723       /* The PLT needs the PIC register, but the epilogue would have
9724          to restore it, so we can only use PC-relative PIC calls for
9725          static functions.  */
9726       && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9727     {
9728       emit_call_insn (gen_sibcall_value_pcrel (operands[0],
9729                                                XEXP (operands[1], 0),
9730                                                operands[2]));
9731       DONE;
9732     }
9733   else
9734     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9736   emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
9737   DONE;
9740 (define_insn "call_value_pop_compact"
9741   [(set (match_operand 0 "" "=rf")
9742         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9743               (match_operand 2 "" "")))
9744    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9745                                  (match_operand 4 "immediate_operand" "n")))
9746    (match_operand 3 "immediate_operand" "n")
9747    (use (reg:SI R0_REG))
9748    (use (reg:SI R1_REG))
9749    (use (reg:PSI FPSCR_REG))
9750    (clobber (reg:SI PR_REG))]
9751   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9752   "jsr  @%1%#"
9753   [(set_attr "type" "call")
9754    (set (attr "fp_mode")
9755         (if_then_else (eq_attr "fpu_single" "yes")
9756                       (const_string "single") (const_string "double")))
9757    (set_attr "needs_delay_slot" "yes")])
9759 (define_insn "call_value_pop_compact_rettramp"
9760   [(set (match_operand 0 "" "=rf")
9761         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9762               (match_operand 2 "" "")))
9763    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9764                                  (match_operand 4 "immediate_operand" "n")))
9765    (match_operand 3 "immediate_operand" "n")
9766    (use (reg:SI R0_REG))
9767    (use (reg:SI R1_REG))
9768    (use (reg:PSI FPSCR_REG))
9769    (clobber (reg:SI R10_REG))
9770    (clobber (reg:SI PR_REG))]
9771   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9772   "jsr  @%1%#"
9773   [(set_attr "type" "call")
9774    (set (attr "fp_mode")
9775         (if_then_else (eq_attr "fpu_single" "yes")
9776                       (const_string "single") (const_string "double")))
9777    (set_attr "needs_delay_slot" "yes")])
9779 (define_expand "call_value_pop"
9780   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9781                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9782                                  (match_operand 2 "" "")))
9783               (match_operand 3 "" "")
9784               (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9785                                             (match_operand 4 "" "")))])]
9786   "TARGET_SHCOMPACT"
9788   rtx cookie_rtx;
9789   long cookie;
9790   rtx func;
9791   rtx r0, r1;
9793   gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
9794   cookie_rtx = operands[3];
9795   cookie = INTVAL (cookie_rtx);
9796   func = XEXP (operands[1], 0);
9798   if (flag_pic)
9799     {
9800       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9801         {
9802           rtx reg = gen_reg_rtx (Pmode);
9804           emit_insn (gen_symGOTPLT2reg (reg, func));
9805           func = reg;
9806         }
9807       else
9808         func = legitimize_pic_address (func, Pmode, 0);
9809     }
9811   r0 = gen_rtx_REG (SImode, R0_REG);
9812   r1 = gen_rtx_REG (SImode, R1_REG);
9814   /* Since such a call function may use all call-clobbered
9815      registers, we force a mode switch earlier, so that we don't
9816      run out of registers when adjusting fpscr for the call.  */
9817   emit_insn (gen_force_mode_for_call ());
9819   operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9820                                  SFUNC_GOT);
9821   operands[1] = force_reg (SImode, operands[1]);
9823   emit_move_insn (r0, func);
9824   emit_move_insn (r1, cookie_rtx);
9826   if (cookie & CALL_COOKIE_RET_TRAMP (1))
9827     emit_call_insn (gen_call_value_pop_compact_rettramp
9828                         (operands[0], operands[1], operands[2],
9829                          operands[3], operands[4]));
9830   else
9831     emit_call_insn (gen_call_value_pop_compact
9832                         (operands[0], operands[1], operands[2],
9833                          operands[3], operands[4]));
9835   DONE;
9838 (define_expand "sibcall_epilogue"
9839   [(return)]
9840   ""
9842   sh_expand_epilogue (true);
9843   if (TARGET_SHCOMPACT)
9844     {
9845       rtx insn, set;
9847       /* If epilogue clobbers r0, preserve it in macl.  */
9848       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
9849         if ((set = single_set (insn))
9850             && REG_P (SET_DEST (set))
9851             && REGNO (SET_DEST (set)) == R0_REG)
9852           {
9853             rtx r0 = gen_rtx_REG (SImode, R0_REG);
9854             rtx tmp = gen_rtx_REG (SImode, MACL_REG);
9856             /* We can't tell at this point whether the sibcall is a
9857                sibcall_compact and, if it is, whether it uses r0 or
9858                mach as operand 2, so let the instructions that
9859                preserve r0 be optimized away if r0 turns out to be
9860                dead.  */
9861             emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
9862             emit_move_insn (r0, tmp);
9863             break;
9864           }
9865     }
9866   DONE;
9869 (define_insn "indirect_jump_compact"
9870   [(set (pc)
9871         (match_operand:SI 0 "arith_reg_operand" "r"))]
9872   "TARGET_SH1"
9873   "jmp  @%0%#"
9874   [(set_attr "needs_delay_slot" "yes")
9875    (set_attr "type" "jump_ind")])
9877 (define_expand "indirect_jump"
9878   [(set (pc)
9879         (match_operand 0 "register_operand" ""))]
9880   ""
9882   if (GET_MODE (operands[0]) != Pmode)
9883     operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
9886 ;; The use of operand 1 / 2 helps us distinguish case table jumps
9887 ;; which can be present in structured code from indirect jumps which can not
9888 ;; be present in structured code.  This allows -fprofile-arcs to work.
9890 ;; For SH1 processors.
9891 (define_insn "casesi_jump_1"
9892   [(set (pc)
9893         (match_operand:SI 0 "register_operand" "r"))
9894    (use (label_ref (match_operand 1 "" "")))]
9895   "TARGET_SH1"
9896   "jmp  @%0%#"
9897   [(set_attr "needs_delay_slot" "yes")
9898    (set_attr "type" "jump_ind")])
9900 ;; For all later processors.
9901 (define_insn "casesi_jump_2"
9902   [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
9903                       (label_ref (match_operand 1 "" ""))))
9904    (use (label_ref (match_operand 2 "" "")))]
9905   "TARGET_SH2
9906    && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
9907   "braf %0%#"
9908   [(set_attr "needs_delay_slot" "yes")
9909    (set_attr "type" "jump_ind")])
9911 (define_insn "casesi_jump_media"
9912   [(set (pc) (match_operand 0 "target_reg_operand" "b"))
9913    (use (label_ref (match_operand 1 "" "")))]
9914   "TARGET_SHMEDIA"
9915   "blink        %0, r63"
9916   [(set_attr "type" "jump_media")])
9918 ;; Call subroutine returning any type.
9919 ;; ??? This probably doesn't work.
9921 (define_expand "untyped_call"
9922   [(parallel [(call (match_operand 0 "" "")
9923                     (const_int 0))
9924               (match_operand 1 "" "")
9925               (match_operand 2 "" "")])]
9926   "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
9928   int i;
9930   emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
9932   for (i = 0; i < XVECLEN (operands[2], 0); i++)
9933     {
9934       rtx set = XVECEXP (operands[2], 0, i);
9935       emit_move_insn (SET_DEST (set), SET_SRC (set));
9936     }
9938   /* The optimizer does not know that the call sets the function value
9939      registers we stored in the result block.  We avoid problems by
9940      claiming that all hard registers are used and clobbered at this
9941      point.  */
9942   emit_insn (gen_blockage ());
9944   DONE;
9947 ;; ------------------------------------------------------------------------
9948 ;; Misc insns
9949 ;; ------------------------------------------------------------------------
9951 (define_insn "dect"
9952   [(set (reg:SI T_REG)
9953         (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
9954    (set (match_operand:SI 0 "arith_reg_dest" "=r")
9955         (plus:SI (match_dup 1) (const_int -1)))]
9956   "TARGET_SH2"
9957   "dt   %0"
9958   [(set_attr "type" "arith")])
9960 (define_insn "nop"
9961   [(const_int 0)]
9962   ""
9963   "nop")
9965 ;; Load address of a label. This is only generated by the casesi expand,
9966 ;; and by machine_dependent_reorg (fixing up fp moves).
9967 ;; This must use unspec, because this only works for labels that are
9968 ;; within range,
9970 (define_insn "mova"
9971   [(set (reg:SI R0_REG)
9972         (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
9973   "TARGET_SH1"
9974   "mova %O0,r0"
9975   [(set_attr "in_delay_slot" "no")
9976    (set_attr "type" "arith")])
9978 ;; machine_dependent_reorg will make this a `mova'.
9979 (define_insn "mova_const"
9980   [(set (reg:SI R0_REG)
9981         (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
9982   "TARGET_SH1"
9983   "#"
9984   [(set_attr "in_delay_slot" "no")
9985    (set_attr "type" "arith")])
9987 (define_expand "GOTaddr2picreg"
9988   [(set (reg:SI R0_REG)
9989         (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
9990                    UNSPEC_MOVA))
9991    (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
9992    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
9993   ""
9995   if (TARGET_VXWORKS_RTP)
9996     {
9997       rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
9998       rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
9999       emit_insn (gen_vxworks_picreg (gott_base, gott_index));
10000       DONE;
10001     }
10003   operands[0] = gen_rtx_REG (Pmode, PIC_REG);
10004   operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
10006   if (TARGET_SHMEDIA)
10007     {
10008       rtx tr = gen_rtx_REG (Pmode, TR0_REG);
10009       rtx pic = operands[0];
10010       rtx lab = PATTERN (gen_call_site ());
10011       rtx insn, equiv;
10013       equiv = operands[1];
10014       operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
10015                                     UNSPEC_PCREL_SYMOFF);
10016       operands[1] = gen_rtx_CONST (Pmode, operands[1]);
10018       if (Pmode == SImode)
10019         {
10020           emit_insn (gen_movsi_const (pic, operands[1]));
10021           emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
10022         }
10023       else
10024         {
10025           emit_insn (gen_movdi_const (pic, operands[1]));
10026           emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
10027         }
10029       insn = emit_move_insn (operands[0], tr);
10031       set_unique_reg_note (insn, REG_EQUAL, equiv);
10033       DONE;
10034     }
10037 ;; A helper for GOTaddr2picreg to finish up the initialization of the
10038 ;; PIC register.
10040 (define_expand "vxworks_picreg"
10041   [(set (reg:SI PIC_REG)
10042         (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
10043    (set (reg:SI R0_REG)
10044         (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
10045    (set (reg:SI PIC_REG)
10046         (mem:SI (reg:SI PIC_REG)))
10047    (set (reg:SI PIC_REG)
10048         (mem:SI (plus:SI (reg:SI PIC_REG)
10049                          (reg:SI R0_REG))))]
10050   "TARGET_VXWORKS_RTP")
10052 (define_insn "*ptb"
10053   [(set (match_operand 0 "target_reg_operand" "=b")
10054         (const (unspec [(match_operand 1 "" "Csy")]
10055                              UNSPEC_DATALABEL)))]
10056   "TARGET_SHMEDIA && flag_pic
10057    && satisfies_constraint_Csy (operands[1])"
10058   "ptb/u        datalabel %1, %0"
10059   [(set_attr "type" "ptabs_media")
10060    (set_attr "length" "*")])
10062 (define_insn "ptrel_si"
10063   [(set (match_operand:SI 0 "target_reg_operand" "=b")
10064         (plus:SI (match_operand:SI 1 "register_operand" "r")
10065               (pc)))
10066    (match_operand:SI 2 "" "")]
10067   "TARGET_SHMEDIA"
10068   "%O2: ptrel/u %1, %0"
10069   [(set_attr "type" "ptabs_media")])
10071 (define_insn "ptrel_di"
10072   [(set (match_operand:DI 0 "target_reg_operand" "=b")
10073         (plus:DI (match_operand:DI 1 "register_operand" "r")
10074               (pc)))
10075    (match_operand:DI 2 "" "")]
10076   "TARGET_SHMEDIA"
10077   "%O2: ptrel/u %1, %0"
10078   [(set_attr "type" "ptabs_media")])
10080 (define_expand "builtin_setjmp_receiver"
10081   [(match_operand 0 "" "")]
10082   "flag_pic"
10084   emit_insn (gen_GOTaddr2picreg ());
10085   DONE;
10088 (define_expand "call_site"
10089   [(unspec [(match_dup 0)] UNSPEC_CALLER)]
10090   "TARGET_SH1"
10092   static HOST_WIDE_INT i = 0;
10093   operands[0] = GEN_INT (i);
10094   i++;
10097 ;; op0 = op1 + r12 but hide it before reload completed.  See the comment
10098 ;; in symGOT_load expand.
10100 (define_insn_and_split "chk_guard_add"
10101   [(set (match_operand:SI 0 "register_operand" "=&r")
10102         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
10103                     (reg:SI PIC_REG)]
10104                    UNSPEC_CHKADD))]
10105   "TARGET_SH1"
10106   "#"
10107   "TARGET_SH1 && reload_completed"
10108   [(set (match_dup 0) (reg:SI PIC_REG))
10109    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
10110   ""
10111   [(set_attr "type" "arith")])
10113 (define_expand "sym_label2reg"
10114   [(set (match_operand:SI 0 "" "")
10115         (const:SI (unspec:SI [(match_operand:SI 1 "" "")
10116                               (const (plus:SI (match_operand:SI 2 "" "")
10117                                               (const_int 2)))]
10118                              UNSPEC_SYMOFF)))]
10119   "TARGET_SH1" "")
10121 (define_expand "symGOT_load"
10122   [(set (match_dup 2) (match_operand 1 "" ""))
10123    (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
10124    (set (match_operand 0 "" "") (mem (match_dup 3)))]
10125   ""
10127   rtx mem;
10129   operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10130   operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10132   if (TARGET_SHMEDIA)
10133     {
10134       rtx reg = operands[2];
10136       if (Pmode == DImode)
10137         {      
10138           if (flag_pic > 1)
10139             emit_insn (gen_movdi_const_32bit (reg, operands[1]));
10140           else
10141             emit_insn (gen_movdi_const_16bit (reg, operands[1]));
10142         }
10143       else
10144         {
10145           if (flag_pic > 1)
10146             emit_insn (gen_movsi_const (reg, operands[1]));
10147           else
10148             emit_insn (gen_movsi_const_16bit (reg, operands[1]));
10149         }
10150     }
10151   else
10152     emit_move_insn (operands[2], operands[1]);
10154   /* When stack protector inserts codes after the result is set to
10155      R0, @(rX, r12) will cause a spill failure for R0.  Use a unspec
10156      insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
10157      when rX is a GOT address for the guard symbol.  Ugly but doesn't
10158      matter because this is a rare situation.  */
10159   if (!TARGET_SHMEDIA
10160       && flag_stack_protect
10161       && GET_CODE (operands[1]) == CONST
10162       && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
10163       && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
10164       && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
10165                  "__stack_chk_guard") == 0)
10166     emit_insn (gen_chk_guard_add (operands[3], operands[2]));
10167   else
10168     emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
10169                                                gen_rtx_REG (Pmode, PIC_REG)));
10171   /* N.B. This is not constant for a GOTPLT relocation.  */
10172   mem = gen_rtx_MEM (Pmode, operands[3]);
10173   MEM_NOTRAP_P (mem) = 1;
10174   /* ??? Should we have a special alias set for the GOT?  */
10175   emit_move_insn (operands[0], mem);
10177   DONE;
10180 (define_expand "sym2GOT"
10181   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
10182   ""
10183   "")
10185 (define_expand "symGOT2reg"
10186   [(match_operand 0 "" "") (match_operand 1 "" "")]
10187   ""
10189   rtx gotsym, insn;
10191   gotsym = gen_sym2GOT (operands[1]);
10192   PUT_MODE (gotsym, Pmode);
10193   insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
10195   MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
10197   DONE;
10200 (define_expand "symGOTPLT2reg"
10201   [(match_operand 0 "" "") (match_operand 1 "" "")]
10202   ""
10204   rtx pltsym = gen_rtx_CONST (Pmode,
10205                               gen_rtx_UNSPEC (Pmode,
10206                                               gen_rtvec (1, operands[1]),
10207                                               UNSPEC_GOTPLT));
10208   emit_insn (gen_symGOT_load (operands[0], pltsym));
10209   DONE;
10212 (define_expand "sym2GOTOFF"
10213   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
10214   ""
10215   "")
10217 (define_expand "symGOTOFF2reg"
10218   [(match_operand 0 "" "") (match_operand 1 "" "")]
10219   ""
10221   rtx gotoffsym, insn;
10222   rtx t = (!can_create_pseudo_p ()
10223            ? operands[0]
10224            : gen_reg_rtx (GET_MODE (operands[0])));
10226   gotoffsym = gen_sym2GOTOFF (operands[1]);
10227   PUT_MODE (gotoffsym, Pmode);
10228   emit_move_insn (t, gotoffsym);
10229   insn = emit_move_insn (operands[0],
10230                          gen_rtx_PLUS (Pmode, t,
10231                                        gen_rtx_REG (Pmode, PIC_REG)));
10233   set_unique_reg_note (insn, REG_EQUAL, operands[1]);
10235   DONE;
10238 (define_expand "symPLT_label2reg"
10239   [(set (match_operand:SI 0 "" "")
10240         (const:SI
10241          (unspec:SI
10242           [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
10243            (const:SI (plus:SI (match_operand:SI 2 "" "")
10244                               (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
10245    ;; Even though the PIC register is not really used by the call
10246    ;; sequence in which this is expanded, the PLT code assumes the PIC
10247    ;; register is set, so we must not skip its initialization.  Since
10248    ;; we only use this expand as part of calling sequences, and never
10249    ;; to take the address of a function, this is the best point to
10250    ;; insert the (use).  Using the PLT to take the address of a
10251    ;; function would be wrong, not only because the PLT entry could
10252    ;; then be called from a function that doesn't initialize the PIC
10253    ;; register to the proper GOT, but also because pointers to the
10254    ;; same function might not compare equal, should they be set by
10255    ;; different shared libraries.
10256    (use (reg:SI PIC_REG))]
10257   "TARGET_SH1"
10258   "")
10260 (define_expand "sym2PIC"
10261   [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
10262   ""
10263   "")
10265 ;; TLS code generation.
10266 ;; ??? this should be a define_insn_and_split
10267 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
10268 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
10269 ;; for details.
10271 (define_insn "tls_global_dynamic"
10272   [(set (match_operand:SI 0 "register_operand" "=&z")
10273         (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10274                                   UNSPEC_TLSGD))
10275               (const_int 0)))
10276    (use (reg:PSI FPSCR_REG))
10277    (use (reg:SI PIC_REG))
10278    (clobber (reg:SI PR_REG))
10279    (clobber (scratch:SI))]
10280   "TARGET_SH1"
10282   return       "mov.l   1f,r4"                  "\n"
10283          "      mova    2f,r0"                  "\n"
10284          "      mov.l   2f,r1"                  "\n"
10285          "      add     r0,r1"                  "\n"
10286          "      jsr     @r1"                    "\n"
10287          "      add     r12,r4"                 "\n"
10288          "      bra     3f"                     "\n"
10289          "      nop"                            "\n"
10290          "      .align  2"                      "\n"
10291          "1:    .long   %a1@TLSGD"              "\n"
10292          "2:    .long   __tls_get_addr@PLT"     "\n"
10293          "3:";
10295   [(set_attr "type" "tls_load")
10296    (set_attr "length" "26")])
10298 (define_insn "tls_local_dynamic"
10299   [(set (match_operand:SI 0 "register_operand" "=&z")
10300         (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10301                                   UNSPEC_TLSLDM))
10302               (const_int 0)))
10303    (use (reg:PSI FPSCR_REG))
10304    (use (reg:SI PIC_REG))
10305    (clobber (reg:SI PR_REG))
10306    (clobber (scratch:SI))]
10307   "TARGET_SH1"
10309   return       "mov.l   1f,r4"                  "\n"
10310          "      mova    2f,r0"                  "\n"
10311          "      mov.l   2f,r1"                  "\n"
10312          "      add     r0,r1"                  "\n"
10313          "      jsr     @r1"                    "\n"
10314          "      add     r12,r4"                 "\n"
10315          "      bra     3f"                     "\n"
10316          "      nop"                            "\n"
10317          "      .align  2"                      "\n"
10318          "1:    .long   %a1@TLSLDM"             "\n"
10319          "2:    .long   __tls_get_addr@PLT"     "\n"
10320          "3:";
10322   [(set_attr "type" "tls_load")
10323    (set_attr "length" "26")])
10325 (define_expand "sym2DTPOFF"
10326   [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
10327   ""
10328   "")
10330 (define_expand "symDTPOFF2reg"
10331   [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
10332   ""
10334   rtx dtpoffsym;
10335   rtx t = (!can_create_pseudo_p ()
10336            ? operands[0]
10337            : gen_reg_rtx (GET_MODE (operands[0])));
10339   dtpoffsym = gen_sym2DTPOFF (operands[1]);
10340   PUT_MODE (dtpoffsym, Pmode);
10341   emit_move_insn (t, dtpoffsym);
10342   emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
10343   DONE;
10346 (define_expand "sym2GOTTPOFF"
10347   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
10348   ""
10349   "")
10351 (define_insn "tls_initial_exec"
10352   [(set (match_operand:SI 0 "register_operand" "=&r")
10353         (unspec:SI [(match_operand:SI 1 "" "")]
10354                     UNSPEC_TLSIE))
10355    (use (reg:SI GBR_REG))
10356    (use (reg:SI PIC_REG))
10357    (clobber (reg:SI R0_REG))]
10358   ""
10360   return       "mov.l   1f,r0"          "\n"
10361          "      stc     gbr,%0"         "\n"
10362          "      mov.l   @(r0,r12),r0"   "\n"
10363          "      bra     2f"             "\n"
10364          "      add     r0,%0"          "\n"
10365          "      .align  2"              "\n"
10366          "1:    .long   %a1"            "\n"
10367          "2:";
10369   [(set_attr "type" "tls_load")
10370    (set_attr "length" "16")])
10372 (define_expand "sym2TPOFF"
10373   [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
10374   ""
10375   "")
10377 (define_expand "symTPOFF2reg"
10378   [(match_operand 0 "" "") (match_operand 1 "" "")]
10379   ""
10381   rtx tpoffsym;
10383   tpoffsym = gen_sym2TPOFF (operands[1]);
10384   PUT_MODE (tpoffsym, Pmode);
10385   emit_move_insn (operands[0], tpoffsym);
10386   DONE;
10389 ;;------------------------------------------------------------------------------
10390 ;; Thread pointer getter and setter.
10392 ;; On SH the thread pointer is kept in the GBR.
10393 ;; These patterns are usually expanded from the respective built-in functions.
10394 (define_expand "get_thread_pointersi"
10395   [(set (match_operand:SI 0 "register_operand") (reg:SI GBR_REG))]
10396   "TARGET_SH1")
10398 ;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses.
10399 (define_insn "store_gbr"
10400   [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))]
10401   ""
10402   "stc  gbr,%0"
10403   [(set_attr "type" "tls_load")])
10405 (define_expand "set_thread_pointersi"
10406   [(set (reg:SI GBR_REG)
10407         (unspec_volatile:SI [(match_operand:SI 0 "register_operand")]
10408          UNSPECV_GBR))]
10409   "TARGET_SH1")
10411 (define_insn "load_gbr"
10412   [(set (reg:SI GBR_REG)
10413         (unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
10414          UNSPECV_GBR))]
10415   "TARGET_SH1"
10416   "ldc  %0,gbr"
10417   [(set_attr "type" "move")])
10419 ;;------------------------------------------------------------------------------
10420 ;; Thread pointer relative memory loads and stores.
10422 ;; On SH there are GBR displacement address modes which can be utilized to
10423 ;; access memory behind the thread pointer.
10424 ;; Since we do not allow using GBR for general purpose memory accesses, these
10425 ;; GBR addressing modes are formed by the combine pass.
10426 ;; This could be done with fewer patterns than below by using a mem predicate
10427 ;; for the GBR mem, but then reload would try to reload addresses with a
10428 ;; zero displacement for some strange reason.
10430 (define_insn "*mov<mode>_gbr_load"
10431   [(set (match_operand:QIHISI 0 "register_operand" "=z")
10432         (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10433                              (match_operand:QIHISI 1 "gbr_displacement"))))]
10434   "TARGET_SH1"
10435   "mov.<bwl>    @(%O1,gbr),%0"
10436   [(set_attr "type" "load")])
10438 (define_insn "*mov<mode>_gbr_load"
10439   [(set (match_operand:QIHISI 0 "register_operand" "=z")
10440         (mem:QIHISI (reg:SI GBR_REG)))]
10441   "TARGET_SH1"
10442   "mov.<bwl>    @(0,gbr),%0"
10443   [(set_attr "type" "load")])
10445 (define_insn "*mov<mode>_gbr_load"
10446   [(set (match_operand:SI 0 "register_operand" "=z")
10447         (sign_extend:SI
10448           (mem:QIHI (plus:SI (reg:SI GBR_REG)
10449                              (match_operand:QIHI 1 "gbr_displacement")))))]
10450   "TARGET_SH1"
10451   "mov.<bw>     @(%O1,gbr),%0"
10452   [(set_attr "type" "load")])
10454 (define_insn "*mov<mode>_gbr_load"
10455   [(set (match_operand:SI 0 "register_operand" "=z")
10456         (sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))]
10457   "TARGET_SH1"
10458   "mov.<bw>     @(0,gbr),%0"
10459   [(set_attr "type" "load")])
10461 (define_insn "*mov<mode>_gbr_store"
10462   [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10463                              (match_operand:QIHISI 0 "gbr_displacement")))
10464         (match_operand:QIHISI 1 "register_operand" "z"))]
10465   "TARGET_SH1"
10466   "mov.<bwl>    %1,@(%O0,gbr)"
10467   [(set_attr "type" "store")])
10469 (define_insn "*mov<mode>_gbr_store"
10470   [(set (mem:QIHISI (reg:SI GBR_REG))
10471         (match_operand:QIHISI 0 "register_operand" "z"))]
10472   "TARGET_SH1"
10473   "mov.<bwl>    %0,@(0,gbr)"
10474   [(set_attr "type" "store")])
10476 ;; DImode memory accesses have to be split in two SImode accesses.
10477 ;; Split them before reload, so that it gets a better chance to figure out
10478 ;; how to deal with the R0 restriction for the individual SImode accesses.
10479 ;; Do not match this insn during or after reload because it can't be split
10480 ;; afterwards.
10481 (define_insn_and_split "*movdi_gbr_load"
10482   [(set (match_operand:DI 0 "register_operand")
10483         (match_operand:DI 1 "gbr_address_mem"))]
10484   "TARGET_SH1 && can_create_pseudo_p ()"
10485   "#"
10486   "&& 1"
10487   [(set (match_dup 3) (match_dup 5))
10488    (set (match_dup 4) (match_dup 6))]
10490   /* Swap low/high part load order on little endian, so that the result reg
10491      of the second load can be used better.  */
10492   int off = TARGET_LITTLE_ENDIAN ? 1 : 0;
10493   operands[3 + off] = gen_lowpart (SImode, operands[0]);
10494   operands[5 + off] = gen_lowpart (SImode, operands[1]);
10495   operands[4 - off] = gen_highpart (SImode, operands[0]);
10496   operands[6 - off] = gen_highpart (SImode, operands[1]);
10499 (define_insn_and_split "*movdi_gbr_store"
10500   [(set (match_operand:DI 0 "gbr_address_mem")
10501         (match_operand:DI 1 "register_operand"))]
10502   "TARGET_SH1 && can_create_pseudo_p ()"
10503   "#"
10504   "&& 1"
10505   [(set (match_dup 3) (match_dup 5))
10506    (set (match_dup 4) (match_dup 6))]
10508   /* Swap low/high part store order on big endian, so that stores of function
10509      call results can save a reg copy.  */
10510   int off = TARGET_LITTLE_ENDIAN ? 0 : 1;
10511   operands[3 + off] = gen_lowpart (SImode, operands[0]);
10512   operands[5 + off] = gen_lowpart (SImode, operands[1]);
10513   operands[4 - off] = gen_highpart (SImode, operands[0]);
10514   operands[6 - off] = gen_highpart (SImode, operands[1]);
10517 ;; Sometimes memory accesses do not get combined with the store_gbr insn,
10518 ;; in particular when the displacements are in the range of the regular move
10519 ;; insns.  Thus, in the first split pass after the combine pass we search
10520 ;; for missed opportunities and try to fix them up ourselves.
10521 ;; If an equivalent GBR address can be determined the load / store is split
10522 ;; into one of the GBR load / store patterns.
10523 ;; All of that must happen before reload (GBR address modes use R0 as the
10524 ;; other operand) and there's no point of doing it if the GBR is not
10525 ;; referenced in a function at all.
10526 (define_split
10527   [(set (match_operand:QIHISIDI 0 "register_operand")
10528         (match_operand:QIHISIDI 1 "memory_operand"))]
10529   "TARGET_SH1 && !reload_in_progress && !reload_completed
10530    && df_regs_ever_live_p (GBR_REG)"
10531   [(set (match_dup 0) (match_dup 1))]
10533   rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10534   if (gbr_mem != NULL_RTX)
10535     operands[1] = replace_equiv_address (operands[1], gbr_mem);
10536   else
10537     FAIL;
10540 (define_split
10541   [(set (match_operand:SI 0 "register_operand")
10542         (sign_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10543   "TARGET_SH1 && !reload_in_progress && !reload_completed
10544    && df_regs_ever_live_p (GBR_REG)"
10545   [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
10547   rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10548   if (gbr_mem != NULL_RTX)
10549     operands[1] = replace_equiv_address (operands[1], gbr_mem);
10550   else
10551     FAIL;
10554 ;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads.
10555 ;; Split those so that a GBR load can be used.
10556 (define_split
10557   [(set (match_operand:SI 0 "register_operand")
10558         (zero_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10559   "TARGET_SH2A && !reload_in_progress && !reload_completed
10560    && df_regs_ever_live_p (GBR_REG)"
10561   [(set (match_dup 2) (match_dup 1))
10562    (set (match_dup 0) (zero_extend:SI (match_dup 2)))]
10564   rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10565   if (gbr_mem != NULL_RTX)
10566     {
10567       operands[2] = gen_reg_rtx (GET_MODE (operands[1]));
10568       operands[1] = replace_equiv_address (operands[1], gbr_mem);
10569     }
10570   else
10571     FAIL;
10574 (define_split
10575   [(set (match_operand:QIHISIDI 0 "memory_operand")
10576         (match_operand:QIHISIDI 1 "register_operand"))]
10577   "TARGET_SH1 && !reload_in_progress && !reload_completed
10578    && df_regs_ever_live_p (GBR_REG)"
10579   [(set (match_dup 0) (match_dup 1))]
10581   rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]);
10582   if (gbr_mem != NULL_RTX)
10583     operands[0] = replace_equiv_address (operands[0], gbr_mem);
10584   else
10585     FAIL;
10588 ;;------------------------------------------------------------------------------
10589 ;; case instruction for switch statements.
10591 ;; Operand 0 is index
10592 ;; operand 1 is the minimum bound
10593 ;; operand 2 is the maximum bound - minimum bound + 1
10594 ;; operand 3 is CODE_LABEL for the table;
10595 ;; operand 4 is the CODE_LABEL to go to if index out of range.
10597 (define_expand "casesi"
10598   [(match_operand:SI 0 "arith_reg_operand" "")
10599    (match_operand:SI 1 "arith_reg_operand" "")
10600    (match_operand:SI 2 "arith_reg_operand" "")
10601    (match_operand 3 "" "") (match_operand 4 "" "")]
10602   ""
10604   rtx reg = gen_reg_rtx (SImode);
10605   rtx reg2 = gen_reg_rtx (SImode);
10606   if (TARGET_SHMEDIA)
10607     {
10608       rtx reg = gen_reg_rtx (DImode);
10609       rtx reg2 = gen_reg_rtx (DImode);
10610       rtx reg3 = gen_reg_rtx (Pmode);
10611       rtx reg4 = gen_reg_rtx (Pmode);
10612       rtx reg5 = gen_reg_rtx (Pmode);
10613       rtx load, test;
10615       operands[0] = convert_modes (DImode, SImode, operands[0], 0);
10616       operands[1] = convert_modes (DImode, SImode, operands[1], 0);
10617       operands[2] = convert_modes (DImode, SImode, operands[2], 1);
10619       test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
10620       emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0], operands[4]));
10621       emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
10622       test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
10623       emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
10624       emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
10625       emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
10626                                                (Pmode, operands[3])));
10627       /* Messy: can we subreg to clean this up? */
10628       if (Pmode == DImode)
10629         load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
10630       else
10631         load = gen_casesi_load_media (reg4,
10632                                       gen_rtx_SUBREG (DImode, reg3, 0),
10633                                       reg2, operands[3]);
10634       PUT_MODE (SET_SRC (load), Pmode);
10635       emit_insn (load);
10636       /* ??? The following add could be eliminated if we used ptrel.  */
10637       emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
10638       emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
10639       emit_barrier ();
10640       DONE;
10641     }
10642   operands[1] = copy_to_mode_reg (SImode, operands[1]);
10643   operands[2] = copy_to_mode_reg (SImode, operands[2]);
10644   /* If optimizing, casesi_worker depends on the mode of the instruction
10645      before label it 'uses' - operands[3].  */
10646   emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
10647                            reg));
10648   emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
10649   if (TARGET_SH2)
10650     emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
10651   else
10652     emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
10653   /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
10654      operands[3], but to lab.  We will fix this up in
10655      machine_dependent_reorg.  */
10656   emit_barrier ();
10657   DONE;
10660 (define_expand "casesi_0"
10661   [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
10662    (set (match_dup 4) (minus:SI (match_dup 4)
10663                                 (match_operand:SI 1 "arith_operand" "")))
10664    (set (reg:SI T_REG)
10665         (gtu:SI (match_dup 4)
10666                 (match_operand:SI 2 "arith_reg_operand" "")))
10667    (set (pc)
10668         (if_then_else (ne (reg:SI T_REG)
10669                           (const_int 0))
10670                       (label_ref (match_operand 3 "" ""))
10671                       (pc)))]
10672   "TARGET_SH1"
10673   "")
10675 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
10676 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
10677 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
10679 (define_insn "casesi_worker_0"
10680   [(set (match_operand:SI 0 "register_operand" "=r,r")
10681         (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
10682                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10683    (clobber (match_scratch:SI 3 "=X,1"))
10684    (clobber (match_scratch:SI 4 "=&z,z"))]
10685   "TARGET_SH1"
10686   "#")
10688 (define_split
10689   [(set (match_operand:SI 0 "register_operand" "")
10690         (unspec:SI [(match_operand:SI 1 "register_operand" "")
10691                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10692    (clobber (match_scratch:SI 3 ""))
10693    (clobber (match_scratch:SI 4 ""))]
10694   "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
10695   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
10696    (parallel [(set (match_dup 0)
10697               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10698                           (label_ref (match_dup 2))] UNSPEC_CASESI))
10699               (clobber (match_dup 3))])
10700    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
10702   if (GET_CODE (operands[2]) == CODE_LABEL)
10703     LABEL_NUSES (operands[2])++;
10706 (define_split
10707   [(set (match_operand:SI 0 "register_operand" "")
10708         (unspec:SI [(match_operand:SI 1 "register_operand" "")
10709                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10710    (clobber (match_scratch:SI 3 ""))
10711    (clobber (match_scratch:SI 4 ""))]
10712   "TARGET_SH2 && reload_completed"
10713   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
10714    (parallel [(set (match_dup 0)
10715               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10716                           (label_ref (match_dup 2))] UNSPEC_CASESI))
10717               (clobber (match_dup 3))])]
10719   if (GET_CODE (operands[2]) == CODE_LABEL)
10720     LABEL_NUSES (operands[2])++;
10723 (define_insn "casesi_worker_1"
10724   [(set (match_operand:SI 0 "register_operand" "=r,r")
10725         (unspec:SI [(reg:SI R0_REG)
10726                     (match_operand:SI 1 "register_operand" "0,r")
10727                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10728    (clobber (match_scratch:SI 3 "=X,1"))]
10729   "TARGET_SH1"
10731   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
10733   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10735   switch (GET_MODE (diff_vec))
10736     {
10737     case SImode:
10738       return   "shll2   %1"     "\n"
10739              "  mov.l   @(r0,%1),%0";
10740     case HImode:
10741       return   "add     %1,%1"  "\n"
10742              "  mov.w   @(r0,%1),%0";
10743     case QImode:
10744       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10745         return         "mov.b   @(r0,%1),%0"    "\n"
10746                "        extu.b  %0,%0";
10747       else
10748         return "mov.b   @(r0,%1),%0";
10750     default:
10751       gcc_unreachable ();
10752     }
10754   [(set_attr "length" "4")])
10756 (define_insn "casesi_worker_2"
10757   [(set (match_operand:SI 0 "register_operand" "=r,r")
10758         (unspec:SI [(reg:SI R0_REG)
10759                     (match_operand:SI 1 "register_operand" "0,r")
10760                     (label_ref (match_operand 2 "" ""))
10761                     (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
10762    (clobber (match_operand:SI 4 "" "=X,1"))]
10763   "TARGET_SH2 && reload_completed && flag_pic"
10765   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
10766   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10768   switch (GET_MODE (diff_vec))
10769     {
10770     case SImode:
10771       return   "shll2   %1"             "\n"
10772              "  add     r0,%1"          "\n"
10773              "  mova    %O3,r0"         "\n"
10774              "  mov.l   @(r0,%1),%0";
10775     case HImode:
10776       return   "add     %1,%1"          "\n"
10777              "  add     r0,%1"          "\n"
10778              "  mova    %O3,r0"         "\n"
10779              "  mov.w   @(r0,%1),%0";
10780     case QImode:
10781       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10782         return         "add     r0,%1"          "\n"
10783                 "       mova    %O3,r0"         "\n"
10784                 "       mov.b   @(r0,%1),%0"    "\n"
10785                 "       extu.b  %0,%0";
10786       else
10787         return         "add     r0,%1"          "\n"
10788                 "       mova    %O3,r0"         "\n"
10789                 "       mov.b   @(r0,%1),%0";
10790     default:
10791       gcc_unreachable ();
10792     }
10794   [(set_attr "length" "8")])
10796 (define_insn "casesi_shift_media"
10797   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10798         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
10799                    (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
10800                     UNSPEC_CASESI)))]
10801   "TARGET_SHMEDIA"
10803   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
10805   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10807   switch (GET_MODE (diff_vec))
10808     {
10809     case SImode:
10810       return "shlli     %1, 2, %0";
10811     case HImode:
10812       return "shlli     %1, 1, %0";
10813     case QImode:
10814       if (rtx_equal_p (operands[0], operands[1]))
10815         return "";
10816       return "add       %1, r63, %0";
10817     default:
10818       gcc_unreachable ();
10819     }
10821   [(set_attr "type" "arith_media")])
10823 (define_insn "casesi_load_media"
10824   [(set (match_operand 0 "any_arith_reg_dest" "=r")
10825         (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
10826                          (match_operand:DI 2 "arith_reg_operand" "r")
10827                          (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
10828   "TARGET_SHMEDIA"
10830   rtx diff_vec = PATTERN (next_real_insn (operands[3]));
10832   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10834   switch (GET_MODE (diff_vec))
10835     {
10836     case SImode:
10837       return "ldx.l     %1, %2, %0";
10838     case HImode:
10839 #if 0
10840       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10841         return "ldx.uw  %1, %2, %0";
10842 #endif
10843       return "ldx.w     %1, %2, %0";
10844     case QImode:
10845       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10846         return "ldx.ub  %1, %2, %0";
10847       return "ldx.b     %1, %2, %0";
10848     default:
10849       gcc_unreachable ();
10850     }
10852   [(set_attr "type" "load_media")])
10854 (define_expand "simple_return"
10855   [(simple_return)]
10856  "sh_can_use_simple_return_p ()")
10858 (define_expand "return"
10859   [(return)]
10860  "reload_completed && epilogue_completed"
10862   if (TARGET_SHMEDIA)
10863     {
10864       emit_jump_insn (gen_return_media ());
10865       DONE;
10866     }
10868   if (TARGET_SHCOMPACT
10869       && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
10870     {
10871       emit_jump_insn (gen_shcompact_return_tramp ());
10872       DONE;
10873     }
10876 (define_insn "*<code>_i"
10877   [(any_return)]
10878   "TARGET_SH1 && ! (TARGET_SHCOMPACT
10879                     && (crtl->args.info.call_cookie
10880                         & CALL_COOKIE_RET_TRAMP (1)))
10881    && reload_completed
10882    && ! sh_cfun_trap_exit_p ()"
10884   if (TARGET_SH2A && (dbr_sequence_length () == 0)
10885       && !current_function_interrupt)
10886     return "rts/n";
10887   else
10888     return "%@  %#";
10890   [(set_attr "type" "return")
10891    (set_attr "needs_delay_slot" "yes")])
10893 ;; trapa has no delay slot.
10894 (define_insn "*return_trapa"
10895   [(return)]
10896   "TARGET_SH1 && !TARGET_SHCOMPACT
10897    && reload_completed"
10898   "%@"
10899   [(set_attr "type" "return")])
10901 (define_expand "shcompact_return_tramp"
10902   [(return)]
10903   "TARGET_SHCOMPACT
10904    && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
10906   rtx reg = gen_rtx_REG (Pmode, R0_REG);
10908   function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC);
10909   emit_jump_insn (gen_shcompact_return_tramp_i ());
10910   DONE;
10913 (define_insn "shcompact_return_tramp_i"
10914   [(parallel [(return) (use (reg:SI R0_REG))])]
10915   "TARGET_SHCOMPACT
10916    && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
10917   "jmp  @r0%#"
10918   [(set_attr "type" "jump_ind")
10919    (set_attr "needs_delay_slot" "yes")])
10921 (define_insn "return_media_i"
10922   [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
10923   "TARGET_SHMEDIA && reload_completed"
10924   "blink        %0, r63"
10925   [(set_attr "type" "jump_media")])
10927 (define_insn "return_media_rte"
10928   [(return)]
10929   "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
10930   "rte"
10931   [(set_attr "type" "jump_media")])
10933 (define_expand "return_media"
10934   [(return)]
10935   "TARGET_SHMEDIA && reload_completed"
10937   int tr_regno = sh_media_register_for_return ();
10938   rtx tr;
10940   if (current_function_interrupt)
10941     {
10942       emit_jump_insn (gen_return_media_rte ());
10943       DONE;
10944     }
10945   if (tr_regno < 0)
10946     {
10947       rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
10949       gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
10950       tr_regno = TR0_REG;
10951       tr = gen_rtx_REG (Pmode, tr_regno);
10952       emit_move_insn (tr, r18);
10953     }
10954   else
10955     tr = gen_rtx_REG (Pmode, tr_regno);
10957   emit_jump_insn (gen_return_media_i (tr));
10958   DONE;
10961 (define_insn "shcompact_preserve_incoming_args"
10962   [(set (match_operand:SI 0 "register_operand" "+r")
10963         (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
10964   "TARGET_SHCOMPACT"
10965   ""
10966   [(set_attr "length" "0")])
10968 (define_insn "shcompact_incoming_args"
10969   [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
10970    (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
10971    (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
10972    (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
10973    (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
10974    (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
10975    (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
10976    (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
10977    (set (mem:BLK (reg:SI MACL_REG))
10978         (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
10979    (use (reg:SI R0_REG))
10980    (clobber (reg:SI R0_REG))
10981    (clobber (reg:SI MACL_REG))
10982    (clobber (reg:SI MACH_REG))
10983    (clobber (reg:SI PR_REG))]
10984   "TARGET_SHCOMPACT"
10985   "jsr  @r0%#"
10986   [(set_attr "needs_delay_slot" "yes")])
10988 (define_insn "shmedia_save_restore_regs_compact"
10989   [(set (reg:SI SP_REG)
10990         (plus:SI (reg:SI SP_REG)
10991                  (match_operand:SI 0 "immediate_operand" "i")))
10992    (use (reg:SI R0_REG))
10993    (clobber (reg:SI PR_REG))]
10994   "TARGET_SHCOMPACT
10995    && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
10996        || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
10997   "jsr @r0%#"
10998   [(set_attr "needs_delay_slot" "yes")])
11000 (define_expand "prologue"
11001   [(const_int 0)]
11002   ""
11004   sh_expand_prologue ();
11005   DONE;
11008 (define_expand "epilogue"
11009   [(return)]
11010   ""
11012   sh_expand_epilogue (false);
11013   if (TARGET_SHMEDIA
11014       || (TARGET_SHCOMPACT
11015           && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))))
11016     {
11017       emit_jump_insn (gen_return ());
11018       DONE;
11019     }
11022 (define_expand "eh_return"
11023   [(use (match_operand 0 "register_operand" ""))]
11024   ""
11026   rtx ra = operands[0];
11028   if (TARGET_SHMEDIA64)
11029     emit_insn (gen_eh_set_ra_di (ra));
11030   else
11031     emit_insn (gen_eh_set_ra_si (ra));
11033   DONE;
11036 ;; Clobber the return address on the stack.  We can't expand this
11037 ;; until we know where it will be put in the stack frame.
11039 (define_insn "eh_set_ra_si"
11040   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
11041       UNSPECV_EH_RETURN)
11042    (clobber (match_scratch:SI 1 "=&r"))]
11043   "! TARGET_SHMEDIA64"
11044   "#")
11046 (define_insn "eh_set_ra_di"
11047   [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
11048       UNSPECV_EH_RETURN)
11049    (clobber (match_scratch:DI 1 "=&r"))]
11050   "TARGET_SHMEDIA64"
11051   "#")
11053 (define_split
11054   [(unspec_volatile [(match_operand 0 "register_operand" "")]
11055       UNSPECV_EH_RETURN)
11056    (clobber (match_scratch 1 ""))]
11057   "reload_completed"
11058   [(const_int 0)]
11060   sh_set_return_address (operands[0], operands[1]);
11061   DONE;
11064 (define_insn "blockage"
11065   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
11066   ""
11067   ""
11068   [(set_attr "length" "0")])
11070 ;; Define movml instructions for SH2A target.  Currently they are
11071 ;; used to push and pop all banked registers only.
11073 (define_insn "movml_push_banked"
11074   [(set (match_operand:SI 0 "register_operand" "=r")
11075           (plus (match_dup 0) (const_int -32)))
11076    (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
11077    (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
11078    (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
11079    (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
11080    (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
11081    (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
11082    (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
11083    (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
11084   "TARGET_SH2A && REGNO (operands[0]) == 15"
11085   "movml.l      r7,@-r15"
11086   [(set_attr "in_delay_slot" "no")])
11088 (define_insn "movml_pop_banked"
11089   [(set (match_operand:SI 0 "register_operand" "=r")
11090           (plus (match_dup 0) (const_int 32)))
11091    (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
11092    (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
11093    (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
11094    (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
11095    (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
11096    (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
11097    (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
11098    (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
11099   "TARGET_SH2A && REGNO (operands[0]) == 15"
11100   "movml.l      @r15+,r7"
11101   [(set_attr "in_delay_slot" "no")])
11103 ;; ------------------------------------------------------------------------
11104 ;; Scc instructions
11105 ;; ------------------------------------------------------------------------
11107 (define_insn "movt"
11108   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11109         (match_operand:SI 1 "t_reg_operand"))]
11110   "TARGET_SH1"
11111   "movt %0"
11112   [(set_attr "type" "arith")])
11114 (define_insn "movrt"
11115   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11116         (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11117   "TARGET_SH2A"
11118   "movrt        %0"
11119   [(set_attr "type" "arith")])
11121 (define_expand "cstore4_media"
11122   [(set (match_operand:SI 0 "register_operand" "=r")
11123         (match_operator:SI 1 "sh_float_comparison_operator"
11124          [(match_operand 2 "logical_operand" "")
11125           (match_operand 3 "cmp_operand" "")]))]
11126   "TARGET_SHMEDIA"
11128   enum machine_mode mode = GET_MODE (operands[2]);
11129   enum rtx_code code = GET_CODE (operands[1]);
11130   bool invert, swap;
11131   if (mode == VOIDmode)
11132     mode = GET_MODE (operands[3]);
11133   if (operands[2] == const0_rtx)
11134     {
11135       if (code == EQ || code == NE)
11136         operands[2] = operands[3], operands[3] = const0_rtx;
11137     }
11138   else
11139     operands[2] = force_reg (mode, operands[2]);
11140   if (operands[3] != const0_rtx)
11141     operands[3] = force_reg (mode, operands[3]);
11143   switch (code)
11144     {
11145     case GEU:
11146     case GE:
11147       swap = invert = !FLOAT_MODE_P (mode);
11148       break;
11150     case LEU:
11151     case LE:
11152       swap = FLOAT_MODE_P (mode), invert = !swap;
11153       break;
11155     case LTU:
11156     case LT:
11157       swap = true, invert = false;
11158       break;
11160     case GTU:
11161     case GT:
11162     case EQ:
11163     case UNORDERED:
11164       swap = invert = false;
11165       break;
11167     case NE:
11168       swap = invert = true;
11169       break;
11171     default:
11172       gcc_unreachable ();
11173   }
11175   if (swap)
11176     {
11177       rtx tem = operands[2];
11178       operands[2] = operands[3];
11179       operands[3] = tem;
11180       code = swap_condition (code);
11181     }
11183   if (invert)
11184     {
11185       rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
11186       code = reverse_condition (code);
11187       operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11188       emit_insn (gen_cstore4_media (tem, operands[1],
11189                                     operands[2], operands[3]));
11190       code = EQ;
11191       operands[2] = tem;
11192       operands[3] = const0_rtx;
11193     }
11195   operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11198 (define_expand "cstoresi4"
11199   [(set (match_operand:SI 0 "register_operand" "=r")
11200         (match_operator:SI 1 "comparison_operator"
11201          [(match_operand:SI 2 "cmpsi_operand" "")
11202           (match_operand:SI 3 "arith_operand" "")]))]
11203   "TARGET_SH1 || TARGET_SHMEDIA"
11205   if (TARGET_SHMEDIA)
11206     {
11207       emit_insn (gen_cstore4_media (operands[0], operands[1],
11208                                     operands[2], operands[3]));
11209       DONE;
11210     }
11212    if (sh_expand_t_scc (operands))
11213      DONE;
11215    if (! currently_expanding_to_rtl)
11216      FAIL;
11217    
11218    sh_emit_compare_and_set (operands, SImode);
11219    DONE;
11222 (define_expand "cstoredi4"
11223   [(set (match_operand:SI 0 "register_operand" "=r")
11224         (match_operator:SI 1 "comparison_operator"
11225          [(match_operand:DI 2 "arith_operand" "")
11226           (match_operand:DI 3 "arith_operand" "")]))]
11227   "TARGET_SH2 || TARGET_SHMEDIA"
11229   if (TARGET_SHMEDIA)
11230     {
11231       emit_insn (gen_cstore4_media (operands[0], operands[1],
11232                                     operands[2], operands[3]));
11233       DONE;
11234     }
11236    if (sh_expand_t_scc (operands))
11237      DONE;
11239    if (! currently_expanding_to_rtl)
11240      FAIL;
11241    
11242    sh_emit_compare_and_set (operands, DImode);
11243    DONE;
11246 ;; Move the complement of the T reg to a reg.
11247 ;; On SH2A the movrt insn can be used.
11248 ;; On anything else than SH2A this has to be done with multiple instructions.
11249 ;; One obvious way would be:
11250 ;;      cmp/eq  ...
11251 ;;      movt    r0
11252 ;;      xor     #1,r0
11254 ;; However, this puts pressure on r0 in most cases and thus the following is
11255 ;; more appealing:
11256 ;;      cmp/eq  ...
11257 ;;      mov     #-1,temp
11258 ;;      negc    temp,dest
11260 ;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
11261 ;; becomes a one instruction operation.  Moreover, care must be taken that
11262 ;; the insn can still be combined with inverted compare and branch code
11263 ;; around it.  On the other hand, if a function returns the complement of
11264 ;; a previous comparison result in the T bit, the xor #1,r0 approach might
11265 ;; lead to better code.
11267 (define_expand "movnegt"
11268   [(set (match_operand:SI 0 "arith_reg_dest" "")
11269         (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11270   "TARGET_SH1"
11272   if (TARGET_SH2A)
11273     emit_insn (gen_movrt (operands[0], operands[1]));
11274   else
11275     {
11276       rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
11277       emit_insn (gen_movrt_negc (operands[0], operands[1], val));
11278     }
11279   DONE;
11282 (define_insn "movrt_negc"
11283   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11284         (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11285    (set (reg:SI T_REG) (const_int 1))
11286    (use (match_operand:SI 2 "arith_reg_operand" "r"))]
11287   "TARGET_SH1"
11288   "negc %2,%0"
11289   [(set_attr "type" "arith")])
11291 ;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the
11292 ;; pattern can be used by the combine pass.  Using a scratch reg for the
11293 ;; -1 constant results in slightly better register allocations compared to
11294 ;; generating a pseudo reg before reload.
11295 (define_insn_and_split "*movrt_negc"
11296   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11297         (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11298    (clobber (match_scratch:SI 2 "=r"))
11299    (clobber (reg:SI T_REG))]
11300   "TARGET_SH1 && ! TARGET_SH2A"
11301   "#"
11302   "&& reload_completed"
11303   [(set (match_dup 2) (const_int -1))
11304    (parallel
11305        [(set (match_dup 0) (xor:SI (match_dup 1) (const_int 1)))
11306         (set (reg:SI T_REG) (const_int 1))
11307         (use (match_dup 2))])])
11309 ;; Store the negated T bit in a reg using r0 and xor.  This one doesn't
11310 ;; clobber the T bit, which is useful when storing the T bit and the
11311 ;; negated T bit in parallel.  On SH2A the movrt insn can be used for that.
11312 ;; Usually we don't want this insn to be matched, except for cases where the
11313 ;; T bit clobber is really not appreciated.  Hence the extra use on T_REG.
11314 (define_insn_and_split "movrt_xor"
11315   [(set (match_operand:SI 0 "arith_reg_dest" "=z")
11316         (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
11317    (use (reg:SI T_REG))]
11318   "TARGET_SH1 && !TARGET_SH2A"
11319   "#"
11320   "&& reload_completed"
11321   [(set (match_dup 0) (reg:SI T_REG))
11322    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))])
11324 ;; Store the T bit and the negated T bit in two regs in parallel.  There is
11325 ;; no real insn to do that, but specifying this pattern will give combine
11326 ;; some opportunities.
11327 (define_insn_and_split "*movt_movrt"
11328   [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11329                    (match_operand:SI 1 "negt_reg_operand"))
11330               (set (match_operand:SI 2 "arith_reg_dest")
11331                    (match_operand:SI 3 "t_reg_operand"))])]
11332   "TARGET_SH1"
11333   "#"
11334   "&& 1"
11335   [(const_int 0)]
11337   rtx i = TARGET_SH2A
11338           ? gen_movrt (operands[0], get_t_reg_rtx ())
11339           : gen_movrt_xor (operands[0], get_t_reg_rtx ());
11340   
11341   emit_insn (i);
11342   emit_insn (gen_movt (operands[2], get_t_reg_rtx ()));
11343   DONE;
11346 (define_insn_and_split "*movt_movrt"
11347   [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11348                    (match_operand:SI 1 "t_reg_operand"))
11349               (set (match_operand:SI 2 "arith_reg_dest")
11350                    (match_operand:SI 3 "negt_reg_operand"))])]
11351   "TARGET_SH1"
11352   "#"
11353   "&& 1"
11354   [(parallel [(set (match_dup 2) (match_dup 3))
11355               (set (match_dup 0) (match_dup 1))])])
11357 ;; Use negc to store the T bit in a MSB of a reg in the following way:
11358 ;;      T = 1: 0x80000000 -> reg
11359 ;;      T = 0: 0x7FFFFFFF -> reg
11360 ;; This works because 0 - 0x80000000 = 0x80000000.
11361 (define_insn_and_split "*mov_t_msb_neg"
11362   [(set (match_operand:SI 0 "arith_reg_dest")
11363         (minus:SI (const_int -2147483648)  ;; 0x80000000
11364                   (match_operand 1 "t_reg_operand")))
11365    (clobber (reg:SI T_REG))]
11366   "TARGET_SH1"
11367   "#"
11368   "&& can_create_pseudo_p ()"
11369   [(set (match_dup 2) (const_int -2147483648))
11370    (parallel [(set (match_dup 0) (minus:SI (neg:SI (match_dup 2))
11371                                  (reg:SI T_REG)))
11372               (clobber (reg:SI T_REG))])]
11374   operands[2] = gen_reg_rtx (SImode);
11377 ;; These are essentially the same as above, but with the inverted T bit.
11378 ;; Combine recognizes the split patterns, but does not take them sometimes
11379 ;; if the T_REG clobber is specified.  Instead it tries to split out the
11380 ;; T bit negation.  Since these splits are supposed to be taken only by
11381 ;; combine, it will see the T_REG clobber of the *mov_t_msb_neg insn, so this
11382 ;; should be fine.
11383 (define_split
11384   [(set (match_operand:SI 0 "arith_reg_dest")
11385         (plus:SI (match_operand 1 "negt_reg_operand")
11386                  (const_int 2147483647)))]  ;; 0x7fffffff
11387   "TARGET_SH1 && can_create_pseudo_p ()"
11388   [(parallel [(set (match_dup 0)
11389                    (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11390               (clobber (reg:SI T_REG))])])
11392 (define_split
11393   [(set (match_operand:SI 0 "arith_reg_dest")
11394         (if_then_else:SI (match_operand 1 "t_reg_operand")
11395                          (const_int 2147483647)  ;; 0x7fffffff
11396                          (const_int -2147483648)))]  ;; 0x80000000
11397   "TARGET_SH1 && can_create_pseudo_p ()"
11398   [(parallel [(set (match_dup 0)
11399                    (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11400               (clobber (reg:SI T_REG))])])
11402 ;; The *negnegt pattern helps the combine pass to figure out how to fold 
11403 ;; an explicit double T bit negation.
11404 (define_insn_and_split "*negnegt"
11405   [(set (reg:SI T_REG)
11406         (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
11407   "TARGET_SH1"
11408   "#"
11409   ""
11410   [(const_int 0)])
11412 ;; Store T bit as all zeros or ones in a reg.
11413 (define_insn "mov_neg_si_t"
11414   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11415         (neg:SI (match_operand 1 "t_reg_operand" "")))]
11416   "TARGET_SH1"
11417   "subc %0,%0"
11418   [(set_attr "type" "arith")])
11420 ;; Store negated T bit as all zeros or ones in a reg.
11421 ;; Use the following sequence:
11422 ;;      subc    Rn,Rn   ! Rn = Rn - Rn - T; T = T
11423 ;;      not     Rn,Rn   ! Rn = 0 - Rn
11424 (define_split
11425   [(set (match_operand:SI 0 "arith_reg_dest" "")
11426         (neg:SI (match_operand 1 "negt_reg_operand" "")))]
11427   "TARGET_SH1"
11428   [(set (match_dup 0) (neg:SI (reg:SI T_REG)))
11429    (set (match_dup 0) (not:SI (match_dup 0)))])
11431 ;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
11432 (define_insn_and_split "*movtt"
11433   [(set (reg:SI T_REG)
11434         (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
11435   "TARGET_SH1"
11436   "#"
11437   ""
11438   [(const_int 0)])
11440 (define_insn_and_split "nott"
11441   [(set (reg:SI T_REG)
11442         (xor:SI (match_operand:SI 0 "t_reg_operand" "") (const_int 1)))]
11443   "TARGET_SH1"
11445   gcc_assert (TARGET_SH2A);
11446   return "nott";
11448   "! TARGET_SH2A && can_create_pseudo_p ()"
11449   [(set (match_dup 0) (reg:SI T_REG))
11450    (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
11452   operands[0] = gen_reg_rtx (SImode);
11455 ;; Store T bit as MSB in a reg.
11456 ;; T = 0: 0x00000000 -> reg
11457 ;; T = 1: 0x80000000 -> reg
11458 (define_insn_and_split "*movt_msb"
11459   [(set (match_operand:SI 0 "arith_reg_dest")
11460         (mult:SI (match_operand:SI 1 "t_reg_operand")
11461                  (const_int -2147483648)))  ;; 0xffffffff80000000
11462    (clobber (reg:SI T_REG))]
11463   "TARGET_SH1"
11464   "#"
11465   "&& 1"
11466   [(set (match_dup 0) (ashift:SI (reg:SI T_REG) (const_int 31)))])
11468 ;; Store inverted T bit as MSB in a reg.
11469 ;; T = 0: 0x80000000 -> reg
11470 ;; T = 1: 0x00000000 -> reg
11471 ;; On SH2A we can get away without clobbering the T_REG.
11472 (define_insn_and_split "*negt_msb"
11473   [(set (match_operand:SI 0 "arith_reg_dest")
11474         (match_operand:SI 1 "negt_reg_shl31_operand"))]
11475   "TARGET_SH2A"
11476   "#"
11477   "&& can_create_pseudo_p ()"
11478   [(const_int 0)]
11480   rtx tmp = gen_reg_rtx (SImode);
11481   emit_insn (gen_movrt (tmp, get_t_reg_rtx ()));
11482   emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx));
11483   DONE;
11486 (define_insn_and_split "*negt_msb"
11487   [(set (match_operand:SI 0 "arith_reg_dest")
11488         (match_operand:SI 1 "negt_reg_shl31_operand"))
11489    (clobber (reg:SI T_REG))]
11490   "TARGET_SH1 && !TARGET_SH2A"
11491   "#"
11492   "&& can_create_pseudo_p ()"
11493   [(const_int 0)]
11495   rtx tmp = gen_reg_rtx (SImode);
11496   emit_move_insn (tmp, get_t_reg_rtx ());
11497   emit_insn (gen_cmpeqsi_t (tmp, const0_rtx));
11498   emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ()));
11499   DONE;
11502 ;; The *cset_zero patterns convert optimizations such as
11503 ;;      "if (test) x = 0;" to "x &= -(test == 0);"
11504 ;; back to conditional branch sequences if zero-displacement branches
11505 ;; are enabled.
11506 ;; FIXME: These patterns can be removed when conditional execution patterns
11507 ;; are implemented, since ifcvt will not perform these optimizations if
11508 ;; conditional execution is supported.
11509 (define_insn "*cset_zero"
11510   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11511         (and:SI (plus:SI (match_operand:SI 1 "t_reg_operand")
11512                          (const_int -1))
11513                 (match_operand:SI 2 "arith_reg_operand" "0")))]
11514   "TARGET_SH1 && TARGET_ZDCBRANCH"
11516   return       "bf      0f"     "\n"
11517          "      mov     #0,%0"  "\n"
11518          "0:";
11520   [(set_attr "type" "arith") ;; poor approximation
11521    (set_attr "length" "4")])
11523 (define_insn "*cset_zero"
11524   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11525         (if_then_else:SI (match_operand:SI 1 "t_reg_operand")
11526                          (match_operand:SI 2 "arith_reg_operand" "0")
11527                          (const_int 0)))]
11528   "TARGET_SH1 && TARGET_ZDCBRANCH"
11530   return       "bt      0f"     "\n"
11531          "      mov     #0,%0"  "\n"
11532          "0:";
11534   [(set_attr "type" "arith") ;; poor approximation
11535    (set_attr "length" "4")])
11537 (define_expand "cstoresf4"
11538   [(set (match_operand:SI 0 "register_operand" "=r")
11539         (match_operator:SI 1 "sh_float_comparison_operator"
11540          [(match_operand:SF 2 "arith_operand" "")
11541           (match_operand:SF 3 "arith_operand" "")]))]
11542   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11544   if (TARGET_SHMEDIA)
11545     {
11546       emit_insn (gen_cstore4_media (operands[0], operands[1],
11547                                     operands[2], operands[3]));
11548       DONE;
11549     }
11551   if (! currently_expanding_to_rtl)
11552     FAIL;
11553    
11554   sh_emit_compare_and_set (operands, SFmode);
11555   DONE;
11558 (define_expand "cstoredf4"
11559   [(set (match_operand:SI 0 "register_operand" "=r")
11560         (match_operator:SI 1 "sh_float_comparison_operator"
11561          [(match_operand:DF 2 "arith_operand" "")
11562           (match_operand:DF 3 "arith_operand" "")]))]
11563   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11565   if (TARGET_SHMEDIA)
11566     {
11567       emit_insn (gen_cstore4_media (operands[0], operands[1],
11568                                     operands[2], operands[3]));
11569       DONE;
11570     }
11572   if (! currently_expanding_to_rtl)
11573     FAIL;
11574    
11575   sh_emit_compare_and_set (operands, DFmode);
11576   DONE;
11579 ;; -------------------------------------------------------------------------
11580 ;; Instructions to cope with inline literal tables
11581 ;; -------------------------------------------------------------------------
11583 ; 2 byte integer in line
11585 (define_insn "consttable_2"
11586  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11587                     (match_operand 1 "" "")]
11588                    UNSPECV_CONST2)]
11589  ""
11591   if (operands[1] != const0_rtx)
11592     assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
11593   return "";
11595  [(set_attr "length" "2")
11596  (set_attr "in_delay_slot" "no")])
11598 ; 4 byte integer in line
11600 (define_insn "consttable_4"
11601  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11602                     (match_operand 1 "" "")]
11603                    UNSPECV_CONST4)]
11604  ""
11606   if (operands[1] != const0_rtx)
11607     {
11608       assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
11609       mark_symbol_refs_as_used (operands[0]);
11610     }
11611   return "";
11613  [(set_attr "length" "4")
11614   (set_attr "in_delay_slot" "no")])
11616 ; 8 byte integer in line
11618 (define_insn "consttable_8"
11619  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11620                     (match_operand 1 "" "")]
11621                    UNSPECV_CONST8)]
11622  ""
11624   if (operands[1] != const0_rtx)
11625     assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
11626   return "";
11628  [(set_attr "length" "8")
11629   (set_attr "in_delay_slot" "no")])
11631 ; 4 byte floating point
11633 (define_insn "consttable_sf"
11634  [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
11635                     (match_operand 1 "" "")]
11636                    UNSPECV_CONST4)]
11637  ""
11639   if (operands[1] != const0_rtx)
11640     {
11641       REAL_VALUE_TYPE d;
11642       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11643       assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
11644     }
11645   return "";
11647  [(set_attr "length" "4")
11648   (set_attr "in_delay_slot" "no")])
11650 ; 8 byte floating point
11652 (define_insn "consttable_df"
11653  [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
11654                     (match_operand 1 "" "")]
11655                    UNSPECV_CONST8)]
11656  ""
11658   if (operands[1] != const0_rtx)
11659     {
11660       REAL_VALUE_TYPE d;
11661       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11662       assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
11663     }
11664   return "";
11666  [(set_attr "length" "8")
11667   (set_attr "in_delay_slot" "no")])
11669 ;; Alignment is needed for some constant tables; it may also be added for
11670 ;; Instructions at the start of loops, or after unconditional branches.
11671 ;; ??? We would get more accurate lengths if we did instruction
11672 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
11673 ;; here is too conservative.
11675 ; align to a two byte boundary
11677 (define_expand "align_2"
11678  [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
11679  ""
11680  "")
11682 ; align to a four byte boundary
11683 ;; align_4 and align_log are instructions for the starts of loops, or
11684 ;; after unconditional branches, which may take up extra room.
11686 (define_expand "align_4"
11687  [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
11688  ""
11689  "")
11691 ; align to a cache line boundary
11693 (define_insn "align_log"
11694  [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
11695  ""
11696  ""
11697  [(set_attr "length" "0")
11698   (set_attr "in_delay_slot" "no")])
11700 ; emitted at the end of the literal table, used to emit the
11701 ; 32bit branch labels if needed.
11703 (define_insn "consttable_end"
11704   [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
11705   ""
11707   return output_jump_label_table ();
11709   [(set_attr "in_delay_slot" "no")])
11711 ; emitted at the end of the window in the literal table.
11713 (define_insn "consttable_window_end"
11714   [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
11715   ""
11716   ""
11717   [(set_attr "length" "0")
11718    (set_attr "in_delay_slot" "no")])
11720 ;; -------------------------------------------------------------------------
11721 ;; Misc
11722 ;; -------------------------------------------------------------------------
11724 ;; String/block move insn.
11726 (define_expand "movmemsi"
11727   [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
11728                    (mem:BLK (match_operand:BLK 1 "" "")))
11729               (use (match_operand:SI 2 "nonmemory_operand" ""))
11730               (use (match_operand:SI 3 "immediate_operand" ""))
11731               (clobber (reg:SI PR_REG))
11732               (clobber (reg:SI R4_REG))
11733               (clobber (reg:SI R5_REG))
11734               (clobber (reg:SI R0_REG))])]
11735   "TARGET_SH1 && ! TARGET_SH5"
11737   if(expand_block_move (operands))
11738      DONE;
11739   else FAIL;
11742 (define_insn "block_move_real"
11743   [(parallel [(set (mem:BLK (reg:SI R4_REG))
11744                    (mem:BLK (reg:SI R5_REG)))
11745               (use (match_operand:SI 0 "arith_reg_operand" "r"))
11746               (clobber (reg:SI PR_REG))
11747               (clobber (reg:SI R0_REG))])]
11748   "TARGET_SH1 && ! TARGET_HARD_SH4"
11749   "jsr  @%0%#"
11750   [(set_attr "type" "sfunc")
11751    (set_attr "needs_delay_slot" "yes")])
11753 (define_insn "block_lump_real"
11754   [(parallel [(set (mem:BLK (reg:SI R4_REG))
11755                    (mem:BLK (reg:SI R5_REG)))
11756               (use (match_operand:SI 0 "arith_reg_operand" "r"))
11757               (use (reg:SI R6_REG))
11758               (clobber (reg:SI PR_REG))
11759               (clobber (reg:SI T_REG))
11760               (clobber (reg:SI R4_REG))
11761               (clobber (reg:SI R5_REG))
11762               (clobber (reg:SI R6_REG))
11763               (clobber (reg:SI R0_REG))])]
11764   "TARGET_SH1 && ! TARGET_HARD_SH4"
11765   "jsr  @%0%#"
11766   [(set_attr "type" "sfunc")
11767    (set_attr "needs_delay_slot" "yes")])
11769 (define_insn "block_move_real_i4"
11770   [(parallel [(set (mem:BLK (reg:SI R4_REG))
11771                    (mem:BLK (reg:SI R5_REG)))
11772               (use (match_operand:SI 0 "arith_reg_operand" "r"))
11773               (clobber (reg:SI PR_REG))
11774               (clobber (reg:SI R0_REG))
11775               (clobber (reg:SI R1_REG))
11776               (clobber (reg:SI R2_REG))])]
11777   "TARGET_HARD_SH4"
11778   "jsr  @%0%#"
11779   [(set_attr "type" "sfunc")
11780    (set_attr "needs_delay_slot" "yes")])
11782 (define_insn "block_lump_real_i4"
11783   [(parallel [(set (mem:BLK (reg:SI R4_REG))
11784                    (mem:BLK (reg:SI R5_REG)))
11785               (use (match_operand:SI 0 "arith_reg_operand" "r"))
11786               (use (reg:SI R6_REG))
11787               (clobber (reg:SI PR_REG))
11788               (clobber (reg:SI T_REG))
11789               (clobber (reg:SI R4_REG))
11790               (clobber (reg:SI R5_REG))
11791               (clobber (reg:SI R6_REG))
11792               (clobber (reg:SI R0_REG))
11793               (clobber (reg:SI R1_REG))
11794               (clobber (reg:SI R2_REG))
11795               (clobber (reg:SI R3_REG))])]
11796   "TARGET_HARD_SH4"
11797   "jsr  @%0%#"
11798   [(set_attr "type" "sfunc")
11799    (set_attr "needs_delay_slot" "yes")])
11801 ;; -------------------------------------------------------------------------
11802 ;; Floating point instructions.
11803 ;; -------------------------------------------------------------------------
11805 ;; ??? All patterns should have a type attribute.
11807 (define_expand "movpsi"
11808   [(set (match_operand:PSI 0 "register_operand" "")
11809         (match_operand:PSI 1 "general_movsrc_operand" ""))]
11810   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11811   "")
11813 ;; The c / m alternative is a fake to guide reload to load directly into
11814 ;; fpscr, since reload doesn't know how to use post-increment.
11815 ;; TARGET_LEGITIMATE_ADDRESS_P guards about bogus addresses before reload,
11816 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
11817 ;; predicate after reload.
11818 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
11819 ;; like a mac -> gpr move.
11820 (define_insn "fpu_switch"
11821   [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
11822         (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
11823   "TARGET_SH2E
11824    && (! reload_completed
11825        || true_regnum (operands[0]) != FPSCR_REG
11826        || !MEM_P (operands[1])
11827        || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
11828   "@
11829         ! precision stays the same
11830         lds.l   %1,fpscr
11831         mov.l   %1,%0
11832         #
11833         lds     %1,fpscr
11834         mov     %1,%0
11835         mov.l   %1,%0
11836         sts     fpscr,%0
11837         sts.l   fpscr,%0"
11838   [(set_attr "length" "0,2,2,4,2,2,2,2,2")
11839    (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,fstore")])
11841 (define_peephole2
11842   [(set (reg:PSI FPSCR_REG)
11843         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
11844   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
11845   [(const_int 0)]
11847   rtx fpscr, mem, new_insn;
11849   fpscr = SET_DEST (PATTERN (curr_insn));
11850   mem = SET_SRC (PATTERN (curr_insn));
11851   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
11853   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
11854   add_reg_note (new_insn, REG_INC, operands[0]);
11855   DONE;
11858 (define_split
11859   [(set (reg:PSI FPSCR_REG)
11860         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
11861   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
11862    && (flag_peephole2 ? epilogue_completed : reload_completed)"
11863   [(const_int 0)]
11865   rtx fpscr, mem, new_insn;
11867   fpscr = SET_DEST (PATTERN (curr_insn));
11868   mem = SET_SRC (PATTERN (curr_insn));
11869   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
11871   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
11872   add_reg_note (new_insn, REG_INC, operands[0]);
11874   if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
11875     emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
11876   DONE;
11879 ;; ??? This uses the fp unit, but has no type indicating that.
11880 ;; If we did that, this would either give a bogus latency or introduce
11881 ;; a bogus FIFO constraint.
11882 ;; Since this insn is currently only used for prologues/epilogues,
11883 ;; it is probably best to claim no function unit, which matches the
11884 ;; current setting.
11885 (define_insn "toggle_sz"
11886   [(set (reg:PSI FPSCR_REG)
11887         (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
11888   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11889   "fschg"
11890   [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
11892 ;; There's no way we can use it today, since optimize mode switching
11893 ;; doesn't enable us to know from which mode we're switching to the
11894 ;; mode it requests, to tell whether we can use a relative mode switch
11895 ;; (like toggle_pr) or an absolute switch (like loading fpscr from
11896 ;; memory).
11897 (define_insn "toggle_pr"
11898   [(set (reg:PSI FPSCR_REG)
11899         (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
11900   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
11901   "fpchg"
11902   [(set_attr "type" "fpscr_toggle")])
11904 (define_expand "addsf3"
11905   [(set (match_operand:SF 0 "arith_reg_operand" "")
11906         (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
11907                  (match_operand:SF 2 "arith_reg_operand" "")))]
11908   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11910   if (TARGET_SH2E)
11911     {
11912       expand_sf_binop (&gen_addsf3_i, operands);
11913       DONE;
11914     }
11917 (define_insn "*addsf3_media"
11918   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11919         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
11920                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
11921   "TARGET_SHMEDIA_FPU"
11922   "fadd.s       %1, %2, %0"
11923   [(set_attr "type" "fparith_media")])
11925 (define_insn_and_split "unary_sf_op"
11926   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
11927         (vec_select:V2SF
11928          (vec_concat:V2SF
11929           (vec_select:SF
11930            (match_dup 0)
11931            (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
11932           (match_operator:SF 2 "unary_float_operator"
11933             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
11934                             (parallel [(match_operand 4
11935                                         "const_int_operand" "n")]))]))
11936          (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
11937   "TARGET_SHMEDIA_FPU"
11938   "#"
11939   "TARGET_SHMEDIA_FPU && reload_completed"
11940   [(set (match_dup 5) (match_dup 6))]
11942   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
11943   rtx op1 = gen_rtx_REG (SFmode,
11944                          (true_regnum (operands[1])
11945                           + (INTVAL (operands[4]) ^ endian)));
11947   operands[7] = gen_rtx_REG (SFmode,
11948                              (true_regnum (operands[0])
11949                               + (INTVAL (operands[3]) ^ endian)));
11950   operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
11952   [(set_attr "type" "fparith_media")])
11954 (define_insn_and_split "binary_sf_op0"
11955   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
11956         (vec_concat:V2SF
11957           (match_operator:SF 3 "binary_float_operator"
11958             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
11959                             (parallel [(const_int 0)]))
11960              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
11961                             (parallel [(const_int 0)]))])
11962           (vec_select:SF
11963            (match_dup 0)
11964            (parallel [(const_int 1)]))))]
11965   "TARGET_SHMEDIA_FPU"
11966   "#"
11967   "&& reload_completed"
11968   [(set (match_dup 4) (match_dup 5))]
11970   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
11971   rtx op1 = gen_rtx_REG (SFmode,
11972                          true_regnum (operands[1]) + endian);
11973   rtx op2 = gen_rtx_REG (SFmode,
11974                          true_regnum (operands[2]) + endian);
11976   operands[4] = gen_rtx_REG (SFmode,
11977                              true_regnum (operands[0]) + endian);
11978   operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
11980   [(set_attr "type" "fparith_media")])
11982 (define_insn_and_split "binary_sf_op1"
11983   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
11984         (vec_concat:V2SF
11985           (vec_select:SF
11986            (match_dup 0)
11987            (parallel [(const_int 0)]))
11988           (match_operator:SF 3 "binary_float_operator"
11989             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
11990                             (parallel [(const_int 1)]))
11991              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
11992                             (parallel [(const_int 1)]))])))]
11993   "TARGET_SHMEDIA_FPU"
11994   "#"
11995   "&& reload_completed"
11996   [(set (match_dup 4) (match_dup 5))]
11998   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
11999   rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian));
12000   rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian));
12002   operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian));
12003   operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
12005   [(set_attr "type" "fparith_media")])
12007 (define_insn "addsf3_i"
12008   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12009         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
12010                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12011    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12012   "TARGET_SH2E"
12013   "fadd %2,%0"
12014   [(set_attr "type" "fp")
12015    (set_attr "fp_mode" "single")])
12017 (define_expand "subsf3"
12018   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12019         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12020                   (match_operand:SF 2 "fp_arith_reg_operand" "")))]
12021   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12023   if (TARGET_SH2E)
12024     {
12025       expand_sf_binop (&gen_subsf3_i, operands);
12026       DONE;
12027     }
12030 (define_insn "*subsf3_media"
12031   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12032         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12033                   (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12034   "TARGET_SHMEDIA_FPU"
12035   "fsub.s       %1, %2, %0"
12036   [(set_attr "type" "fparith_media")])
12038 (define_insn "subsf3_i"
12039   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12040         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
12041                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12042    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12043   "TARGET_SH2E"
12044   "fsub %2,%0"
12045   [(set_attr "type" "fp")
12046    (set_attr "fp_mode" "single")])
12048 (define_expand "mulsf3"
12049   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12050         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12051                  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
12052   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12054   if (TARGET_SH2E)
12055     {
12056       emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2],
12057                  get_fpscr_rtx ()));
12058       DONE;
12059     }
12062 (define_insn "*mulsf3_media"
12063   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12064         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12065                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12066   "TARGET_SHMEDIA_FPU"
12067   "fmul.s       %1, %2, %0"
12068   [(set_attr "type" "fparith_media")])
12070 (define_insn "mulsf3_i"
12071   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12072         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
12073                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12074    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12075   "TARGET_SH2E"
12076   "fmul %2,%0"
12077   [(set_attr "type" "fp")
12078    (set_attr "fp_mode" "single")])
12080 ;; FMA (fused multiply-add) patterns
12081 (define_expand "fmasf4"
12082   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12083         (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12084                 (match_operand:SF 2 "fp_arith_reg_operand" "")
12085                 (match_operand:SF 3 "fp_arith_reg_operand" "")))]
12086   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12088   if (TARGET_SH2E)
12089     {
12090       emit_sf_insn (gen_fmasf4_i (operands[0], operands[1], operands[2],
12091                                   operands[3], get_fpscr_rtx ()));
12092       DONE;
12093     }
12096 (define_insn "fmasf4_i"
12097   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12098         (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w")
12099                 (match_operand:SF 2 "fp_arith_reg_operand" "f")
12100                 (match_operand:SF 3 "fp_arith_reg_operand" "0")))
12101    (use (match_operand:PSI 4 "fpscr_operand" "c"))]
12102   "TARGET_SH2E"
12103   "fmac %1,%2,%0"
12104   [(set_attr "type" "fp")
12105    (set_attr "fp_mode" "single")])
12107 (define_insn "fmasf4_media"
12108   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12109         (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12110                 (match_operand:SF 2 "fp_arith_reg_operand" "f")
12111                 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
12112   "TARGET_SHMEDIA_FPU"
12113   "fmac.s %1, %2, %0"
12114   [(set_attr "type" "fparith_media")])
12116 (define_expand "divsf3"
12117   [(set (match_operand:SF 0 "arith_reg_operand" "")
12118         (div:SF (match_operand:SF 1 "arith_reg_operand" "")
12119                 (match_operand:SF 2 "arith_reg_operand" "")))]
12120   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12122   if (TARGET_SH2E)
12123     {
12124       expand_sf_binop (&gen_divsf3_i, operands);
12125       DONE;
12126     }
12129 (define_insn "*divsf3_media"
12130   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12131         (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12132                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12133   "TARGET_SHMEDIA_FPU"
12134   "fdiv.s       %1, %2, %0"
12135   [(set_attr "type" "fdiv_media")])
12137 (define_insn "divsf3_i"
12138   [(set (match_operand:SF 0 "arith_reg_dest" "=f")
12139         (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
12140                  (match_operand:SF 2 "arith_reg_operand" "f")))
12141    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12142   "TARGET_SH2E"
12143   "fdiv %2,%0"
12144   [(set_attr "type" "fdiv")
12145    (set_attr "fp_mode" "single")])
12147 (define_insn "floatdisf2"
12148   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12149         (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
12150   "TARGET_SHMEDIA_FPU"
12151   "float.qs %1, %0"
12152   [(set_attr "type" "fpconv_media")])
12154 (define_expand "floatsisf2"
12155   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12156         (float:SF (match_operand:SI 1 "fpul_operand" "")))]
12157   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12159   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
12160     {
12161       emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
12162       DONE;
12163     }
12166 (define_insn "*floatsisf2_media"
12167   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12168         (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
12169   "TARGET_SHMEDIA_FPU"
12170   "float.ls     %1, %0"
12171   [(set_attr "type" "fpconv_media")])
12173 (define_insn "floatsisf2_i4"
12174   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12175         (float:SF (match_operand:SI 1 "fpul_operand" "y")))
12176    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12177   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12178   "float        %1,%0"
12179   [(set_attr "type" "fp")
12180    (set_attr "fp_mode" "single")])
12182 (define_insn "*floatsisf2_ie"
12183   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12184         (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
12185   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12186   "float        %1,%0"
12187   [(set_attr "type" "fp")])
12189 (define_insn "fix_truncsfdi2"
12190   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
12191         (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12192   "TARGET_SHMEDIA_FPU"
12193   "ftrc.sq %1, %0"
12194   [(set_attr "type" "fpconv_media")])
12196 (define_expand "fix_truncsfsi2"
12197   [(set (match_operand:SI 0 "fpul_operand" "=y")
12198         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12199   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12201   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
12202     {
12203       emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
12204       DONE;
12205     }
12208 (define_insn "*fix_truncsfsi2_media"
12209   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
12210         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12211   "TARGET_SHMEDIA_FPU"
12212   "ftrc.sl      %1, %0"
12213   [(set_attr "type" "fpconv_media")])
12215 (define_insn "fix_truncsfsi2_i4"
12216   [(set (match_operand:SI 0 "fpul_operand" "=y")
12217         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12218    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12219   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12220   "ftrc %1,%0"
12221   [(set_attr "type" "ftrc_s")
12222    (set_attr "fp_mode" "single")])
12224 ;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
12225 ;; fix_truncsfsi2_i4.
12226 ;; (define_insn "fix_truncsfsi2_i4_2"
12227 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12228 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
12229 ;;   (use (reg:PSI FPSCR_REG))
12230 ;;   (clobber (reg:SI FPUL_REG))]
12231 ;;  "TARGET_SH4"
12232 ;;  "#"
12233 ;;  [(set_attr "length" "4")
12234 ;;   (set_attr "fp_mode" "single")])
12236 ;;(define_split
12237 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12238 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
12239 ;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
12240 ;;   (clobber (reg:SI FPUL_REG))]
12241 ;;  "TARGET_SH4"
12242 ;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
12243 ;;            (use (match_dup 2))])
12244 ;;   (set (match_dup 0) (reg:SI FPUL_REG))])
12246 (define_insn "*fixsfsi"
12247   [(set (match_operand:SI 0 "fpul_operand" "=y")
12248         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12249   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12250   "ftrc %1,%0"
12251   [(set_attr "type" "fp")])
12253 (define_insn "cmpgtsf_t"
12254   [(set (reg:SI T_REG)
12255         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12256                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12257   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12258   "fcmp/gt      %1,%0"
12259   [(set_attr "type" "fp_cmp")
12260    (set_attr "fp_mode" "single")])
12262 (define_insn "cmpeqsf_t"
12263   [(set (reg:SI T_REG)
12264         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12265                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12266   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12267   "fcmp/eq      %1,%0"
12268   [(set_attr "type" "fp_cmp")
12269    (set_attr "fp_mode" "single")])
12271 (define_insn "ieee_ccmpeqsf_t"
12272   [(set (reg:SI T_REG)
12273         (ior:SI (reg:SI T_REG)
12274                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12275                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
12276   "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12278   return output_ieee_ccmpeq (insn, operands);
12280   [(set_attr "length" "4")])
12283 (define_insn "cmpgtsf_t_i4"
12284   [(set (reg:SI T_REG)
12285         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12286                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12287    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12288   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12289   "fcmp/gt      %1,%0"
12290   [(set_attr "type" "fp_cmp")
12291    (set_attr "fp_mode" "single")])
12293 (define_insn "cmpeqsf_t_i4"
12294   [(set (reg:SI T_REG)
12295         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12296                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12297    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12298   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12299   "fcmp/eq      %1,%0"
12300   [(set_attr "type" "fp_cmp")
12301    (set_attr "fp_mode" "single")])
12303 (define_insn "*ieee_ccmpeqsf_t_4"
12304   [(set (reg:SI T_REG)
12305         (ior:SI (reg:SI T_REG)
12306                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12307                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
12308    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12309   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12311   return output_ieee_ccmpeq (insn, operands);
12313   [(set_attr "length" "4")
12314    (set_attr "fp_mode" "single")])
12316 (define_insn "cmpeqsf_media"
12317   [(set (match_operand:SI 0 "register_operand" "=r")
12318         (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12319                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12320   "TARGET_SHMEDIA_FPU"
12321   "fcmpeq.s     %1, %2, %0"
12322   [(set_attr "type" "fcmp_media")])
12324 (define_insn "cmpgtsf_media"
12325   [(set (match_operand:SI 0 "register_operand" "=r")
12326         (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12327                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12328   "TARGET_SHMEDIA_FPU"
12329   "fcmpgt.s     %1, %2, %0"
12330   [(set_attr "type" "fcmp_media")])
12332 (define_insn "cmpgesf_media"
12333   [(set (match_operand:SI 0 "register_operand" "=r")
12334         (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12335                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12336   "TARGET_SHMEDIA_FPU"
12337   "fcmpge.s     %1, %2, %0"
12338   [(set_attr "type" "fcmp_media")])
12340 (define_insn "cmpunsf_media"
12341   [(set (match_operand:SI 0 "register_operand" "=r")
12342         (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12343                       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12344   "TARGET_SHMEDIA_FPU"
12345   "fcmpun.s     %1, %2, %0"
12346   [(set_attr "type" "fcmp_media")])
12348 (define_expand "cbranchsf4"
12349   [(set (pc)
12350         (if_then_else (match_operator 0 "sh_float_comparison_operator"
12351                        [(match_operand:SF 1 "arith_operand" "")
12352                         (match_operand:SF 2 "arith_operand" "")])
12353                       (match_operand 3 "" "")
12354                       (pc)))]
12355   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12357   if (TARGET_SHMEDIA)
12358     emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
12359                                           operands[3]));
12360   else
12361     sh_emit_compare_and_branch (operands, SFmode);
12362   DONE;
12365 (define_expand "negsf2"
12366   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12367         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12368   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12370   if (TARGET_SH2E)
12371     {
12372       expand_sf_unop (&gen_negsf2_i, operands);
12373       DONE;
12374     }
12377 (define_insn "*negsf2_media"
12378   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12379         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12380   "TARGET_SHMEDIA_FPU"
12381   "fneg.s       %1, %0"
12382   [(set_attr "type" "fmove_media")])
12384 (define_insn "negsf2_i"
12385   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12386         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12387    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12388   "TARGET_SH2E"
12389   "fneg %0"
12390   [(set_attr "type" "fmove")
12391    (set_attr "fp_mode" "single")])
12393 (define_expand "sqrtsf2"
12394   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12395         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12396   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
12398   if (TARGET_SH3E)
12399     {
12400       expand_sf_unop (&gen_sqrtsf2_i, operands);
12401       DONE;
12402     }
12405 (define_insn "*sqrtsf2_media"
12406   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12407         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12408   "TARGET_SHMEDIA_FPU"
12409   "fsqrt.s      %1, %0"
12410   [(set_attr "type" "fdiv_media")])
12412 (define_insn "sqrtsf2_i"
12413   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12414         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12415    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12416   "TARGET_SH3E"
12417   "fsqrt        %0"
12418   [(set_attr "type" "fdiv")
12419    (set_attr "fp_mode" "single")])
12421 (define_insn "rsqrtsf2"
12422   [(set (match_operand:SF 0 "register_operand" "=f")
12423         (div:SF (match_operand:SF 1 "immediate_operand" "i")
12424                 (sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
12425    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12426   "TARGET_FPU_ANY && TARGET_FSRRA
12427    && operands[1] == CONST1_RTX (SFmode)"
12428   "fsrra        %0"
12429   [(set_attr "type" "fsrra")
12430    (set_attr "fp_mode" "single")])
12432 ;; When the sincos pattern is defined, the builtin functions sin and cos
12433 ;; will be expanded to the sincos pattern and one of the output values will
12434 ;; remain unused.
12435 (define_expand "sincossf3"
12436   [(set (match_operand:SF 0 "nonimmediate_operand")
12437         (unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand")] UNSPEC_FCOSA))
12438    (set (match_operand:SF 1 "nonimmediate_operand")
12439         (unspec:SF [(match_dup 2)] UNSPEC_FSINA))]
12440   "TARGET_FPU_ANY && TARGET_FSCA"
12442   rtx scaled = gen_reg_rtx (SFmode);
12443   rtx truncated = gen_reg_rtx (SImode);
12444   rtx fsca = gen_reg_rtx (V2SFmode);
12445   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
12447   emit_sf_insn (gen_mulsf3 (scaled, operands[2], scale_reg));
12448   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
12449   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
12450                           get_fpscr_rtx ()));
12452   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
12453   emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 0));
12454   DONE;
12457 (define_insn_and_split "fsca"
12458   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12459         (vec_concat:V2SF
12460          (unspec:SF [(mult:SF
12461                       (float:SF (match_operand:SI 1 "fpul_fsca_operand" "y"))
12462                       (match_operand:SF 2 "fsca_scale_factor" "i"))
12463                     ] UNSPEC_FSINA)
12464          (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
12465                     ] UNSPEC_FCOSA)))
12466    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12467   "TARGET_FPU_ANY && TARGET_FSCA"
12468   "fsca fpul,%d0"
12469   "&& !fpul_operand (operands[1], SImode)"
12470   [(const_int 0)]
12472   /* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it
12473      to a simple reg, otherwise reload will have trouble reloading the
12474      pseudo into fpul.  */
12475   rtx x = XEXP (operands[1], 0);
12476   while (x != NULL_RTX && !fpul_operand (x, SImode))
12477     {
12478       gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT);
12479       x = XEXP (x, 0);
12480     }
12482   gcc_assert (x != NULL_RTX && fpul_operand (x, SImode));
12483   emit_insn (gen_fsca (operands[0], x, operands[2], operands[3]));
12484   DONE;
12486   [(set_attr "type" "fsca")
12487    (set_attr "fp_mode" "single")])
12489 (define_expand "abssf2"
12490   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12491         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12492   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12494   if (TARGET_SH2E)
12495     {
12496       expand_sf_unop (&gen_abssf2_i, operands);
12497       DONE;
12498     }
12501 (define_insn "*abssf2_media"
12502   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12503         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12504   "TARGET_SHMEDIA_FPU"
12505   "fabs.s       %1, %0"
12506   [(set_attr "type" "fmove_media")])
12508 (define_insn "abssf2_i"
12509   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12510         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12511    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12512   "TARGET_SH2E"
12513   "fabs %0"
12514   [(set_attr "type" "fmove")
12515    (set_attr "fp_mode" "single")])
12517 (define_expand "adddf3"
12518   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12519         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12520                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12521   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12523   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12524     {
12525       expand_df_binop (&gen_adddf3_i, operands);
12526       DONE;
12527     }
12530 (define_insn "*adddf3_media"
12531   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12532         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12533                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12534   "TARGET_SHMEDIA_FPU"
12535   "fadd.d       %1, %2, %0"
12536   [(set_attr "type" "dfparith_media")])
12538 (define_insn "adddf3_i"
12539   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12540         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12541                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12542    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12543   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12544   "fadd %2,%0"
12545   [(set_attr "type" "dfp_arith")
12546    (set_attr "fp_mode" "double")])
12548 (define_expand "subdf3"
12549   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12550         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12551                   (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12552   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12554   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12555     {
12556       expand_df_binop (&gen_subdf3_i, operands);
12557       DONE;
12558     }
12561 (define_insn "*subdf3_media"
12562   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12563         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12564                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12565   "TARGET_SHMEDIA_FPU"
12566   "fsub.d       %1, %2, %0"
12567   [(set_attr "type" "dfparith_media")])
12569 (define_insn "subdf3_i"
12570   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12571         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12572                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12573    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12574   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12575   "fsub %2,%0"
12576   [(set_attr "type" "dfp_arith")
12577    (set_attr "fp_mode" "double")])
12579 (define_expand "muldf3"
12580   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12581         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12582                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12583   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12585   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12586     {
12587       expand_df_binop (&gen_muldf3_i, operands);
12588       DONE;
12589     }
12592 (define_insn "*muldf3_media"
12593   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12594         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12595                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12596   "TARGET_SHMEDIA_FPU"
12597   "fmul.d       %1, %2, %0"
12598   [(set_attr "type" "dfmul_media")])
12600 (define_insn "muldf3_i"
12601   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12602         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12603                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12604    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12605   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12606   "fmul %2,%0"
12607   [(set_attr "type" "dfp_mul")
12608    (set_attr "fp_mode" "double")])
12610 (define_expand "divdf3"
12611   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12612         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12613                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12614   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12616   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12617     {
12618       expand_df_binop (&gen_divdf3_i, operands);
12619       DONE;
12620     }
12623 (define_insn "*divdf3_media"
12624   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12625         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12626                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12627   "TARGET_SHMEDIA_FPU"
12628   "fdiv.d       %1, %2, %0"
12629   [(set_attr "type" "dfdiv_media")])
12631 (define_insn "divdf3_i"
12632   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12633         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12634                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12635    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12636   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12637   "fdiv %2,%0"
12638   [(set_attr "type" "dfdiv")
12639    (set_attr "fp_mode" "double")])
12641 (define_insn "floatdidf2"
12642   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12643         (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
12644   "TARGET_SHMEDIA_FPU"
12645   "float.qd     %1, %0"
12646   [(set_attr "type" "dfpconv_media")])
12648 (define_expand "floatsidf2"
12649   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12650         (float:DF (match_operand:SI 1 "fpul_operand" "")))]
12651   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12653   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12654     {
12655       emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
12656                                       get_fpscr_rtx ()));
12657       DONE;
12658     }
12661 (define_insn "*floatsidf2_media"
12662   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12663         (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
12664   "TARGET_SHMEDIA_FPU"
12665   "float.ld     %1, %0"
12666   [(set_attr "type" "dfpconv_media")])
12668 (define_insn "floatsidf2_i"
12669   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12670         (float:DF (match_operand:SI 1 "fpul_operand" "y")))
12671    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12672   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12673   "float        %1,%0"
12674   [(set_attr "type" "dfp_conv")
12675    (set_attr "fp_mode" "double")])
12677 (define_insn "fix_truncdfdi2"
12678   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
12679         (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12680   "TARGET_SHMEDIA_FPU"
12681   "ftrc.dq      %1, %0"
12682   [(set_attr "type" "dfpconv_media")])
12684 (define_expand "fix_truncdfsi2"
12685   [(set (match_operand:SI 0 "fpul_operand" "")
12686         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
12687   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12689   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12690     {
12691       emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
12692                                           get_fpscr_rtx ()));
12693       DONE;
12694     }
12697 (define_insn "*fix_truncdfsi2_media"
12698   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
12699         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12700   "TARGET_SHMEDIA_FPU"
12701   "ftrc.dl      %1, %0"
12702   [(set_attr "type" "dfpconv_media")])
12704 (define_insn "fix_truncdfsi2_i"
12705   [(set (match_operand:SI 0 "fpul_operand" "=y")
12706         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
12707    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12708   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12709   "ftrc %1,%0"
12710   [(set_attr "type" "dfp_conv")
12711    (set_attr "dfp_comp" "no")
12712    (set_attr "fp_mode" "double")])
12714 ;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
12715 ;; fix_truncdfsi2_i.
12716 ;; (define_insn "fix_truncdfsi2_i4"
12717 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12718 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
12719 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
12720 ;;    (clobber (reg:SI FPUL_REG))]
12721 ;;   "TARGET_SH4"
12722 ;;   "#"
12723 ;;   [(set_attr "length" "4")
12724 ;;    (set_attr "fp_mode" "double")])
12726 ;; (define_split
12727 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12728 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
12729 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
12730 ;;    (clobber (reg:SI FPUL_REG))]
12731 ;;   "TARGET_SH4"
12732 ;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
12733 ;;            (use (match_dup 2))])
12734 ;;    (set (match_dup 0) (reg:SI FPUL_REG))])
12736 (define_insn "cmpgtdf_t"
12737   [(set (reg:SI T_REG)
12738         (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
12739                (match_operand:DF 1 "arith_reg_operand" "f")))
12740    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12741   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12742   "fcmp/gt      %1,%0"
12743   [(set_attr "type" "dfp_cmp")
12744    (set_attr "fp_mode" "double")])
12746 (define_insn "cmpeqdf_t"
12747   [(set (reg:SI T_REG)
12748         (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
12749                (match_operand:DF 1 "arith_reg_operand" "f")))
12750    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12751   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12752   "fcmp/eq      %1,%0"
12753   [(set_attr "type" "dfp_cmp")
12754    (set_attr "fp_mode" "double")])
12756 (define_insn "*ieee_ccmpeqdf_t"
12757   [(set (reg:SI T_REG)
12758         (ior:SI (reg:SI T_REG)
12759                 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
12760                        (match_operand:DF 1 "arith_reg_operand" "f"))))
12761    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12762   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12764   return output_ieee_ccmpeq (insn, operands);
12766   [(set_attr "length" "4")
12767    (set_attr "fp_mode" "double")])
12769 (define_insn "cmpeqdf_media"
12770   [(set (match_operand:SI 0 "register_operand" "=r")
12771         (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
12772                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12773   "TARGET_SHMEDIA_FPU"
12774   "fcmpeq.d     %1,%2,%0"
12775   [(set_attr "type" "fcmp_media")])
12777 (define_insn "cmpgtdf_media"
12778   [(set (match_operand:SI 0 "register_operand" "=r")
12779         (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
12780                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12781   "TARGET_SHMEDIA_FPU"
12782   "fcmpgt.d     %1,%2,%0"
12783   [(set_attr "type" "fcmp_media")])
12785 (define_insn "cmpgedf_media"
12786   [(set (match_operand:SI 0 "register_operand" "=r")
12787         (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
12788                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12789   "TARGET_SHMEDIA_FPU"
12790   "fcmpge.d     %1,%2,%0"
12791   [(set_attr "type" "fcmp_media")])
12793 (define_insn "cmpundf_media"
12794   [(set (match_operand:SI 0 "register_operand" "=r")
12795         (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
12796                       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12797   "TARGET_SHMEDIA_FPU"
12798   "fcmpun.d     %1,%2,%0"
12799   [(set_attr "type" "fcmp_media")])
12801 (define_expand "cbranchdf4"
12802   [(set (pc)
12803         (if_then_else (match_operator 0 "sh_float_comparison_operator"
12804                        [(match_operand:DF 1 "arith_operand" "")
12805                         (match_operand:DF 2 "arith_operand" "")])
12806                       (match_operand 3 "" "")
12807                       (pc)))]
12808   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12810   if (TARGET_SHMEDIA)
12811     emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
12812                                           operands[3]));
12813   else
12814     sh_emit_compare_and_branch (operands, DFmode);
12815   DONE;
12819 (define_expand "negdf2"
12820   [(set (match_operand:DF 0 "arith_reg_operand" "")
12821         (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
12822   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12824   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12825     {
12826       expand_df_unop (&gen_negdf2_i, operands);
12827       DONE;
12828     }
12831 (define_insn "*negdf2_media"
12832   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12833         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12834   "TARGET_SHMEDIA_FPU"
12835   "fneg.d       %1, %0"
12836   [(set_attr "type" "fmove_media")])
12838 (define_insn "negdf2_i"
12839   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12840         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
12841    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12842   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12843   "fneg %0"
12844   [(set_attr "type" "fmove")
12845    (set_attr "fp_mode" "double")])
12847 (define_expand "sqrtdf2"
12848   [(set (match_operand:DF 0 "arith_reg_operand" "")
12849         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
12850   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12852   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12853     {
12854       expand_df_unop (&gen_sqrtdf2_i, operands);
12855       DONE;
12856     }
12859 (define_insn "*sqrtdf2_media"
12860   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12861         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12862   "TARGET_SHMEDIA_FPU"
12863   "fsqrt.d      %1, %0"
12864   [(set_attr "type" "dfdiv_media")])
12866 (define_insn "sqrtdf2_i"
12867   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12868         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
12869    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12870   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12871   "fsqrt        %0"
12872   [(set_attr "type" "dfdiv")
12873    (set_attr "fp_mode" "double")])
12875 (define_expand "absdf2"
12876   [(set (match_operand:DF 0 "arith_reg_operand" "")
12877         (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
12878   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12880   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12881     {
12882       expand_df_unop (&gen_absdf2_i, operands);
12883       DONE;
12884     }
12887 (define_insn "*absdf2_media"
12888   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12889         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12890   "TARGET_SHMEDIA_FPU"
12891   "fabs.d       %1, %0"
12892   [(set_attr "type" "fmove_media")])
12894 (define_insn "absdf2_i"
12895   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12896         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
12897    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12898   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12899   "fabs %0"
12900   [(set_attr "type" "fmove")
12901    (set_attr "fp_mode" "double")])
12903 (define_expand "extendsfdf2"
12904   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12905         (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
12906   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12908   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12909     {
12910       emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
12911                                         get_fpscr_rtx ()));
12912       DONE;
12913     }
12916 (define_insn "*extendsfdf2_media"
12917   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12918         (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12919   "TARGET_SHMEDIA_FPU"
12920   "fcnv.sd      %1, %0"
12921   [(set_attr "type" "dfpconv_media")])
12923 (define_insn "extendsfdf2_i4"
12924   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12925         (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
12926    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12927   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12928   "fcnvsd  %1,%0"
12929   [(set_attr "type" "fp")
12930    (set_attr "fp_mode" "double")])
12932 (define_expand "truncdfsf2"
12933   [(set (match_operand:SF 0 "fpul_operand" "")
12934         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
12935   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12937   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12938     {
12939       emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
12940                                        get_fpscr_rtx ()));
12941       DONE;
12942     }
12945 (define_insn "*truncdfsf2_media"
12946   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12947         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12948   "TARGET_SHMEDIA_FPU"
12949   "fcnv.ds      %1, %0"
12950   [(set_attr "type" "dfpconv_media")])
12952 (define_insn "truncdfsf2_i4"
12953   [(set (match_operand:SF 0 "fpul_operand" "=y")
12954         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
12955    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12956   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12957   "fcnvds  %1,%0"
12958   [(set_attr "type" "fp")
12959    (set_attr "fp_mode" "double")])
12961 ;; Bit field extract patterns.  These give better code for packed bitfields,
12962 ;; because they allow auto-increment addresses to be generated.
12964 (define_expand "insv"
12965   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
12966                          (match_operand:SI 1 "immediate_operand" "")
12967                          (match_operand:SI 2 "immediate_operand" ""))
12968         (match_operand:SI 3 "general_operand" ""))]
12969   "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
12971   rtx addr_target, orig_address, shift_reg, qi_val;
12972   HOST_WIDE_INT bitsize, size, v = 0;
12973   rtx x = operands[3];
12975   if (TARGET_SH2A && TARGET_BITOPS
12976       && (satisfies_constraint_Sbw (operands[0])
12977           || satisfies_constraint_Sbv (operands[0]))
12978       && satisfies_constraint_M (operands[1])
12979       && satisfies_constraint_K03 (operands[2]))
12980     {
12981       if (satisfies_constraint_N (operands[3]))
12982         {
12983           emit_insn (gen_bclr_m2a (operands[0], operands[2]));
12984           DONE;
12985         }
12986       else if (satisfies_constraint_M (operands[3]))
12987         {
12988           emit_insn (gen_bset_m2a (operands[0], operands[2]));
12989           DONE;
12990         }
12991       else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
12992                 && satisfies_constraint_M (operands[1]))
12993         {
12994           emit_insn (gen_bst_m2a (operands[0], operands[2]));
12995           DONE;
12996         }
12997       else if (REG_P (operands[3])
12998                && satisfies_constraint_M (operands[1]))
12999         {
13000           emit_insn (gen_bld_reg (operands[3], const0_rtx));
13001           emit_insn (gen_bst_m2a (operands[0], operands[2]));
13002           DONE;
13003         }
13004     }
13005   /* ??? expmed doesn't care for non-register predicates.  */
13006   if (! memory_operand (operands[0], VOIDmode)
13007       || ! immediate_operand (operands[1], VOIDmode)
13008       || ! immediate_operand (operands[2], VOIDmode)
13009       || ! general_operand (x, VOIDmode))
13010     FAIL;
13011   /* If this isn't a 16 / 24 / 32 bit field, or if
13012      it doesn't start on a byte boundary, then fail.  */
13013   bitsize = INTVAL (operands[1]);
13014   if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
13015       || (INTVAL (operands[2]) % 8) != 0)
13016     FAIL;
13018   size = bitsize / 8;
13019   orig_address = XEXP (operands[0], 0);
13020   shift_reg = gen_reg_rtx (SImode);
13021   if (CONST_INT_P (x))
13022     {
13023       v = INTVAL (x);
13024       qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
13025     }
13026   else
13027     {
13028       emit_insn (gen_movsi (shift_reg, operands[3]));
13029       qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13030     }
13031   addr_target = copy_addr_to_reg (plus_constant (Pmode,
13032                                                  orig_address, size - 1));
13034   operands[0] = replace_equiv_address (operands[0], addr_target);
13035   emit_insn (gen_movqi (operands[0], qi_val));
13037   while (size -= 1)
13038     {
13039       if (CONST_INT_P (x))
13040         qi_val
13041           = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
13042       else
13043         {
13044           emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
13045           qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13046         }
13047       emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
13048       emit_insn (gen_movqi (operands[0], qi_val));
13049     }
13051   DONE;
13054 (define_insn "movua"
13055   [(set (match_operand:SI 0 "register_operand" "=z")
13056         (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
13057                    UNSPEC_MOVUA))]
13058   "TARGET_SH4A_ARCH"
13059   "movua.l      %1,%0"
13060   [(set_attr "type" "movua")])
13062 ;; We shouldn't need this, but cse replaces increments with references
13063 ;; to other regs before flow has a chance to create post_inc
13064 ;; addressing modes, and only postreload's cse_move2add brings the
13065 ;; increments back to a usable form.
13066 (define_peephole2
13067   [(set (match_operand:SI 0 "register_operand" "")
13068         (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
13069                          (const_int 32) (const_int 0)))
13070    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
13071   "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
13072   [(set (match_operand:SI 0 "register_operand" "")
13073         (sign_extract:SI (mem:SI (post_inc:SI
13074                                   (match_operand:SI 1 "register_operand" "")))
13075                          (const_int 32) (const_int 0)))]
13076   "")
13078 (define_expand "extv"
13079   [(set (match_operand:SI 0 "register_operand" "")
13080         (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
13081                          (match_operand 2 "const_int_operand" "")
13082                          (match_operand 3 "const_int_operand" "")))]
13083   "TARGET_SH4A_ARCH || TARGET_SH2A"
13085   if (TARGET_SH2A && TARGET_BITOPS
13086       && (satisfies_constraint_Sbw (operands[1])
13087           || satisfies_constraint_Sbv (operands[1]))
13088       && satisfies_constraint_M (operands[2])
13089       && satisfies_constraint_K03 (operands[3]))
13090    {
13091       emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
13092       if (REGNO (operands[0]) != T_REG)
13093         emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
13094       DONE;
13095    }
13096   if (TARGET_SH4A_ARCH
13097       && INTVAL (operands[2]) == 32
13098       && INTVAL (operands[3]) == 0
13099       && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
13100     {
13101       rtx src = adjust_address (operands[1], BLKmode, 0);
13102       set_mem_size (src, 4);
13103       emit_insn (gen_movua (operands[0], src));
13104       DONE;
13105     }
13107   FAIL;
13110 (define_expand "extzv"
13111   [(set (match_operand:SI 0 "register_operand" "")
13112         (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
13113                          (match_operand 2 "const_int_operand" "")
13114                          (match_operand 3 "const_int_operand" "")))]
13115   "TARGET_SH4A_ARCH || TARGET_SH2A"
13117   if (TARGET_SH2A && TARGET_BITOPS
13118       && (satisfies_constraint_Sbw (operands[1])
13119           || satisfies_constraint_Sbv (operands[1]))
13120       && satisfies_constraint_M (operands[2])
13121       && satisfies_constraint_K03 (operands[3]))
13122     {
13123       emit_insn (gen_bld_m2a (operands[1], operands[3]));
13124       if (REGNO (operands[0]) != T_REG)
13125         emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
13126       DONE;
13127     }
13128   if (TARGET_SH4A_ARCH
13129       && INTVAL (operands[2]) == 32
13130       && INTVAL (operands[3]) == 0
13131       && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
13132     {
13133       rtx src = adjust_address (operands[1], BLKmode, 0);
13134       set_mem_size (src, 4);
13135       emit_insn (gen_movua (operands[0], src));
13136       DONE;
13137     }
13139   FAIL;
13142 ;; SH2A instructions for bitwise operations.
13144 ;; Clear a bit in a memory location.
13145 (define_insn "bclr_m2a"
13146   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13147         (and:QI
13148             (not:QI (ashift:QI (const_int 1)
13149                         (match_operand:QI 1 "const_int_operand" "K03,K03")))
13150             (match_dup 0)))]
13151   "TARGET_SH2A && TARGET_BITOPS"
13152   "@
13153         bclr.b  %1,%0
13154         bclr.b  %1,@(0,%t0)"
13155 [(set_attr "length" "4,4")])
13157 (define_insn "bclrmem_m2a"
13158   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13159         (and:QI (match_dup 0)
13160                 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
13161   "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
13162   "@
13163         bclr.b  %W1,%0
13164         bclr.b  %W1,@(0,%t0)"
13165   [(set_attr "length" "4,4")])
13167 ;; Set a bit in a memory location.
13168 (define_insn "bset_m2a"
13169   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13170         (ior:QI
13171             (ashift:QI (const_int 1)
13172                        (match_operand:QI 1 "const_int_operand" "K03,K03"))
13173             (match_dup 0)))]
13174   "TARGET_SH2A && TARGET_BITOPS"
13175   "@
13176         bset.b  %1,%0
13177         bset.b  %1,@(0,%t0)"
13178   [(set_attr "length" "4,4")])
13180 (define_insn "bsetmem_m2a"
13181   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13182         (ior:QI (match_dup 0)
13183                 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
13184   "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
13185   "@
13186         bset.b  %V1,%0
13187         bset.b  %V1,@(0,%t0)"
13188   [(set_attr "length" "4,4")])
13190 ;;; Transfer the contents of the T bit to a specified bit of memory.
13191 (define_insn "bst_m2a"
13192   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
13193         (if_then_else (eq (reg:SI T_REG) (const_int 0))
13194             (and:QI
13195                 (not:QI (ashift:QI (const_int 1)
13196                         (match_operand:QI 1 "const_int_operand" "K03,K03")))
13197                 (match_dup 0))
13198             (ior:QI
13199                 (ashift:QI (const_int 1) (match_dup 1))
13200                 (match_dup 0))))]
13201   "TARGET_SH2A && TARGET_BITOPS"
13202   "@
13203         bst.b   %1,%0
13204         bst.b   %1,@(0,%t0)"
13205   [(set_attr "length" "4")])
13207 ;; Store a specified bit of memory in the T bit.
13208 (define_insn "bld_m2a"
13209   [(set (reg:SI T_REG)
13210         (zero_extract:SI
13211             (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
13212             (const_int 1)
13213             (match_operand 1 "const_int_operand" "K03,K03")))]
13214   "TARGET_SH2A && TARGET_BITOPS"
13215   "@
13216         bld.b   %1,%0
13217         bld.b   %1,@(0,%t0)"
13218   [(set_attr "length" "4,4")])
13220 ;; Store a specified bit of memory in the T bit.
13221 (define_insn "bldsign_m2a"
13222   [(set (reg:SI T_REG)
13223         (sign_extract:SI
13224             (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13225             (const_int 1)
13226             (match_operand 1 "const_int_operand" "K03,K03")))]
13227   "TARGET_SH2A && TARGET_BITOPS"
13228   "@
13229         bld.b   %1,%0
13230         bld.b   %1,@(0,%t0)"
13231   [(set_attr "length" "4,4")])
13233 ;; Store a specified bit of the LSB 8 bits of a register in the T bit.
13234 (define_insn "bld_reg"
13235   [(set (reg:SI T_REG)
13236         (zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
13237                          (const_int 1)
13238                          (match_operand 1 "const_int_operand" "K03")))]
13239   "TARGET_SH2A"
13240   "bld  %1,%0")
13242 (define_insn "*bld_regqi"
13243   [(set (reg:SI T_REG)
13244         (zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
13245                          (const_int 1)
13246                          (match_operand 1 "const_int_operand" "K03")))]
13247   "TARGET_SH2A"
13248   "bld  %1,%0")
13250 ;; Take logical and of a specified bit of memory with the T bit and
13251 ;; store its result in the T bit.
13252 (define_insn "band_m2a"
13253   [(set (reg:SI T_REG)
13254         (and:SI (reg:SI T_REG)
13255                 (zero_extract:SI
13256                     (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13257                     (const_int 1)
13258                     (match_operand 1 "const_int_operand" "K03,K03"))))]
13259   "TARGET_SH2A && TARGET_BITOPS"
13260   "@
13261         band.b  %1,%0
13262         band.b  %1,@(0,%t0)"
13263   [(set_attr "length" "4,4")])
13265 (define_insn "bandreg_m2a"
13266   [(set (match_operand:SI 0 "register_operand" "=r,r")
13267         (and:SI (zero_extract:SI
13268                     (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13269                     (const_int 1)
13270                     (match_operand 2 "const_int_operand" "K03,K03"))
13271                 (match_operand:SI 3 "register_operand" "r,r")))]
13272   "TARGET_SH2A && TARGET_BITOPS"
13274   static const char* alt[] =
13275   {
13276        "band.b  %2,%1"          "\n"
13277     "   movt    %0",
13279        "band.b  %2,@(0,%t1)"    "\n"
13280     "   movt    %0"
13281   };
13282   return alt[which_alternative];
13284   [(set_attr "length" "6,6")])
13286 ;; Take logical or of a specified bit of memory with the T bit and
13287 ;; store its result in the T bit.
13288 (define_insn "bor_m2a"
13289   [(set (reg:SI T_REG)
13290         (ior:SI (reg:SI T_REG)
13291                 (zero_extract:SI
13292                     (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13293                     (const_int 1)
13294                     (match_operand 1 "const_int_operand" "K03,K03"))))]
13295   "TARGET_SH2A && TARGET_BITOPS"
13296   "@
13297         bor.b   %1,%0
13298         bor.b   %1,@(0,%t0)"
13299   [(set_attr "length" "4,4")])
13301 (define_insn "borreg_m2a"
13302   [(set (match_operand:SI 0 "register_operand" "=r,r")
13303         (ior:SI (zero_extract:SI
13304                     (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13305                     (const_int 1)
13306                     (match_operand 2 "const_int_operand" "K03,K03"))
13307                 (match_operand:SI 3 "register_operand" "=r,r")))]
13308   "TARGET_SH2A && TARGET_BITOPS"
13310   static const char* alt[] =
13311   {
13312        "bor.b   %2,%1"          "\n"
13313     "   movt    %0",
13315        "bor.b   %2,@(0,%t1)"    "\n"
13316     "   movt    %0"
13317   };
13318   return alt[which_alternative];
13320   [(set_attr "length" "6,6")])
13322 ;; Take exclusive or of a specified bit of memory with the T bit and
13323 ;; store its result in the T bit.
13324 (define_insn "bxor_m2a"
13325   [(set (reg:SI T_REG)
13326         (xor:SI (reg:SI T_REG)
13327                 (zero_extract:SI
13328                     (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13329                     (const_int 1)
13330                     (match_operand 1 "const_int_operand" "K03,K03"))))]
13331   "TARGET_SH2A && TARGET_BITOPS"
13332   "@
13333         bxor.b  %1,%0
13334         bxor.b  %1,@(0,%t0)"
13335   [(set_attr "length" "4,4")])
13337 (define_insn "bxorreg_m2a"
13338   [(set (match_operand:SI 0 "register_operand" "=r,r")
13339         (xor:SI (zero_extract:SI
13340                     (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13341                     (const_int 1)
13342                     (match_operand 2 "const_int_operand" "K03,K03"))
13343                 (match_operand:SI 3 "register_operand" "=r,r")))]
13344   "TARGET_SH2A && TARGET_BITOPS"
13346   static const char* alt[] =
13347   {
13348        "bxor.b  %2,%1"          "\n"
13349     "   movt    %0",
13351        "bxor.b  %2,@(0,%t1)"    "\n"
13352     "   movt    %0"
13353   };
13354   return alt[which_alternative];
13356   [(set_attr "length" "6,6")])
13359 ;; -------------------------------------------------------------------------
13360 ;; Peepholes
13361 ;; -------------------------------------------------------------------------
13362 ;; This matches cases where the bit in a memory location is set.
13363 (define_peephole2
13364   [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
13365         (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
13366    (set (match_dup 0)
13367         (ior:SI (match_dup 0)
13368         (match_operand:SI 2 "const_int_operand" "Pso,Pso")))
13369    (set (match_dup 1)
13370         (match_operand 3 "arith_reg_operand" "r,r"))]
13371   "TARGET_SH2A && TARGET_BITOPS
13372    && satisfies_constraint_Pso (operands[2])
13373    && REGNO (operands[0]) == REGNO (operands[3])"
13374   [(set (match_dup 1)
13375         (ior:QI (match_dup 1)
13376                 (match_dup 2)))]
13377   "")
13379 ;; This matches cases where the bit in a memory location is cleared.
13380 (define_peephole2
13381   [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
13382         (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
13383    (set (match_dup 0)
13384         (and:SI (match_dup 0)
13385         (match_operand:SI 2 "const_int_operand" "Psz,Psz")))
13386    (set (match_dup 1)
13387         (match_operand 3 "arith_reg_operand" "r,r"))]
13388   "TARGET_SH2A && TARGET_BITOPS
13389    && satisfies_constraint_Psz (operands[2])
13390    && REGNO (operands[0]) == REGNO (operands[3])"
13391   [(set (match_dup 1)
13392         (and:QI (match_dup 1)
13393                 (match_dup 2)))]
13394   "")
13396 ;; This matches cases where a stack pointer increment at the start of the
13397 ;; epilogue combines with a stack slot read loading the return value.
13399 (define_peephole
13400   [(set (match_operand:SI 0 "arith_reg_operand" "")
13401         (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
13402    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
13403   "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
13404   "mov.l        @%1+,%0")
13406 ;; See the comment on the dt combiner pattern above.
13408 (define_peephole
13409   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
13410         (plus:SI (match_dup 0)
13411                  (const_int -1)))
13412    (set (reg:SI T_REG)
13413         (eq:SI (match_dup 0)
13414                (const_int 0)))]
13415   "TARGET_SH2"
13416   "dt   %0")
13418 ;; The following peepholes fold load sequences for which reload was not
13419 ;; able to generate a displacement addressing move insn.
13420 ;; This can happen when reload has to transform a move insn 
13421 ;; without displacement into one with displacement.  Or when reload can't
13422 ;; fit a displacement into the insn's constraints.  In the latter case, the
13423 ;; load destination reg remains at r0, which reload compensates by inserting
13424 ;; another mov insn.
13426 ;; Fold sequence:
13427 ;;      mov #54,r0
13428 ;;      mov.{b,w} @(r0,r15),r0
13429 ;;      mov r0,r3
13430 ;; into:
13431 ;;      mov.{b,w} @(54,r15),r3
13433 (define_peephole2
13434   [(set (match_operand:SI 0 "arith_reg_dest" "")
13435         (match_operand:SI 1 "const_int_operand" ""))
13436    (set (match_operand:SI 2 "arith_reg_dest" "")
13437         (sign_extend:SI
13438          (mem:QI (plus:SI (match_dup 0)
13439                           (match_operand:SI 3 "arith_reg_operand" "")))))
13440    (set (match_operand:QI 4 "arith_reg_dest" "")
13441         (match_operand:QI 5 "arith_reg_operand" ""))]
13442   "TARGET_SH2A
13443    && sh_legitimate_index_p (QImode, operands[1], true, true)
13444    && REGNO (operands[2]) == REGNO (operands[5])
13445    && peep2_reg_dead_p (3, operands[5])"
13446   [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))]
13447   "")
13449 (define_peephole2
13450   [(set (match_operand:SI 0 "arith_reg_dest" "")
13451         (match_operand:SI 1 "const_int_operand" ""))
13452    (set (match_operand:SI 2 "arith_reg_dest" "")
13453         (sign_extend:SI
13454          (mem:HI (plus:SI (match_dup 0)
13455                           (match_operand:SI 3 "arith_reg_operand" "")))))
13456    (set (match_operand:HI 4 "arith_reg_dest" "")
13457         (match_operand:HI 5 "arith_reg_operand" ""))]
13458   "TARGET_SH2A
13459    && sh_legitimate_index_p (HImode, operands[1], true, true)
13460    && REGNO (operands[2]) == REGNO (operands[5])
13461    && peep2_reg_dead_p (3, operands[5])"
13462   [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))]
13463   "")
13465 ;; Fold sequence:
13466 ;;      mov #54,r0
13467 ;;      mov.{b,w} @(r0,r15),r1
13468 ;; into:
13469 ;;      mov.{b,w} @(54,r15),r1
13471 (define_peephole2
13472   [(set (match_operand:SI 0 "arith_reg_dest" "")
13473         (match_operand:SI 1 "const_int_operand" ""))
13474    (set (match_operand:SI 2 "arith_reg_dest" "")
13475          (sign_extend:SI
13476          (mem:QI (plus:SI (match_dup 0)
13477                           (match_operand:SI 3 "arith_reg_operand" "")))))]
13478   "TARGET_SH2A
13479    && sh_legitimate_index_p (QImode, operands[1], true, true)
13480    && (peep2_reg_dead_p (2, operands[0])
13481        || REGNO (operands[0]) == REGNO (operands[2]))"
13482   [(set (match_dup 2)
13483         (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))]
13484   "")
13486 (define_peephole2
13487   [(set (match_operand:SI 0 "arith_reg_dest" "")
13488         (match_operand:SI 1 "const_int_operand" ""))
13489    (set (match_operand:SI 2 "arith_reg_dest" "")
13490          (sign_extend:SI
13491          (mem:HI (plus:SI (match_dup 0)
13492                           (match_operand:SI 3 "arith_reg_operand" "")))))]
13493   "TARGET_SH2A
13494    && sh_legitimate_index_p (HImode, operands[1], true, true)
13495    && (peep2_reg_dead_p (2, operands[0])
13496        || REGNO (operands[0]) == REGNO (operands[2]))"
13497   [(set (match_dup 2)
13498         (sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))]
13499   "")
13501 ;; Fold sequence:
13502 ;;      mov.{b,w} @(r0,r15),r0
13503 ;;      mov r0,r3
13504 ;; into:
13505 ;;      mov.{b,w} @(r0,r15),r3
13507 ;; This can happen when initially a displacement address is picked, where
13508 ;; the destination reg is fixed to r0, and then the address is transformed
13509 ;; into 'r0 + reg'.
13510 (define_peephole2
13511   [(set (match_operand:SI 0 "arith_reg_dest" "")
13512         (sign_extend:SI
13513          (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13514                           (match_operand:SI 2 "arith_reg_operand" "")))))
13515    (set (match_operand:QI 3 "arith_reg_dest" "")
13516         (match_operand:QI 4 "arith_reg_operand" ""))]
13517   "TARGET_SH1
13518    && REGNO (operands[0]) == REGNO (operands[4])
13519    && peep2_reg_dead_p (2, operands[0])"
13520   [(set (match_dup 3)
13521         (mem:QI (plus:SI (match_dup 1) (match_dup 2))))]
13522   "")
13524 (define_peephole2
13525   [(set (match_operand:SI 0 "arith_reg_dest" "")
13526         (sign_extend:SI
13527          (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13528                           (match_operand:SI 2 "arith_reg_operand" "")))))
13529    (set (match_operand:HI 3 "arith_reg_dest" "")
13530         (match_operand:HI 4 "arith_reg_operand" ""))]
13531   "TARGET_SH1
13532    && REGNO (operands[0]) == REGNO (operands[4])
13533    && peep2_reg_dead_p (2, operands[0])"
13534   [(set (match_dup 3)
13535         (mem:HI (plus:SI (match_dup 1) (match_dup 2))))]
13536   "")
13538 (define_peephole
13539   [(set (match_operand:SI 0 "register_operand" "=r")
13540         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13541    (set (mem:SF (match_dup 0))
13542         (match_operand:SF 2 "general_movsrc_operand" ""))]
13543   "TARGET_SH1 && REGNO (operands[0]) == 0
13544    && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
13545        || (GET_CODE (operands[2]) == SUBREG
13546            && REGNO (SUBREG_REG (operands[2])) < 16))
13547    && reg_unused_after (operands[0], insn)"
13548   "mov.l        %2,@(%0,%1)")
13550 (define_peephole
13551   [(set (match_operand:SI 0 "register_operand" "=r")
13552         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13553    (set (match_operand:SF 2 "general_movdst_operand" "")
13555         (mem:SF (match_dup 0)))]
13556   "TARGET_SH1 && REGNO (operands[0]) == 0
13557    && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
13558        || (GET_CODE (operands[2]) == SUBREG
13559            && REGNO (SUBREG_REG (operands[2])) < 16))
13560    && reg_unused_after (operands[0], insn)"
13561   "mov.l        @(%0,%1),%2")
13563 (define_peephole
13564   [(set (match_operand:SI 0 "register_operand" "=r")
13565         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13566    (set (mem:SF (match_dup 0))
13567         (match_operand:SF 2 "general_movsrc_operand" ""))]
13568   "TARGET_SH2E && REGNO (operands[0]) == 0
13569    && ((REG_P (operands[2])
13570         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
13571        || (GET_CODE (operands[2]) == SUBREG
13572            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
13573    && reg_unused_after (operands[0], insn)"
13574   "fmov{.s|}    %2,@(%0,%1)")
13576 (define_peephole
13577   [(set (match_operand:SI 0 "register_operand" "=r")
13578         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13579    (set (match_operand:SF 2 "general_movdst_operand" "")
13581         (mem:SF (match_dup 0)))]
13582   "TARGET_SH2E && REGNO (operands[0]) == 0
13583    && ((REG_P (operands[2])
13584         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
13585        || (GET_CODE (operands[2]) == SUBREG
13586            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
13587    && reg_unused_after (operands[0], insn)"
13588   "fmov{.s|}    @(%0,%1),%2")
13590 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).
13591 (define_insn "sp_switch_1"
13592   [(const_int 1) (match_operand:SI 0 "symbol_ref_operand" "s")]
13593   "TARGET_SH1"
13595   return       "mov.l   r0,@-r15"       "\n"
13596          "      mov.l   %0,r0"          "\n"
13597          "      mov.l   @r0,r0"         "\n"
13598          "      mov.l   r15,@-r0"       "\n"
13599          "      mov     r0,r15";
13601   [(set_attr "length" "10")])
13603 ;; Switch back to the original stack for interrupt functions with the
13604 ;; sp_switch attribute.
13605 (define_insn "sp_switch_2"
13606   [(const_int 2)]
13607   "TARGET_SH1"
13609   return       "mov.l   @r15+,r15"      "\n"
13610          "      mov.l   @r15+,r0";
13612   [(set_attr "length" "4")])
13614 ;; Integer vector moves
13616 (define_expand "movv8qi"
13617   [(set (match_operand:V8QI 0 "general_movdst_operand" "")
13618         (match_operand:V8QI 1 "general_movsrc_operand" ""))]
13619   "TARGET_SHMEDIA"
13621   prepare_move_operands (operands, V8QImode);
13624 (define_insn "movv8qi_i"
13625   [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
13626         (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13627   "TARGET_SHMEDIA
13628    && (register_operand (operands[0], V8QImode)
13629        || sh_register_operand (operands[1], V8QImode))"
13630   "@
13631         add     %1, r63, %0
13632         movi    %1, %0
13633         #
13634         ld%M1.q %m1, %0
13635         st%M0.q %m0, %N1"
13636   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
13637    (set_attr "length" "4,4,16,4,4")])
13639 (define_split
13640   [(set (match_operand:V8QI 0 "arith_reg_dest" "")
13641         (subreg:V8QI (const_int 0) 0))]
13642   "TARGET_SHMEDIA"
13643   [(set (match_dup 0)
13644         (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
13645                             (const_int 0) (const_int 0) (const_int 0)
13646                             (const_int 0) (const_int 0)]))])
13648 (define_split
13649   [(set (match_operand 0 "arith_reg_dest" "")
13650         (match_operand 1 "sh_rep_vec" ""))]
13651   "TARGET_SHMEDIA && reload_completed
13652    && GET_MODE (operands[0]) == GET_MODE (operands[1])
13653    && sh_vector_mode_supported_p (GET_MODE (operands[0]))
13654    && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
13655    && (XVECEXP (operands[1], 0, 0) != const0_rtx
13656        || XVECEXP (operands[1], 0, 1) != const0_rtx)
13657    && (XVECEXP (operands[1], 0, 0) != constm1_rtx
13658        || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
13659   [(set (match_dup 0) (match_dup 1))
13660    (match_dup 2)]
13662   int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
13663   rtx elt1 = XVECEXP (operands[1], 0, 1);
13665   if (unit_size > 2)
13666     operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
13667   else
13668     {
13669       if (unit_size < 2)
13670         operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
13671       operands[2] = gen_mperm_w0 (operands[0], operands[0]);
13672     }
13673   operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
13674   operands[1] = XVECEXP (operands[1], 0, 0);
13675   if (unit_size < 2)
13676     {
13677       if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
13678         operands[1]
13679           = GEN_INT (TARGET_LITTLE_ENDIAN
13680                      ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
13681                      : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
13682       else
13683         {
13684           operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
13685           operands[1]
13686             = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
13687         }
13688     }
13691 (define_split
13692   [(set (match_operand 0 "arith_reg_dest" "")
13693         (match_operand 1 "sh_const_vec" ""))]
13694   "TARGET_SHMEDIA && reload_completed
13695    && GET_MODE (operands[0]) == GET_MODE (operands[1])
13696    && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
13697   [(set (match_dup 0) (match_dup 1))]
13699   rtx v = operands[1];
13700   enum machine_mode new_mode
13701     = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
13703   operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
13704   operands[1]
13705     = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
13708 (define_expand "movv2hi"
13709   [(set (match_operand:V2HI 0 "general_movdst_operand" "")
13710         (match_operand:V2HI 1 "general_movsrc_operand" ""))]
13711   "TARGET_SHMEDIA"
13713   prepare_move_operands (operands, V2HImode);
13716 (define_insn "movv2hi_i"
13717   [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
13718         (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13719   "TARGET_SHMEDIA
13720    && (register_operand (operands[0], V2HImode)
13721        || sh_register_operand (operands[1], V2HImode))"
13722   "@
13723         add.l   %1, r63, %0
13724         movi    %1, %0
13725         #
13726         ld%M1.l %m1, %0
13727         st%M0.l %m0, %N1"
13728   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
13729    (set_attr "length" "4,4,16,4,4")
13730    (set (attr "highpart")
13731         (cond [(match_test "sh_contains_memref_p (insn)")
13732                (const_string "user")]
13733               (const_string "ignore")))])
13735 (define_expand "movv4hi"
13736   [(set (match_operand:V4HI 0 "general_movdst_operand" "")
13737         (match_operand:V4HI 1 "general_movsrc_operand" ""))]
13738   "TARGET_SHMEDIA"
13740   prepare_move_operands (operands, V4HImode);
13743 (define_insn "movv4hi_i"
13744   [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
13745         (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13746   "TARGET_SHMEDIA
13747    && (register_operand (operands[0], V4HImode)
13748        || sh_register_operand (operands[1], V4HImode))"
13749   "@
13750         add     %1, r63, %0
13751         movi    %1, %0
13752         #
13753         ld%M1.q %m1, %0
13754         st%M0.q %m0, %N1"
13755   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
13756    (set_attr "length" "4,4,16,4,4")
13757    (set_attr "highpart" "depend")])
13759 (define_expand "movv2si"
13760   [(set (match_operand:V2SI 0 "general_movdst_operand" "")
13761         (match_operand:V2SI 1 "general_movsrc_operand" ""))]
13762   "TARGET_SHMEDIA"
13764   prepare_move_operands (operands, V2SImode);
13767 (define_insn "movv2si_i"
13768   [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
13769         (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13770   "TARGET_SHMEDIA
13771    && (register_operand (operands[0], V2SImode)
13772        || sh_register_operand (operands[1], V2SImode))"
13773   "@
13774         add     %1, r63, %0
13775         #
13776         #
13777         ld%M1.q %m1, %0
13778         st%M0.q %m0, %N1"
13779   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
13780    (set_attr "length" "4,4,16,4,4")
13781    (set_attr "highpart" "depend")])
13783 ;; Multimedia Intrinsics
13785 (define_insn "absv2si2"
13786   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13787         (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
13788   "TARGET_SHMEDIA"
13789   "mabs.l       %1, %0"
13790   [(set_attr "type" "mcmp_media")
13791    (set_attr "highpart" "depend")])
13793 (define_insn "absv4hi2"
13794   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13795         (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
13796   "TARGET_SHMEDIA"
13797   "mabs.w       %1, %0"
13798   [(set_attr "type" "mcmp_media")
13799    (set_attr "highpart" "depend")])
13801 (define_insn "addv2si3"
13802   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13803         (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
13804                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
13805   "TARGET_SHMEDIA"
13806   "madd.l       %1, %2, %0"
13807   [(set_attr "type" "arith_media")
13808    (set_attr "highpart" "depend")])
13810 (define_insn "addv4hi3"
13811   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13812         (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
13813                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
13814   "TARGET_SHMEDIA"
13815   "madd.w       %1, %2, %0"
13816   [(set_attr "type" "arith_media")
13817    (set_attr "highpart" "depend")])
13819 (define_insn_and_split "addv2hi3"
13820   [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
13821         (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
13822                    (match_operand:V2HI 2 "extend_reg_operand" "r")))]
13823   "TARGET_SHMEDIA"
13824   "#"
13825   "TARGET_SHMEDIA"
13826   [(const_int 0)]
13828   rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
13829   rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
13830   rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
13831   rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
13832   rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
13834   emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
13835   emit_insn (gen_truncdisi2 (si_dst, di_dst));
13836   DONE;
13838   [(set_attr "highpart" "must_split")])
13840 (define_insn "ssaddv2si3"
13841   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13842         (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
13843                       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
13844   "TARGET_SHMEDIA"
13845   "madds.l      %1, %2, %0"
13846   [(set_attr "type" "mcmp_media")
13847    (set_attr "highpart" "depend")])
13849 (define_insn "usaddv8qi3"
13850   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13851         (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
13852                       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
13853   "TARGET_SHMEDIA"
13854   "madds.ub     %1, %2, %0"
13855   [(set_attr "type" "mcmp_media")
13856    (set_attr "highpart" "depend")])
13858 (define_insn "ssaddv4hi3"
13859   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13860         (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
13861                       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
13862   "TARGET_SHMEDIA"
13863   "madds.w      %1, %2, %0"
13864   [(set_attr "type" "mcmp_media")
13865    (set_attr "highpart" "depend")])
13867 (define_insn "negcmpeqv8qi"
13868   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13869         (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
13870                            (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
13871   "TARGET_SHMEDIA"
13872   "mcmpeq.b     %N1, %N2, %0"
13873   [(set_attr "type" "mcmp_media")
13874    (set_attr "highpart" "depend")])
13876 (define_insn "negcmpeqv2si"
13877   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13878         (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
13879                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
13880   "TARGET_SHMEDIA"
13881   "mcmpeq.l     %N1, %N2, %0"
13882   [(set_attr "type" "mcmp_media")
13883    (set_attr "highpart" "depend")])
13885 (define_insn "negcmpeqv4hi"
13886   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13887         (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
13888                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
13889   "TARGET_SHMEDIA"
13890   "mcmpeq.w     %N1, %N2, %0"
13891   [(set_attr "type" "mcmp_media")
13892    (set_attr "highpart" "depend")])
13894 (define_insn "negcmpgtuv8qi"
13895   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13896         (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
13897                             (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
13898   "TARGET_SHMEDIA"
13899   "mcmpgt.ub    %N1, %N2, %0"
13900   [(set_attr "type" "mcmp_media")
13901    (set_attr "highpart" "depend")])
13903 (define_insn "negcmpgtv2si"
13904   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13905         (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
13906                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
13907   "TARGET_SHMEDIA"
13908   "mcmpgt.l     %N1, %N2, %0"
13909   [(set_attr "type" "mcmp_media")
13910    (set_attr "highpart" "depend")])
13912 (define_insn "negcmpgtv4hi"
13913   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13914         (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
13915                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
13916   "TARGET_SHMEDIA"
13917   "mcmpgt.w     %N1, %N2, %0"
13918   [(set_attr "type" "mcmp_media")
13919    (set_attr "highpart" "depend")])
13921 (define_insn "mcmv"
13922   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13923         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13924                         (match_operand:DI 2 "arith_reg_operand" "r"))
13925                 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
13926                         (not:DI (match_dup 2)))))]
13927   "TARGET_SHMEDIA"
13928   "mcmv %N1, %2, %0"
13929   [(set_attr "type" "arith_media")
13930    (set_attr "highpart" "depend")])
13932 (define_insn "mcnvs_lw"
13933   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13934         (vec_concat:V4HI
13935          (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
13936          (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
13937   "TARGET_SHMEDIA"
13938   "mcnvs.lw     %N1, %N2, %0"
13939   [(set_attr "type" "mcmp_media")])
13941 (define_insn "mcnvs_wb"
13942   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13943         (vec_concat:V8QI
13944          (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
13945          (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
13946   "TARGET_SHMEDIA"
13947   "mcnvs.wb     %N1, %N2, %0"
13948   [(set_attr "type" "mcmp_media")])
13950 (define_insn "mcnvs_wub"
13951   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13952         (vec_concat:V8QI
13953          (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
13954          (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
13955   "TARGET_SHMEDIA"
13956   "mcnvs.wub    %N1, %N2, %0"
13957   [(set_attr "type" "mcmp_media")])
13959 (define_insn "mextr_rl"
13960   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13961         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13962                              (match_operand:HI 3 "mextr_bit_offset" "i"))
13963                (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
13964                           (match_operand:HI 4 "mextr_bit_offset" "i"))))]
13965   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
13967   static char templ[21];
13968   sprintf (templ, "mextr%d      %%N1, %%N2, %%0",
13969            (int) INTVAL (operands[3]) >> 3);
13970   return templ;
13972   [(set_attr "type" "arith_media")])
13974 (define_insn "*mextr_lr"
13975   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13976         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13977                            (match_operand:HI 3 "mextr_bit_offset" "i"))
13978                (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
13979                             (match_operand:HI 4 "mextr_bit_offset" "i"))))]
13980   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
13982   static char templ[21];
13983   sprintf (templ, "mextr%d      %%N2, %%N1, %%0",
13984            (int) INTVAL (operands[4]) >> 3);
13985   return templ;
13987   [(set_attr "type" "arith_media")])
13989 ; mextrN can be modelled with vec_select / vec_concat, but the selection
13990 ; vector then varies depending on endianness.
13991 (define_expand "mextr1"
13992   [(match_operand:DI 0 "arith_reg_dest" "")
13993    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13994    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
13995   "TARGET_SHMEDIA"
13997   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
13998                            GEN_INT (1 * 8), GEN_INT (7 * 8)));
13999   DONE;
14002 (define_expand "mextr2"
14003   [(match_operand:DI 0 "arith_reg_dest" "")
14004    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14005    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14006   "TARGET_SHMEDIA"
14008   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14009                            GEN_INT (2 * 8), GEN_INT (6 * 8)));
14010   DONE;
14013 (define_expand "mextr3"
14014   [(match_operand:DI 0 "arith_reg_dest" "")
14015    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14016    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14017   "TARGET_SHMEDIA"
14019   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14020                            GEN_INT (3 * 8), GEN_INT (5 * 8)));
14021   DONE;
14024 (define_expand "mextr4"
14025   [(match_operand:DI 0 "arith_reg_dest" "")
14026    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14027    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14028   "TARGET_SHMEDIA"
14030   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14031                            GEN_INT (4 * 8), GEN_INT (4 * 8)));
14032   DONE;
14035 (define_expand "mextr5"
14036   [(match_operand:DI 0 "arith_reg_dest" "")
14037    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14038    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14039   "TARGET_SHMEDIA"
14041   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14042                            GEN_INT (5 * 8), GEN_INT (3 * 8)));
14043   DONE;
14046 (define_expand "mextr6"
14047   [(match_operand:DI 0 "arith_reg_dest" "")
14048    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14049    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14050   "TARGET_SHMEDIA"
14052   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14053                            GEN_INT (6 * 8), GEN_INT (2 * 8)));
14054   DONE;
14057 (define_expand "mextr7"
14058   [(match_operand:DI 0 "arith_reg_dest" "")
14059    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14060    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14061   "TARGET_SHMEDIA"
14063   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14064                            GEN_INT (7 * 8), GEN_INT (1 * 8)));
14065   DONE;
14068 (define_expand "mmacfx_wl"
14069   [(match_operand:V2SI 0 "arith_reg_dest" "")
14070    (match_operand:V2HI 1 "extend_reg_operand" "")
14071    (match_operand:V2HI 2 "extend_reg_operand" "")
14072    (match_operand:V2SI 3 "arith_reg_operand" "")]
14073   "TARGET_SHMEDIA"
14075   emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
14076                               operands[1], operands[2]));
14077   DONE;
14080 ;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
14081 ;; is depend
14082 (define_insn "mmacfx_wl_i"
14083   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14084         (ss_plus:V2SI
14085          (match_operand:V2SI 1 "arith_reg_operand" "0")
14086          (ss_truncate:V2SI
14087           (ashift:V2DI
14088            (sign_extend:V2DI
14089             (mult:V2SI
14090              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
14091              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
14092            (const_int 1)))))]
14093   "TARGET_SHMEDIA"
14094   "mmacfx.wl    %2, %3, %0"
14095   [(set_attr "type" "mac_media")
14096    (set_attr "highpart" "depend")])
14098 (define_expand "mmacnfx_wl"
14099   [(match_operand:V2SI 0 "arith_reg_dest" "")
14100    (match_operand:V2HI 1 "extend_reg_operand" "")
14101    (match_operand:V2HI 2 "extend_reg_operand" "")
14102    (match_operand:V2SI 3 "arith_reg_operand" "")]
14103   "TARGET_SHMEDIA"
14105   emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
14106                                operands[1], operands[2]));
14107   DONE;
14110 (define_insn "mmacnfx_wl_i"
14111   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14112         (ss_minus:V2SI
14113          (match_operand:V2SI 1 "arith_reg_operand" "0")
14114          (ss_truncate:V2SI
14115           (ashift:V2DI
14116            (sign_extend:V2DI
14117             (mult:V2SI
14118              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
14119              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
14120            (const_int 1)))))]
14121   "TARGET_SHMEDIA"
14122   "mmacnfx.wl   %2, %3, %0"
14123   [(set_attr "type" "mac_media")
14124    (set_attr "highpart" "depend")])
14126 (define_insn "mulv2si3"
14127   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14128         (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14129                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14130   "TARGET_SHMEDIA"
14131   "mmul.l       %1, %2, %0"
14132   [(set_attr "type" "d2mpy_media")
14133    (set_attr "highpart" "depend")])
14135 (define_insn "mulv4hi3"
14136   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14137         (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14138                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14139   "TARGET_SHMEDIA"
14140   "mmul.w       %1, %2, %0"
14141   [(set_attr "type" "dmpy_media")
14142    (set_attr "highpart" "depend")])
14144 (define_insn "mmulfx_l"
14145   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14146         (ss_truncate:V2SI
14147          (ashiftrt:V2DI
14148           (mult:V2DI
14149            (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14150            (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
14151           (const_int 31))))]
14152   "TARGET_SHMEDIA"
14153   "mmulfx.l     %1, %2, %0"
14154   [(set_attr "type" "d2mpy_media")
14155    (set_attr "highpart" "depend")])
14157 (define_insn "mmulfx_w"
14158   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14159         (ss_truncate:V4HI
14160          (ashiftrt:V4SI
14161           (mult:V4SI
14162            (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14163            (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14164           (const_int 15))))]
14165   "TARGET_SHMEDIA"
14166   "mmulfx.w     %1, %2, %0"
14167   [(set_attr "type" "dmpy_media")
14168    (set_attr "highpart" "depend")])
14170 (define_insn "mmulfxrp_w"
14171   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14172         (ss_truncate:V4HI
14173          (ashiftrt:V4SI
14174           (plus:V4SI
14175            (mult:V4SI
14176             (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14177             (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14178            (const_int 16384))
14179           (const_int 15))))]
14180   "TARGET_SHMEDIA"
14181   "mmulfxrp.w   %1, %2, %0"
14182   [(set_attr "type" "dmpy_media")
14183    (set_attr "highpart" "depend")])
14186 (define_expand "mmulhi_wl"
14187   [(match_operand:V2SI 0 "arith_reg_dest" "")
14188    (match_operand:V4HI 1 "arith_reg_operand" "")
14189    (match_operand:V4HI 2 "arith_reg_operand" "")]
14190   "TARGET_SHMEDIA"
14192   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
14193              (operands[0], operands[1], operands[2]));
14194   DONE;
14197 (define_expand "mmullo_wl"
14198   [(match_operand:V2SI 0 "arith_reg_dest" "")
14199    (match_operand:V4HI 1 "arith_reg_operand" "")
14200    (match_operand:V4HI 2 "arith_reg_operand" "")]
14201   "TARGET_SHMEDIA"
14203   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
14204              (operands[0], operands[1], operands[2]));
14205   DONE;
14208 (define_insn "mmul23_wl"
14209   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14210         (vec_select:V2SI
14211          (mult:V4SI
14212           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14213           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14214          (parallel [(const_int 2) (const_int 3)])))]
14215   "TARGET_SHMEDIA"
14217   return (TARGET_LITTLE_ENDIAN
14218           ? "mmulhi.wl  %1, %2, %0"
14219           : "mmullo.wl  %1, %2, %0");
14221   [(set_attr "type" "dmpy_media")
14222    (set (attr "highpart")
14223         (cond [(eq_attr "endian" "big") (const_string "ignore")]
14224          (const_string "user")))])
14226 (define_insn "mmul01_wl"
14227   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14228         (vec_select:V2SI
14229          (mult:V4SI
14230           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14231           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14232          (parallel [(const_int 0) (const_int 1)])))]
14233   "TARGET_SHMEDIA"
14235   return (TARGET_LITTLE_ENDIAN
14236           ? "mmullo.wl  %1, %2, %0"
14237           : "mmulhi.wl  %1, %2, %0");
14239   [(set_attr "type" "dmpy_media")
14240    (set (attr "highpart")
14241         (cond [(eq_attr "endian" "little") (const_string "ignore")]
14242          (const_string "user")))])
14245 (define_expand "mmulsum_wq"
14246   [(match_operand:DI 0 "arith_reg_dest" "")
14247    (match_operand:V4HI 1 "arith_reg_operand" "")
14248    (match_operand:V4HI 2 "arith_reg_operand" "")
14249    (match_operand:DI 3 "arith_reg_operand" "")]
14250   "TARGET_SHMEDIA"
14252   emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
14253                                operands[1], operands[2]));
14254   DONE;
14257 (define_insn "mmulsum_wq_i"
14258   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14259         (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
14260          (plus:DI
14261           (plus:DI
14262            (vec_select:DI
14263             (mult:V4DI
14264              (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
14265              (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
14266             (parallel [(const_int 0)]))
14267            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14268                                      (sign_extend:V4DI (match_dup 3)))
14269                           (parallel [(const_int 1)])))
14270           (plus:DI
14271            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14272                                      (sign_extend:V4DI (match_dup 3)))
14273                           (parallel [(const_int 2)]))
14274            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14275                                      (sign_extend:V4DI (match_dup 3)))
14276                           (parallel [(const_int 3)]))))))]
14277   "TARGET_SHMEDIA"
14278   "mmulsum.wq   %2, %3, %0"
14279   [(set_attr "type" "mac_media")])
14281 (define_expand "mperm_w"
14282   [(match_operand:V4HI 0 "arith_reg_dest" "=r")
14283    (match_operand:V4HI 1 "arith_reg_operand" "r")
14284    (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
14285   "TARGET_SHMEDIA"
14287   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
14288              (operands[0], operands[1], operands[2]));
14289   DONE;
14292 ; This use of vec_select isn't exactly correct according to rtl.texi
14293 ; (because not constant), but it seems a straightforward extension.
14294 (define_insn "mperm_w_little"
14295   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14296         (vec_select:V4HI
14297          (match_operand:V4HI 1 "arith_reg_operand" "r")
14298          (parallel
14299           [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
14300                             (const_int 2) (const_int 0))
14301            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
14302            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
14303            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
14304   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
14305   "mperm.w      %1, %N2, %0"
14306   [(set_attr "type" "arith_media")])
14308 (define_insn "mperm_w_big"
14309   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14310         (vec_select:V4HI
14311          (match_operand:V4HI 1 "arith_reg_operand" "r")
14312          (parallel
14313           [(zero_extract:QI (not:QI (match_operand:QI 2
14314                                      "extend_reg_or_0_operand" "rZ"))
14315                             (const_int 2) (const_int 0))
14316            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
14317            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
14318            (zero_extract:QI (not:QI (match_dup 2))
14319                             (const_int 2) (const_int 6))])))]
14320   "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
14321   "mperm.w      %1, %N2, %0"
14322   [(set_attr "type" "arith_media")])
14324 (define_insn "mperm_w0"
14325   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14326         (vec_duplicate:V4HI (truncate:HI (match_operand 1
14327                                           "trunc_hi_operand" "r"))))]
14328   "TARGET_SHMEDIA"
14329   "mperm.w      %1, r63, %0"
14330   [(set_attr "type" "arith_media")
14331    (set_attr "highpart" "ignore")])
14333 (define_expand "msad_ubq"
14334   [(match_operand:DI 0 "arith_reg_dest" "")
14335    (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
14336    (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
14337    (match_operand:DI 3 "arith_reg_operand" "")]
14338   "TARGET_SHMEDIA"
14340   emit_insn (gen_msad_ubq_i (operands[0], operands[3],
14341                              operands[1], operands[2]));
14342   DONE;
14345 (define_insn "msad_ubq_i"
14346   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14347         (plus:DI
14348          (plus:DI
14349           (plus:DI
14350            (plus:DI
14351             (match_operand:DI 1 "arith_reg_operand" "0")
14352             (abs:DI (vec_select:DI
14353                      (minus:V8DI
14354                       (zero_extend:V8DI
14355                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14356                       (zero_extend:V8DI
14357                        (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
14358                      (parallel [(const_int 0)]))))
14359            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14360                                               (zero_extend:V8DI (match_dup 3)))
14361                                   (parallel [(const_int 1)]))))
14362           (plus:DI
14363            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14364                                               (zero_extend:V8DI (match_dup 3)))
14365                                   (parallel [(const_int 2)])))
14366            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14367                                               (zero_extend:V8DI (match_dup 3)))
14368                                   (parallel [(const_int 3)])))))
14369          (plus:DI
14370           (plus:DI
14371            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14372                                               (zero_extend:V8DI (match_dup 3)))
14373                                   (parallel [(const_int 4)])))
14374            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14375                                               (zero_extend:V8DI (match_dup 3)))
14376                                   (parallel [(const_int 5)]))))
14377           (plus:DI
14378            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14379                                               (zero_extend:V8DI (match_dup 3)))
14380                                   (parallel [(const_int 6)])))
14381            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14382                                               (zero_extend:V8DI (match_dup 3)))
14383                                   (parallel [(const_int 7)])))))))]
14384   "TARGET_SHMEDIA"
14385   "msad.ubq     %N2, %N3, %0"
14386   [(set_attr "type" "mac_media")])
14388 (define_insn "mshalds_l"
14389   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14390         (ss_truncate:V2SI
14391          (ashift:V2DI
14392           (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14393           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14394                   (const_int 31)))))]
14395   "TARGET_SHMEDIA"
14396   "mshalds.l    %1, %2, %0"
14397   [(set_attr "type" "mcmp_media")
14398    (set_attr "highpart" "depend")])
14400 (define_insn "mshalds_w"
14401   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14402         (ss_truncate:V4HI
14403          (ashift:V4SI
14404           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14405           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14406                   (const_int 15)))))]
14407   "TARGET_SHMEDIA"
14408   "mshalds.w    %1, %2, %0"
14409   [(set_attr "type" "mcmp_media")
14410    (set_attr "highpart" "depend")])
14412 (define_insn "ashrv2si3"
14413   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14414         (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14415                        (match_operand:DI 2 "arith_reg_operand" "r")))]
14416   "TARGET_SHMEDIA"
14417   "mshard.l     %1, %2, %0"
14418   [(set_attr "type" "arith_media")
14419    (set_attr "highpart" "depend")])
14421 (define_insn "ashrv4hi3"
14422   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14423         (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14424                        (match_operand:DI 2 "arith_reg_operand" "r")))]
14425   "TARGET_SHMEDIA"
14426   "mshard.w     %1, %2, %0"
14427   [(set_attr "type" "arith_media")
14428    (set_attr "highpart" "depend")])
14430 (define_insn "mshards_q"
14431   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
14432         (ss_truncate:HI
14433          (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
14434                       (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
14435   "TARGET_SHMEDIA"
14436   "mshards.q    %1, %N2, %0"
14437   [(set_attr "type" "mcmp_media")])
14439 (define_expand "mshfhi_b"
14440   [(match_operand:V8QI 0 "arith_reg_dest" "")
14441    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14442    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
14443   "TARGET_SHMEDIA"
14445   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
14446              (operands[0], operands[1], operands[2]));
14447   DONE;
14450 (define_expand "mshflo_b"
14451   [(match_operand:V8QI 0 "arith_reg_dest" "")
14452    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14453    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
14454   "TARGET_SHMEDIA"
14456   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
14457              (operands[0], operands[1], operands[2]));
14458   DONE;
14461 (define_insn "mshf4_b"
14462   [(set
14463     (match_operand:V8QI 0 "arith_reg_dest" "=r")
14464     (vec_select:V8QI
14465      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14466                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14467      (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
14468                 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
14469   "TARGET_SHMEDIA"
14471   return (TARGET_LITTLE_ENDIAN
14472           ? "mshfhi.b   %N1, %N2, %0"
14473           : "mshflo.b   %N1, %N2, %0");
14475   [(set_attr "type" "arith_media")
14476    (set (attr "highpart")
14477         (cond [(eq_attr "endian" "big") (const_string "ignore")]
14478          (const_string "user")))])
14480 (define_insn "mshf0_b"
14481   [(set
14482     (match_operand:V8QI 0 "arith_reg_dest" "=r")
14483     (vec_select:V8QI
14484      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14485                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14486      (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
14487                 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
14488   "TARGET_SHMEDIA"
14490   return (TARGET_LITTLE_ENDIAN
14491           ? "mshflo.b   %N1, %N2, %0"
14492           : "mshfhi.b   %N1, %N2, %0");
14494   [(set_attr "type" "arith_media")
14495    (set (attr "highpart")
14496         (cond [(eq_attr "endian" "little") (const_string "ignore")]
14497          (const_string "user")))])
14499 (define_expand "mshfhi_l"
14500   [(match_operand:V2SI 0 "arith_reg_dest" "")
14501    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14502    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
14503   "TARGET_SHMEDIA"
14505   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
14506              (operands[0], operands[1], operands[2]));
14507   DONE;
14510 (define_expand "mshflo_l"
14511   [(match_operand:V2SI 0 "arith_reg_dest" "")
14512    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14513    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
14514   "TARGET_SHMEDIA"
14516   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
14517              (operands[0], operands[1], operands[2]));
14518   DONE;
14521 (define_insn "mshf4_l"
14522   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14523         (vec_select:V2SI
14524          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14525                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
14526          (parallel [(const_int 1) (const_int 3)])))]
14527   "TARGET_SHMEDIA"
14529   return (TARGET_LITTLE_ENDIAN
14530           ? "mshfhi.l   %N1, %N2, %0"
14531           : "mshflo.l   %N1, %N2, %0");
14533   [(set_attr "type" "arith_media")
14534    (set (attr "highpart")
14535         (cond [(eq_attr "endian" "big") (const_string "ignore")]
14536          (const_string "user")))])
14538 (define_insn "mshf0_l"
14539   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14540         (vec_select:V2SI
14541          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14542                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
14543          (parallel [(const_int 0) (const_int 2)])))]
14544   "TARGET_SHMEDIA"
14546   return (TARGET_LITTLE_ENDIAN
14547           ? "mshflo.l   %N1, %N2, %0"
14548           : "mshfhi.l   %N1, %N2, %0");
14550   [(set_attr "type" "arith_media")
14551    (set (attr "highpart")
14552         (cond [(eq_attr "endian" "little") (const_string "ignore")]
14553          (const_string "user")))])
14555 (define_expand "mshfhi_w"
14556   [(match_operand:V4HI 0 "arith_reg_dest" "")
14557    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14558    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
14559   "TARGET_SHMEDIA"
14561   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
14562              (operands[0], operands[1], operands[2]));
14563   DONE;
14566 (define_expand "mshflo_w"
14567   [(match_operand:V4HI 0 "arith_reg_dest" "")
14568    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14569    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
14570   "TARGET_SHMEDIA"
14572   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
14573              (operands[0], operands[1], operands[2]));
14574   DONE;
14577 (define_insn "mshf4_w"
14578   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14579         (vec_select:V4HI
14580          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14581                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
14582          (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
14583   "TARGET_SHMEDIA"
14585   return (TARGET_LITTLE_ENDIAN
14586           ? "mshfhi.w   %N1, %N2, %0"
14587           : "mshflo.w   %N1, %N2, %0");
14589   [(set_attr "type" "arith_media")
14590    (set (attr "highpart")
14591         (cond [(eq_attr "endian" "big") (const_string "ignore")]
14592          (const_string "user")))])
14594 (define_insn "mshf0_w"
14595   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14596         (vec_select:V4HI
14597          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14598                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
14599          (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
14600   "TARGET_SHMEDIA"
14602   return (TARGET_LITTLE_ENDIAN
14603           ? "mshflo.w   %N1, %N2, %0"
14604           : "mshfhi.w   %N1, %N2, %0");
14606   [(set_attr "type" "arith_media")
14607    (set (attr "highpart")
14608         (cond [(eq_attr "endian" "little") (const_string "ignore")]
14609          (const_string "user")))])
14611 (define_insn "mshflo_w_x"
14612   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14613         (vec_select:V4HI
14614          (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
14615                           (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
14616          (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
14617   "TARGET_SHMEDIA"
14618   "mshflo.w     %N1, %N2, %0"
14619   [(set_attr "type" "arith_media")
14620    (set_attr "highpart" "ignore")])
14622 ;; These are useful to expand ANDs and as combiner patterns.
14623 (define_insn_and_split "mshfhi_l_di"
14624   [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
14625         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
14626                              (const_int 32))
14627                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
14628                         (const_int -4294967296))))]
14629   "TARGET_SHMEDIA"
14630   "@
14631         mshfhi.l        %N1, %N2, %0
14632         #"
14633   "TARGET_SHMEDIA && reload_completed
14634    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
14635   [(set (match_dup 3) (match_dup 4))
14636    (set (match_dup 5) (match_dup 6))]
14638   operands[3] = gen_lowpart (SImode, operands[0]);
14639   operands[4] = gen_highpart (SImode, operands[1]);
14640   operands[5] = gen_highpart (SImode, operands[0]);
14641   operands[6] = gen_highpart (SImode, operands[2]);
14643   [(set_attr "type" "arith_media")])
14645 (define_insn "*mshfhi_l_di_rev"
14646   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14647         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14648                         (const_int -4294967296))
14649                 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14650                              (const_int 32))))]
14651   "TARGET_SHMEDIA"
14652   "mshfhi.l     %N2, %N1, %0"
14653   [(set_attr "type" "arith_media")])
14655 (define_split
14656   [(set (match_operand:DI 0 "arith_reg_dest" "")
14657         (ior:DI (zero_extend:DI (match_operand:SI 1
14658                                               "extend_reg_or_0_operand" ""))
14659                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
14660                         (const_int -4294967296))))
14661    (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
14662   "TARGET_SHMEDIA"
14663   [(const_int 0)]
14665   emit_insn (gen_ashldi3_media (operands[3],
14666                                 simplify_gen_subreg (DImode, operands[1],
14667                                                      SImode, 0),
14668                                 GEN_INT (32)));
14669   emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
14670   DONE;
14673 (define_insn "mshflo_l_di"
14674   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14675         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14676                         (const_int 4294967295))
14677                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14678                            (const_int 32))))]
14680   "TARGET_SHMEDIA"
14681   "mshflo.l     %N1, %N2, %0"
14682   [(set_attr "type" "arith_media")
14683    (set_attr "highpart" "ignore")])
14685 (define_insn "*mshflo_l_di_rev"
14686   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14687         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14688                            (const_int 32))
14689                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14690                         (const_int 4294967295))))]
14692   "TARGET_SHMEDIA"
14693   "mshflo.l     %N2, %N1, %0"
14694   [(set_attr "type" "arith_media")
14695    (set_attr "highpart" "ignore")])
14697 ;; Combiner pattern for trampoline initialization.
14698 (define_insn_and_split "*double_shori"
14699   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14700         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
14701                            (const_int 32))
14702                 (match_operand:DI 2 "const_int_operand" "n")))]
14703   "TARGET_SHMEDIA
14704    && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
14705   "#"
14706   "rtx_equal_p (operands[0], operands[1])"
14707   [(const_int 0)]
14709   HOST_WIDE_INT v = INTVAL (operands[2]);
14711   emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
14712   emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
14713   DONE;
14715   [(set_attr "highpart" "ignore")])
14718 (define_insn "*mshflo_l_di_x"
14719   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14720         (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
14721                                  "rZ"))
14722                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14723                            (const_int 32))))]
14725   "TARGET_SHMEDIA"
14726   "mshflo.l     %N1, %N2, %0"
14727   [(set_attr "type" "arith_media")
14728    (set_attr "highpart" "ignore")])
14730 (define_insn_and_split "concat_v2sf"
14731   [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
14732 ;;      (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
14733         (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
14734                          (match_operand:SF 2 "register_operand" "rZ,f,f")))]
14736   "TARGET_SHMEDIA"
14737   "@
14738         mshflo.l        %N1, %N2, %0
14739         #
14740         #"
14741   "TARGET_SHMEDIA && reload_completed
14742    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
14743   [(set (match_dup 3) (match_dup 1))
14744    (set (match_dup 4) (match_dup 2))]
14746   operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
14747   operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
14749   [(set_attr "type" "arith_media")
14750    (set_attr "highpart" "ignore")])
14752 (define_insn "*mshflo_l_di_x_rev"
14753   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14754         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14755                            (const_int 32))
14756                 (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
14758   "TARGET_SHMEDIA"
14759   "mshflo.l     %N2, %N1, %0"
14760   [(set_attr "type" "arith_media")
14761    (set_attr "highpart" "ignore")])
14763 (define_insn "ashlv2si3"
14764   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14765         (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14766                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
14767   "TARGET_SHMEDIA"
14768   "mshlld.l     %1, %2, %0"
14769   [(set_attr "type" "arith_media")
14770    (set_attr "highpart" "depend")])
14772 (define_split
14773   [(set (match_operand 0 "any_register_operand" "")
14774         (match_operator 3 "shift_operator"
14775           [(match_operand 1 "any_register_operand" "")
14776            (match_operand 2 "shift_count_reg_operand" "")]))]
14777   "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
14778   [(set (match_dup 0) (match_dup 3))]
14780   rtx count = operands[2];
14781   enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
14783   while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
14784          || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
14785          || GET_CODE (count) == TRUNCATE)
14786     count = XEXP (count, 0);
14787   inner_mode = GET_MODE (count);
14788   count = simplify_gen_subreg (outer_mode, count, inner_mode,
14789                                subreg_lowpart_offset (outer_mode, inner_mode));
14790   operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
14791                                 operands[1], count);
14794 (define_insn "ashlv4hi3"
14795   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14796         (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14797                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
14798   "TARGET_SHMEDIA"
14799   "mshlld.w     %1, %2, %0"
14800   [(set_attr "type" "arith_media")
14801    (set_attr "highpart" "depend")])
14803 (define_insn "lshrv2si3"
14804   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14805         (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14806                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
14807   "TARGET_SHMEDIA"
14808   "mshlrd.l     %1, %2, %0"
14809   [(set_attr "type" "arith_media")
14810    (set_attr "highpart" "depend")])
14812 (define_insn "lshrv4hi3"
14813   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14814         (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14815                        (match_operand:DI 2 "shift_count_reg_operand" "r")))]
14816   "TARGET_SHMEDIA"
14817   "mshlrd.w     %1, %2, %0"
14818   [(set_attr "type" "arith_media")
14819    (set_attr "highpart" "depend")])
14821 (define_insn "subv2si3"
14822   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14823         (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14824                     (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14825   "TARGET_SHMEDIA"
14826   "msub.l       %N1, %2, %0"
14827   [(set_attr "type" "arith_media")
14828    (set_attr "highpart" "depend")])
14830 (define_insn "subv4hi3"
14831   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14832         (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14833                     (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14834   "TARGET_SHMEDIA"
14835   "msub.w       %N1, %2, %0"
14836   [(set_attr "type" "arith_media")
14837    (set_attr "highpart" "depend")])
14839 (define_insn_and_split "subv2hi3"
14840   [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
14841         (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
14842                    (match_operand:V2HI 2 "arith_reg_operand" "r")))]
14843   "TARGET_SHMEDIA"
14844   "#"
14845   "TARGET_SHMEDIA"
14846   [(const_int 0)]
14848   rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
14849   rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
14850   rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
14851   rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
14852   rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
14854   emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
14855   emit_insn (gen_truncdisi2 (si_dst, di_dst));
14856   DONE;
14858   [(set_attr "highpart" "must_split")])
14860 (define_insn "sssubv2si3"
14861   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14862         (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14863                        (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14864   "TARGET_SHMEDIA"
14865   "msubs.l      %N1, %2, %0"
14866   [(set_attr "type" "mcmp_media")
14867    (set_attr "highpart" "depend")])
14869 (define_insn "ussubv8qi3"
14870   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14871         (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14872                        (match_operand:V8QI 2 "arith_reg_operand" "r")))]
14873   "TARGET_SHMEDIA"
14874   "msubs.ub     %N1, %2, %0"
14875   [(set_attr "type" "mcmp_media")
14876    (set_attr "highpart" "depend")])
14878 (define_insn "sssubv4hi3"
14879   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14880         (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14881                        (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14882   "TARGET_SHMEDIA"
14883   "msubs.w      %N1, %2, %0"
14884   [(set_attr "type" "mcmp_media")
14885    (set_attr "highpart" "depend")])
14887 ;; Floating Point Intrinsics
14889 (define_insn "fcosa_s"
14890   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14891         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
14892                    UNSPEC_FCOSA))]
14893   "TARGET_SHMEDIA"
14894   "fcosa.s      %1, %0"
14895   [(set_attr "type" "atrans_media")])
14897 (define_insn "fsina_s"
14898   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14899         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
14900                    UNSPEC_FSINA))]
14901   "TARGET_SHMEDIA"
14902   "fsina.s      %1, %0"
14903   [(set_attr "type" "atrans_media")])
14905 (define_insn "fipr"
14906   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14907         (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
14908                                                     "fp_arith_reg_operand" "f")
14909                                                    (match_operand:V4SF 2
14910                                                     "fp_arith_reg_operand" "f"))
14911                                          (parallel [(const_int 0)]))
14912                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
14913                                          (parallel [(const_int 1)])))
14914                  (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
14915                                          (parallel [(const_int 2)]))
14916                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
14917                                          (parallel [(const_int 3)])))))]
14918   "TARGET_SHMEDIA"
14919   "fipr.s       %1, %2, %0"
14920   [(set_attr "type" "fparith_media")])
14922 (define_insn "fsrra_s"
14923   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14924         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
14925                    UNSPEC_FSRRA))]
14926   "TARGET_SHMEDIA"
14927   "fsrra.s      %1, %0"
14928   [(set_attr "type" "atrans_media")])
14930 (define_insn "ftrv"
14931   [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
14932         (plus:V4SF
14933          (plus:V4SF
14934           (mult:V4SF
14935            (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
14936                             (parallel [(const_int 0) (const_int 5)
14937                                        (const_int 10) (const_int 15)]))
14938            (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
14939           (mult:V4SF
14940            (vec_select:V4SF (match_dup 1)
14941                             (parallel [(const_int 4) (const_int 9)
14942                                        (const_int 14) (const_int 3)]))
14943            (vec_select:V4SF (match_dup 2)
14944                             (parallel [(const_int 1) (const_int 2)
14945                                        (const_int 3) (const_int 0)]))))
14946          (plus:V4SF
14947           (mult:V4SF
14948            (vec_select:V4SF (match_dup 1)
14949                             (parallel [(const_int 8) (const_int 13)
14950                                        (const_int 2) (const_int 7)]))
14951            (vec_select:V4SF (match_dup 2)
14952                             (parallel [(const_int 2) (const_int 3)
14953                                        (const_int 0) (const_int 1)])))
14954           (mult:V4SF
14955            (vec_select:V4SF (match_dup 1)
14956                             (parallel [(const_int 12) (const_int 1)
14957                                        (const_int 6) (const_int 11)]))
14958            (vec_select:V4SF (match_dup 2)
14959                             (parallel [(const_int 3) (const_int 0)
14960                                        (const_int 1) (const_int 2)]))))))]
14961   "TARGET_SHMEDIA"
14962   "ftrv.s %1, %2, %0"
14963   [(set_attr "type" "fparith_media")])
14965 (define_insn "ldhi_l"
14966   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
14967         (zero_extract:SI
14968          (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
14969                                   (const_int 3))
14970                           (const_int -3)))
14971          (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
14972          (const_int 0)))]
14973   "TARGET_SHMEDIA32"
14974   "ldhi.l       %U1, %0"
14975   [(set_attr "type" "load_media")])
14977 (define_insn "ldhi_q"
14978   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14979         (zero_extract:DI
14980          (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
14981                                   (const_int 7))
14982                           (const_int -7)))
14983          (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
14984          (const_int 0)))]
14985   "TARGET_SHMEDIA32"
14986   "ldhi.q       %U1, %0"
14987   [(set_attr "type" "load_media")])
14989 (define_insn_and_split "*ldhi_q_comb0"
14990   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14991         (zero_extract:DI
14992          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
14993                                             "register_operand" "r")
14994                                            (match_operand:SI 2
14995                                             "ua_offset" "I06"))
14996                                   (const_int 7))
14997                           (const_int -7)))
14998          (plus:SI (and:SI (match_dup 1) (const_int 7))
14999                   (const_int 1))
15000          (const_int 0)))]
15001   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
15002   "#"
15003   ""
15004   [(pc)]
15006   emit_insn (gen_ldhi_q (operands[0],
15007                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
15008   DONE;
15011 (define_insn_and_split "*ldhi_q_comb1"
15012   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15013         (zero_extract:DI
15014          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
15015                                             "register_operand" "r")
15016                                            (match_operand:SI 2
15017                                             "ua_offset" "I06"))
15018                                   (const_int 7))
15019                           (const_int -7)))
15020          (plus:SI (and:SI (plus:SI (match_dup 1)  (match_operand:SI 3
15021                                                    "ua_offset" "I06"))
15022                           (const_int 7))
15023                   (const_int 1))
15024          (const_int 0)))]
15025   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
15026    && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
15027   "#"
15028   ""
15029   [(pc)]
15031   emit_insn (gen_ldhi_q (operands[0],
15032                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
15033   DONE;
15036 (define_insn "ldlo_l"
15037   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15038         (zero_extract:SI
15039          (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
15040                          (const_int -4)))
15041          (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
15042          (and:SI (match_dup 1) (const_int 3))))]
15043   "TARGET_SHMEDIA32"
15044   "ldlo.l       %U1, %0"
15045   [(set_attr "type" "load_media")])
15047 (define_insn "ldlo_q"
15048   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15049         (zero_extract:DI
15050          (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
15051                          (const_int -8)))
15052          (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
15053          (and:SI (match_dup 1) (const_int 7))))]
15054   "TARGET_SHMEDIA32"
15055   "ldlo.q       %U1, %0"
15056   [(set_attr "type" "load_media")])
15058 (define_insn_and_split "*ldlo_q_comb0"
15059   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15060         (zero_extract:DI
15061          (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
15062                                   (match_operand:SI 2 "ua_offset" "I06"))
15063                          (const_int -8)))
15064          (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
15065          (and:SI (match_dup 1) (const_int 7))))]
15066   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
15067   "#"
15068   ""
15069   [(pc)]
15071   emit_insn (gen_ldlo_q (operands[0],
15072                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
15073   DONE;
15076 (define_insn_and_split "*ldlo_q_comb1"
15077   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15078         (zero_extract:DI
15079          (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
15080                                   (match_operand:SI 2 "ua_offset" "I06"))
15081                          (const_int -8)))
15082          (minus:SI (const_int 8)
15083                    (and:SI (plus:SI (match_dup 1)
15084                                     (match_operand:SI 3 "ua_offset" "I06"))
15085                            (const_int 7)))
15086          (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
15087   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
15088    && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
15089   "#"
15090   ""
15091   [(pc)]
15093   emit_insn (gen_ldlo_q (operands[0],
15094                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
15095   DONE;
15098 (define_insn "sthi_l"
15099   [(set (zero_extract:SI
15100          (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
15101                                   (const_int 3))
15102                           (const_int -3)))
15103          (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
15104          (const_int 0))
15105         (match_operand:SI 1 "arith_reg_operand" "r"))]
15106   "TARGET_SHMEDIA32"
15107   "sthi.l       %U0, %1"
15108   [(set_attr "type" "ustore_media")])
15110 ;; All unaligned stores are considered to be 'narrow' because they typically
15111 ;; operate on less that a quadword, and when they operate on a full quadword,
15112 ;; the vanilla store high / store low sequence will cause a stall if not
15113 ;; scheduled apart.
15114 (define_insn "sthi_q"
15115   [(set (zero_extract:DI
15116          (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
15117                                   (const_int 7))
15118                           (const_int -7)))
15119          (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
15120          (const_int 0))
15121         (match_operand:DI 1 "arith_reg_operand" "r"))]
15122   "TARGET_SHMEDIA32"
15123   "sthi.q       %U0, %1"
15124   [(set_attr "type" "ustore_media")])
15126 (define_insn_and_split "*sthi_q_comb0"
15127   [(set (zero_extract:DI
15128          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
15129                                             "register_operand" "r")
15130                                            (match_operand:SI 1 "ua_offset"
15131                                             "I06"))
15132                                   (const_int 7))
15133                           (const_int -7)))
15134          (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
15135          (const_int 0))
15136         (match_operand:DI 2 "arith_reg_operand" "r"))]
15137   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15138   "#"
15139   ""
15140   [(pc)]
15142   emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15143                          operands[2]));
15144   DONE;
15147 (define_insn_and_split "*sthi_q_comb1"
15148   [(set (zero_extract:DI
15149          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
15150                                             "register_operand" "r")
15151                                            (match_operand:SI 1 "ua_offset"
15152                                             "I06"))
15153                                   (const_int 7))
15154                           (const_int -7)))
15155          (plus:SI (and:SI (plus:SI (match_dup 0)
15156                                    (match_operand:SI 2 "ua_offset" "I06"))
15157                           (const_int 7))
15158                   (const_int 1))
15159          (const_int 0))
15160         (match_operand:DI 3 "arith_reg_operand" "r"))]
15161   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
15162    && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15163   "#"
15164   ""
15165   [(pc)]
15167   emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15168                          operands[3]));
15169   DONE;
15172 ;; This is highpart user because the address is used as full 64 bit.
15173 (define_insn "stlo_l"
15174   [(set (zero_extract:SI
15175          (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
15176                          (const_int -4)))
15177          (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
15178          (and:SI (match_dup 0) (const_int 3)))
15179         (match_operand:SI 1 "arith_reg_operand" "r"))]
15180   "TARGET_SHMEDIA32"
15181   "stlo.l       %U0, %1"
15182   [(set_attr "type" "ustore_media")])
15184 (define_insn "stlo_q"
15185   [(set (zero_extract:DI
15186          (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
15187                          (const_int -8)))
15188          (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
15189          (and:SI (match_dup 0) (const_int 7)))
15190         (match_operand:DI 1 "arith_reg_operand" "r"))]
15191   "TARGET_SHMEDIA32"
15192   "stlo.q       %U0, %1"
15193   [(set_attr "type" "ustore_media")])
15195 (define_insn_and_split "*stlo_q_comb0"
15196   [(set (zero_extract:DI
15197          (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15198                                   (match_operand:SI 1 "ua_offset" "I06"))
15199                          (const_int -8)))
15200          (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
15201          (and:SI (match_dup 0) (const_int 7)))
15202         (match_operand:DI 2 "arith_reg_operand" "r"))]
15203   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15204   "#"
15205   ""
15206   [(pc)]
15208   emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15209                          operands[2]));
15210   DONE;
15213 (define_insn_and_split "*stlo_q_comb1"
15214   [(set (zero_extract:DI
15215          (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15216                                   (match_operand:SI 1 "ua_offset" "I06"))
15217                          (const_int -8)))
15218          (minus:SI (const_int 8) (and:SI (plus:SI (match_dup 0)
15219                                                   (match_operand:SI 2
15220                                                    "ua_offset" "I06"))
15221                                          (const_int 7)))
15222          (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
15223         (match_operand:DI 3 "arith_reg_operand" "r"))]
15224   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15225   "#"
15226   ""
15227   [(pc)]
15229   emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15230                          operands[3]));
15231    DONE;
15234 (define_insn "ldhi_l64"
15235   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15236         (zero_extract:SI
15237          (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15238                                   (const_int 3))
15239                           (const_int -3)))
15240          (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
15241          (const_int 0)))]
15242   "TARGET_SHMEDIA64"
15243   "ldhi.l       %U1, %0"
15244   [(set_attr "type" "load_media")])
15246 (define_insn "ldhi_q64"
15247   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15248         (zero_extract:DI
15249          (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15250                                   (const_int 7))
15251                           (const_int -7)))
15252          (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
15253          (const_int 0)))]
15254   "TARGET_SHMEDIA64"
15255   "ldhi.q       %U1, %0"
15256   [(set_attr "type" "load_media")])
15258 (define_insn "ldlo_l64"
15259   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15260         (zero_extract:SI
15261          (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15262                          (const_int -4)))
15263          (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
15264          (and:DI (match_dup 1) (const_int 3))))]
15265   "TARGET_SHMEDIA64"
15266   "ldlo.l       %U1, %0"
15267   [(set_attr "type" "load_media")])
15269 (define_insn "ldlo_q64"
15270   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15271         (zero_extract:DI
15272          (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15273                          (const_int -8)))
15274          (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
15275          (and:DI (match_dup 1) (const_int 7))))]
15276   "TARGET_SHMEDIA64"
15277   "ldlo.q       %U1, %0"
15278   [(set_attr "type" "load_media")])
15280 (define_insn "sthi_l64"
15281   [(set (zero_extract:SI
15282          (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15283                                   (const_int 3))
15284                           (const_int -3)))
15285          (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
15286          (const_int 0))
15287         (match_operand:SI 1 "arith_reg_operand" "r"))]
15288   "TARGET_SHMEDIA64"
15289   "sthi.l       %U0, %1"
15290   [(set_attr "type" "ustore_media")])
15292 (define_insn "sthi_q64"
15293   [(set (zero_extract:DI
15294          (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15295                                   (const_int 7))
15296                           (const_int -7)))
15297          (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
15298          (const_int 0))
15299         (match_operand:DI 1 "arith_reg_operand" "r"))]
15300   "TARGET_SHMEDIA64"
15301   "sthi.q       %U0, %1"
15302   [(set_attr "type" "ustore_media")])
15304 (define_insn "stlo_l64"
15305   [(set (zero_extract:SI
15306          (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15307                          (const_int -4)))
15308          (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
15309          (and:DI (match_dup 0) (const_int 3)))
15310         (match_operand:SI 1 "arith_reg_operand" "r"))]
15311   "TARGET_SHMEDIA64"
15312   "stlo.l       %U0, %1"
15313   [(set_attr "type" "ustore_media")])
15315 (define_insn "stlo_q64"
15316   [(set (zero_extract:DI
15317          (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15318                          (const_int -8)))
15319          (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
15320          (and:DI (match_dup 0) (const_int 7)))
15321         (match_operand:DI 1 "arith_reg_operand" "r"))]
15322   "TARGET_SHMEDIA64"
15323   "stlo.q       %U0, %1"
15324   [(set_attr "type" "ustore_media")])
15326 (define_insn "nsb"
15327   [(set (match_operand:QI 0 "arith_reg_dest" "=r")
15328         (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15329                    UNSPEC_NSB))]
15330   "TARGET_SHMEDIA"
15331   "nsb  %1, %0"
15332   [(set_attr "type" "arith_media")])
15334 (define_insn "nsbsi"
15335   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15336         (zero_extend:SI
15337          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15338                     UNSPEC_NSB)))]
15339   "TARGET_SHMEDIA"
15340   "nsb  %1, %0"
15341   [(set_attr "type" "arith_media")])
15343 (define_insn "nsbdi"
15344   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15345         (zero_extend:DI
15346          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15347                     UNSPEC_NSB)))]
15348   "TARGET_SHMEDIA"
15349   "nsb  %1, %0"
15350   [(set_attr "type" "arith_media")])
15352 (define_expand "ffsdi2"
15353   [(set (match_operand:DI 0 "arith_reg_dest" "")
15354         (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
15355   "TARGET_SHMEDIA"
15357   rtx scratch = gen_reg_rtx (DImode);
15358   rtx last;
15360   emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
15361   emit_insn (gen_xordi3 (scratch, operands[1], scratch));
15362   emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
15363   emit_insn (gen_nsbdi (scratch, scratch));
15364   emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
15365   emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
15366   last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
15367   set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
15369   DONE;
15372 (define_expand "ffssi2"
15373   [(set (match_operand:SI 0 "arith_reg_dest" "")
15374         (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
15375   "TARGET_SHMEDIA"
15377   rtx scratch = gen_reg_rtx (SImode);
15378   rtx discratch = gen_reg_rtx (DImode);
15379   rtx last;
15381   emit_insn (gen_adddi3 (discratch,
15382                          simplify_gen_subreg (DImode, operands[1], SImode, 0),
15383                          constm1_rtx));
15384   emit_insn (gen_andcdi3 (discratch,
15385                           simplify_gen_subreg (DImode, operands[1], SImode, 0),
15386                           discratch));
15387   emit_insn (gen_nsbsi (scratch, discratch));
15388   last = emit_insn (gen_subsi3 (operands[0],
15389                                 force_reg (SImode, GEN_INT (63)), scratch));
15390   set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
15392   DONE;
15395 (define_insn "byterev"
15396   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15397         (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
15398                          (parallel [(const_int 7) (const_int 6) (const_int 5)
15399                                     (const_int 4) (const_int 3) (const_int 2)
15400                                     (const_int 1) (const_int 0)])))]
15401   "TARGET_SHMEDIA"
15402   "byterev      %1, %0"
15403   [(set_attr "type" "arith_media")])
15405 ;; In user mode, the "pref" instruction will raise a RADDERR exception
15406 ;; for accesses to [0x80000000,0xffffffff].  This makes it an unsuitable
15407 ;; implementation of __builtin_prefetch for VxWorks RTPs.
15408 (define_expand "prefetch"
15409   [(prefetch (match_operand 0 "address_operand" "")
15410              (match_operand:SI 1 "const_int_operand" "")
15411              (match_operand:SI 2 "const_int_operand" ""))]
15412   "(TARGET_SH2A || TARGET_SH3 || TARGET_SH5)
15413    && (TARGET_SHMEDIA || ! TARGET_VXWORKS_RTP)")
15415 (define_insn "*prefetch"
15416   [(prefetch (match_operand:SI 0 "register_operand" "r")
15417              (match_operand:SI 1 "const_int_operand" "n")
15418              (match_operand:SI 2 "const_int_operand" "n"))]
15419   "(TARGET_SH2A || TARGET_SH3 || TARGET_SHCOMPACT) && ! TARGET_VXWORKS_RTP"
15420   "pref @%0"
15421   [(set_attr "type" "other")])
15423 (define_insn "*prefetch_media"
15424   [(prefetch (match_operand:QI 0 "address_operand" "p")
15425              (match_operand:SI 1 "const_int_operand" "n")
15426              (match_operand:SI 2 "const_int_operand" "n"))]
15427   "TARGET_SHMEDIA"
15429   operands[0] = gen_rtx_MEM (QImode, operands[0]);
15430   output_asm_insn ("ld%M0.b    %m0,r63", operands);
15431   return "";
15433   [(set_attr "type" "other")])
15435 (define_insn "alloco_i"
15436   [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
15437         (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
15438   "TARGET_SHMEDIA32"
15440   rtx xops[2];
15442   if (GET_CODE (operands[0]) == PLUS)
15443     {
15444       xops[0] = XEXP (operands[0], 0);
15445       xops[1] = XEXP (operands[0], 1);
15446     }
15447   else
15448     {
15449       xops[0] = operands[0];
15450       xops[1] = const0_rtx;
15451     }
15452   output_asm_insn ("alloco   %0, %1", xops);
15453   return "";
15455   [(set_attr "type" "other")])
15457 (define_split
15458   [(set (match_operand 0 "any_register_operand" "")
15459         (match_operand 1 "" ""))]
15460   "TARGET_SHMEDIA && reload_completed"
15461   [(set (match_dup 0) (match_dup 1))]
15463   int n_changes = 0;
15465   for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
15466   if (!n_changes)
15467     FAIL;
15470 ; Stack Protector Patterns
15472 (define_expand "stack_protect_set"
15473   [(set (match_operand 0 "memory_operand" "")
15474         (match_operand 1 "memory_operand" ""))]
15475   ""
15477   if (TARGET_SHMEDIA)
15478     {
15479       if (TARGET_SHMEDIA64)
15480         emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
15481       else
15482         emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
15483     }
15484   else
15485     emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
15487   DONE;
15490 (define_insn "stack_protect_set_si"
15491   [(set (match_operand:SI 0 "memory_operand" "=m")
15492         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15493    (set (match_scratch:SI 2 "=&r") (const_int 0))]
15494   "!TARGET_SHMEDIA"
15496   return       "mov.l   %1,%2"  "\n"
15497          "      mov.l   %2,%0"  "\n"
15498          "      mov     #0,%2";
15500   [(set_attr "type" "other")
15501    (set_attr "length" "6")])
15503 (define_insn "stack_protect_set_si_media"
15504   [(set (match_operand:SI 0 "memory_operand" "=m")
15505         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15506    (set (match_scratch:SI 2 "=&r") (const_int 0))]
15507   "TARGET_SHMEDIA"
15509   return       "ld%M1.l %m1,%2" "\n"
15510          "      st%M0.l %m0,%2" "\n"
15511          "      movi    0,%2";
15513   [(set_attr "type" "other")
15514    (set_attr "length" "12")])
15516 (define_insn "stack_protect_set_di_media"
15517   [(set (match_operand:DI 0 "memory_operand" "=m")
15518         (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15519    (set (match_scratch:DI 2 "=&r") (const_int 0))]
15520   "TARGET_SHMEDIA64"
15522   return       "ld%M1.q %m1,%2" "\n"
15523          "      st%M0.q %m0,%2" "\n"
15524          "      movi    0,%2";
15526   [(set_attr "type" "other")
15527    (set_attr "length" "12")])
15529 (define_expand "stack_protect_test"
15530   [(match_operand 0 "memory_operand" "")
15531    (match_operand 1 "memory_operand" "")
15532    (match_operand 2 "" "")]
15533   ""
15535   if (TARGET_SHMEDIA)
15536     {
15537       rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
15538       rtx test;
15540       test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
15541       if (TARGET_SHMEDIA64)
15542         {
15543           emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
15544                                                       operands[1]));
15545           emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
15546         }
15547       else
15548         {
15549           emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
15550                                                       operands[1]));
15551           emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
15552         }
15553     }
15554   else
15555     {
15556       emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
15557       emit_jump_insn (gen_branch_true (operands[2]));
15558     }
15560   DONE;
15563 (define_insn "stack_protect_test_si"
15564   [(set (reg:SI T_REG)
15565         (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
15566                     (match_operand:SI 1 "memory_operand" "m")]
15567                    UNSPEC_SP_TEST))
15568   (set (match_scratch:SI 2 "=&r") (const_int 0))
15569   (set (match_scratch:SI 3 "=&r") (const_int 0))]
15570   "!TARGET_SHMEDIA"
15572   return       "mov.l   %0,%2"  "\n"
15573          "      mov.l   %1,%3"  "\n"
15574          "      cmp/eq  %2,%3"  "\n"
15575          "      mov     #0,%2"  "\n"
15576          "      mov     #0,%3";
15578   [(set_attr "type" "other")
15579    (set_attr "length" "10")])
15581 (define_insn "stack_protect_test_si_media"
15582   [(set (match_operand:SI 0 "register_operand" "=&r")
15583         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
15584                     (match_operand:SI 2 "memory_operand" "m")]
15585                    UNSPEC_SP_TEST))
15586   (set (match_scratch:SI 3 "=&r") (const_int 0))]
15587   "TARGET_SHMEDIA"
15589   return       "ld%M1.l %m1,%0"         "\n"
15590          "      ld%M2.l %m2,%3"         "\n"
15591          "      cmpeq   %0,%3,%0"       "\n"
15592          "      movi    0,%3";
15594   [(set_attr "type" "other")
15595    (set_attr "length" "16")])
15597 (define_insn "stack_protect_test_di_media"
15598   [(set (match_operand:DI 0 "register_operand" "=&r")
15599         (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
15600                     (match_operand:DI 2 "memory_operand" "m")]
15601                    UNSPEC_SP_TEST))
15602   (set (match_scratch:DI 3 "=&r") (const_int 0))]
15603   "TARGET_SHMEDIA64"
15605   return       "ld%M1.q %m1,%0"         "\n"
15606          "      ld%M2.q %m2,%3"         "\n"
15607          "      cmpeq   %0,%3,%0"       "\n"
15608          "      movi    0,%3";
15610   [(set_attr "type" "other")
15611    (set_attr "length" "16")])
15613 (include "sync.md")