OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [config/] [sh/] [sh.md] - Blame information for rev 816

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
;;- 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 Free Software Foundation, Inc.
4
;;  Contributed by Steve Chamberlain (sac@cygnus.com).
5
;;  Improved by Jim Wilson (wilson@cygnus.com).
6
 
7
;; This file is part of GCC.
8
 
9
;; GCC is free software; you can redistribute it and/or modify
10
;; it under the terms of the GNU General Public License as published by
11
;; the Free Software Foundation; either version 3, or (at your option)
12
;; any later version.
13
 
14
;; GCC is distributed in the hope that it will be useful,
15
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
;; GNU General Public License for more details.
18
 
19
;; You should have received a copy of the GNU General Public License
20
;; along with GCC; see the file COPYING3.  If not see
21
;; .
22
 
23
 
24
;; ??? Should prepend a * to all pattern names which are not used.
25
;; This will make the compiler smaller, and rebuilds after changes faster.
26
 
27
;; ??? Should be enhanced to include support for many more GNU superoptimizer
28
;; sequences.  Especially the sequences for arithmetic right shifts.
29
 
30
;; ??? Should check all DImode patterns for consistency and usefulness.
31
 
32
;; ??? The MAC.W and MAC.L instructions are not supported.  There is no
33
;; way to generate them.
34
 
35
;; ??? The cmp/str instruction is not supported.  Perhaps it can be used
36
;; for a str* inline function.
37
 
38
;; BSR is not generated by the compiler proper, but when relaxing, it
39
;; generates .uses pseudo-ops that allow linker relaxation to create
40
;; BSR.  This is actually implemented in bfd/{coff,elf32}-sh.c
41
 
42
;; Special constraints for SH machine description:
43
;;
44
;;    t -- T
45
;;    x -- mac
46
;;    l -- pr
47
;;    z -- r0
48
;;
49
;; Special formats used for outputting SH instructions:
50
;;
51
;;   %.  --  print a .s if insn needs delay slot
52
;;   %@  --  print rte/rts if is/isn't an interrupt function
53
;;   %#  --  output a nop if there is nothing to put in the delay slot
54
;;   %O  --  print a constant without the #
55
;;   %R  --  print the lsw reg of a double
56
;;   %S  --  print the msw reg of a double
57
;;   %T  --  print next word of a double REG or MEM
58
;;
59
;; Special predicates:
60
;;
61
;;  arith_operand          -- operand is valid source for arithmetic op
62
;;  arith_reg_operand      -- operand is valid register for arithmetic op
63
;;  general_movdst_operand -- operand is valid move destination
64
;;  general_movsrc_operand -- operand is valid move source
65
;;  logical_operand        -- operand is valid source for logical op
66
 
67
;; -------------------------------------------------------------------------
68
;; Constants
69
;; -------------------------------------------------------------------------
70
 
71
(define_constants [
72
  (AP_REG       145)
73
  (PR_REG       146)
74
  (T_REG        147)
75
  (GBR_REG      144)
76
  (MACH_REG     148)
77
  (MACL_REG     149)
78
  (FPUL_REG     150)
79
  (RAP_REG      152)
80
 
81
  (FPSCR_REG    151)
82
 
83
  (PIC_REG      12)
84
  (FP_REG       14)
85
  (SP_REG       15)
86
 
87
  (PR_MEDIA_REG 18)
88
  (T_MEDIA_REG  19)
89
 
90
  (R0_REG       0)
91
  (R1_REG       1)
92
  (R2_REG       2)
93
  (R3_REG       3)
94
  (R4_REG       4)
95
  (R5_REG       5)
96
  (R6_REG       6)
97
  (R7_REG       7)
98
  (R8_REG       8)
99
  (R9_REG       9)
100
  (R10_REG      10)
101
  (R20_REG      20)
102
  (R21_REG      21)
103
  (R22_REG      22)
104
  (R23_REG      23)
105
 
106
  (DR0_REG      64)
107
  (DR2_REG      66)
108
  (DR4_REG      68)
109
  (FR23_REG     87)
110
 
111
  (TR0_REG      128)
112
  (TR1_REG      129)
113
  (TR2_REG      130)
114
 
115
  (XD0_REG      136)
116
 
117
  ;; These are used with unspec.
118
  (UNSPEC_COMPACT_ARGS  0)
119
  (UNSPEC_MOVA          1)
120
  (UNSPEC_CASESI        2)
121
  (UNSPEC_DATALABEL     3)
122
  (UNSPEC_BBR           4)
123
  (UNSPEC_SFUNC         5)
124
  (UNSPEC_PIC           6)
125
  (UNSPEC_GOT           7)
126
  (UNSPEC_GOTOFF        8)
127
  (UNSPEC_PLT           9)
128
  (UNSPEC_CALLER        10)
129
  (UNSPEC_GOTPLT        11)
130
  (UNSPEC_ICACHE        12)
131
  (UNSPEC_INIT_TRAMP    13)
132
  (UNSPEC_FCOSA         14)
133
  (UNSPEC_FSRRA         15)
134
  (UNSPEC_FSINA         16)
135
  (UNSPEC_NSB           17)
136
  (UNSPEC_ALLOCO        18)
137
  (UNSPEC_EH_RETURN     19)
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_SP_SET        40)
154
  (UNSPEC_SP_TEST       41)
155
 
156
  ;; These are used with unspec_volatile.
157
  (UNSPECV_BLOCKAGE     0)
158
  (UNSPECV_ALIGN        1)
159
  (UNSPECV_CONST2       2)
160
  (UNSPECV_CONST4       4)
161
  (UNSPECV_CONST8       6)
162
  (UNSPECV_WINDOW_END   10)
163
  (UNSPECV_CONST_END    11)
164
])
165
 
166
;; -------------------------------------------------------------------------
167
;; Attributes
168
;; -------------------------------------------------------------------------
169
 
170
;; Target CPU.
171
 
172
(define_attr "cpu"
173
 "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
174
  (const (symbol_ref "sh_cpu_attr")))
175
 
176
(define_attr "endian" "big,little"
177
 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
178
                      (const_string "little") (const_string "big"))))
179
 
180
;; Indicate if the default fpu mode is single precision.
181
(define_attr "fpu_single" "yes,no"
182
  (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
183
                         (const_string "yes") (const_string "no"))))
184
 
185
(define_attr "fmovd" "yes,no"
186
  (const (if_then_else (symbol_ref "TARGET_FMOVD")
187
                       (const_string "yes") (const_string "no"))))
188
;; pipeline model
189
(define_attr "pipe_model" "sh1,sh4,sh5media"
190
  (const
191
   (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
192
          (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
193
         (const_string "sh1"))))
194
 
195
;; cbranch      conditional branch instructions
196
;; jump         unconditional jumps
197
;; arith        ordinary arithmetic
198
;; arith3       a compound insn that behaves similarly to a sequence of
199
;;              three insns of type arith
200
;; arith3b      like above, but might end with a redirected branch
201
;; load         from memory
202
;; load_si      Likewise, SImode variant for general register.
203
;; fload        Likewise, but load to fp register.
204
;; store        to memory
205
;; move         general purpose register to register
206
;; mt_group     other sh4 mt instructions
207
;; fmove        register to register, floating point
208
;; smpy         word precision integer multiply
209
;; dmpy         longword or doublelongword precision integer multiply
210
;; return       rts
211
;; pload        load of pr reg, which can't be put into delay slot of rts
212
;; prset        copy register to pr reg, ditto
213
;; pstore       store of pr reg, which can't be put into delay slot of jsr
214
;; prget        copy pr to register, ditto
215
;; pcload       pc relative load of constant value
216
;; pcfload      Likewise, but load to fp register.
217
;; pcload_si    Likewise, SImode variant for general register.
218
;; rte          return from exception
219
;; sfunc        special function call with known used registers
220
;; call         function call
221
;; fp           floating point
222
;; fdiv         floating point divide (or square root)
223
;; gp_fpul      move from general purpose register to fpul
224
;; fpul_gp      move from fpul to general purpose register
225
;; mac_gp       move from mac[lh] to general purpose register
226
;; dfp_arith, dfp_cmp,dfp_conv
227
;; ftrc_s       fix_truncsfsi2_i4
228
;; dfdiv        double precision floating point divide (or square root)
229
;; cwb          ic_invalidate_line_i
230
;; movua        SH4a unaligned load
231
;; fsrra        square root reciprocal approximate
232
;; fsca         sine and cosine approximate
233
;; tls_load     load TLS related address
234
;; arith_media  SHmedia arithmetic, logical, and shift instructions
235
;; cbranch_media SHmedia conditional branch instructions
236
;; cmp_media    SHmedia compare instructions
237
;; dfdiv_media  SHmedia double precision divide and square root
238
;; dfmul_media  SHmedia double precision multiply instruction
239
;; dfparith_media SHmedia double precision floating point arithmetic
240
;; dfpconv_media SHmedia double precision floating point conversions
241
;; dmpy_media   SHmedia longword multiply
242
;; fcmp_media   SHmedia floating point compare instructions
243
;; fdiv_media   SHmedia single precision divide and square root
244
;; fload_media  SHmedia floating point register load instructions
245
;; fmove_media  SHmedia floating point register moves (inc. fabs and fneg)
246
;; fparith_media SHmedia single precision floating point arithmetic
247
;; fpconv_media SHmedia single precision floating point conversions
248
;; fstore_media SHmedia floating point register store instructions
249
;; gettr_media  SHmedia gettr instruction
250
;; invalidate_line_media SHmedia invalidate_line sequence
251
;; jump_media   SHmedia unconditional branch instructions
252
;; load_media   SHmedia general register load instructions
253
;; pt_media     SHmedia pt instruction (expanded by assembler)
254
;; ptabs_media  SHmedia ptabs instruction
255
;; store_media  SHmedia general register store instructions
256
;; mcmp_media   SHmedia multimedia compare, absolute, saturating ops
257
;; mac_media    SHmedia mac-style fixed point operations
258
;; d2mpy_media  SHmedia: two 32 bit integer multiplies
259
;; atrans_media SHmedia approximate transcendental functions
260
;; ustore_media SHmedia unaligned stores
261
;; nil          no-op move, will be deleted.
262
 
263
(define_attr "type"
264
 "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,fload,store,move,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fdiv,ftrc_s,dfp_arith,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,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"
265
  (const_string "other"))
266
 
267
;; We define a new attribute namely "insn_class".We use
268
;; this for the DFA based pipeline description.
269
;;
270
;; mt_group      SH4 "mt" group instructions.
271
;;
272
;; ex_group      SH4 "ex" group instructions.
273
;;
274
;; ls_group      SH4 "ls" group instructions.
275
;;
276
 
277
(define_attr "insn_class"
278
  "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
279
  (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
280
         (eq_attr "type" "arith,dyn_shift") (const_string "ex_group")
281
         (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,store,gp_fpul,fpul_gp") (const_string "ls_group")
282
         (eq_attr "type" "cbranch,jump") (const_string "br_group")
283
         (eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_conv,dfdiv")
284
           (const_string "fe_group")
285
         (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb") (const_string "co_group")]
286
        (const_string "none")))
287
;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
288
;; so these do not belong in an insn group, although they are modeled
289
;; with their own define_insn_reservations.
290
 
291
;; Indicate what precision must be selected in fpscr for this insn, if any.
292
 
293
(define_attr "fp_mode" "single,double,none" (const_string "none"))
294
 
295
;; Indicate if the fpu mode is set by this instruction
296
;; "unknown" must have the value as "none" in fp_mode, and means
297
;; that the instruction/abi has left the processor in an unknown
298
;; state.
299
;; "none" means that nothing has changed and no mode is set.
300
;; This attribute is only used for the Renesas ABI.
301
(define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
302
 
303
; If a conditional branch destination is within -252..258 bytes away
304
; from the instruction it can be 2 bytes long.  Something in the
305
; range -4090..4100 bytes can be 6 bytes long.  All other conditional
306
; branches are initially assumed to be 16 bytes long.
307
; In machine_dependent_reorg, we split all branches that are longer than
308
; 2 bytes.
309
 
310
;; The maximum range used for SImode constant pool entries is 1018.  A final
311
;; instruction can add 8 bytes while only being 4 bytes in size, thus we
312
;; can have a total of 1022 bytes in the pool.  Add 4 bytes for a branch
313
;; instruction around the pool table, 2 bytes of alignment before the table,
314
;; and 30 bytes of alignment after the table.  That gives a maximum total
315
;; pool size of 1058 bytes.
316
;; Worst case code/pool content size ratio is 1:2 (using asms).
317
;; Thus, in the worst case, there is one instruction in front of a maximum
318
;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
319
;; code.  For the last n bytes of code, there are 2n + 36 bytes of pool.
320
;; If we have a forward branch, the initial table will be put after the
321
;; unconditional branch.
322
;;
323
;; ??? We could do much better by keeping track of the actual pcloads within
324
;; the branch range and in the pcload range in front of the branch range.
325
 
326
;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
327
;; inside an le.
328
(define_attr "short_cbranch_p" "no,yes"
329
  (cond [(ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
330
         (const_string "no")
331
         (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
332
         (const_string "yes")
333
         (ne (symbol_ref "NEXT_INSN (PREV_INSN (insn)) != insn") (const_int 0))
334
         (const_string "no")
335
         (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
336
         (const_string "yes")
337
         ] (const_string "no")))
338
 
339
(define_attr "med_branch_p" "no,yes"
340
  (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
341
              (const_int 1988))
342
         (const_string "yes")
343
         (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
344
         (const_string "no")
345
         (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
346
              (const_int 8186))
347
         (const_string "yes")
348
         ] (const_string "no")))
349
 
350
(define_attr "med_cbranch_p" "no,yes"
351
  (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
352
              (const_int 1986))
353
         (const_string "yes")
354
         (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
355
         (const_string "no")
356
         (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
357
               (const_int 8184))
358
         (const_string "yes")
359
         ] (const_string "no")))
360
 
361
(define_attr "braf_branch_p" "no,yes"
362
  (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
363
         (const_string "no")
364
         (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
365
              (const_int 20660))
366
         (const_string "yes")
367
         (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
368
         (const_string "no")
369
         (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
370
              (const_int 65530))
371
         (const_string "yes")
372
         ] (const_string "no")))
373
 
374
(define_attr "braf_cbranch_p" "no,yes"
375
  (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
376
         (const_string "no")
377
         (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
378
              (const_int 20658))
379
         (const_string "yes")
380
         (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
381
         (const_string "no")
382
         (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
383
              (const_int 65528))
384
         (const_string "yes")
385
         ] (const_string "no")))
386
 
387
; An unconditional jump in the range -4092..4098 can be 2 bytes long.
388
; For wider ranges, we need a combination of a code and a data part.
389
; If we can get a scratch register for a long range jump, the code
390
; part can be 4 bytes long; otherwise, it must be 8 bytes long.
391
; If the jump is in the range -32764..32770, the data part can be 2 bytes
392
; long; otherwise, it must be 6 bytes long.
393
 
394
; All other instructions are two bytes long by default.
395
 
396
;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
397
;; but getattrtab doesn't understand this.
398
(define_attr "length" ""
399
  (cond [(eq_attr "type" "cbranch")
400
         (cond [(eq_attr "short_cbranch_p" "yes")
401
                (const_int 2)
402
                (eq_attr "med_cbranch_p" "yes")
403
                (const_int 6)
404
                (eq_attr "braf_cbranch_p" "yes")
405
                (const_int 12)
406
;; ??? using pc is not computed transitively.
407
                (ne (match_dup 0) (match_dup 0))
408
                (const_int 14)
409
                (ne (symbol_ref ("flag_pic")) (const_int 0))
410
                (const_int 24)
411
                ] (const_int 16))
412
         (eq_attr "type" "jump")
413
         (cond [(eq_attr "med_branch_p" "yes")
414
                (const_int 2)
415
                (and (ne (symbol_ref "prev_nonnote_insn (insn)")
416
                         (const_int 0))
417
                     (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
418
                              (symbol_ref "INSN"))
419
                          (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
420
                              (symbol_ref "code_for_indirect_jump_scratch"))))
421
                (cond [(eq_attr "braf_branch_p" "yes")
422
                       (const_int 6)
423
                       (eq (symbol_ref "flag_pic") (const_int 0))
424
                       (const_int 10)
425
                       (ne (symbol_ref "TARGET_SH2") (const_int 0))
426
                       (const_int 10)] (const_int 18))
427
                (eq_attr "braf_branch_p" "yes")
428
                (const_int 10)
429
;; ??? using pc is not computed transitively.
430
                (ne (match_dup 0) (match_dup 0))
431
                (const_int 12)
432
                (ne (symbol_ref ("flag_pic")) (const_int 0))
433
                (const_int 22)
434
                ] (const_int 14))
435
         (eq_attr "type" "pt_media")
436
         (if_then_else (ne (symbol_ref "TARGET_SHMEDIA64") (const_int 0))
437
                       (const_int 20) (const_int 12))
438
         (and (eq_attr "type" "jump_media")
439
              (ne (symbol_ref "TARGET_SH5_CUT2_WORKAROUND") (const_int 0)))
440
         (const_int 8)
441
         ] (if_then_else (ne (symbol_ref "TARGET_SHMEDIA") (const_int 0))
442
                         (const_int 4)
443
                         (const_int 2))))
444
 
445
;; DFA descriptions for the pipelines
446
 
447
(include "sh1.md")
448
(include "shmedia.md")
449
(include "sh4.md")
450
 
451
(include "predicates.md")
452
 
453
;; Definitions for filling delay slots
454
 
455
(define_attr "needs_delay_slot" "yes,no" (const_string "no"))
456
 
457
;; ??? This should be (nil) instead of (const_int 0)
458
(define_attr "hit_stack" "yes,no"
459
        (cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)")
460
                   (const_int 0))
461
               (const_string "no")]
462
              (const_string "yes")))
463
 
464
(define_attr "interrupt_function" "no,yes"
465
  (const (symbol_ref "current_function_interrupt")))
466
 
467
(define_attr "in_delay_slot" "yes,no"
468
  (cond [(eq_attr "type" "cbranch") (const_string "no")
469
         (eq_attr "type" "pcload,pcload_si") (const_string "no")
470
         (eq_attr "needs_delay_slot" "yes") (const_string "no")
471
         (eq_attr "length" "2") (const_string "yes")
472
         ] (const_string "no")))
473
 
474
(define_attr "cond_delay_slot" "yes,no"
475
  (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
476
         ] (const_string "no")))
477
 
478
(define_attr "is_sfunc" ""
479
  (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
480
 
481
(define_attr "is_mac_media" ""
482
  (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
483
 
484
(define_attr "branch_zero" "yes,no"
485
  (cond [(eq_attr "type" "!cbranch") (const_string "no")
486
         (ne (symbol_ref "(next_active_insn (insn)\
487
                           == (prev_active_insn\
488
                               (XEXP (SET_SRC (PATTERN (insn)), 1))))\
489
                          && get_attr_length (next_active_insn (insn)) == 2")
490
             (const_int 0))
491
         (const_string "yes")]
492
        (const_string "no")))
493
 
494
;; SH4 Double-precision computation with double-precision result -
495
;; the two halves are ready at different times.
496
(define_attr "dfp_comp" "yes,no"
497
  (cond [(eq_attr "type" "dfp_arith,dfp_conv,dfdiv") (const_string "yes")]
498
        (const_string "no")))
499
 
500
;; Insns for which the latency of a preceding fp insn is decreased by one.
501
(define_attr "late_fp_use" "yes,no" (const_string "no"))
502
;; And feeding insns for which this relevant.
503
(define_attr "any_fp_comp" "yes,no"
504
  (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_conv,dfdiv")
505
         (const_string "yes")]
506
        (const_string "no")))
507
 
508
(define_attr "any_int_load" "yes,no"
509
  (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
510
         (const_string "yes")]
511
        (const_string "no")))
512
 
513
(define_attr "highpart" "user, ignore, extend, depend, must_split"
514
  (const_string "user"))
515
 
516
(define_delay
517
  (eq_attr "needs_delay_slot" "yes")
518
  [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
519
 
520
;; On the SH and SH2, the rte instruction reads the return pc from the stack,
521
;; and thus we can't put a pop instruction in its delay slot.
522
;; ??? On the SH3, the rte instruction does not use the stack, so a pop
523
;; instruction can go in the delay slot.
524
 
525
;; Since a normal return (rts) implicitly uses the PR register,
526
;; we can't allow PR register loads in an rts delay slot.
527
 
528
(define_delay
529
  (eq_attr "type" "return")
530
  [(and (eq_attr "in_delay_slot" "yes")
531
        (ior (and (eq_attr "interrupt_function" "no")
532
                  (eq_attr "type" "!pload,prset"))
533
             (and (eq_attr "interrupt_function" "yes")
534
                  (ior
535
                   (ne (symbol_ref "TARGET_SH3") (const_int 0))
536
                   (eq_attr "hit_stack" "no"))))) (nil) (nil)])
537
 
538
;; Since a call implicitly uses the PR register, we can't allow
539
;; a PR register store in a jsr delay slot.
540
 
541
(define_delay
542
  (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
543
  [(and (eq_attr "in_delay_slot" "yes")
544
        (eq_attr "type" "!pstore,prget")) (nil) (nil)])
545
 
546
;; Say that we have annulled true branches, since this gives smaller and
547
;; faster code when branches are predicted as not taken.
548
 
549
;; ??? The non-annulled condition should really be "in_delay_slot",
550
;; but insns that can be filled in non-annulled get priority over insns
551
;; that can only be filled in anulled.
552
 
553
(define_delay
554
  (and (eq_attr "type" "cbranch")
555
       (ne (symbol_ref "TARGET_SH2") (const_int 0)))
556
  ;; SH2e has a hardware bug that pretty much prohibits the use of
557
  ;; annuled delay slots.
558
  [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
559
                                          (not (eq_attr "cpu" "sh2e"))) (nil)])
560
 
561
;; -------------------------------------------------------------------------
562
;; SImode signed integer comparisons
563
;; -------------------------------------------------------------------------
564
 
565
(define_insn ""
566
  [(set (reg:SI T_REG)
567
        (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
568
                       (match_operand:SI 1 "arith_operand" "K08,r"))
569
               (const_int 0)))]
570
  "TARGET_SH1"
571
  "tst  %1,%0"
572
  [(set_attr "type" "mt_group")])
573
 
574
;; ??? Perhaps should only accept reg/constant if the register is reg 0.
575
;; That would still allow reload to create cmpi instructions, but would
576
;; perhaps allow forcing the constant into a register when that is better.
577
;; Probably should use r0 for mem/imm compares, but force constant into a
578
;; register for pseudo/imm compares.
579
 
580
(define_insn "cmpeqsi_t"
581
  [(set (reg:SI T_REG)
582
        (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
583
               (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
584
  "TARGET_SH1"
585
  "@
586
        tst     %0,%0
587
        cmp/eq  %1,%0
588
        cmp/eq  %1,%0"
589
   [(set_attr "type" "mt_group")])
590
 
591
(define_insn "cmpgtsi_t"
592
  [(set (reg:SI T_REG)
593
        (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
594
               (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
595
  "TARGET_SH1"
596
  "@
597
        cmp/gt  %1,%0
598
        cmp/pl  %0"
599
   [(set_attr "type" "mt_group")])
600
 
601
(define_insn "cmpgesi_t"
602
  [(set (reg:SI T_REG)
603
        (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
604
               (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
605
  "TARGET_SH1"
606
  "@
607
        cmp/ge  %1,%0
608
        cmp/pz  %0"
609
   [(set_attr "type" "mt_group")])
610
 
611
;; -------------------------------------------------------------------------
612
;; SImode unsigned integer comparisons
613
;; -------------------------------------------------------------------------
614
 
615
(define_insn "cmpgeusi_t"
616
  [(set (reg:SI T_REG)
617
        (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
618
                (match_operand:SI 1 "arith_reg_operand" "r")))]
619
  "TARGET_SH1"
620
  "cmp/hs       %1,%0"
621
   [(set_attr "type" "mt_group")])
622
 
623
(define_insn "cmpgtusi_t"
624
  [(set (reg:SI T_REG)
625
        (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
626
                (match_operand:SI 1 "arith_reg_operand" "r")))]
627
  "TARGET_SH1"
628
  "cmp/hi       %1,%0"
629
   [(set_attr "type" "mt_group")])
630
 
631
;; We save the compare operands in the cmpxx patterns and use them when
632
;; we generate the branch.
633
 
634
(define_expand "cmpsi"
635
  [(set (reg:SI T_REG)
636
        (compare (match_operand:SI 0 "cmpsi_operand" "")
637
                 (match_operand:SI 1 "arith_operand" "")))]
638
  "TARGET_SH1 || TARGET_SHMEDIA"
639
  "
640
{
641
  if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == T_REG
642
      && GET_CODE (operands[1]) != CONST_INT)
643
    operands[0] = copy_to_mode_reg (SImode, operands[0]);
644
  sh_compare_op0 = operands[0];
645
  sh_compare_op1 = operands[1];
646
  DONE;
647
}")
648
 
649
;; -------------------------------------------------------------------------
650
;; DImode signed integer comparisons
651
;; -------------------------------------------------------------------------
652
 
653
;; ??? Could get better scheduling by splitting the initial test from the
654
;; rest of the insn after reload.  However, the gain would hardly justify
655
;; the sh.md size increase necessary to do that.
656
 
657
(define_insn ""
658
  [(set (reg:SI T_REG)
659
        (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
660
                       (match_operand:DI 1 "arith_operand" "r"))
661
               (const_int 0)))]
662
  "TARGET_SH1"
663
  "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",
664
                                 insn, operands);"
665
  [(set_attr "length" "6")
666
   (set_attr "type" "arith3b")])
667
 
668
(define_insn "cmpeqdi_t"
669
  [(set (reg:SI T_REG)
670
        (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
671
               (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
672
  "TARGET_SH1"
673
  "@
674
        tst     %S0,%S0\;bf     %,Ldi%=\;tst    %R0,%R0\\n%,Ldi%=:
675
        cmp/eq  %S1,%S0\;bf     %,Ldi%=\;cmp/eq %R1,%R0\\n%,Ldi%=:"
676
  [(set_attr "length" "6")
677
   (set_attr "type" "arith3b")])
678
 
679
(define_split
680
  [(set (reg:SI T_REG)
681
        (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
682
               (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
683
;; If we applied this split when not optimizing, it would only be
684
;; applied during the machine-dependent reorg, when no new basic blocks
685
;; may be created.
686
  "TARGET_SH1 && reload_completed && optimize"
687
  [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
688
   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
689
                           (label_ref (match_dup 6))
690
                           (pc)))
691
   (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
692
   (match_dup 6)]
693
  "
694
{
695
  operands[2]
696
    = gen_rtx_REG (SImode,
697
                   true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
698
  operands[3]
699
    = (operands[1] == const0_rtx
700
       ? const0_rtx
701
       : gen_rtx_REG (SImode,
702
                      true_regnum (operands[1])
703
                      + (TARGET_LITTLE_ENDIAN ? 1 : 0)));
704
  operands[4] = gen_lowpart (SImode, operands[0]);
705
  operands[5] = gen_lowpart (SImode, operands[1]);
706
  operands[6] = gen_label_rtx ();
707
}")
708
 
709
(define_insn "cmpgtdi_t"
710
  [(set (reg:SI T_REG)
711
        (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
712
               (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
713
  "TARGET_SH2"
714
  "@
715
        cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:
716
        tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"
717
  [(set_attr "length" "8")
718
   (set_attr "type" "arith3")])
719
 
720
(define_insn "cmpgedi_t"
721
  [(set (reg:SI T_REG)
722
        (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
723
               (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
724
  "TARGET_SH2"
725
  "@
726
        cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:
727
        cmp/pz\\t%S0"
728
  [(set_attr "length" "8,2")
729
   (set_attr "type" "arith3,mt_group")])
730
 
731
;; -------------------------------------------------------------------------
732
;; DImode unsigned integer comparisons
733
;; -------------------------------------------------------------------------
734
 
735
(define_insn "cmpgeudi_t"
736
  [(set (reg:SI T_REG)
737
        (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
738
                (match_operand:DI 1 "arith_reg_operand" "r")))]
739
  "TARGET_SH2"
740
  "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"
741
  [(set_attr "length" "8")
742
   (set_attr "type" "arith3")])
743
 
744
(define_insn "cmpgtudi_t"
745
  [(set (reg:SI T_REG)
746
        (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
747
                (match_operand:DI 1 "arith_reg_operand" "r")))]
748
  "TARGET_SH2"
749
  "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"
750
  [(set_attr "length" "8")
751
   (set_attr "type" "arith3")])
752
 
753
(define_insn "cmpeqsi_media"
754
  [(set (match_operand:SI 0 "register_operand" "=r")
755
        (eq:SI (match_operand:SI 1 "logical_operand" "%r")
756
               (match_operand:SI 2 "cmp_operand" "Nr")))]
757
  "TARGET_SHMEDIA"
758
  "cmpeq        %1, %N2, %0"
759
  [(set_attr "type" "cmp_media")])
760
 
761
(define_insn "cmpeqdi_media"
762
  [(set (match_operand:SI 0 "register_operand" "=r")
763
        (eq:SI (match_operand:DI 1 "register_operand" "%r")
764
               (match_operand:DI 2 "cmp_operand" "Nr")))]
765
  "TARGET_SHMEDIA"
766
  "cmpeq        %1, %N2, %0"
767
  [(set_attr "type" "cmp_media")])
768
 
769
(define_insn "cmpgtsi_media"
770
  [(set (match_operand:SI 0 "register_operand" "=r")
771
        (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
772
               (match_operand:SI 2 "cmp_operand" "rN")))]
773
  "TARGET_SHMEDIA"
774
  "cmpgt        %N1, %N2, %0"
775
  [(set_attr "type" "cmp_media")])
776
 
777
(define_insn "cmpgtdi_media"
778
  [(set (match_operand:SI 0 "register_operand" "=r")
779
        (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
780
               (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
781
  "TARGET_SHMEDIA"
782
  "cmpgt        %N1, %N2, %0"
783
  [(set_attr "type" "cmp_media")])
784
 
785
(define_insn "cmpgtusi_media"
786
  [(set (match_operand:SI 0 "register_operand" "=r")
787
        (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
788
                (match_operand:SI 2 "cmp_operand" "rN")))]
789
  "TARGET_SHMEDIA"
790
  "cmpgtu       %N1, %N2, %0"
791
  [(set_attr "type" "cmp_media")])
792
 
793
(define_insn "cmpgtudi_media"
794
  [(set (match_operand:SI 0 "register_operand" "=r")
795
        (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
796
                (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
797
  "TARGET_SHMEDIA"
798
  "cmpgtu       %N1, %N2, %0"
799
  [(set_attr "type" "cmp_media")])
800
 
801
; These two patterns are for combine.
802
(define_insn "*cmpne0sisi_media"
803
  [(set (match_operand:SI 0 "register_operand" "=r")
804
        (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
805
  "TARGET_SHMEDIA"
806
  "cmpgtu       %1,r63,%0"
807
  [(set_attr "type" "cmp_media")])
808
 
809
;; We save the compare operands in the cmpxx patterns and use them when
810
;; we generate the branch.
811
 
812
(define_expand "cmpdi"
813
  [(set (reg:SI T_REG)
814
        (compare (match_operand:DI 0 "arith_operand" "")
815
                 (match_operand:DI 1 "arith_operand" "")))]
816
  "TARGET_SH2 || TARGET_SHMEDIA"
817
  "
818
{
819
  sh_compare_op0 = operands[0];
820
  sh_compare_op1 = operands[1];
821
  DONE;
822
}")
823
;; -------------------------------------------------------------------------
824
;; Conditional move instructions
825
;; -------------------------------------------------------------------------
826
 
827
;; The insn names may seem reversed, but note that cmveq performs the move
828
;; if op1 == 0, and cmvne does it if op1 != 0.
829
 
830
(define_insn "movdicc_false"
831
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
832
        (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
833
                             (const_int 0))
834
         (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
835
         (match_operand:DI 3 "arith_reg_operand" "0")))]
836
  "TARGET_SHMEDIA"
837
  "cmveq        %1, %N2, %0"
838
  [(set_attr "type" "arith_media")])
839
 
840
(define_insn "movdicc_true"
841
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
842
        (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
843
                             (const_int 0))
844
         (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
845
         (match_operand:DI 3 "arith_reg_operand" "0")))]
846
  "TARGET_SHMEDIA"
847
  "cmvne        %1, %N2, %0"
848
  [(set_attr "type" "arith_media")])
849
 
850
(define_peephole2
851
  [(set (match_operand:DI 0 "arith_reg_dest" "")
852
        (if_then_else:DI (match_operator 3 "equality_comparison_operator"
853
                           [(match_operand:DI 1 "arith_reg_operand" "")
854
                            (const_int 0)])
855
         (match_operand:DI 2 "arith_reg_dest" "")
856
         (match_dup 0)))
857
   (set (match_dup 2) (match_dup 0))]
858
  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
859
  [(set (match_dup 2)
860
        (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
861
  "
862
{
863
  operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
864
                                VOIDmode, operands[1], CONST0_RTX (DImode));
865
}")
866
 
867
(define_peephole2
868
  [(set (match_operand:DI 0 "general_movdst_operand" "")
869
        (match_operand:DI 1 "arith_reg_or_0_operand" ""))
870
   (set (match_operand:DI 2 "arith_reg_dest" "")
871
        (if_then_else:DI (match_operator 4 "equality_comparison_operator"
872
                           [(match_operand:DI 3 "arith_reg_operand" "")
873
                            (const_int 0)])
874
         (match_dup 0)
875
         (match_dup 2)))]
876
  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
877
  [(set (match_dup 2)
878
        (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
879
  "")
880
 
881
(define_expand "movdicc"
882
  [(set (match_operand:DI 0 "register_operand" "")
883
        (if_then_else:DI (match_operand 1 "comparison_operator" "")
884
                         (match_operand:DI 2 "register_operand" "")
885
                         (match_operand:DI 3 "register_operand" "")))]
886
  "TARGET_SHMEDIA"
887
  "
888
{
889
  if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
890
      && GET_MODE (sh_compare_op0) == DImode
891
      && sh_compare_op1 == const0_rtx)
892
    operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
893
                                  sh_compare_op0, sh_compare_op1);
894
  else
895
    {
896
      rtx tmp;
897
 
898
      if (no_new_pseudos)
899
        FAIL;
900
 
901
      tmp = gen_reg_rtx (DImode);
902
 
903
      switch (GET_CODE (operands[1]))
904
        {
905
        case EQ:
906
          emit_insn (gen_seq (tmp));
907
          operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
908
          break;
909
 
910
        case NE:
911
          emit_insn (gen_seq (tmp));
912
          operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
913
          break;
914
 
915
        case GT:
916
          emit_insn (gen_sgt (tmp));
917
          operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
918
          break;
919
 
920
        case LT:
921
          emit_insn (gen_slt (tmp));
922
          operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
923
          break;
924
 
925
        case GE:
926
          emit_insn (gen_slt (tmp));
927
          operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
928
          break;
929
 
930
        case LE:
931
          emit_insn (gen_sgt (tmp));
932
          operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
933
          break;
934
 
935
        case GTU:
936
          emit_insn (gen_sgtu (tmp));
937
          operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
938
          break;
939
 
940
        case LTU:
941
          emit_insn (gen_sltu (tmp));
942
          operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
943
          break;
944
 
945
        case GEU:
946
          emit_insn (gen_sltu (tmp));
947
          operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
948
          break;
949
 
950
        case LEU:
951
          emit_insn (gen_sgtu (tmp));
952
          operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
953
          break;
954
 
955
        case UNORDERED:
956
          emit_insn (gen_sunordered (tmp));
957
          operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
958
          break;
959
 
960
        case ORDERED:
961
          emit_insn (gen_sunordered (tmp));
962
          operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
963
          break;
964
 
965
        case UNEQ:
966
        case UNGE:
967
        case UNGT:
968
        case UNLE:
969
        case UNLT:
970
        case LTGT:
971
          FAIL;
972
 
973
        default:
974
          gcc_unreachable ();
975
        }
976
    }
977
}")
978
 
979
;; Add SImode variants for cmveq / cmvne to compensate for not promoting
980
;; SImode to DImode.
981
(define_insn "movsicc_false"
982
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
983
        (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
984
                          (const_int 0))
985
         (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
986
         (match_operand:SI 3 "arith_reg_operand" "0")))]
987
  "TARGET_SHMEDIA"
988
  "cmveq        %1, %N2, %0"
989
  [(set_attr "type" "arith_media")])
990
 
991
(define_insn "movsicc_true"
992
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
993
        (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
994
                          (const_int 0))
995
         (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
996
         (match_operand:SI 3 "arith_reg_operand" "0")))]
997
  "TARGET_SHMEDIA"
998
  "cmvne        %1, %N2, %0"
999
  [(set_attr "type" "arith_media")])
1000
 
1001
(define_peephole2
1002
  [(set (match_operand:SI 0 "arith_reg_dest" "")
1003
        (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1004
                           [(match_operand:SI 1 "arith_reg_operand" "")
1005
                            (const_int 0)])
1006
         (match_operand:SI 2 "arith_reg_dest" "")
1007
         (match_dup 0)))
1008
   (set (match_dup 2) (match_dup 0))]
1009
  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1010
  [(set (match_dup 2)
1011
        (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1012
  "
1013
{
1014
  operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1015
                                VOIDmode, operands[1], CONST0_RTX (SImode));
1016
}")
1017
 
1018
(define_peephole2
1019
  [(set (match_operand:SI 0 "general_movdst_operand" "")
1020
        (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1021
   (set (match_operand:SI 2 "arith_reg_dest" "")
1022
        (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1023
                           [(match_operand:SI 3 "arith_reg_operand" "")
1024
                            (const_int 0)])
1025
         (match_dup 0)
1026
         (match_dup 2)))]
1027
  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1028
   && (GET_CODE (operands[1]) != REG || GENERAL_REGISTER_P (REGNO (operands[1])))"
1029
  [(set (match_dup 2)
1030
        (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1031
  "
1032
{
1033
  replace_rtx (operands[4], operands[0], operands[1]);
1034
}")
1035
 
1036
(define_peephole2
1037
  [(set (match_operand 0 "any_register_operand" "")
1038
        (match_operand 1 "any_register_operand" ""))
1039
   (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1040
   (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1041
  "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1042
    <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1043
   && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1044
   && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1045
   && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1046
   && ! reg_overlap_mentioned_p (operands[0], operands[3])
1047
   && ! reg_overlap_mentioned_p (operands[2], operands[0])
1048
   && ! reg_overlap_mentioned_p (operands[0], operands[1])
1049
   && (REGNO_REG_CLASS (REGNO (operands[0]))
1050
       == REGNO_REG_CLASS (REGNO (operands[2])))
1051
   && (REGNO_REG_CLASS (REGNO (operands[1]))
1052
       == REGNO_REG_CLASS (REGNO (operands[0])))"
1053
  [(set (match_dup 0) (match_dup 3))
1054
   (set (match_dup 4) (match_dup 5))]
1055
  "
1056
{
1057
  rtx set1, set2;
1058
  rtx replacements[4];
1059
 
1060
  /* We want to replace occurrences of operands[0] with operands[1] and
1061
     operands[2] with operands[0] in operands[4]/operands[5].
1062
     Doing just two replace_rtx calls naively would result in the second
1063
     replacement undoing all that the first did if operands[1] and operands[2]
1064
     are identical, so we must do this simultaneously.  */
1065
  replacements[0] = operands[0];
1066
  replacements[1] = operands[1];
1067
  replacements[2] = operands[2];
1068
  replacements[3] = operands[0];
1069
  if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1070
      || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1071
      || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1072
    FAIL;
1073
 
1074
  operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1075
  replace_n_hard_rtx (operands[4], replacements, 2, 1);
1076
  operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1077
  /* The operands array is aliased to recog_data.operand, which gets
1078
     clobbered by extract_insn, so finish with it now.  */
1079
  set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1080
  set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1081
  /* ??? The last insn might be a jump insn, but the generic peephole2 code
1082
     always uses emit_insn.  */
1083
  /* Check that we don't violate matching constraints or earlyclobbers.  */
1084
  extract_insn (emit_insn (set1));
1085
  if (! constrain_operands (1))
1086
    goto failure;
1087
  extract_insn (emit (set2));
1088
  if (! constrain_operands (1))
1089
    {
1090
      rtx tmp;
1091
    failure:
1092
      tmp = replacements[0];
1093
      replacements[0] = replacements[1];
1094
      replacements[1] = tmp;
1095
      tmp = replacements[2];
1096
      replacements[2] = replacements[3];
1097
      replacements[3] = tmp;
1098
      replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1099
      replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1100
      replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1101
      FAIL;
1102
    }
1103
  DONE;
1104
}")
1105
 
1106
;; The register allocator is rather clumsy in handling multi-way conditional
1107
;; moves, so allow the combiner to make them, and we split them up after
1108
;; reload.  */
1109
(define_insn_and_split "*movsicc_umin"
1110
  [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1111
        (umin:SI (if_then_else:SI
1112
                   (eq (match_operand:SI 1 "arith_reg_operand" "r")
1113
                       (const_int 0))
1114
                   (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1115
                   (match_operand:SI 3 "register_operand" "0"))
1116
                 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1117
   (clobber (match_scratch:SI 5 "=&r"))]
1118
  "TARGET_SHMEDIA && no_new_pseudos"
1119
  "#"
1120
  "TARGET_SHMEDIA && reload_completed"
1121
  [(pc)]
1122
  "
1123
{
1124
  emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1125
                                operands[3]));
1126
  emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1127
  emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1128
                                operands[0]));
1129
  DONE;
1130
}")
1131
 
1132
(define_insn "*movsicc_t_false"
1133
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1134
        (if_then_else (eq (reg:SI T_REG) (const_int 0))
1135
                      (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1136
                      (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1137
  "TARGET_PRETEND_CMOVE
1138
   && (arith_reg_operand (operands[1], SImode)
1139
       || (immediate_operand (operands[1], SImode)
1140
           && CONST_OK_FOR_I08 (INTVAL (operands[1]))))"
1141
  "bt 0f\;mov %1,%0\\n0:"
1142
  [(set_attr "type" "mt_group,arith") ;; poor approximation
1143
   (set_attr "length" "4")])
1144
 
1145
(define_insn "*movsicc_t_true"
1146
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1147
        (if_then_else (ne (reg:SI T_REG) (const_int 0))
1148
                      (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1149
                      (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1150
  "TARGET_PRETEND_CMOVE
1151
   && (arith_reg_operand (operands[1], SImode)
1152
       || (immediate_operand (operands[1], SImode)
1153
           && CONST_OK_FOR_I08 (INTVAL (operands[1]))))"
1154
  "bf 0f\;mov %1,%0\\n0:"
1155
  [(set_attr "type" "mt_group,arith") ;; poor approximation
1156
   (set_attr "length" "4")])
1157
 
1158
(define_expand "movsicc"
1159
  [(set (match_operand:SI 0 "arith_reg_dest" "")
1160
        (if_then_else:SI (match_operand 1 "comparison_operator" "")
1161
                         (match_operand:SI 2 "arith_reg_or_0_operand" "")
1162
                         (match_operand:SI 3 "arith_reg_operand" "")))]
1163
  "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1164
  "
1165
{
1166
  if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1167
      && GET_MODE (sh_compare_op0) == SImode
1168
      && (TARGET_SHMEDIA
1169
          || (REG_P (sh_compare_op0) && REGNO (sh_compare_op0) == T_REG))
1170
      && sh_compare_op1 == const0_rtx)
1171
    operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
1172
                                  sh_compare_op0, sh_compare_op1);
1173
  else if (TARGET_PRETEND_CMOVE)
1174
    {
1175
      enum rtx_code code = GET_CODE (operands[1]);
1176
      enum rtx_code new_code = code;
1177
      rtx tmp;
1178
 
1179
      if (! currently_expanding_to_rtl)
1180
        FAIL;
1181
      switch (code)
1182
        {
1183
        case LT: case LE: case LEU: case LTU:
1184
          if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) != MODE_INT)
1185
            break;
1186
        case NE:
1187
          new_code = reverse_condition (code);
1188
          break;
1189
        case EQ: case GT: case GE: case GEU: case GTU:
1190
          break;
1191
        default:
1192
          FAIL;
1193
        }
1194
      tmp = prepare_scc_operands (new_code);
1195
      operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1196
                                    tmp, const0_rtx);
1197
    }
1198
  else
1199
    {
1200
      rtx tmp;
1201
 
1202
      if (no_new_pseudos)
1203
        FAIL;
1204
 
1205
      tmp = gen_reg_rtx (SImode);
1206
 
1207
      switch (GET_CODE (operands[1]))
1208
        {
1209
        case EQ:
1210
          emit_insn (gen_seq (tmp));
1211
          operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1212
          break;
1213
 
1214
        case NE:
1215
          emit_insn (gen_seq (tmp));
1216
          operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1217
          break;
1218
 
1219
        case GT:
1220
          emit_insn (gen_sgt (tmp));
1221
          operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1222
          break;
1223
 
1224
        case LT:
1225
          emit_insn (gen_slt (tmp));
1226
          operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1227
          break;
1228
 
1229
        case GE:
1230
          emit_insn (gen_slt (tmp));
1231
          operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1232
          break;
1233
 
1234
        case LE:
1235
          emit_insn (gen_sgt (tmp));
1236
          operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1237
          break;
1238
 
1239
        case GTU:
1240
          emit_insn (gen_sgtu (tmp));
1241
          operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1242
          break;
1243
 
1244
        case LTU:
1245
          emit_insn (gen_sltu (tmp));
1246
          operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1247
          break;
1248
 
1249
        case GEU:
1250
          emit_insn (gen_sltu (tmp));
1251
          operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1252
          break;
1253
 
1254
        case LEU:
1255
          emit_insn (gen_sgtu (tmp));
1256
          operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1257
          break;
1258
 
1259
        case UNORDERED:
1260
          emit_insn (gen_sunordered (tmp));
1261
          operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1262
          break;
1263
 
1264
        case ORDERED:
1265
          emit_insn (gen_sunordered (tmp));
1266
          operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1267
          break;
1268
 
1269
        case UNEQ:
1270
        case UNGE:
1271
        case UNGT:
1272
        case UNLE:
1273
        case UNLT:
1274
        case LTGT:
1275
          FAIL;
1276
 
1277
        default:
1278
          abort ();
1279
        }
1280
    }
1281
}")
1282
 
1283
(define_expand "movqicc"
1284
  [(set (match_operand:QI 0 "register_operand" "")
1285
        (if_then_else:QI (match_operand 1 "comparison_operator" "")
1286
                         (match_operand:QI 2 "register_operand" "")
1287
                         (match_operand:QI 3 "register_operand" "")))]
1288
  "TARGET_SHMEDIA"
1289
  "
1290
{
1291
  operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1292
  operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1293
  operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1294
  emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1295
  DONE;
1296
}")
1297
 
1298
;; -------------------------------------------------------------------------
1299
;; Addition instructions
1300
;; -------------------------------------------------------------------------
1301
 
1302
(define_expand "adddi3"
1303
  [(set (match_operand:DI 0 "arith_reg_operand" "")
1304
        (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1305
                 (match_operand:DI 2 "arith_operand" "")))]
1306
  ""
1307
  "
1308
{
1309
  if (TARGET_SH1)
1310
    {
1311
      if (no_new_pseudos && ! arith_reg_operand (operands[2], DImode))
1312
        FAIL;
1313
      operands[2] = force_reg (DImode, operands[2]);
1314
      emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1315
      DONE;
1316
    }
1317
}")
1318
 
1319
(define_insn "*adddi3_media"
1320
  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1321
        (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1322
                 (match_operand:DI 2 "arith_operand" "r,I10")))]
1323
  "TARGET_SHMEDIA"
1324
  "@
1325
        add     %1, %2, %0
1326
        addi    %1, %2, %0"
1327
  [(set_attr "type" "arith_media")])
1328
 
1329
(define_insn "*adddisi3_media"
1330
  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1331
        (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1332
                 (match_operand:DI 2 "arith_operand" "r,I10")))]
1333
  "TARGET_SHMEDIA"
1334
  "@
1335
        add.l   %1, %2, %0
1336
        addi.l  %1, %2, %0"
1337
  [(set_attr "type" "arith_media")
1338
   (set_attr "highpart" "ignore")])
1339
 
1340
(define_insn "adddi3z_media"
1341
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1342
        (zero_extend:DI
1343
         (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1344
                  (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1345
  "TARGET_SHMEDIA"
1346
  "addz.l       %1, %N2, %0"
1347
  [(set_attr "type" "arith_media")
1348
   (set_attr "highpart" "ignore")])
1349
 
1350
(define_insn "adddi3_compact"
1351
  [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1352
        (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1353
                 (match_operand:DI 2 "arith_reg_operand" "r")))
1354
   (clobber (reg:SI T_REG))]
1355
  "TARGET_SH1"
1356
  "#"
1357
  [(set_attr "length" "6")])
1358
 
1359
(define_split
1360
  [(set (match_operand:DI 0 "arith_reg_dest" "")
1361
        (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1362
                 (match_operand:DI 2 "arith_reg_operand" "")))
1363
   (clobber (reg:SI T_REG))]
1364
  "TARGET_SH1 && reload_completed"
1365
  [(const_int 0)]
1366
  "
1367
{
1368
  rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1369
  high0 = gen_rtx_REG (SImode,
1370
                       true_regnum (operands[0])
1371
                       + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1372
  high2 = gen_rtx_REG (SImode,
1373
                       true_regnum (operands[2])
1374
                       + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1375
  emit_insn (gen_clrt ());
1376
  emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
1377
  emit_insn (gen_addc1 (high0, high0, high2));
1378
  DONE;
1379
}")
1380
 
1381
(define_insn "addc"
1382
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1383
        (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1384
                          (match_operand:SI 2 "arith_reg_operand" "r"))
1385
                 (reg:SI T_REG)))
1386
   (set (reg:SI T_REG)
1387
        (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1388
  "TARGET_SH1"
1389
  "addc %2,%0"
1390
  [(set_attr "type" "arith")])
1391
 
1392
(define_insn "addc1"
1393
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1394
        (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1395
                          (match_operand:SI 2 "arith_reg_operand" "r"))
1396
                 (reg:SI T_REG)))
1397
   (clobber (reg:SI T_REG))]
1398
  "TARGET_SH1"
1399
  "addc %2,%0"
1400
  [(set_attr "type" "arith")])
1401
 
1402
(define_expand "addsi3"
1403
  [(set (match_operand:SI 0 "arith_reg_operand" "")
1404
        (plus:SI (match_operand:SI 1 "arith_operand" "")
1405
                 (match_operand:SI 2 "arith_operand" "")))]
1406
  ""
1407
  "
1408
{
1409
  if (TARGET_SHMEDIA)
1410
    operands[1] = force_reg (SImode, operands[1]);
1411
}")
1412
 
1413
(define_insn "addsi3_media"
1414
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1415
        (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1416
                 (match_operand:SI 2 "arith_operand" "r,I10")))]
1417
  "TARGET_SHMEDIA"
1418
  "@
1419
        add.l   %1, %2, %0
1420
        addi.l  %1, %2, %0"
1421
  [(set_attr "type" "arith_media")
1422
   (set_attr "highpart" "ignore")])
1423
 
1424
(define_insn "addsidi3_media"
1425
  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1426
        (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
1427
                                  "%r,r")
1428
                                 (match_operand:SI 2 "arith_operand"
1429
                                  "r,I10"))))]
1430
  "TARGET_SHMEDIA"
1431
  "@
1432
        add.l   %1, %2, %0
1433
        addi.l  %1, %2, %0"
1434
  [(set_attr "type" "arith_media")
1435
   (set_attr "highpart" "ignore")])
1436
 
1437
(define_insn "*addsi3_compact"
1438
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1439
        (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1440
                 (match_operand:SI 2 "arith_operand" "rI08")))]
1441
  "TARGET_SH1"
1442
  "add  %2,%0"
1443
  [(set_attr "type" "arith")])
1444
 
1445
;; -------------------------------------------------------------------------
1446
;; Subtraction instructions
1447
;; -------------------------------------------------------------------------
1448
 
1449
(define_expand "subdi3"
1450
  [(set (match_operand:DI 0 "arith_reg_operand" "")
1451
        (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1452
                  (match_operand:DI 2 "arith_reg_operand" "")))]
1453
  ""
1454
  "
1455
{
1456
  if (TARGET_SH1)
1457
    {
1458
      operands[1] = force_reg (DImode, operands[1]);
1459
      emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1460
      DONE;
1461
    }
1462
}")
1463
 
1464
(define_insn "*subdi3_media"
1465
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1466
        (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1467
                  (match_operand:DI 2 "arith_reg_operand" "r")))]
1468
  "TARGET_SHMEDIA"
1469
  "sub  %N1, %2, %0"
1470
  [(set_attr "type" "arith_media")])
1471
 
1472
(define_insn "subdisi3_media"
1473
  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
1474
        (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1475
                  (match_operand:DI 2 "arith_reg_operand" "r")))]
1476
  "TARGET_SHMEDIA"
1477
  "sub.l        %N1, %2, %0"
1478
  [(set_attr "type" "arith_media")
1479
   (set_attr "highpart" "ignore")])
1480
 
1481
(define_insn "subdi3_compact"
1482
  [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1483
        (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1484
                 (match_operand:DI 2 "arith_reg_operand" "r")))
1485
   (clobber (reg:SI T_REG))]
1486
  "TARGET_SH1"
1487
  "#"
1488
  [(set_attr "length" "6")])
1489
 
1490
(define_split
1491
  [(set (match_operand:DI 0 "arith_reg_dest" "")
1492
        (minus:DI (match_operand:DI 1 "arith_reg_operand" "")
1493
                  (match_operand:DI 2 "arith_reg_operand" "")))
1494
   (clobber (reg:SI T_REG))]
1495
  "TARGET_SH1 && reload_completed"
1496
  [(const_int 0)]
1497
  "
1498
{
1499
  rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1500
  high0 = gen_rtx_REG (SImode,
1501
                       true_regnum (operands[0])
1502
                       + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1503
  high2 = gen_rtx_REG (SImode,
1504
                       true_regnum (operands[2])
1505
                       + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1506
  emit_insn (gen_clrt ());
1507
  emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1508
  emit_insn (gen_subc1 (high0, high0, high2));
1509
  DONE;
1510
}")
1511
 
1512
(define_insn "subc"
1513
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1514
        (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1515
                            (match_operand:SI 2 "arith_reg_operand" "r"))
1516
                  (reg:SI T_REG)))
1517
   (set (reg:SI T_REG)
1518
        (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1519
                          (reg:SI T_REG))
1520
                (match_dup 1)))]
1521
  "TARGET_SH1"
1522
  "subc %2,%0"
1523
  [(set_attr "type" "arith")])
1524
 
1525
(define_insn "subc1"
1526
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1527
        (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1528
                            (match_operand:SI 2 "arith_reg_operand" "r"))
1529
                  (reg:SI T_REG)))
1530
   (clobber (reg:SI T_REG))]
1531
  "TARGET_SH1"
1532
  "subc %2,%0"
1533
  [(set_attr "type" "arith")])
1534
 
1535
;; life_analysis thinks rn is live before subc rn,rn, so make a special
1536
;; pattern for this case.  This helps multimedia applications that compute
1537
;; the sum of absolute differences.
1538
(define_insn "mov_neg_si_t"
1539
  [(set (match_operand:SI 0 "arith_reg_dest" "=r") (neg:SI (reg:SI T_REG)))]
1540
  "TARGET_SH1"
1541
  "subc %0,%0"
1542
  [(set_attr "type" "arith")])
1543
 
1544
(define_insn "*subsi3_internal"
1545
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1546
        (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1547
                  (match_operand:SI 2 "arith_reg_operand" "r")))]
1548
  "TARGET_SH1"
1549
  "sub  %2,%0"
1550
  [(set_attr "type" "arith")])
1551
 
1552
(define_insn_and_split "*subsi3_media"
1553
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1554
        (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
1555
                  (match_operand:SI 2 "extend_reg_operand" "r")))]
1556
  "TARGET_SHMEDIA
1557
   && (operands[1] != constm1_rtx
1558
       || (GET_CODE (operands[2]) != TRUNCATE
1559
           && GET_CODE (operands[2]) != SUBREG))"
1560
  "sub.l        %N1, %2, %0"
1561
  "operands[1] == constm1_rtx"
1562
  [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
1563
  ""
1564
  [(set_attr "type" "arith_media")
1565
   (set_attr "highpart" "ignore")])
1566
 
1567
(define_split
1568
  [(set (match_operand:SI 0 "arith_reg_dest" "")
1569
        (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1570
                                                       "general_extend_operand"
1571
                                                       "") 0)) 0)))]
1572
  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
1573
  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1574
   (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1575
  "")
1576
 
1577
(define_split
1578
  [(set (match_operand:SI 0 "arith_reg_dest" "")
1579
        (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1580
                                                       "general_extend_operand"
1581
                                                       "") 0)) 3)))]
1582
  "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
1583
  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1584
   (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1585
  "")
1586
;; Convert `constant - reg' to `neg rX; add rX, #const' since this
1587
;; will sometimes save one instruction.  Otherwise we might get
1588
;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
1589
;; are the same.
1590
 
1591
(define_expand "subsi3"
1592
  [(set (match_operand:SI 0 "arith_reg_operand" "")
1593
        (minus:SI (match_operand:SI 1 "arith_operand" "")
1594
                  (match_operand:SI 2 "arith_reg_operand" "")))]
1595
  ""
1596
  "
1597
{
1598
  if (TARGET_SH1 && GET_CODE (operands[1]) == CONST_INT)
1599
    {
1600
      emit_insn (gen_negsi2 (operands[0], operands[2]));
1601
      emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
1602
      DONE;
1603
    }
1604
  if (TARGET_SHMEDIA)
1605
    {
1606
      if (no_new_pseudos && ! arith_reg_or_0_operand (operands[1], SImode))
1607
        FAIL;
1608
      if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
1609
        operands[1] = force_reg (SImode, operands[1]);
1610
    }
1611
}")
1612
 
1613
;; -------------------------------------------------------------------------
1614
;; Division instructions
1615
;; -------------------------------------------------------------------------
1616
 
1617
;; We take advantage of the library routines which don't clobber as many
1618
;; registers as a normal function call would.
1619
 
1620
;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
1621
;; also has an effect on the register that holds the address of the sfunc.
1622
;; To make this work, we have an extra dummy insn that shows the use
1623
;; of this register for reorg.
1624
 
1625
(define_insn "use_sfunc_addr"
1626
  [(set (reg:SI PR_REG)
1627
        (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
1628
  "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
1629
  ""
1630
  [(set_attr "length" "0")])
1631
 
1632
(define_insn "udivsi3_sh2a"
1633
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1634
        (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
1635
                (match_operand:SI 2 "arith_reg_operand" "z")))]
1636
  "TARGET_SH2A"
1637
  "divu %2,%1"
1638
  [(set_attr "type" "arith")
1639
   (set_attr "in_delay_slot" "no")])
1640
 
1641
;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
1642
;; hard register 0.  If we used hard register 0, then the next instruction
1643
;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
1644
;; gets allocated to a stack slot that needs its address reloaded, then
1645
;; there is nothing to prevent reload from using r0 to reload the address.
1646
;; This reload would clobber the value in r0 we are trying to store.
1647
;; If we let reload allocate r0, then this problem can never happen.
1648
 
1649
(define_insn "udivsi3_i1"
1650
  [(set (match_operand:SI 0 "register_operand" "=z")
1651
        (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1652
   (clobber (reg:SI T_REG))
1653
   (clobber (reg:SI PR_REG))
1654
   (clobber (reg:SI R4_REG))
1655
   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1656
  "TARGET_SH1 && ! TARGET_SH4"
1657
  "jsr  @%1%#"
1658
  [(set_attr "type" "sfunc")
1659
   (set_attr "needs_delay_slot" "yes")])
1660
 
1661
; Since shmedia-nofpu code could be linked against shcompact code, and
1662
; the udivsi3 libcall has the same name, we must consider all registers
1663
; clobbered that are in the union of the registers clobbered by the
1664
; shmedia and the shcompact implementation.  Note, if the shcompact
1665
; implementation actually used shcompact code, we'd need to clobber
1666
; also r23 and fr23.
1667
(define_insn "udivsi3_i1_media"
1668
  [(set (match_operand:SI 0 "register_operand" "=z")
1669
        (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1670
   (clobber (reg:SI T_MEDIA_REG))
1671
   (clobber (reg:SI PR_MEDIA_REG))
1672
   (clobber (reg:SI R20_REG))
1673
   (clobber (reg:SI R21_REG))
1674
   (clobber (reg:SI R22_REG))
1675
   (clobber (reg:DI TR0_REG))
1676
   (clobber (reg:DI TR1_REG))
1677
   (clobber (reg:DI TR2_REG))
1678
   (use (match_operand 1 "target_reg_operand" "b"))]
1679
  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1680
  "blink        %1, r18"
1681
  [(set_attr "type" "sfunc")
1682
   (set_attr "needs_delay_slot" "yes")])
1683
 
1684
(define_expand "udivsi3_i4_media"
1685
  [(set (match_dup 3)
1686
        (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
1687
   (set (match_dup 4)
1688
        (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1689
   (set (match_dup 5) (float:DF (match_dup 3)))
1690
   (set (match_dup 6) (float:DF (match_dup 4)))
1691
   (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
1692
   (set (match_dup 8) (fix:DI (match_dup 7)))
1693
   (set (match_operand:SI 0 "register_operand" "")
1694
        (truncate:SI (match_dup 8)))]
1695
  "TARGET_SHMEDIA_FPU"
1696
  "
1697
{
1698
  operands[3] = gen_reg_rtx (DImode);
1699
  operands[4] = gen_reg_rtx (DImode);
1700
  operands[5] = gen_reg_rtx (DFmode);
1701
  operands[6] = gen_reg_rtx (DFmode);
1702
  operands[7] = gen_reg_rtx (DFmode);
1703
  operands[8] = gen_reg_rtx (DImode);
1704
}")
1705
 
1706
(define_insn "udivsi3_i4"
1707
  [(set (match_operand:SI 0 "register_operand" "=y")
1708
        (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1709
   (clobber (reg:SI T_REG))
1710
   (clobber (reg:SI PR_REG))
1711
   (clobber (reg:DF DR0_REG))
1712
   (clobber (reg:DF DR2_REG))
1713
   (clobber (reg:DF DR4_REG))
1714
   (clobber (reg:SI R0_REG))
1715
   (clobber (reg:SI R1_REG))
1716
   (clobber (reg:SI R4_REG))
1717
   (clobber (reg:SI R5_REG))
1718
   (use (reg:PSI FPSCR_REG))
1719
   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1720
  "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1721
  "jsr  @%1%#"
1722
  [(set_attr "type" "sfunc")
1723
   (set_attr "fp_mode" "double")
1724
   (set_attr "needs_delay_slot" "yes")])
1725
 
1726
(define_insn "udivsi3_i4_single"
1727
  [(set (match_operand:SI 0 "register_operand" "=y")
1728
        (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1729
   (clobber (reg:SI T_REG))
1730
   (clobber (reg:SI PR_REG))
1731
   (clobber (reg:DF DR0_REG))
1732
   (clobber (reg:DF DR2_REG))
1733
   (clobber (reg:DF DR4_REG))
1734
   (clobber (reg:SI R0_REG))
1735
   (clobber (reg:SI R1_REG))
1736
   (clobber (reg:SI R4_REG))
1737
   (clobber (reg:SI R5_REG))
1738
   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1739
  "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1740
  "jsr  @%1%#"
1741
  [(set_attr "type" "sfunc")
1742
   (set_attr "needs_delay_slot" "yes")])
1743
 
1744
(define_insn "udivsi3_i4_int"
1745
  [(set (match_operand:SI 0 "register_operand" "=z")
1746
        (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1747
   (clobber (reg:SI T_REG))
1748
   (clobber (reg:SI R1_REG))
1749
   (clobber (reg:SI PR_REG))
1750
   (clobber (reg:SI MACH_REG))
1751
   (clobber (reg:SI MACL_REG))
1752
   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1753
  "TARGET_SH1"
1754
  "jsr  @%1%#"
1755
  [(set_attr "type" "sfunc")
1756
   (set_attr "needs_delay_slot" "yes")])
1757
 
1758
 
1759
(define_expand "udivsi3"
1760
  [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
1761
   (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1762
   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1763
   (parallel [(set (match_operand:SI 0 "register_operand" "")
1764
                   (udiv:SI (reg:SI R4_REG)
1765
                            (reg:SI R5_REG)))
1766
              (clobber (reg:SI T_REG))
1767
              (clobber (reg:SI PR_REG))
1768
              (clobber (reg:SI R4_REG))
1769
              (use (match_dup 3))])]
1770
  ""
1771
  "
1772
{
1773
  rtx first, last;
1774
 
1775
  operands[3] = gen_reg_rtx (Pmode);
1776
  /* Emit the move of the address to a pseudo outside of the libcall.  */
1777
  if (TARGET_DIVIDE_CALL_TABLE)
1778
    {
1779
      /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
1780
         that causes problems when the divide code is supposed to come from a
1781
         separate library.  Division by zero is undefined, so dividing 1 can be
1782
         implemented by comparing with the divisor.  */
1783
      if (operands[1] == const1_rtx && currently_expanding_to_rtl)
1784
        {
1785
          emit_insn (gen_cmpsi (operands[1], operands[2]));
1786
          emit_insn (gen_sgeu (operands[0]));
1787
          DONE;
1788
        }
1789
      else if (operands[2] == const0_rtx)
1790
        {
1791
          emit_move_insn (operands[0], operands[2]);
1792
          DONE;
1793
        }
1794
      function_symbol (operands[3], \"__udivsi3_i4i\", SFUNC_GOT);
1795
      last = gen_udivsi3_i4_int (operands[0], operands[3]);
1796
    }
1797
  else if (TARGET_DIVIDE_CALL_FP)
1798
    {
1799
      function_symbol (operands[3], \"__udivsi3_i4\", SFUNC_STATIC);
1800
      if (TARGET_FPU_SINGLE)
1801
        last = gen_udivsi3_i4_single (operands[0], operands[3]);
1802
      else
1803
        last = gen_udivsi3_i4 (operands[0], operands[3]);
1804
    }
1805
  else if (TARGET_SHMEDIA_FPU)
1806
    {
1807
      operands[1] = force_reg (SImode, operands[1]);
1808
      operands[2] = force_reg (SImode, operands[2]);
1809
      emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
1810
      DONE;
1811
    }
1812
  else if (TARGET_SH2A)
1813
    {
1814
      operands[1] = force_reg (SImode, operands[1]);
1815
      operands[2] = force_reg (SImode, operands[2]);
1816
      emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
1817
      DONE;
1818
    }
1819
  else if (TARGET_SH5)
1820
    {
1821
      function_symbol (operands[3],
1822
                       TARGET_FPU_ANY ? \"__udivsi3_i4\" : \"__udivsi3\",
1823
                       SFUNC_STATIC);
1824
 
1825
      if (TARGET_SHMEDIA)
1826
        last = gen_udivsi3_i1_media (operands[0], operands[3]);
1827
      else if (TARGET_FPU_ANY)
1828
        last = gen_udivsi3_i4_single (operands[0], operands[3]);
1829
      else
1830
        last = gen_udivsi3_i1 (operands[0], operands[3]);
1831
    }
1832
  else
1833
    {
1834
      function_symbol (operands[3], \"__udivsi3\", SFUNC_STATIC);
1835
      last = gen_udivsi3_i1 (operands[0], operands[3]);
1836
    }
1837
  first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1838
  emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1839
  last = emit_insn (last);
1840
  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1841
     invariant code motion can move it.  */
1842
  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1843
  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1844
  DONE;
1845
}")
1846
 
1847
(define_insn "divsi3_sh2a"
1848
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1849
        (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
1850
                (match_operand:SI 2 "arith_reg_operand" "z")))]
1851
  "TARGET_SH2A"
1852
  "divs %2,%1"
1853
  [(set_attr "type" "arith")
1854
   (set_attr "in_delay_slot" "no")])
1855
 
1856
(define_insn "divsi3_i1"
1857
  [(set (match_operand:SI 0 "register_operand" "=z")
1858
        (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1859
   (clobber (reg:SI T_REG))
1860
   (clobber (reg:SI PR_REG))
1861
   (clobber (reg:SI R1_REG))
1862
   (clobber (reg:SI R2_REG))
1863
   (clobber (reg:SI R3_REG))
1864
   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1865
  "TARGET_SH1 && ! TARGET_SH4"
1866
  "jsr  @%1%#"
1867
  [(set_attr "type" "sfunc")
1868
   (set_attr "needs_delay_slot" "yes")])
1869
 
1870
(define_insn "divsi3_i1_media"
1871
  [(set (match_operand:SI 0 "register_operand" "=z")
1872
        (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1873
   (clobber (reg:SI T_MEDIA_REG))
1874
   (clobber (reg:SI PR_MEDIA_REG))
1875
   (clobber (reg:SI R1_REG))
1876
   (clobber (reg:SI R20_REG))
1877
   (clobber (reg:SI R21_REG))
1878
   (clobber (reg:SI TR0_REG))
1879
   (use (match_operand 1 "target_reg_operand" "b"))]
1880
  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1881
  "blink        %1, r18"
1882
  [(set_attr "type" "sfunc")])
1883
 
1884
(define_insn "divsi3_media_2"
1885
  [(set (match_operand:SI 0 "register_operand" "=z")
1886
        (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1887
   (clobber (reg:SI T_MEDIA_REG))
1888
   (clobber (reg:SI PR_MEDIA_REG))
1889
   (clobber (reg:SI R1_REG))
1890
   (clobber (reg:SI R21_REG))
1891
   (clobber (reg:SI TR0_REG))
1892
   (use (reg:SI R20_REG))
1893
   (use (match_operand 1 "target_reg_operand" "b"))]
1894
  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1895
  "blink        %1, r18"
1896
  [(set_attr "type" "sfunc")])
1897
 
1898
;; This pattern acts as a placeholder for -mdiv=inv:call to carry
1899
;; hard reg clobbers and data dependencies that we need when we want
1900
;; to rematerialize the division into a call.
1901
(define_insn_and_split "divsi_inv_call"
1902
  [(set (match_operand:SI 0 "register_operand" "=r")
1903
        (div:SI (match_operand:SI 1 "register_operand" "r")
1904
                (match_operand:SI 2 "register_operand" "r")))
1905
   (clobber (reg:SI R4_REG))
1906
   (clobber (reg:SI R5_REG))
1907
   (clobber (reg:SI T_MEDIA_REG))
1908
   (clobber (reg:SI PR_MEDIA_REG))
1909
   (clobber (reg:SI R1_REG))
1910
   (clobber (reg:SI R21_REG))
1911
   (clobber (reg:SI TR0_REG))
1912
   (clobber (reg:SI R20_REG))
1913
   (use (match_operand:SI 3 "register_operand" "r"))]
1914
  "TARGET_SHMEDIA"
1915
  "#"
1916
  "&& (high_life_started || reload_completed)"
1917
  [(set (match_dup 0) (match_dup 3))]
1918
  ""
1919
  [(set_attr "highpart" "must_split")])
1920
 
1921
;; This is the combiner pattern for -mdiv=inv:call .
1922
(define_insn_and_split "*divsi_inv_call_combine"
1923
  [(set (match_operand:SI 0 "register_operand" "=z")
1924
        (div:SI (match_operand:SI 1 "register_operand" "r")
1925
                (match_operand:SI 2 "register_operand" "r")))
1926
   (clobber (reg:SI R4_REG))
1927
   (clobber (reg:SI R5_REG))
1928
   (clobber (reg:SI T_MEDIA_REG))
1929
   (clobber (reg:SI PR_MEDIA_REG))
1930
   (clobber (reg:SI R1_REG))
1931
   (clobber (reg:SI R21_REG))
1932
   (clobber (reg:SI TR0_REG))
1933
   (clobber (reg:SI R20_REG))
1934
   (use (unspec:SI [(match_dup 1)
1935
                    (match_operand:SI 3 "" "")
1936
                    (unspec:SI [(match_operand:SI 4 "" "")
1937
                                (match_dup 3)
1938
                                (match_operand:DI 5 "" "")]
1939
                     UNSPEC_DIV_INV_M2)
1940
                    (match_operand:DI 6 "" "")
1941
                    (const_int 0)
1942
                    (const_int 0)]
1943
         UNSPEC_DIV_INV_M3))]
1944
  "TARGET_SHMEDIA"
1945
  "#"
1946
  "&& (high_life_started || reload_completed)"
1947
  [(pc)]
1948
  "
1949
{
1950
  const char *name = sh_divsi3_libfunc;
1951
  enum sh_function_kind kind = SFUNC_GOT;
1952
  rtx sym;
1953
 
1954
  emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
1955
  emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
1956
  while (TARGET_DIVIDE_INV_CALL2)
1957
    {
1958
      rtx x = operands[3];
1959
 
1960
      if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
1961
        break;
1962
      x = XVECEXP (x, 0, 0);
1963
      name = \"__sdivsi3_2\";
1964
      kind = SFUNC_STATIC;
1965
      emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
1966
      break;
1967
    }
1968
  sym = function_symbol (NULL, name, kind);
1969
  emit_insn (gen_divsi3_media_2 (operands[0], sym));
1970
  DONE;
1971
}"
1972
  [(set_attr "highpart" "must_split")])
1973
 
1974
(define_expand "divsi3_i4_media"
1975
  [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
1976
   (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
1977
   (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
1978
   (set (match_operand:SI 0 "register_operand" "=r")
1979
        (fix:SI (match_dup 5)))]
1980
  "TARGET_SHMEDIA_FPU"
1981
  "
1982
{
1983
  operands[3] = gen_reg_rtx (DFmode);
1984
  operands[4] = gen_reg_rtx (DFmode);
1985
  operands[5] = gen_reg_rtx (DFmode);
1986
}")
1987
 
1988
(define_insn "divsi3_i4"
1989
  [(set (match_operand:SI 0 "register_operand" "=y")
1990
        (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1991
   (clobber (reg:SI PR_REG))
1992
   (clobber (reg:DF DR0_REG))
1993
   (clobber (reg:DF DR2_REG))
1994
   (use (reg:PSI FPSCR_REG))
1995
   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1996
  "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1997
  "jsr  @%1%#"
1998
  [(set_attr "type" "sfunc")
1999
   (set_attr "fp_mode" "double")
2000
   (set_attr "needs_delay_slot" "yes")])
2001
 
2002
(define_insn "divsi3_i4_single"
2003
  [(set (match_operand:SI 0 "register_operand" "=y")
2004
        (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2005
   (clobber (reg:SI PR_REG))
2006
   (clobber (reg:DF DR0_REG))
2007
   (clobber (reg:DF DR2_REG))
2008
   (clobber (reg:SI R2_REG))
2009
   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2010
  "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
2011
  "jsr  @%1%#"
2012
  [(set_attr "type" "sfunc")
2013
   (set_attr "needs_delay_slot" "yes")])
2014
 
2015
(define_insn "divsi3_i4_int"
2016
  [(set (match_operand:SI 0 "register_operand" "=z")
2017
        (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2018
   (clobber (reg:SI T_REG))
2019
   (clobber (reg:SI PR_REG))
2020
   (clobber (reg:SI R1_REG))
2021
   (clobber (reg:SI MACH_REG))
2022
   (clobber (reg:SI MACL_REG))
2023
   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2024
  "TARGET_SH1"
2025
  "jsr  @%1%#"
2026
  [(set_attr "type" "sfunc")
2027
   (set_attr "needs_delay_slot" "yes")])
2028
 
2029
(define_expand "divsi3"
2030
  [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2031
   (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2032
   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2033
   (parallel [(set (match_operand:SI 0 "register_operand" "")
2034
                   (div:SI (reg:SI R4_REG)
2035
                           (reg:SI R5_REG)))
2036
              (clobber (reg:SI T_REG))
2037
              (clobber (reg:SI PR_REG))
2038
              (clobber (reg:SI R1_REG))
2039
              (clobber (reg:SI R2_REG))
2040
              (clobber (reg:SI R3_REG))
2041
              (use (match_dup 3))])]
2042
  ""
2043
  "
2044
{
2045
  rtx first, last;
2046
 
2047
  operands[3] = gen_reg_rtx (Pmode);
2048
  /* Emit the move of the address to a pseudo outside of the libcall.  */
2049
  if (TARGET_DIVIDE_CALL_TABLE)
2050
    {
2051
      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2052
      last = gen_divsi3_i4_int (operands[0], operands[3]);
2053
    }
2054
  else if (TARGET_DIVIDE_CALL_FP)
2055
    {
2056
      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2057
      if (TARGET_FPU_SINGLE)
2058
        last = gen_divsi3_i4_single (operands[0], operands[3]);
2059
      else
2060
        last = gen_divsi3_i4 (operands[0], operands[3]);
2061
    }
2062
  else if (TARGET_SH2A)
2063
    {
2064
      operands[1] = force_reg (SImode, operands[1]);
2065
      operands[2] = force_reg (SImode, operands[2]);
2066
      emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2067
      DONE;
2068
    }
2069
  else if (TARGET_DIVIDE_INV)
2070
    {
2071
      rtx dividend = operands[1];
2072
      rtx divisor = operands[2];
2073
      rtx tab_base;
2074
      rtx nsb_res = gen_reg_rtx (DImode);
2075
      rtx norm64 = gen_reg_rtx (DImode);
2076
      rtx tab_ix = gen_reg_rtx (DImode);
2077
      rtx norm32 = gen_reg_rtx (SImode);
2078
      rtx i92 = force_reg (DImode, GEN_INT (92));
2079
      rtx scratch0a = gen_reg_rtx (DImode);
2080
      rtx scratch0b = gen_reg_rtx (DImode);
2081
      rtx inv0 = gen_reg_rtx (SImode);
2082
      rtx scratch1a = gen_reg_rtx (DImode);
2083
      rtx scratch1b = gen_reg_rtx (DImode);
2084
      rtx shift = gen_reg_rtx (DImode);
2085
      rtx i2p27, i43;
2086
      rtx inv1 = gen_reg_rtx (SImode);
2087
      rtx scratch2a = gen_reg_rtx (DImode);
2088
      rtx scratch2b = gen_reg_rtx (SImode);
2089
      rtx inv2 = gen_reg_rtx (SImode);
2090
      rtx scratch3a = gen_reg_rtx (DImode);
2091
      rtx scratch3b = gen_reg_rtx (DImode);
2092
      rtx scratch3c = gen_reg_rtx (DImode);
2093
      rtx scratch3d = gen_reg_rtx (SImode);
2094
      rtx scratch3e = gen_reg_rtx (DImode);
2095
      rtx result = gen_reg_rtx (SImode);
2096
 
2097
      if (! arith_reg_or_0_operand (dividend, SImode))
2098
        dividend = force_reg (SImode, dividend);
2099
      if (! arith_reg_operand (divisor, SImode))
2100
        divisor = force_reg (SImode, divisor);
2101
      if (flag_pic && Pmode != DImode)
2102
        {
2103
          tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2104
          tab_base = gen_datalabel_ref (tab_base);
2105
          tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2106
        }
2107
      else
2108
        {
2109
          tab_base = gen_rtx_SYMBOL_REF (DImode, \"__div_table\");
2110
          tab_base = gen_datalabel_ref (tab_base);
2111
          tab_base = force_reg (DImode, tab_base);
2112
        }
2113
      if (TARGET_DIVIDE_INV20U)
2114
        i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2115
      else
2116
        i2p27 = GEN_INT (0);
2117
      if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2118
        i43 = force_reg (DImode, GEN_INT (43));
2119
      else
2120
        i43 = GEN_INT (0);
2121
      emit_insn (gen_nsbdi (nsb_res,
2122
                            simplify_gen_subreg (DImode, divisor, SImode, 0)));
2123
      emit_insn (gen_ashldi3_media (norm64,
2124
                                    gen_rtx_SUBREG (DImode, divisor, 0),
2125
                                    nsb_res));
2126
      emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2127
      emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2128
      emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2129
                                   inv0, scratch0a, scratch0b,
2130
                                   scratch1a, scratch1b));
2131
      emit_insn (gen_subdi3 (shift, i92, nsb_res));
2132
      emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2133
                                   scratch2a));
2134
      emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2135
                                   i2p27, i43,
2136
                                   scratch3a, scratch3b, scratch3c,
2137
                                   scratch2a, scratch2b, scratch3d, scratch3e));
2138
      if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2139
        emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2140
      else if (TARGET_DIVIDE_INV_FP)
2141
        emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2142
                                     gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2143
                                     gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2144
                                     gen_reg_rtx (DFmode)));
2145
      else
2146
        emit_move_insn (operands[0], result);
2147
      DONE;
2148
    }
2149
  else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2150
    {
2151
      operands[1] = force_reg (SImode, operands[1]);
2152
      operands[2] = force_reg (SImode, operands[2]);
2153
      emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2154
      DONE;
2155
    }
2156
  else if (TARGET_SH5)
2157
    {
2158
      if (TARGET_DIVIDE_CALL2)
2159
        {
2160
          rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2161
          tab_base = gen_datalabel_ref (tab_base);
2162
          emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2163
        }
2164
      if (TARGET_FPU_ANY && TARGET_SH1)
2165
        function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2166
      else if (TARGET_DIVIDE_CALL2)
2167
        function_symbol (operands[3], \"__sdivsi3_2\", SFUNC_STATIC);
2168
      else
2169
        function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2170
 
2171
      if (TARGET_SHMEDIA)
2172
        last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2173
                (operands[0], operands[3]));
2174
      else if (TARGET_FPU_ANY)
2175
        last = gen_divsi3_i4_single (operands[0], operands[3]);
2176
      else
2177
        last = gen_divsi3_i1 (operands[0], operands[3]);
2178
    }
2179
  else
2180
    {
2181
      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2182
      last = gen_divsi3_i1 (operands[0], operands[3]);
2183
    }
2184
  first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2185
  emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2186
  last = emit_insn (last);
2187
  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
2188
     invariant code motion can move it.  */
2189
  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
2190
  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2191
  DONE;
2192
}")
2193
 
2194
;; operands: scratch, tab_base, tab_ix
2195
;; These are unspecs because we could generate an indexed addressing mode
2196
;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2197
;; confuse reload.  See PR27117.
2198
 
2199
(define_insn "divsi_inv_qitable"
2200
  [(set (match_operand:DI 0 "register_operand" "=r")
2201
        (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2202
                                    (match_operand:DI 2 "register_operand" "r")]
2203
                         UNSPEC_DIV_INV_TABLE)))]
2204
  "TARGET_SHMEDIA"
2205
  "@
2206
        ldx.ub  %1, %2, %0"
2207
  [(set_attr "type" "load_media")
2208
   (set_attr "highpart" "user")])
2209
 
2210
;; operands: scratch, tab_base, tab_ix
2211
(define_insn "divsi_inv_hitable"
2212
  [(set (match_operand:DI 0 "register_operand" "=r")
2213
        (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2214
                                    (match_operand:DI 2 "register_operand" "r")]
2215
                         UNSPEC_DIV_INV_TABLE)))]
2216
  "TARGET_SHMEDIA"
2217
  "@
2218
        ldx.w   %1, %2, %0"
2219
  [(set_attr "type" "load_media")
2220
   (set_attr "highpart" "user")])
2221
 
2222
;; operands: inv0, tab_base, tab_ix, norm32
2223
;; scratch equiv in sdivsi3_2: r19, r21
2224
(define_expand "divsi_inv_m0"
2225
  [(set (match_operand:SI 0 "register_operand" "=r")
2226
        (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2227
                    (match_operand:DI 2 "register_operand" "r")
2228
                    (match_operand:SI 3 "register_operand" "r")]
2229
         UNSPEC_DIV_INV_M0))
2230
   (clobber (match_operand:DI 4 "register_operand" "=r"))
2231
   (clobber (match_operand:DI 5 "register_operand" "=r"))]
2232
  "TARGET_SHMEDIA"
2233
  "
2234
{
2235
/*
2236
tab_base: r20
2237
tab_ix: r21
2238
norm32: r25
2239
 ldx.ub r20, r21, r19 // u0.8
2240
 shlli r21, 1, r21
2241
 muls.l r25, r19, r19 // s2.38
2242
 ldx.w r20, r21, r21  // s2.14
2243
 shari r19, 24, r19   // truncate to s2.14
2244
 sub r21, r19, r19    // some 11 bit inverse in s1.14
2245
*/
2246
 
2247
  rtx inv0 = operands[0];
2248
  rtx tab_base = operands[1];
2249
  rtx tab_ix = operands[2];
2250
  rtx norm32 = operands[3];
2251
  rtx scratch0 = operands[4];
2252
  rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2253
  rtx scratch1 = operands[5];
2254
 
2255
  emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2256
  emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2257
  emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2258
  emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2259
  emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2260
  emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2261
  DONE;
2262
}")
2263
 
2264
;; operands: inv1, tab_base, tab_ix, norm32
2265
(define_insn_and_split "divsi_inv_m1"
2266
  [(set (match_operand:SI 0 "register_operand" "=r")
2267
        (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2268
                    (match_operand:DI 2 "register_operand" "r")
2269
                    (match_operand:SI 3 "register_operand" "r")]
2270
         UNSPEC_DIV_INV_M1))
2271
   (clobber (match_operand:SI 4 "register_operand" "=r"))
2272
   (clobber (match_operand:DI 5 "register_operand" "=r"))
2273
   (clobber (match_operand:DI 6 "register_operand" "=r"))
2274
   (clobber (match_operand:DI 7 "register_operand" "=r"))
2275
   (clobber (match_operand:DI 8 "register_operand" "=r"))]
2276
  "TARGET_SHMEDIA"
2277
  "#"
2278
  "&& no_new_pseudos"
2279
  [(pc)]
2280
  "
2281
{
2282
/* inv0: r19
2283
 muls.l r19, r19, r18 // u0.28
2284
 muls.l r25, r18, r18 // s2.58
2285
 shlli r19, 45, r0    // multiply by two and convert to s2.58
2286
 sub r0, r18, r18
2287
 shari r18, 28, r18   // some 18 bit inverse in s1.30
2288
*/
2289
 
2290
  rtx inv1 = operands[0];
2291
  rtx tab_base = operands[1];
2292
  rtx tab_ix = operands[2];
2293
  rtx norm32 = operands[3];
2294
  rtx inv0 = operands[4];
2295
  rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2296
  rtx scratch0a = operands[5];
2297
  rtx scratch0b = operands[6];
2298
  rtx scratch0 = operands[7];
2299
  rtx scratch1 = operands[8];
2300
  rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2301
 
2302
  emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2303
                               scratch0a, scratch0b));
2304
  emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2305
  emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2306
  emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2307
  emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2308
  emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2309
  DONE;
2310
}")
2311
 
2312
;; operands: inv2, norm32, inv1, i92
2313
(define_insn_and_split "divsi_inv_m2"
2314
  [(set (match_operand:SI 0 "register_operand" "=r")
2315
        (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2316
                    (match_operand:SI 2 "register_operand" "r")
2317
                    (match_operand:DI 3 "register_operand" "r")]
2318
         UNSPEC_DIV_INV_M2))
2319
   (clobber (match_operand:DI 4 "register_operand" "=r"))]
2320
  "TARGET_SHMEDIA"
2321
  "#"
2322
  "&& no_new_pseudos"
2323
  [(pc)]
2324
  "
2325
{
2326
/*
2327
 muls.l r18, r25, r0  // s2.60
2328
 shari r0, 16, r0     // s-16.44
2329
  sub
2330
 muls.l r0, r18, r19  // s-16.74
2331
 shari r19, 30, r19   // s-16.44
2332
*/
2333
  rtx inv2 = operands[0];
2334
  rtx norm32 = operands[1];
2335
  rtx inv1 = operands[2];
2336
  rtx i92 = operands[3];
2337
  rtx scratch0 = operands[4];
2338
  rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2339
 
2340
  emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2341
  emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2342
  emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2343
  emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2344
  emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2345
  DONE;
2346
}")
2347
 
2348
(define_insn_and_split "divsi_inv_m3"
2349
  [(set (match_operand:SI 0 "register_operand" "=r")
2350
        (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2351
                    (match_operand:SI 2 "register_operand" "r")
2352
                    (match_operand:SI 3 "register_operand" "r")
2353
                    (match_operand:DI 4 "register_operand" "r")
2354
                    (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
2355
                    (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
2356
         UNSPEC_DIV_INV_M3))
2357
   (clobber (match_operand:DI 7 "register_operand" "=r"))
2358
   (clobber (match_operand:DI 8 "register_operand" "=r"))
2359
   (clobber (match_operand:DI 9 "register_operand" "=r"))
2360
   (clobber (match_operand:DI 10 "register_operand" "=r"))
2361
   (clobber (match_operand:SI 11 "register_operand" "=r"))
2362
   (clobber (match_operand:SI 12 "register_operand" "=r"))
2363
   (clobber (match_operand:DI 13 "register_operand" "=r"))]
2364
  "TARGET_SHMEDIA"
2365
  "#"
2366
  "&& no_new_pseudos"
2367
  [(pc)]
2368
  "
2369
{
2370
/*
2371
  r0: result  r1: shift  r4: dividend  r18: inv1  r19: inv2
2372
  r0: scratch0  r19: scratch1 r21: scratch2
2373
 
2374
  muls.l r18, r4, r25 // s32.30
2375
 muls.l r19, r4, r19  // s15.30
2376
 shari r25, 63, r21
2377
  shari r19, 14, r19  // s18.-14
2378
 sub r25, r19, r0
2379
 shard r0, r1, r0
2380
 sub r0, r21, r0
2381
*/
2382
 
2383
  rtx result = operands[0];
2384
  rtx dividend = operands[1];
2385
  rtx inv1 = operands[2];
2386
  rtx inv2 = operands[3];
2387
  rtx shift = operands[4];
2388
  rtx scratch0 = operands[7];
2389
  rtx scratch1 = operands[8];
2390
  rtx scratch2 = operands[9];
2391
 
2392
  emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
2393
  emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
2394
  emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
2395
  emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
2396
  emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
2397
  emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
2398
  emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
2399
  DONE;
2400
}")
2401
 
2402
;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
2403
;; inv1: tab_base, tab_ix, norm32
2404
;; inv2: norm32, inv1, i92
2405
(define_insn_and_split "divsi_inv_m1_3"
2406
  [(set (match_operand:SI 0 "register_operand" "=r")
2407
        (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2408
                    (unspec:SI [(match_operand:DI 2 "register_operand" "r")
2409
                                (match_operand:DI 3 "register_operand" "r")
2410
                                (match_operand:SI 4 "register_operand" "r")]
2411
                     UNSPEC_DIV_INV_M1)
2412
                    (unspec:SI [(match_dup 4)
2413
                                (unspec:SI [(match_dup 2)
2414
                                            (match_dup 3)
2415
                                            (match_dup 4)] UNSPEC_DIV_INV_M1)
2416
                                (match_operand:SI 5 "" "")]
2417
                     UNSPEC_DIV_INV_M2)
2418
                    (match_operand:DI 6 "register_operand" "r")
2419
                    (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
2420
                    (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
2421
         UNSPEC_DIV_INV_M3))
2422
   (clobber (match_operand:DI 9 "register_operand" "=r"))
2423
   (clobber (match_operand:DI 10 "register_operand" "=r"))
2424
   (clobber (match_operand:DI 11 "register_operand" "=r"))
2425
   (clobber (match_operand:DI 12 "register_operand" "=r"))
2426
   (clobber (match_operand:SI 13 "register_operand" "=r"))
2427
   (clobber (match_operand:SI 14 "register_operand" "=r"))
2428
   (clobber (match_operand:DI 15 "register_operand" "=r"))]
2429
  "TARGET_SHMEDIA
2430
   && (TARGET_DIVIDE_INV_MINLAT
2431
       || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2432
  "#"
2433
  "&& no_new_pseudos"
2434
  [(pc)]
2435
  "
2436
{
2437
  rtx result = operands[0];
2438
  rtx dividend = operands[1];
2439
  rtx tab_base = operands[2];
2440
  rtx tab_ix = operands[3];
2441
  rtx norm32 = operands[4];
2442
  /* rtx i92 = operands[5]; */
2443
  rtx shift = operands[6];
2444
  rtx i2p27 = operands[7];
2445
  rtx i43 = operands[8];
2446
  rtx scratch0 = operands[9];
2447
  rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2448
  rtx scratch1 = operands[10];
2449
  rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2450
  rtx scratch2 = operands[11];
2451
  rtx scratch3 = operands[12];
2452
  rtx scratch4 = operands[13];
2453
  rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
2454
  rtx scratch5 = operands[14];
2455
  rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
2456
  rtx scratch6 = operands[15];
2457
 
2458
  emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
2459
                               scratch0, scratch1));
2460
  /* inv0 == scratch4 */
2461
  if (! TARGET_DIVIDE_INV20U)
2462
    {
2463
      emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
2464
      i2p27 = scratch0;
2465
      emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
2466
    }
2467
  else
2468
    {
2469
      emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
2470
      emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2471
    }
2472
  emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
2473
  emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
2474
  emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
2475
  /* inv1 == scratch4 */
2476
 
2477
  if (TARGET_DIVIDE_INV_MINLAT)
2478
    {
2479
      emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
2480
      emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
2481
      emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
2482
      emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
2483
      emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
2484
      emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
2485
      emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
2486
      emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
2487
      emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
2488
      emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
2489
      emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
2490
    }
2491
  else
2492
    {
2493
      rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
2494
      /* Use separate scratch regs for nsb and sign to allow scheduling.  */
2495
      emit_insn (gen_nsbdi (scratch6,
2496
                            simplify_gen_subreg (DImode, dividend, SImode, 0)));
2497
      emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
2498
      emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
2499
      emit_insn (gen_divsi_inv20 (scratch2,
2500
                                  norm32, scratch4, dividend,
2501
                                  scratch6, scratch3, i43,
2502
                                  /* scratch0 may be shared with i2p27.  */
2503
                                  scratch0, scratch1, scratch5,
2504
                                  label, label, i2p27));
2505
    }
2506
  emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
2507
  emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
2508
  DONE;
2509
}")
2510
 
2511
(define_insn "divsi_inv20"
2512
  [(set (match_operand:DI 0 "register_operand" "=&r")
2513
        (unspec:DI [(match_operand:SI 1 "register_operand" "r")
2514
                    (match_operand:SI 2 "register_operand" "r")
2515
                    (match_operand:SI 3 "register_operand" "r")
2516
                    (match_operand:DI 4 "register_operand" "r")
2517
                    (match_operand:DI 5 "register_operand" "r")
2518
                    (match_operand:DI 6 "register_operand" "r")
2519
                    (match_operand:DI 12 "register_operand" "r")
2520
                    (match_operand 10 "target_operand" "b")
2521
                    (match_operand 11 "immediate_operand" "i")]
2522
         UNSPEC_DIV_INV20))
2523
   (clobber (match_operand:DI 7 "register_operand" "=&r"))
2524
   (clobber (match_operand:DI 8 "register_operand" "=&r"))
2525
   (clobber (match_operand:SI 9 "register_operand" "=r"))]
2526
  "TARGET_SHMEDIA
2527
   && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2528
  "*
2529
{
2530
/* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
2531
             %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
2532
             %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
2533
             %10 label (tr), %11 label (imm)
2534
 
2535
 muls.l inv1, norm32, scratch0  // s2.60
2536
  muls.l inv1, dividend, result // s32.30
2537
  xor i2p27, result_sign, round_scratch
2538
 bge/u dividend_nsb, i43, tr.. (label)
2539
 shari scratch0, 16, scratch0   // s-16.44
2540
 muls.l sratch0_si, inv1, scratch0 // s-16.74
2541
  sub result, round_scratch, result
2542
  shari dividend, 14, scratch1   // s19.-14
2543
 shari scratch0, 30, scratch0   // s-16.44
2544
 muls.l scratch0, scratch1, round_scratch // s15.30
2545
label:
2546
 sub result, round_scratch, result */
2547
 
2548
  int likely = TARGET_DIVIDE_INV20L;
2549
 
2550
  if (! likely) output_asm_insn (\"muls.l\t%2, %1 , %8\", operands);
2551
  output_asm_insn (\"muls.l\t%2, %3, %0\;xor\t%12, %5, %7\", operands);
2552
  output_asm_insn (likely
2553
                   ? \"bge/l\t%4, %6, %10\;muls.l\t%2, %1 , %8\"
2554
                   : \"bge/u\t%4, %6, %10\", operands);
2555
  output_asm_insn (\"shari\t%8, 16, %8\;muls.l\t%8, %2, %8\", operands);
2556
  if (! likely) output_asm_insn (\"sub\t%0, %7, %0\", operands);
2557
  output_asm_insn (\"shari\t%3, 14, %9\;shari\t%8, 30, %8\", operands);
2558
  return (likely
2559
          ? \"muls.l\t%8, %9, %8\;sub\t%0, %8, %0\n%11:\tadd\t%0, %7, %0\"
2560
          : \"muls.l\t%8, %9, %7\n%11:\tsub\t%0, %7, %0\");
2561
}")
2562
 
2563
(define_insn_and_split "divsi_inv_fp"
2564
  [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
2565
        (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
2566
                (match_operand:SI 2 "register_operand" "rf")))
2567
   (use (match_operand:SI 3 "general_movsrc_operand" "r"))
2568
   (clobber (match_operand:SI 4 "register_operand" "=r"))
2569
   (clobber (match_operand:SI 5 "register_operand" "=r"))
2570
   (clobber (match_operand:DF 6 "register_operand" "=r"))
2571
   (clobber (match_operand:DF 7 "register_operand" "=r"))
2572
   (clobber (match_operand:DF 8 "register_operand" "=r"))]
2573
  "TARGET_SHMEDIA_FPU"
2574
  "#"
2575
  "&& (high_life_started || reload_completed)"
2576
  [(set (match_dup 0) (match_dup 3))]
2577
  ""
2578
  [(set_attr "highpart" "must_split")])
2579
 
2580
;; If a matching group of divide-by-inverse instructions is in the same
2581
;; basic block after gcse & loop optimizations, we want to transform them
2582
;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
2583
(define_insn_and_split "*divsi_inv_fp_combine"
2584
  [(set (match_operand:SI 0 "register_operand" "=f")
2585
        (div:SI (match_operand:SI 1 "register_operand" "f")
2586
                (match_operand:SI 2 "register_operand" "f")))
2587
   (use (unspec:SI [(match_dup 1)
2588
                    (match_operand:SI 3 "" "")
2589
                    (unspec:SI [(match_operand:SI 4 "" "")
2590
                                (match_dup 3)
2591
                                (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
2592
                    (match_operand:DI 6 "" "")
2593
                    (const_int 0)
2594
                    (const_int 0)] UNSPEC_DIV_INV_M3))
2595
   (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
2596
   (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
2597
   (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
2598
   (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
2599
   (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
2600
  "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && no_new_pseudos"
2601
  "#"
2602
  "&& 1"
2603
  [(set (match_dup 9) (float:DF (match_dup 1)))
2604
   (set (match_dup 10) (float:DF (match_dup 2)))
2605
   (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
2606
   (set (match_dup 8)
2607
        (fix:SI (match_dup 11)))
2608
   (set (match_dup 0) (match_dup 8))]
2609
  "
2610
{
2611
  if (! fp_arith_reg_operand (operands[1], SImode))
2612
    {
2613
      emit_move_insn (operands[7], operands[1]);
2614
      operands[1] = operands[7];
2615
    }
2616
  if (! fp_arith_reg_operand (operands[2], SImode))
2617
    {
2618
      emit_move_insn (operands[8], operands[2]);
2619
      operands[2] = operands[8];
2620
    }
2621
}"
2622
  [(set_attr "highpart" "must_split")])
2623
 
2624
;; -------------------------------------------------------------------------
2625
;; Multiplication instructions
2626
;; -------------------------------------------------------------------------
2627
 
2628
(define_insn "umulhisi3_i"
2629
  [(set (reg:SI MACL_REG)
2630
        (mult:SI (zero_extend:SI
2631
                  (match_operand:HI 0 "arith_reg_operand" "r"))
2632
                 (zero_extend:SI
2633
                  (match_operand:HI 1 "arith_reg_operand" "r"))))]
2634
  "TARGET_SH1"
2635
  "mulu.w       %1,%0"
2636
  [(set_attr "type" "smpy")])
2637
 
2638
(define_insn "mulhisi3_i"
2639
  [(set (reg:SI MACL_REG)
2640
        (mult:SI (sign_extend:SI
2641
                  (match_operand:HI 0 "arith_reg_operand" "r"))
2642
                 (sign_extend:SI
2643
                  (match_operand:HI 1 "arith_reg_operand" "r"))))]
2644
  "TARGET_SH1"
2645
  "muls.w       %1,%0"
2646
  [(set_attr "type" "smpy")])
2647
 
2648
(define_expand "mulhisi3"
2649
  [(set (reg:SI MACL_REG)
2650
        (mult:SI (sign_extend:SI
2651
                  (match_operand:HI 1 "arith_reg_operand" ""))
2652
                 (sign_extend:SI
2653
                  (match_operand:HI 2 "arith_reg_operand" ""))))
2654
   (set (match_operand:SI 0 "arith_reg_operand" "")
2655
        (reg:SI MACL_REG))]
2656
  "TARGET_SH1"
2657
  "
2658
{
2659
  rtx first, last;
2660
 
2661
  first = emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
2662
  last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
2663
  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
2664
     invariant code motion can move it.  */
2665
  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
2666
  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2667
  /* expand_binop can't find a suitable code in umul_widen_optab to
2668
     make a REG_EQUAL note from, so make one here.
2669
     See also smulsi3_highpart.
2670
     ??? Alternatively, we could put this at the calling site of expand_binop,
2671
     i.e. expand_expr.  */
2672
  REG_NOTES (last)
2673
    = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
2674
                         REG_NOTES (last));
2675
  DONE;
2676
}")
2677
 
2678
(define_expand "umulhisi3"
2679
  [(set (reg:SI MACL_REG)
2680
        (mult:SI (zero_extend:SI
2681
                  (match_operand:HI 1 "arith_reg_operand" ""))
2682
                 (zero_extend:SI
2683
                  (match_operand:HI 2 "arith_reg_operand" ""))))
2684
   (set (match_operand:SI 0 "arith_reg_operand" "")
2685
        (reg:SI MACL_REG))]
2686
  "TARGET_SH1"
2687
  "
2688
{
2689
  rtx first, last;
2690
 
2691
  first = emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
2692
  last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
2693
  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
2694
     invariant code motion can move it.  */
2695
  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
2696
  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2697
  /* expand_binop can't find a suitable code in umul_widen_optab to
2698
     make a REG_EQUAL note from, so make one here.
2699
     See also smulsi3_highpart.
2700
     ??? Alternatively, we could put this at the calling site of expand_binop,
2701
     i.e. expand_expr.  */
2702
  REG_NOTES (last)
2703
    = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
2704
                         REG_NOTES (last));
2705
  DONE;
2706
}")
2707
 
2708
;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
2709
;; a call to a routine which clobbers known registers.
2710
 
2711
(define_insn ""
2712
  [(set (match_operand:SI 1 "register_operand" "=z")
2713
        (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2714
   (clobber (reg:SI MACL_REG))
2715
   (clobber (reg:SI T_REG))
2716
   (clobber (reg:SI PR_REG))
2717
   (clobber (reg:SI R3_REG))
2718
   (clobber (reg:SI R2_REG))
2719
   (clobber (reg:SI R1_REG))
2720
   (use (match_operand:SI 0 "arith_reg_operand" "r"))]
2721
  "TARGET_SH1"
2722
  "jsr  @%0%#"
2723
  [(set_attr "type" "sfunc")
2724
   (set_attr "needs_delay_slot" "yes")])
2725
 
2726
(define_expand "mulsi3_call"
2727
  [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2728
   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2729
   (parallel[(set (match_operand:SI 0 "register_operand" "")
2730
                  (mult:SI (reg:SI R4_REG)
2731
                           (reg:SI R5_REG)))
2732
             (clobber (reg:SI MACL_REG))
2733
             (clobber (reg:SI T_REG))
2734
             (clobber (reg:SI PR_REG))
2735
             (clobber (reg:SI R3_REG))
2736
             (clobber (reg:SI R2_REG))
2737
             (clobber (reg:SI R1_REG))
2738
             (use (match_operand:SI 3 "register_operand" ""))])]
2739
  "TARGET_SH1"
2740
  "")
2741
 
2742
(define_insn "mul_r"
2743
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2744
        (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
2745
                 (match_operand:SI 2 "arith_reg_operand" "z")))]
2746
  "TARGET_SH2A"
2747
  "mulr %2,%0"
2748
  [(set_attr "type" "dmpy")])
2749
 
2750
(define_insn "mul_l"
2751
  [(set (reg:SI MACL_REG)
2752
        (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
2753
                 (match_operand:SI 1 "arith_reg_operand" "r")))]
2754
  "TARGET_SH2"
2755
  "mul.l        %1,%0"
2756
  [(set_attr "type" "dmpy")])
2757
 
2758
(define_expand "mulsi3"
2759
  [(set (reg:SI MACL_REG)
2760
        (mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
2761
                  (match_operand:SI 2 "arith_reg_operand" "")))
2762
   (set (match_operand:SI 0 "arith_reg_operand" "")
2763
        (reg:SI MACL_REG))]
2764
  "TARGET_SH1"
2765
  "
2766
{
2767
  rtx first, last;
2768
 
2769
  if (!TARGET_SH2)
2770
    {
2771
      /* The address must be set outside the libcall,
2772
         since it goes into a pseudo.  */
2773
      rtx sym = function_symbol (NULL, \"__mulsi3\", SFUNC_STATIC);
2774
      rtx addr = force_reg (SImode, sym);
2775
      rtx insns = gen_mulsi3_call (operands[0], operands[1],
2776
                                   operands[2], addr);
2777
      first = insns;
2778
      last = emit_insn (insns);
2779
    }
2780
  else
2781
    {
2782
      rtx macl = gen_rtx_REG (SImode, MACL_REG);
2783
 
2784
      first = emit_insn (gen_mul_l (operands[1], operands[2]));
2785
      /* consec_sets_giv can only recognize the first insn that sets a
2786
         giv as the giv insn.  So we must tag this also with a REG_EQUAL
2787
         note.  */
2788
      last = emit_insn (gen_movsi_i ((operands[0]), macl));
2789
    }
2790
  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
2791
     invariant code motion can move it.  */
2792
  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
2793
  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2794
  DONE;
2795
}")
2796
 
2797
(define_insn "mulsidi3_i"
2798
  [(set (reg:SI MACH_REG)
2799
        (truncate:SI
2800
         (lshiftrt:DI
2801
          (mult:DI
2802
           (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2803
           (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2804
          (const_int 32))))
2805
   (set (reg:SI MACL_REG)
2806
        (mult:SI (match_dup 0)
2807
                 (match_dup 1)))]
2808
  "TARGET_SH2"
2809
  "dmuls.l      %1,%0"
2810
  [(set_attr "type" "dmpy")])
2811
 
2812
(define_expand "mulsidi3"
2813
  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2814
        (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2815
                 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2816
  "TARGET_SH2 || TARGET_SHMEDIA"
2817
  "
2818
{
2819
  if (TARGET_SH2)
2820
    {
2821
       emit_insn (gen_mulsidi3_compact (operands[0], operands[1],
2822
                                        operands[2]));
2823
       DONE;
2824
    }
2825
}")
2826
 
2827
(define_insn "mulsidi3_media"
2828
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2829
        (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2830
                 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2831
  "TARGET_SHMEDIA"
2832
  "muls.l       %1, %2, %0"
2833
  [(set_attr "type" "dmpy_media")
2834
   (set_attr "highpart" "ignore")])
2835
 
2836
(define_insn "mulsidi3_compact"
2837
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2838
        (mult:DI
2839
         (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2840
         (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2841
   (clobber (reg:SI MACH_REG))
2842
   (clobber (reg:SI MACL_REG))]
2843
  "TARGET_SH2"
2844
  "#")
2845
 
2846
(define_split
2847
  [(set (match_operand:DI 0 "arith_reg_dest" "")
2848
        (mult:DI
2849
         (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2850
         (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2851
   (clobber (reg:SI MACH_REG))
2852
   (clobber (reg:SI MACL_REG))]
2853
  "TARGET_SH2"
2854
  [(const_int 0)]
2855
  "
2856
{
2857
  rtx low_dst = gen_lowpart (SImode, operands[0]);
2858
  rtx high_dst = gen_highpart (SImode, operands[0]);
2859
 
2860
  emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
2861
 
2862
  emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
2863
  emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
2864
  /* We need something to tag the possible REG_EQUAL notes on to.  */
2865
  emit_move_insn (operands[0], operands[0]);
2866
  DONE;
2867
}")
2868
 
2869
(define_insn "umulsidi3_i"
2870
  [(set (reg:SI MACH_REG)
2871
        (truncate:SI
2872
         (lshiftrt:DI
2873
          (mult:DI
2874
           (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2875
           (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2876
          (const_int 32))))
2877
   (set (reg:SI MACL_REG)
2878
        (mult:SI (match_dup 0)
2879
                 (match_dup 1)))]
2880
  "TARGET_SH2"
2881
  "dmulu.l      %1,%0"
2882
  [(set_attr "type" "dmpy")])
2883
 
2884
(define_expand "umulsidi3"
2885
  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2886
        (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2887
                 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2888
  "TARGET_SH2 || TARGET_SHMEDIA"
2889
  "
2890
{
2891
  if (TARGET_SH2)
2892
    {
2893
       emit_insn (gen_umulsidi3_compact (operands[0], operands[1],
2894
                                         operands[2]));
2895
       DONE;
2896
    }
2897
}")
2898
 
2899
(define_insn "umulsidi3_media"
2900
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2901
        (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2902
                 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2903
  "TARGET_SHMEDIA"
2904
  "mulu.l       %1, %2, %0"
2905
  [(set_attr "type" "dmpy_media")
2906
   (set_attr "highpart" "ignore")])
2907
 
2908
(define_insn "umulsidi3_compact"
2909
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2910
        (mult:DI
2911
         (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2912
         (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2913
   (clobber (reg:SI MACH_REG))
2914
   (clobber (reg:SI MACL_REG))]
2915
  "TARGET_SH2"
2916
  "#")
2917
 
2918
(define_split
2919
  [(set (match_operand:DI 0 "arith_reg_dest" "")
2920
        (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2921
                 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2922
   (clobber (reg:SI MACH_REG))
2923
   (clobber (reg:SI MACL_REG))]
2924
  "TARGET_SH2"
2925
  [(const_int 0)]
2926
  "
2927
{
2928
  rtx low_dst = gen_lowpart (SImode, operands[0]);
2929
  rtx high_dst = gen_highpart (SImode, operands[0]);
2930
 
2931
  emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
2932
 
2933
  emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
2934
  emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
2935
  /* We need something to tag the possible REG_EQUAL notes on to.  */
2936
  emit_move_insn (operands[0], operands[0]);
2937
  DONE;
2938
}")
2939
 
2940
(define_insn "smulsi3_highpart_i"
2941
  [(set (reg:SI MACH_REG)
2942
        (truncate:SI
2943
         (lshiftrt:DI
2944
          (mult:DI
2945
           (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2946
           (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2947
          (const_int 32))))
2948
   (clobber (reg:SI MACL_REG))]
2949
  "TARGET_SH2"
2950
  "dmuls.l      %1,%0"
2951
  [(set_attr "type" "dmpy")])
2952
 
2953
(define_expand "smulsi3_highpart"
2954
  [(parallel
2955
    [(set (reg:SI MACH_REG)
2956
          (truncate:SI
2957
           (lshiftrt:DI
2958
            (mult:DI
2959
             (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2960
             (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
2961
            (const_int 32))))
2962
    (clobber (reg:SI MACL_REG))])
2963
   (set (match_operand:SI 0 "arith_reg_operand" "")
2964
        (reg:SI MACH_REG))]
2965
  "TARGET_SH2"
2966
  "
2967
{
2968
  rtx first, last;
2969
 
2970
  first = emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
2971
  last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
2972
  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
2973
     invariant code motion can move it.  */
2974
  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
2975
  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2976
  /* expand_binop can't find a suitable code in mul_highpart_optab to
2977
     make a REG_EQUAL note from, so make one here.
2978
     See also {,u}mulhisi.
2979
     ??? Alternatively, we could put this at the calling site of expand_binop,
2980
     i.e. expand_mult_highpart.  */
2981
  REG_NOTES (last)
2982
    = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
2983
                         REG_NOTES (last));
2984
  DONE;
2985
}")
2986
 
2987
(define_insn "umulsi3_highpart_i"
2988
  [(set (reg:SI MACH_REG)
2989
        (truncate:SI
2990
         (lshiftrt:DI
2991
          (mult:DI
2992
           (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2993
           (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2994
          (const_int 32))))
2995
   (clobber (reg:SI MACL_REG))]
2996
  "TARGET_SH2"
2997
  "dmulu.l      %1,%0"
2998
  [(set_attr "type" "dmpy")])
2999
 
3000
(define_expand "umulsi3_highpart"
3001
  [(parallel
3002
    [(set (reg:SI MACH_REG)
3003
          (truncate:SI
3004
           (lshiftrt:DI
3005
            (mult:DI
3006
             (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3007
             (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3008
            (const_int 32))))
3009
    (clobber (reg:SI MACL_REG))])
3010
   (set (match_operand:SI 0 "arith_reg_operand" "")
3011
        (reg:SI MACH_REG))]
3012
  "TARGET_SH2"
3013
  "
3014
{
3015
  rtx first, last;
3016
 
3017
  first = emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3018
  last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
3019
  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
3020
     invariant code motion can move it.  */
3021
  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
3022
  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
3023
  DONE;
3024
}")
3025
 
3026
(define_insn_and_split "muldi3"
3027
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3028
        (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3029
                 (match_operand:DI 2 "arith_reg_operand" "r")))
3030
   (clobber (match_scratch:DI 3 "=&r"))
3031
   (clobber (match_scratch:DI 4 "=r"))]
3032
  "TARGET_SHMEDIA"
3033
  "#"
3034
  "reload_completed"
3035
  [(const_int 0)]
3036
  "
3037
{
3038
  rtx op3_v2si, op2_v2si;
3039
 
3040
  op3_v2si = operands[3];
3041
  if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3042
    {
3043
      op3_v2si = XEXP (op3_v2si, 0);
3044
      op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3045
    }
3046
  op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3047
  op2_v2si = operands[2];
3048
  if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3049
    {
3050
      op2_v2si = XEXP (op2_v2si, 0);
3051
      op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3052
    }
3053
  op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3054
  emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3055
  emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3056
  emit_insn (gen_umulsidi3_media (operands[4],
3057
                                 sh_gen_truncate (SImode, operands[1], 0),
3058
                                 sh_gen_truncate (SImode, operands[2], 0)));
3059
  emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3060
  emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3061
  emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3062
  emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3063
  DONE;
3064
}")
3065
 
3066
 
3067
;; -------------------------------------------------------------------------
3068
;; Logical operations
3069
;; -------------------------------------------------------------------------
3070
 
3071
(define_insn "*andsi3_compact"
3072
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3073
        (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3074
                (match_operand:SI 2 "logical_operand" "r,K08")))]
3075
  "TARGET_SH1"
3076
  "and  %2,%0"
3077
  [(set_attr "type" "arith")])
3078
 
3079
(define_insn "*andsi3_media"
3080
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3081
        (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3082
                (match_operand:SI 2 "logical_operand" "r,I10")))]
3083
  "TARGET_SHMEDIA"
3084
  "@
3085
        and     %1, %2, %0
3086
        andi    %1, %2, %0"
3087
  [(set_attr "type" "arith_media")])
3088
 
3089
;; If the constant is 255, then emit an extu.b instruction instead of an
3090
;; and, since that will give better code.
3091
 
3092
(define_expand "andsi3"
3093
  [(set (match_operand:SI 0 "arith_reg_operand" "")
3094
        (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3095
                (match_operand:SI 2 "logical_operand" "")))]
3096
  ""
3097
  "
3098
{
3099
  if (TARGET_SH1
3100
      && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 255)
3101
    {
3102
      emit_insn (gen_zero_extendqisi2 (operands[0],
3103
                                       gen_lowpart (QImode, operands[1])));
3104
      DONE;
3105
    }
3106
}")
3107
 
3108
(define_insn_and_split "anddi3"
3109
  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3110
        (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3111
                (match_operand:DI 2 "and_operand" "r,I10,J16")))]
3112
  "TARGET_SHMEDIA"
3113
  "@
3114
        and     %1, %2, %0
3115
        andi    %1, %2, %0
3116
        #"
3117
  "reload_completed
3118
   && ! logical_operand (operands[2], DImode)"
3119
  [(const_int 0)]
3120
  "
3121
{
3122
  if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3123
    emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3124
  else
3125
    emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3126
  DONE;
3127
}"
3128
  [(set_attr "type" "arith_media")])
3129
 
3130
(define_insn "andcsi3"
3131
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3132
        (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3133
                (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3134
  "TARGET_SHMEDIA"
3135
  "andc %1,%2,%0"
3136
  [(set_attr "type" "arith_media")])
3137
 
3138
(define_insn "andcdi3"
3139
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3140
        (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3141
                (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3142
  "TARGET_SHMEDIA"
3143
  "andc %1,%2,%0"
3144
  [(set_attr "type" "arith_media")])
3145
 
3146
(define_expand "iorsi3"
3147
  [(set (match_operand:SI 0 "arith_reg_operand" "")
3148
        (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3149
                (match_operand:SI 2 "logical_operand" "")))]
3150
  ""
3151
  "")
3152
 
3153
(define_insn "*iorsi3_compact"
3154
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3155
        (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3156
                (match_operand:SI 2 "logical_operand" "r,K08")))]
3157
  "TARGET_SH1"
3158
  "or   %2,%0"
3159
  [(set_attr "type" "arith")])
3160
 
3161
(define_insn "*iorsi3_media"
3162
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3163
        (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3164
                (match_operand:SI 2 "logical_operand" "r,I10")))]
3165
  "TARGET_SHMEDIA"
3166
  "@
3167
        or      %1, %2, %0
3168
        ori     %1, %2, %0"
3169
  [(set_attr "type" "arith_media")])
3170
 
3171
(define_insn "iordi3"
3172
  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3173
        (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3174
                (match_operand:DI 2 "logical_operand" "r,I10")))]
3175
  "TARGET_SHMEDIA"
3176
  "@
3177
        or      %1, %2, %0
3178
        ori     %1, %2, %0"
3179
  [(set_attr "type" "arith_media")])
3180
 
3181
(define_insn_and_split "*logical_sidi3"
3182
  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3183
        (sign_extend:DI (match_operator:SI 3 "logical_operator"
3184
                          [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3185
                           (match_operand:SI 2 "logical_operand" "r,I10")])))]
3186
  "TARGET_SHMEDIA"
3187
  "#"
3188
  "&& reload_completed"
3189
  [(set (match_dup 0) (match_dup 3))]
3190
  "
3191
{
3192
  operands[3]
3193
    = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3194
                      simplify_gen_subreg (DImode, operands[1], SImode, 0),
3195
                      simplify_gen_subreg (DImode, operands[2], SImode, 0));
3196
}")
3197
 
3198
(define_insn_and_split "*logical_sidisi3"
3199
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3200
        (truncate:SI (sign_extend:DI
3201
                        (match_operator:SI 3 "logical_operator"
3202
                          [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3203
                           (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3204
  "TARGET_SHMEDIA"
3205
  "#"
3206
  "&& 1"
3207
  [(set (match_dup 0) (match_dup 3))])
3208
 
3209
(define_insn_and_split "*logical_sidi3_2"
3210
  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3211
        (sign_extend:DI (truncate:SI (sign_extend:DI
3212
                        (match_operator:SI 3 "logical_operator"
3213
                          [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3214
                           (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3215
  "TARGET_SHMEDIA"
3216
  "#"
3217
  "&& 1"
3218
  [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3219
 
3220
(define_expand "xorsi3"
3221
  [(set (match_operand:SI 0 "arith_reg_operand" "")
3222
        (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3223
                (match_operand:SI 2 "xor_operand" "")))]
3224
  ""
3225
  "")
3226
 
3227
(define_insn "*xorsi3_compact"
3228
  [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3229
        (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3230
                (match_operand:SI 2 "logical_operand" "K08,r")))]
3231
  "TARGET_SH1"
3232
  "xor  %2,%0"
3233
  [(set_attr "type" "arith")])
3234
 
3235
(define_insn "*xorsi3_media"
3236
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3237
        (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3238
                (match_operand:SI 2 "xor_operand" "r,I06")))]
3239
  "TARGET_SHMEDIA"
3240
  "@
3241
        xor     %1, %2, %0
3242
        xori    %1, %2, %0"
3243
  [(set_attr "type" "arith_media")])
3244
 
3245
(define_insn "xordi3"
3246
  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3247
        (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3248
                (match_operand:DI 2 "xor_operand" "r,I06")))]
3249
  "TARGET_SHMEDIA"
3250
  "@
3251
        xor     %1, %2, %0
3252
        xori    %1, %2, %0"
3253
  [(set_attr "type" "arith_media")])
3254
 
3255
;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3256
;; converts 2 * sign extend -> logical op into logical op -> sign extend
3257
(define_split
3258
  [(set (match_operand:DI 0 "arith_reg_dest" "")
3259
        (sign_extend:DI (match_operator 4 "binary_logical_operator"
3260
                          [(match_operand 1 "any_register_operand" "")
3261
                           (match_operand 2 "any_register_operand" "")])))]
3262
  "TARGET_SHMEDIA"
3263
  [(set (match_dup 5) (match_dup 4))
3264
   (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3265
"
3266
{
3267
  enum machine_mode inmode = GET_MODE (operands[1]);
3268
  int offset = 0;
3269
 
3270
  if (GET_CODE (operands[0]) == SUBREG)
3271
    {
3272
      offset = SUBREG_BYTE (operands[0]);
3273
      operands[0] = SUBREG_REG (operands[0]);
3274
    }
3275
  gcc_assert (GET_CODE (operands[0]) == REG);
3276
  if (! TARGET_LITTLE_ENDIAN)
3277
    offset += 8 - GET_MODE_SIZE (inmode);
3278
  operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3279
}")
3280
 
3281
;; -------------------------------------------------------------------------
3282
;; Shifts and rotates
3283
;; -------------------------------------------------------------------------
3284
 
3285
(define_expand "rotldi3"
3286
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3287
        (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3288
                   (match_operand:HI 2 "mextr_bit_offset" "i")))]
3289
  "TARGET_SHMEDIA"
3290
  "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3291
 
3292
(define_insn "rotldi3_mextr"
3293
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3294
        (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3295
                   (match_operand:HI 2 "mextr_bit_offset" "i")))]
3296
  "TARGET_SHMEDIA"
3297
  "*
3298
{
3299
  static char templ[16];
3300
 
3301
  sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\",
3302
           8 - (int) (INTVAL (operands[2]) >> 3));
3303
  return templ;
3304
}"
3305
  [(set_attr "type" "arith_media")])
3306
 
3307
(define_expand "rotrdi3"
3308
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3309
        (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3310
                     (match_operand:HI 2 "mextr_bit_offset" "i")))]
3311
  "TARGET_SHMEDIA"
3312
  "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3313
 
3314
(define_insn "rotrdi3_mextr"
3315
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3316
        (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3317
                     (match_operand:HI 2 "mextr_bit_offset" "i")))]
3318
  "TARGET_SHMEDIA"
3319
  "*
3320
{
3321
  static char templ[16];
3322
 
3323
  sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\", (int) INTVAL (operands[2]) >> 3);
3324
  return templ;
3325
}"
3326
  [(set_attr "type" "arith_media")])
3327
 
3328
(define_split
3329
  [(set (match_operand:DI 0 "arith_reg_dest" "")
3330
        (ior:DI (zero_extend:DI (mem:QI (match_operand 1
3331
                                         "ua_address_operand" "")))
3332
                (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
3333
                           (const_int 8))))
3334
   (clobber (match_operand:DI 3 "register_operand" ""))]
3335
  "TARGET_SHMEDIA"
3336
  [(match_dup 4) (match_dup 5)]
3337
  "
3338
{
3339
  operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
3340
                 (operands[3], operands[1]));
3341
  operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
3342
                              GEN_INT (56), GEN_INT (8));
3343
}")
3344
 
3345
(define_insn "rotlsi3_1"
3346
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3347
        (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3348
                   (const_int 1)))
3349
   (set (reg:SI T_REG)
3350
        (lshiftrt:SI (match_dup 1) (const_int 31)))]
3351
  "TARGET_SH1"
3352
  "rotl %0"
3353
  [(set_attr "type" "arith")])
3354
 
3355
(define_insn "rotlsi3_31"
3356
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3357
        (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3358
                   (const_int 31)))
3359
   (clobber (reg:SI T_REG))]
3360
  "TARGET_SH1"
3361
  "rotr %0"
3362
  [(set_attr "type" "arith")])
3363
 
3364
(define_insn "rotlsi3_16"
3365
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3366
        (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
3367
                   (const_int 16)))]
3368
  "TARGET_SH1"
3369
  "swap.w       %1,%0"
3370
  [(set_attr "type" "arith")])
3371
 
3372
(define_expand "rotlsi3"
3373
  [(set (match_operand:SI 0 "arith_reg_dest" "")
3374
        (rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
3375
                   (match_operand:SI 2 "immediate_operand" "")))]
3376
  "TARGET_SH1"
3377
  "
3378
{
3379
  static const char rot_tab[] = {
3380
    000, 000, 000, 000, 000, 000, 010, 001,
3381
    001, 001, 011, 013, 003, 003, 003, 003,
3382
    003, 003, 003, 003, 003, 013, 012, 002,
3383
    002, 002, 010, 000, 000, 000, 000, 000,
3384
  };
3385
 
3386
  int count, choice;
3387
 
3388
  if (GET_CODE (operands[2]) != CONST_INT)
3389
    FAIL;
3390
  count = INTVAL (operands[2]);
3391
  choice = rot_tab[count];
3392
  if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
3393
    FAIL;
3394
  choice &= 7;
3395
  switch (choice)
3396
    {
3397
    case 0:
3398
      emit_move_insn (operands[0], operands[1]);
3399
      count -= (count & 16) * 2;
3400
      break;
3401
    case 3:
3402
     emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
3403
     count -= 16;
3404
     break;
3405
    case 1:
3406
    case 2:
3407
      {
3408
        rtx parts[2];
3409
        parts[0] = gen_reg_rtx (SImode);
3410
        parts[1] = gen_reg_rtx (SImode);
3411
        emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
3412
        emit_move_insn (parts[choice-1], operands[1]);
3413
        emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
3414
        emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
3415
        emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
3416
        count = (count & ~16) - 8;
3417
      }
3418
    }
3419
 
3420
  for (; count > 0; count--)
3421
    emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
3422
  for (; count < 0; count++)
3423
    emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
3424
 
3425
  DONE;
3426
}")
3427
 
3428
(define_insn "*rotlhi3_8"
3429
  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3430
        (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
3431
                   (const_int 8)))]
3432
  "TARGET_SH1"
3433
  "swap.b       %1,%0"
3434
  [(set_attr "type" "arith")])
3435
 
3436
(define_expand "rotlhi3"
3437
  [(set (match_operand:HI 0 "arith_reg_operand" "")
3438
        (rotate:HI (match_operand:HI 1 "arith_reg_operand" "")
3439
                   (match_operand:HI 2 "immediate_operand" "")))]
3440
  "TARGET_SH1"
3441
  "
3442
{
3443
  if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8)
3444
    FAIL;
3445
}")
3446
 
3447
;;
3448
;; shift left
3449
 
3450
(define_insn "ashlsi3_sh2a"
3451
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3452
        (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3453
                   (match_operand:SI 2 "arith_reg_operand" "r")))]
3454
  "TARGET_SH2A"
3455
  "shad %2,%0"
3456
  [(set_attr "type" "arith")
3457
   (set_attr "length" "4")])
3458
 
3459
;; This pattern is used by init_expmed for computing the costs of shift
3460
;; insns.
3461
 
3462
(define_insn_and_split "ashlsi3_std"
3463
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,r,r")
3464
        (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
3465
                   (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
3466
   (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
3467
  "TARGET_SH3
3468
   || (TARGET_SH1 && GET_CODE (operands[2]) == CONST_INT
3469
       && CONST_OK_FOR_P27 (INTVAL (operands[2])))"
3470
  "@
3471
   shld %2,%0
3472
   add  %0,%0
3473
   shll%O2      %0
3474
   #"
3475
  "TARGET_SH3
3476
   && reload_completed
3477
   && GET_CODE (operands[2]) == CONST_INT
3478
   && ! CONST_OK_FOR_P27 (INTVAL (operands[2]))"
3479
  [(set (match_dup 3) (match_dup 2))
3480
   (parallel
3481
    [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
3482
     (clobber (match_dup 4))])]
3483
  "operands[4] = gen_rtx_SCRATCH (SImode);"
3484
  [(set_attr "length" "*,*,*,4")
3485
   (set_attr "type" "dyn_shift,arith,arith,arith")])
3486
 
3487
(define_insn "ashlhi3_k"
3488
  [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
3489
        (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
3490
                   (match_operand:HI 2 "const_int_operand" "M,P27")))]
3491
  "TARGET_SH1 && CONST_OK_FOR_P27 (INTVAL (operands[2]))"
3492
  "@
3493
        add     %0,%0
3494
        shll%O2 %0"
3495
  [(set_attr "type" "arith")])
3496
 
3497
(define_insn "ashlsi3_n"
3498
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3499
        (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3500
                   (match_operand:SI 2 "const_int_operand" "n")))
3501
   (clobber (reg:SI T_REG))]
3502
  "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3503
  "#"
3504
  [(set (attr "length")
3505
        (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3506
               (const_string "2")
3507
               (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3508
               (const_string "4")
3509
               (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3510
               (const_string "6")]
3511
              (const_string "8")))
3512
   (set_attr "type" "arith")])
3513
 
3514
(define_split
3515
  [(set (match_operand:SI 0 "arith_reg_dest" "")
3516
        (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3517
                   (match_operand:SI 2 "const_int_operand" "")))
3518
   (clobber (reg:SI T_REG))]
3519
  "TARGET_SH1 && reload_completed"
3520
  [(use (reg:SI R0_REG))]
3521
  "
3522
{
3523
  gen_shifty_op (ASHIFT, operands);
3524
  DONE;
3525
}")
3526
 
3527
(define_insn "ashlsi3_media"
3528
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3529
        (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3530
                   (match_operand:SI 2 "shift_count_operand" "r,n")))]
3531
  "TARGET_SHMEDIA"
3532
  "@
3533
        shlld.l %1, %2, %0
3534
        shlli.l %1, %2, %0"
3535
  [(set_attr "type" "arith_media")
3536
   (set_attr "highpart" "ignore")])
3537
 
3538
(define_expand "ashlsi3"
3539
  [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3540
                   (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3541
                              (match_operand:SI 2 "nonmemory_operand" "")))
3542
              (clobber (reg:SI T_REG))])]
3543
  ""
3544
  "
3545
{
3546
  if (TARGET_SHMEDIA)
3547
    {
3548
      emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
3549
      DONE;
3550
    }
3551
  if (GET_CODE (operands[2]) == CONST_INT
3552
      && sh_dynamicalize_shift_p (operands[2]))
3553
    operands[2] = force_reg (SImode, operands[2]);
3554
  if (TARGET_SH3)
3555
    {
3556
      emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
3557
      DONE;
3558
    }
3559
  if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3560
    FAIL;
3561
}")
3562
 
3563
(define_insn "*ashlhi3_n"
3564
  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3565
        (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
3566
                   (match_operand:HI 2 "const_int_operand" "n")))
3567
   (clobber (reg:SI T_REG))]
3568
  "TARGET_SH1"
3569
  "#"
3570
  [(set (attr "length")
3571
        (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3572
               (const_string "2")
3573
               (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3574
               (const_string "4")]
3575
              (const_string "6")))
3576
   (set_attr "type" "arith")])
3577
 
3578
(define_expand "ashlhi3"
3579
  [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
3580
                   (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3581
                              (match_operand:SI 2 "nonmemory_operand" "")))
3582
              (clobber (reg:SI T_REG))])]
3583
  "TARGET_SH1"
3584
  "
3585
{
3586
  if (GET_CODE (operands[2]) != CONST_INT)
3587
    FAIL;
3588
  /* It may be possible to call gen_ashlhi3 directly with more generic
3589
     operands.  Make sure operands[1] is a HImode register here.  */
3590
  if (!arith_reg_operand (operands[1], HImode))
3591
    operands[1] = copy_to_mode_reg (HImode, operands[1]);
3592
}")
3593
 
3594
(define_split
3595
  [(set (match_operand:HI 0 "arith_reg_dest" "")
3596
        (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3597
                   (match_operand:HI 2 "const_int_operand" "")))
3598
   (clobber (reg:SI T_REG))]
3599
  "TARGET_SH1 && reload_completed"
3600
  [(use (reg:SI R0_REG))]
3601
  "
3602
{
3603
  gen_shifty_hi_op (ASHIFT, operands);
3604
  DONE;
3605
}")
3606
 
3607
;
3608
; arithmetic shift right
3609
;
3610
 
3611
(define_insn "ashrsi3_sh2a"
3612
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3613
        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3614
                   (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3615
  "TARGET_SH2A"
3616
  "shad %2,%0"
3617
  [(set_attr "type" "dyn_shift")
3618
   (set_attr "length" "4")])
3619
 
3620
(define_insn "ashrsi3_k"
3621
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3622
        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3623
                     (match_operand:SI 2 "const_int_operand" "M")))
3624
   (clobber (reg:SI T_REG))]
3625
  "TARGET_SH1 && INTVAL (operands[2]) == 1"
3626
  "shar %0"
3627
  [(set_attr "type" "arith")])
3628
 
3629
;; We can't do HImode right shifts correctly unless we start out with an
3630
;; explicit zero / sign extension; doing that would result in worse overall
3631
;; code, so just let the machine independent code widen the mode.
3632
;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
3633
 
3634
 
3635
;; ??? This should be a define expand.
3636
 
3637
(define_insn "ashrsi2_16"
3638
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3639
        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
3640
                     (const_int 16)))]
3641
  "TARGET_SH1"
3642
  "#"
3643
  [(set_attr "length" "4")])
3644
 
3645
(define_split
3646
  [(set (match_operand:SI 0 "arith_reg_dest" "")
3647
        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3648
                     (const_int 16)))]
3649
  "TARGET_SH1"
3650
  [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
3651
   (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3652
  "operands[2] = gen_lowpart (HImode, operands[0]);")
3653
 
3654
;; ??? This should be a define expand.
3655
 
3656
(define_insn "ashrsi2_31"
3657
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3658
        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3659
                     (const_int 31)))
3660
   (clobber (reg:SI T_REG))]
3661
  "TARGET_SH1"
3662
  "#"
3663
  [(set_attr "length" "4")])
3664
 
3665
(define_split
3666
  [(set (match_operand:SI 0 "arith_reg_dest" "")
3667
        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3668
                     (const_int 31)))
3669
   (clobber (reg:SI T_REG))]
3670
  "TARGET_SH1"
3671
  [(const_int 0)]
3672
  "
3673
{
3674
  emit_insn (gen_ashlsi_c (operands[0], operands[1]));
3675
  emit_insn (gen_mov_neg_si_t (operands[0]));
3676
  DONE;
3677
}")
3678
 
3679
(define_peephole2
3680
  [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
3681
   (set (reg:SI T_REG)
3682
        (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
3683
  "TARGET_SH1
3684
   && peep2_reg_dead_p (2, operands[0])
3685
   && peep2_reg_dead_p (2, operands[1])"
3686
  [(const_int 0)]
3687
  "
3688
{
3689
  emit_insn (gen_ashlsi_c (operands[1], operands[1]));
3690
  DONE;
3691
}")
3692
 
3693
(define_insn "ashlsi_c"
3694
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3695
        (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
3696
   (set (reg:SI T_REG)
3697
        (lt:SI (match_dup 1) (const_int 0)))]
3698
  "TARGET_SH1"
3699
  "shll %0"
3700
  [(set_attr "type" "arith")])
3701
 
3702
(define_insn "*ashlsi_c_void"
3703
  [(set (reg:SI T_REG)
3704
        (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
3705
   (clobber (match_scratch:SI 1 "=0"))]
3706
  "TARGET_SH1 && cse_not_expected"
3707
  "shll %0"
3708
  [(set_attr "type" "arith")])
3709
 
3710
(define_insn "ashrsi3_d"
3711
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3712
        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3713
                     (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3714
  "TARGET_SH3"
3715
  "shad %2,%0"
3716
  [(set_attr "type" "dyn_shift")])
3717
 
3718
(define_insn "ashrsi3_n"
3719
  [(set (reg:SI R4_REG)
3720
        (ashiftrt:SI (reg:SI R4_REG)
3721
                     (match_operand:SI 0 "const_int_operand" "i")))
3722
   (clobber (reg:SI T_REG))
3723
   (clobber (reg:SI PR_REG))
3724
   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
3725
  "TARGET_SH1"
3726
  "jsr  @%1%#"
3727
  [(set_attr "type" "sfunc")
3728
   (set_attr "needs_delay_slot" "yes")])
3729
 
3730
(define_insn "ashrsi3_media"
3731
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3732
        (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3733
                     (match_operand:SI 2 "shift_count_operand" "r,n")))]
3734
  "TARGET_SHMEDIA"
3735
  "@
3736
        shard.l %1, %2, %0
3737
        shari.l %1, %2, %0"
3738
  [(set_attr "type" "arith_media")
3739
   (set_attr "highpart" "ignore")])
3740
 
3741
(define_expand "ashrsi3"
3742
  [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3743
                   (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3744
                                (match_operand:SI 2 "nonmemory_operand" "")))
3745
              (clobber (reg:SI T_REG))])]
3746
  ""
3747
  "
3748
{
3749
  if (TARGET_SHMEDIA)
3750
    {
3751
      emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
3752
      DONE;
3753
    }
3754
  if (expand_ashiftrt (operands))
3755
    DONE;
3756
  else
3757
    FAIL;
3758
}")
3759
 
3760
;; logical shift right
3761
 
3762
(define_insn "lshrsi3_sh2a"
3763
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3764
        (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3765
                     (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3766
  "TARGET_SH2A"
3767
  "shld %2,%0"
3768
  [(set_attr "type" "dyn_shift")
3769
   (set_attr "length" "4")])
3770
 
3771
(define_insn "lshrsi3_d"
3772
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3773
        (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3774
                     (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3775
  "TARGET_SH3"
3776
  "shld %2,%0"
3777
  [(set_attr "type" "dyn_shift")])
3778
 
3779
;;  Only the single bit shift clobbers the T bit.
3780
 
3781
(define_insn "lshrsi3_m"
3782
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3783
        (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3784
                     (match_operand:SI 2 "const_int_operand" "M")))
3785
   (clobber (reg:SI T_REG))]
3786
  "TARGET_SH1 && CONST_OK_FOR_M (INTVAL (operands[2]))"
3787
  "shlr %0"
3788
  [(set_attr "type" "arith")])
3789
 
3790
(define_insn "lshrsi3_k"
3791
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3792
        (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3793
                     (match_operand:SI 2 "const_int_operand" "P27")))]
3794
  "TARGET_SH1 && CONST_OK_FOR_P27 (INTVAL (operands[2]))
3795
   && ! CONST_OK_FOR_M (INTVAL (operands[2]))"
3796
  "shlr%O2      %0"
3797
  [(set_attr "type" "arith")])
3798
 
3799
(define_insn "lshrsi3_n"
3800
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3801
        (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3802
                     (match_operand:SI 2 "const_int_operand" "n")))
3803
   (clobber (reg:SI T_REG))]
3804
  "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3805
  "#"
3806
  [(set (attr "length")
3807
        (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3808
               (const_string "2")
3809
               (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3810
               (const_string "4")
3811
               (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3812
               (const_string "6")]
3813
              (const_string "8")))
3814
   (set_attr "type" "arith")])
3815
 
3816
(define_split
3817
  [(set (match_operand:SI 0 "arith_reg_dest" "")
3818
        (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3819
                     (match_operand:SI 2 "const_int_operand" "")))
3820
   (clobber (reg:SI T_REG))]
3821
  "TARGET_SH1 && reload_completed"
3822
  [(use (reg:SI R0_REG))]
3823
  "
3824
{
3825
  gen_shifty_op (LSHIFTRT, operands);
3826
  DONE;
3827
}")
3828
 
3829
(define_insn "lshrsi3_media"
3830
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3831
        (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3832
                     (match_operand:SI 2 "shift_count_operand" "r,n")))]
3833
  "TARGET_SHMEDIA"
3834
  "@
3835
        shlrd.l %1, %2, %0
3836
        shlri.l %1, %2, %0"
3837
  [(set_attr "type" "arith_media")
3838
   (set_attr "highpart" "ignore")])
3839
 
3840
(define_expand "lshrsi3"
3841
  [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
3842
                   (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3843
                                (match_operand:SI 2 "nonmemory_operand" "")))
3844
              (clobber (reg:SI T_REG))])]
3845
  ""
3846
  "
3847
{
3848
  if (TARGET_SHMEDIA)
3849
    {
3850
      emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
3851
      DONE;
3852
    }
3853
  if (GET_CODE (operands[2]) == CONST_INT
3854
      && sh_dynamicalize_shift_p (operands[2]))
3855
    operands[2] = force_reg (SImode, operands[2]);
3856
  if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
3857
    {
3858
      rtx count = copy_to_mode_reg (SImode, operands[2]);
3859
      emit_insn (gen_negsi2 (count, count));
3860
      emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
3861
      DONE;
3862
    }
3863
  if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3864
    FAIL;
3865
}")
3866
 
3867
;; ??? This should be a define expand.
3868
 
3869
(define_insn "ashldi3_k"
3870
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3871
        (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
3872
                   (const_int 1)))
3873
   (clobber (reg:SI T_REG))]
3874
  "TARGET_SH1"
3875
  "shll %R0\;rotcl      %S0"
3876
  [(set_attr "length" "4")
3877
   (set_attr "type" "arith")])
3878
 
3879
(define_insn "ashldi3_media"
3880
  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3881
        (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3882
                   (match_operand:DI 2 "shift_count_operand" "r,n")))]
3883
  "TARGET_SHMEDIA"
3884
  "@
3885
        shlld   %1, %2, %0
3886
        shlli   %1, %2, %0"
3887
  [(set_attr "type" "arith_media")])
3888
 
3889
(define_insn "*ashldisi3_media"
3890
  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
3891
        (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
3892
                   (match_operand:DI 2 "const_int_operand" "n")))]
3893
  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
3894
  "shlli.l      %1, %2, %0"
3895
  [(set_attr "type" "arith_media")
3896
   (set_attr "highpart" "ignore")])
3897
 
3898
(define_expand "ashldi3"
3899
  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
3900
                   (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
3901
                              (match_operand:DI 2 "immediate_operand" "")))
3902
              (clobber (reg:SI T_REG))])]
3903
  ""
3904
  "
3905
{
3906
  if (TARGET_SHMEDIA)
3907
    {
3908
      emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
3909
      DONE;
3910
    }
3911
  if (GET_CODE (operands[2]) != CONST_INT
3912
      || INTVAL (operands[2]) != 1)
3913
    FAIL;
3914
}")
3915
 
3916
;; ??? This should be a define expand.
3917
 
3918
(define_insn "lshrdi3_k"
3919
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3920
        (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
3921
                     (const_int 1)))
3922
   (clobber (reg:SI T_REG))]
3923
  "TARGET_SH1"
3924
  "shlr %S0\;rotcr      %R0"
3925
  [(set_attr "length" "4")
3926
   (set_attr "type" "arith")])
3927
 
3928
(define_insn "lshrdi3_media"
3929
  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
3930
        (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3931
                     (match_operand:DI 2 "shift_count_operand" "r,n")))]
3932
  "TARGET_SHMEDIA
3933
   && (arith_reg_dest (operands[0], DImode)
3934
       || (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 32))"
3935
  "@
3936
        shlrd   %1, %2, %0
3937
        shlri   %1, %2, %0"
3938
  [(set_attr "type" "arith_media")])
3939
 
3940
(define_insn "*lshrdisi3_media"
3941
  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
3942
        (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
3943
                     (match_operand:DI 2 "const_int_operand" "n")))]
3944
  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
3945
  "shlri.l      %1, %2, %0"
3946
  [(set_attr "type" "arith_media")
3947
   (set_attr "highpart" "ignore")])
3948
 
3949
(define_expand "lshrdi3"
3950
  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
3951
                   (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
3952
                               (match_operand:DI 2 "immediate_operand" "")))
3953
             (clobber (reg:SI T_REG))])]
3954
  ""
3955
  "
3956
{
3957
  if (TARGET_SHMEDIA)
3958
    {
3959
      emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
3960
      DONE;
3961
    }
3962
  if (GET_CODE (operands[2]) != CONST_INT
3963
      || INTVAL (operands[2]) != 1)
3964
    FAIL;
3965
}")
3966
 
3967
;; ??? This should be a define expand.
3968
 
3969
(define_insn "ashrdi3_k"
3970
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3971
        (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
3972
                     (const_int 1)))
3973
   (clobber (reg:SI T_REG))]
3974
  "TARGET_SH1"
3975
  "shar %S0\;rotcr      %R0"
3976
  [(set_attr "length" "4")
3977
   (set_attr "type" "arith")])
3978
 
3979
(define_insn "ashrdi3_media"
3980
  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
3981
        (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3982
                     (match_operand:DI 2 "shift_count_operand" "r,n")))]
3983
  "TARGET_SHMEDIA
3984
   && (arith_reg_dest (operands[0], DImode)
3985
       || (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32))"
3986
  "@
3987
        shard   %1, %2, %0
3988
        shari   %1, %2, %0"
3989
  [(set_attr "type" "arith_media")])
3990
 
3991
(define_insn "*ashrdisi3_media"
3992
  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
3993
        (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
3994
                     (match_operand:DI 2 "const_int_operand" "n")))]
3995
  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
3996
  "shari.l      %1, %2, %0"
3997
  [(set_attr "type" "arith_media")
3998
   (set_attr "highpart" "ignore")])
3999
 
4000
(define_insn "ashrdisi3_media_high"
4001
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4002
        (truncate:SI
4003
           (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4004
                        (match_operand:DI 2 "const_int_operand" "n"))))]
4005
  "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
4006
  "shari        %1, %2, %0"
4007
  [(set_attr "type" "arith_media")])
4008
 
4009
(define_insn "ashrdisi3_media_opaque"
4010
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4011
        (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
4012
                    (match_operand:DI 2 "const_int_operand" "n")]
4013
         UNSPEC_ASHIFTRT))]
4014
  "TARGET_SHMEDIA"
4015
  "shari        %1, %2, %0"
4016
  [(set_attr "type" "arith_media")])
4017
 
4018
(define_expand "ashrdi3"
4019
  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4020
                   (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4021
                                (match_operand:DI 2 "immediate_operand" "")))
4022
              (clobber (reg:SI T_REG))])]
4023
  ""
4024
  "
4025
{
4026
  if (TARGET_SHMEDIA)
4027
    {
4028
      emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4029
      DONE;
4030
    }
4031
  if (GET_CODE (operands[2]) != CONST_INT
4032
      || INTVAL (operands[2]) != 1)
4033
    FAIL;
4034
}")
4035
 
4036
;; combined left/right shift
4037
 
4038
(define_split
4039
  [(set (match_operand:SI 0 "register_operand" "")
4040
        (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4041
                           (match_operand:SI 2 "const_int_operand" ""))
4042
                (match_operand:SI 3 "const_int_operand" "")))]
4043
  "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4044
  [(use (reg:SI R0_REG))]
4045
  "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4046
   DONE;")
4047
 
4048
(define_split
4049
  [(set (match_operand:SI 0 "register_operand" "")
4050
        (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4051
                           (match_operand:SI 2 "const_int_operand" ""))
4052
                (match_operand:SI 3 "const_int_operand" "")))
4053
   (clobber (reg:SI T_REG))]
4054
  "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4055
  [(use (reg:SI R0_REG))]
4056
  "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4057
   DONE;")
4058
 
4059
(define_insn ""
4060
  [(set (match_operand:SI 0 "register_operand" "=r")
4061
        (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4062
                           (match_operand:SI 2 "const_int_operand" "n"))
4063
                (match_operand:SI 3 "const_int_operand" "n")))
4064
   (clobber (reg:SI T_REG))]
4065
  "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
4066
 "#"
4067
  [(set (attr "length")
4068
        (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4069
               (const_string "4")
4070
               (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4071
               (const_string "6")
4072
               (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4073
               (const_string "8")
4074
               (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
4075
               (const_string "10")
4076
               (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
4077
               (const_string "12")
4078
               (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
4079
               (const_string "14")
4080
               (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
4081
               (const_string "16")]
4082
              (const_string "18")))
4083
   (set_attr "type" "arith")])
4084
 
4085
(define_insn ""
4086
  [(set (match_operand:SI 0 "register_operand" "=z")
4087
        (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4088
                           (match_operand:SI 2 "const_int_operand" "n"))
4089
                (match_operand:SI 3 "const_int_operand" "n")))
4090
   (clobber (reg:SI T_REG))]
4091
  "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
4092
 "#"
4093
  [(set (attr "length")
4094
        (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4095
               (const_string "4")
4096
               (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4097
               (const_string "6")
4098
               (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4099
               (const_string "8")]
4100
              (const_string "10")))
4101
   (set_attr "type" "arith")])
4102
 
4103
;; shift left / and combination with a scratch register: The combine pass
4104
;; does not accept the individual instructions, even though they are
4105
;; cheap.  But it needs a precise description so that it is usable after
4106
;; reload.
4107
(define_insn "and_shl_scratch"
4108
  [(set (match_operand:SI 0 "register_operand" "=r,&r")
4109
        (lshiftrt:SI
4110
         (ashift:SI
4111
          (and:SI
4112
           (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
4113
                        (match_operand:SI 2 "const_int_operand" "N,n"))
4114
           (match_operand:SI 3 "" "0,r"))
4115
          (match_operand:SI 4 "const_int_operand" "n,n"))
4116
         (match_operand:SI 5 "const_int_operand" "n,n")))
4117
   (clobber (reg:SI T_REG))]
4118
  "TARGET_SH1"
4119
  "#"
4120
  [(set (attr "length")
4121
        (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
4122
               (const_string "4")
4123
               (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
4124
               (const_string "6")
4125
               (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
4126
               (const_string "8")
4127
               (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
4128
               (const_string "10")]
4129
              (const_string "12")))
4130
   (set_attr "type" "arith")])
4131
 
4132
(define_split
4133
  [(set (match_operand:SI 0 "register_operand" "")
4134
        (lshiftrt:SI
4135
         (ashift:SI
4136
          (and:SI
4137
           (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
4138
                        (match_operand:SI 2 "const_int_operand" ""))
4139
           (match_operand:SI 3 "register_operand" ""))
4140
          (match_operand:SI 4 "const_int_operand" ""))
4141
         (match_operand:SI 5 "const_int_operand" "")))
4142
   (clobber (reg:SI T_REG))]
4143
  "TARGET_SH1"
4144
  [(use (reg:SI R0_REG))]
4145
  "
4146
{
4147
  rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
4148
 
4149
  if (INTVAL (operands[2]))
4150
    {
4151
      gen_shifty_op (LSHIFTRT, operands);
4152
    }
4153
  emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
4154
  operands[2] = operands[4];
4155
  gen_shifty_op (ASHIFT, operands);
4156
  if (INTVAL (operands[5]))
4157
    {
4158
      operands[2] = operands[5];
4159
      gen_shifty_op (LSHIFTRT, operands);
4160
    }
4161
  DONE;
4162
}")
4163
 
4164
;; signed left/right shift combination.
4165
(define_split
4166
  [(set (match_operand:SI 0 "register_operand" "")
4167
        (sign_extract:SI
4168
         (ashift:SI (match_operand:SI 1 "register_operand" "")
4169
                    (match_operand:SI 2 "const_int_operand" ""))
4170
         (match_operand:SI 3 "const_int_operand" "")
4171
         (const_int 0)))
4172
   (clobber (reg:SI T_REG))]
4173
  "TARGET_SH1"
4174
  [(use (reg:SI R0_REG))]
4175
  "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL;
4176
   DONE;")
4177
 
4178
(define_insn "shl_sext_ext"
4179
  [(set (match_operand:SI 0 "register_operand" "=r")
4180
        (sign_extract:SI
4181
         (ashift:SI (match_operand:SI 1 "register_operand" "0")
4182
                    (match_operand:SI 2 "const_int_operand" "n"))
4183
         (match_operand:SI 3 "const_int_operand" "n")
4184
         (const_int 0)))
4185
   (clobber (reg:SI T_REG))]
4186
  "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
4187
  "#"
4188
  [(set (attr "length")
4189
        (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1))
4190
               (const_string "2")
4191
               (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
4192
               (const_string "4")
4193
               (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4194
               (const_string "6")
4195
               (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4196
               (const_string "8")
4197
               (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4198
               (const_string "10")
4199
               (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4200
               (const_string "12")
4201
               (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
4202
               (const_string "14")
4203
               (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
4204
               (const_string "16")]
4205
              (const_string "18")))
4206
    (set_attr "type" "arith")])
4207
 
4208
(define_insn "shl_sext_sub"
4209
  [(set (match_operand:SI 0 "register_operand" "=z")
4210
        (sign_extract:SI
4211
         (ashift:SI (match_operand:SI 1 "register_operand" "0")
4212
                    (match_operand:SI 2 "const_int_operand" "n"))
4213
         (match_operand:SI 3 "const_int_operand" "n")
4214
         (const_int 0)))
4215
   (clobber (reg:SI T_REG))]
4216
  "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
4217
  "#"
4218
  [(set (attr "length")
4219
        (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4220
               (const_string "6")
4221
               (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4222
               (const_string "8")
4223
               (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4224
               (const_string "10")
4225
               (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4226
               (const_string "12")]
4227
              (const_string "14")))
4228
    (set_attr "type" "arith")])
4229
 
4230
;; These patterns are found in expansions of DImode shifts by 16, and
4231
;; allow the xtrct instruction to be generated from C source.
4232
 
4233
(define_insn "xtrct_left"
4234
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4235
        (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
4236
                           (const_int 16))
4237
                (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
4238
                             (const_int 16))))]
4239
  "TARGET_SH1"
4240
  "xtrct        %1,%0"
4241
  [(set_attr "type" "arith")])
4242
 
4243
(define_insn "xtrct_right"
4244
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4245
        (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4246
                             (const_int 16))
4247
                (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
4248
                           (const_int 16))))]
4249
  "TARGET_SH1"
4250
  "xtrct        %2,%0"
4251
  [(set_attr "type" "arith")])
4252
 
4253
;; -------------------------------------------------------------------------
4254
;; Unary arithmetic
4255
;; -------------------------------------------------------------------------
4256
 
4257
(define_insn "negc"
4258
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4259
        (neg:SI (plus:SI (reg:SI T_REG)
4260
                         (match_operand:SI 1 "arith_reg_operand" "r"))))
4261
   (set (reg:SI T_REG)
4262
        (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
4263
               (const_int 0)))]
4264
  "TARGET_SH1"
4265
  "negc %1,%0"
4266
  [(set_attr "type" "arith")])
4267
 
4268
(define_insn "*negdi_media"
4269
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4270
        (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
4271
  "TARGET_SHMEDIA"
4272
  "sub  r63, %1, %0"
4273
  [(set_attr "type" "arith_media")])
4274
 
4275
(define_expand "negdi2"
4276
  [(set (match_operand:DI 0 "arith_reg_operand" "")
4277
        (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))]
4278
  ""
4279
  "
4280
{
4281
  if (TARGET_SH1)
4282
    {
4283
      int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
4284
      int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
4285
 
4286
      rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
4287
      rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
4288
 
4289
      rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
4290
      rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
4291
 
4292
      emit_insn (gen_clrt ());
4293
      emit_insn (gen_negc (low_dst, low_src));
4294
      emit_insn (gen_negc (high_dst, high_src));
4295
      DONE;
4296
    }
4297
}")
4298
 
4299
(define_insn "negsi2"
4300
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4301
        (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4302
  "TARGET_SH1"
4303
  "neg  %1,%0"
4304
  [(set_attr "type" "arith")])
4305
 
4306
(define_insn "one_cmplsi2"
4307
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4308
        (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4309
  "TARGET_SH1"
4310
  "not  %1,%0"
4311
  [(set_attr "type" "arith")])
4312
 
4313
(define_expand "one_cmpldi2"
4314
  [(set (match_operand:DI 0 "arith_reg_dest" "")
4315
        (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
4316
                (const_int -1)))]
4317
  "TARGET_SHMEDIA" "")
4318
 
4319
/* The SH4 202 can do zero-offset branches without pipeline stalls.
4320
   This can be used as some kind of conditional execution, which is useful
4321
   for abs.  */
4322
(define_split
4323
  [(set (match_operand:SI 0 "arith_reg_dest" "")
4324
        (plus:SI (xor:SI (neg:SI (reg:SI T_REG))
4325
                         (match_operand:SI 1 "arith_reg_operand" ""))
4326
                 (reg:SI T_REG)))]
4327
  "TARGET_HARD_SH4"
4328
  [(const_int 0)]
4329
  "emit_insn (gen_movsi_i (operands[0], operands[1]));
4330
   emit_insn (gen_cneg (operands[0], operands[0], operands[0]));
4331
   DONE;")
4332
 
4333
(define_insn "cneg"
4334
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4335
        (if_then_else:SI (eq:SI (reg:SI T_REG) (const_int 0))
4336
                      (match_operand:SI 1 "arith_reg_operand" "0")
4337
                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4338
  "TARGET_HARD_SH4"
4339
  "bf 0f\;neg %2,%0\\n0:"
4340
  [(set_attr "type" "arith") ;; poor approximation
4341
   (set_attr "length" "4")])
4342
 
4343
 
4344
;; -------------------------------------------------------------------------
4345
;; Zero extension instructions
4346
;; -------------------------------------------------------------------------
4347
 
4348
(define_insn "zero_extendsidi2"
4349
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4350
        (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
4351
  "TARGET_SHMEDIA"
4352
  "addz.l       %1, r63, %0"
4353
  [(set_attr "type" "arith_media")
4354
   (set_attr "highpart" "extend")])
4355
 
4356
(define_insn "zero_extendhidi2"
4357
  [(set (match_operand:DI 0 "register_operand" "=r,r")
4358
        (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4359
  "TARGET_SHMEDIA"
4360
  "@
4361
        #
4362
        ld%M1.uw        %m1, %0"
4363
  [(set_attr "type" "*,load_media")
4364
   (set (attr "highpart")
4365
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4366
               (const_string "user")]
4367
              (const_string "ignore")))])
4368
 
4369
(define_split
4370
  [(set (match_operand:DI 0 "register_operand" "")
4371
        (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4372
  "TARGET_SHMEDIA && reload_completed"
4373
  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4374
   (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
4375
  "
4376
{
4377
  if (GET_CODE (operands[1]) == TRUNCATE)
4378
    operands[1] = XEXP (operands[1], 0);
4379
}")
4380
 
4381
;; ??? when a truncated input to a zero_extend is reloaded, reload will
4382
;; reload the entire truncate expression.
4383
(define_insn_and_split "*loaddi_trunc"
4384
  [(set (match_operand 0 "any_register_operand" "=r")
4385
        (truncate (match_operand:DI 1 "memory_operand" "m")))]
4386
  "TARGET_SHMEDIA && reload_completed"
4387
  "#"
4388
  "TARGET_SHMEDIA && reload_completed"
4389
  [(set (match_dup 0) (match_dup 1))]
4390
  "operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));")
4391
 
4392
(define_insn "zero_extendqidi2"
4393
  [(set (match_operand:DI 0 "register_operand" "=r,r")
4394
        (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4395
  "TARGET_SHMEDIA"
4396
  "@
4397
        andi    %1, 255, %0
4398
        ld%M1.ub        %m1, %0"
4399
  [(set_attr "type" "arith_media,load_media")
4400
   (set (attr "highpart")
4401
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4402
               (const_string "user")]
4403
              (const_string "ignore")))])
4404
 
4405
(define_expand "zero_extendhisi2"
4406
  [(set (match_operand:SI 0 "arith_reg_operand" "")
4407
        (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "")))]
4408
  ""
4409
  "
4410
{
4411
  if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], HImode))
4412
    operands[1] = copy_to_mode_reg (HImode, operands[1]);
4413
}")
4414
 
4415
(define_insn "*zero_extendhisi2_compact"
4416
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4417
        (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))]
4418
  "TARGET_SH1"
4419
  "extu.w       %1,%0"
4420
  [(set_attr "type" "arith")])
4421
 
4422
(define_insn "*zero_extendhisi2_media"
4423
  [(set (match_operand:SI 0 "register_operand" "=r,r")
4424
        (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4425
  "TARGET_SHMEDIA"
4426
  "@
4427
        #
4428
        ld%M1.uw        %m1, %0"
4429
  [(set_attr "type" "arith_media,load_media")
4430
   (set (attr "highpart")
4431
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4432
               (const_string "user")]
4433
              (const_string "ignore")))])
4434
 
4435
(define_split
4436
  [(set (match_operand:SI 0 "register_operand" "")
4437
        (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4438
  "TARGET_SHMEDIA && reload_completed"
4439
  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4440
   (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4441
  "
4442
{
4443
  rtx op1 = operands[1];
4444
 
4445
  if (GET_CODE (op1) == TRUNCATE)
4446
    op1 = XEXP (op1, 0);
4447
  operands[2]
4448
    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4449
                           subreg_lowpart_offset (SImode, GET_MODE (op1)));
4450
}")
4451
 
4452
(define_expand "zero_extendqisi2"
4453
  [(set (match_operand:SI 0 "arith_reg_operand" "")
4454
        (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
4455
  ""
4456
  "
4457
{
4458
  if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], QImode))
4459
    operands[1] = copy_to_mode_reg (QImode, operands[1]);
4460
}")
4461
 
4462
(define_insn "*zero_extendqisi2_compact"
4463
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4464
        (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))]
4465
  "TARGET_SH1"
4466
  "extu.b       %1,%0"
4467
  [(set_attr "type" "arith")])
4468
 
4469
(define_insn "*zero_extendqisi2_media"
4470
  [(set (match_operand:SI 0 "register_operand" "=r,r")
4471
        (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4472
  "TARGET_SHMEDIA"
4473
  "@
4474
        andi    %1, 255, %0
4475
        ld%M1.ub        %m1, %0"
4476
  [(set_attr "type" "arith_media,load_media")
4477
   (set (attr "highpart")
4478
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4479
               (const_string "user")]
4480
              (const_string "ignore")))])
4481
 
4482
(define_insn "zero_extendqihi2"
4483
  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4484
        (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
4485
  "TARGET_SH1"
4486
  "extu.b       %1,%0"
4487
  [(set_attr "type" "arith")])
4488
 
4489
;; -------------------------------------------------------------------------
4490
;; Sign extension instructions
4491
;; -------------------------------------------------------------------------
4492
 
4493
;; ??? This should be a define expand.
4494
;; ??? Or perhaps it should be dropped?
4495
 
4496
;; convert_move generates good code for SH[1-4].
4497
(define_insn "extendsidi2"
4498
  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
4499
        (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
4500
  "TARGET_SHMEDIA"
4501
  "@
4502
        add.l   %1, r63, %0
4503
        ld%M1.l %m1, %0
4504
        fmov.sl %1, %0"
4505
  [(set_attr "type" "arith_media,load_media,fpconv_media")
4506
   (set (attr "highpart")
4507
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4508
               (const_string "user")]
4509
              (const_string "extend")))])
4510
 
4511
(define_insn "extendhidi2"
4512
  [(set (match_operand:DI 0 "register_operand" "=r,r")
4513
        (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4514
  "TARGET_SHMEDIA"
4515
  "@
4516
        #
4517
        ld%M1.w %m1, %0"
4518
  [(set_attr "type" "*,load_media")
4519
   (set (attr "highpart")
4520
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4521
               (const_string "user")]
4522
              (const_string "ignore")))])
4523
 
4524
(define_split
4525
  [(set (match_operand:DI 0 "register_operand" "")
4526
        (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4527
  "TARGET_SHMEDIA && reload_completed"
4528
  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4529
   (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
4530
  "
4531
{
4532
  if (GET_CODE (operands[1]) == TRUNCATE)
4533
    operands[1] = XEXP (operands[1], 0);
4534
}")
4535
 
4536
(define_insn "extendqidi2"
4537
  [(set (match_operand:DI 0 "register_operand" "=r,r")
4538
        (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4539
  "TARGET_SHMEDIA"
4540
  "@
4541
        #
4542
        ld%M1.b %m1, %0"
4543
  [(set_attr "type" "*,load_media")
4544
   (set (attr "highpart")
4545
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4546
               (const_string "user")]
4547
              (const_string "ignore")))])
4548
 
4549
(define_split
4550
  [(set (match_operand:DI 0 "register_operand" "")
4551
        (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
4552
  "TARGET_SHMEDIA && reload_completed"
4553
  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
4554
   (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
4555
  "
4556
{
4557
  if (GET_CODE (operands[1]) == TRUNCATE)
4558
    operands[1] = XEXP (operands[1], 0);
4559
}")
4560
 
4561
(define_expand "extendhisi2"
4562
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4563
        (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4564
  ""
4565
  "")
4566
 
4567
(define_insn "*extendhisi2_compact"
4568
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4569
        (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))]
4570
  "TARGET_SH1"
4571
  "@
4572
        exts.w  %1,%0
4573
        mov.w   %1,%0"
4574
  [(set_attr "type" "arith,load")])
4575
 
4576
(define_insn "*extendhisi2_media"
4577
  [(set (match_operand:SI 0 "register_operand" "=r,r")
4578
        (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4579
  "TARGET_SHMEDIA"
4580
  "@
4581
        #
4582
        ld%M1.w %m1, %0"
4583
  [(set_attr "type" "arith_media,load_media")
4584
   (set (attr "highpart")
4585
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4586
               (const_string "user")]
4587
              (const_string "ignore")))])
4588
 
4589
(define_split
4590
  [(set (match_operand:SI 0 "register_operand" "")
4591
        (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4592
  "TARGET_SHMEDIA && reload_completed"
4593
  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4594
   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4595
  "
4596
{
4597
  rtx op1 = operands[1];
4598
  if (GET_CODE (op1) == TRUNCATE)
4599
    op1 = XEXP (op1, 0);
4600
  operands[2]
4601
    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4602
                           subreg_lowpart_offset (SImode, GET_MODE (op1)));
4603
}")
4604
 
4605
(define_expand "extendqisi2"
4606
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4607
        (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4608
  ""
4609
  "")
4610
 
4611
(define_insn "*extendqisi2_compact"
4612
  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4613
        (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
4614
  "TARGET_SH1"
4615
  "@
4616
        exts.b  %1,%0
4617
        mov.b   %1,%0"
4618
  [(set_attr "type" "arith,load")])
4619
 
4620
(define_insn "*extendqisi2_media"
4621
  [(set (match_operand:SI 0 "register_operand" "=r,r")
4622
        (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4623
  "TARGET_SHMEDIA"
4624
  "@
4625
        #
4626
        ld%M1.b %m1, %0"
4627
  [(set_attr "type" "arith_media,load_media")
4628
   (set (attr "highpart")
4629
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4630
               (const_string "user")]
4631
              (const_string "ignore")))])
4632
 
4633
(define_split
4634
  [(set (match_operand:SI 0 "register_operand" "")
4635
        (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
4636
  "TARGET_SHMEDIA && reload_completed"
4637
  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4638
   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4639
   "
4640
{
4641
  rtx op1 = operands[1];
4642
  if (GET_CODE (op1) == TRUNCATE)
4643
    op1 = XEXP (op1, 0);
4644
  operands[2]
4645
    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4646
                           subreg_lowpart_offset (SImode, GET_MODE (op1)));
4647
}")
4648
 
4649
(define_insn "extendqihi2"
4650
  [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4651
        (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
4652
  "TARGET_SH1"
4653
  "@
4654
        exts.b  %1,%0
4655
        mov.b   %1,%0"
4656
  [(set_attr "type" "arith,load")])
4657
 
4658
/* It would seem useful to combine the truncXi patterns into the movXi
4659
   patterns, but unary operators are ignored when matching constraints,
4660
   so we need separate patterns.  */
4661
(define_insn "truncdisi2"
4662
  [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
4663
        (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
4664
  "TARGET_SHMEDIA"
4665
  "@
4666
        add.l   %1, r63, %0
4667
        st%M0.l %m0, %1
4668
        fst%M0.s        %m0, %T1
4669
        fmov.ls %1, %0
4670
        fmov.sl %T1, %0
4671
        fmov.s  %T1, %0"
4672
  [(set_attr "type"   "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")
4673
   (set (attr "highpart")
4674
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4675
               (const_string "user")]
4676
              (const_string "extend")))])
4677
 
4678
(define_insn "truncdihi2"
4679
  [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
4680
        (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
4681
  "TARGET_SHMEDIA"
4682
  "@
4683
        shlli\\t%1,48,%0\;shlri\\t%0,48,%0
4684
        st%M0.w %m0, %1"
4685
  [(set_attr "type"   "arith_media,store_media")
4686
   (set_attr "length" "8,4")
4687
   (set (attr "highpart")
4688
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4689
               (const_string "user")]
4690
              (const_string "extend")))])
4691
 
4692
; N.B. This should agree with LOAD_EXTEND_OP and movqi.
4693
; Because we use zero extension, we can't provide signed QImode compares
4694
; using a simple compare or conditional banch insn.
4695
(define_insn "truncdiqi2"
4696
  [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
4697
        (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
4698
  "TARGET_SHMEDIA"
4699
  "@
4700
        andi    %1, 255, %0
4701
        st%M0.b %m0, %1"
4702
  [(set_attr "type"   "arith_media,store")
4703
   (set (attr "highpart")
4704
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4705
               (const_string "user")]
4706
              (const_string "extend")))])
4707
;; -------------------------------------------------------------------------
4708
;; Move instructions
4709
;; -------------------------------------------------------------------------
4710
 
4711
;; define push and pop so it is easy for sh.c
4712
;; We can't use push and pop on SHcompact because the stack must always
4713
;; be 8-byte aligned.
4714
 
4715
(define_expand "push"
4716
  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
4717
        (match_operand:SI 0 "register_operand" "r,l,x"))]
4718
  "TARGET_SH1 && ! TARGET_SH5"
4719
  "")
4720
 
4721
(define_expand "pop"
4722
  [(set (match_operand:SI 0 "register_operand" "=r,l,x")
4723
        (mem:SI (post_inc:SI (reg:SI SP_REG))))]
4724
  "TARGET_SH1 && ! TARGET_SH5"
4725
  "")
4726
 
4727
(define_expand "push_e"
4728
  [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
4729
                   (match_operand:SF 0 "" ""))
4730
              (use (reg:PSI FPSCR_REG))
4731
              (clobber (scratch:SI))])]
4732
  "TARGET_SH1 && ! TARGET_SH5"
4733
  "")
4734
 
4735
(define_insn "push_fpul"
4736
  [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
4737
  "TARGET_SH2E && ! TARGET_SH5"
4738
  "sts.l        fpul,@-r15"
4739
  [(set_attr "type" "store")
4740
   (set_attr "late_fp_use" "yes")
4741
   (set_attr "hit_stack" "yes")])
4742
 
4743
;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
4744
;; so use that.
4745
(define_expand "push_4"
4746
  [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
4747
                   (match_operand:DF 0 "" ""))
4748
              (use (reg:PSI FPSCR_REG))
4749
              (clobber (scratch:SI))])]
4750
  "TARGET_SH1 && ! TARGET_SH5"
4751
  "")
4752
 
4753
(define_expand "pop_e"
4754
  [(parallel [(set (match_operand:SF 0 "" "")
4755
              (mem:SF (post_inc:SI (reg:SI SP_REG))))
4756
              (use (reg:PSI FPSCR_REG))
4757
              (clobber (scratch:SI))])]
4758
  "TARGET_SH1 && ! TARGET_SH5"
4759
  "")
4760
 
4761
(define_insn "pop_fpul"
4762
  [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
4763
  "TARGET_SH2E && ! TARGET_SH5"
4764
  "lds.l        @r15+,fpul"
4765
  [(set_attr "type" "load")
4766
   (set_attr "hit_stack" "yes")])
4767
 
4768
(define_expand "pop_4"
4769
  [(parallel [(set (match_operand:DF 0 "" "")
4770
                   (mem:DF (post_inc:SI (reg:SI SP_REG))))
4771
              (use (reg:PSI FPSCR_REG))
4772
              (clobber (scratch:SI))])]
4773
  "TARGET_SH1 && ! TARGET_SH5"
4774
  "")
4775
 
4776
(define_expand "push_fpscr"
4777
  [(const_int 0)]
4778
  "TARGET_SH2E"
4779
  "
4780
{
4781
  rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
4782
                                                 gen_rtx_PRE_DEC (Pmode,
4783
                                                          stack_pointer_rtx)),
4784
                                        get_fpscr_rtx ()));
4785
  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
4786
  DONE;
4787
}")
4788
 
4789
(define_expand "pop_fpscr"
4790
  [(const_int 0)]
4791
  "TARGET_SH2E"
4792
  "
4793
{
4794
  rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
4795
                                        gen_frame_mem (PSImode,
4796
                                                 gen_rtx_POST_INC (Pmode,
4797
                                                          stack_pointer_rtx))));
4798
  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
4799
  DONE;
4800
}")
4801
 
4802
;; These two patterns can happen as the result of optimization, when
4803
;; comparisons get simplified to a move of zero or 1 into the T reg.
4804
;; They don't disappear completely, because the T reg is a fixed hard reg.
4805
 
4806
(define_insn "clrt"
4807
  [(set (reg:SI T_REG) (const_int 0))]
4808
  "TARGET_SH1"
4809
  "clrt")
4810
 
4811
(define_insn "sett"
4812
  [(set (reg:SI T_REG) (const_int 1))]
4813
  "TARGET_SH1"
4814
  "sett")
4815
 
4816
;; t/r must come after r/r, lest reload will try to reload stuff like
4817
;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
4818
;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
4819
(define_insn "movsi_i"
4820
  [(set (match_operand:SI 0 "general_movdst_operand"
4821
            "=r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
4822
        (match_operand:SI 1 "general_movsrc_operand"
4823
         "Q,rI08,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
4824
  "TARGET_SH1
4825
   && ! TARGET_SH2E
4826
   && ! TARGET_SH2A
4827
   && (register_operand (operands[0], SImode)
4828
       || register_operand (operands[1], SImode))"
4829
  "@
4830
        mov.l   %1,%0
4831
        mov     %1,%0
4832
        cmp/pl  %1
4833
        mov.l   %1,%0
4834
        sts     %1,%0
4835
        sts     %1,%0
4836
        movt    %0
4837
        mov.l   %1,%0
4838
        sts.l   %1,%0
4839
        sts.l   %1,%0
4840
        lds     %1,%0
4841
        lds     %1,%0
4842
        lds.l   %1,%0
4843
        lds.l   %1,%0
4844
        fake    %1,%0"
4845
  [(set_attr "type" "pcload_si,move,mt_group,load_si,mac_gp,prget,move,store,store,pstore,move,prset,load,pload,pcload_si")
4846
   (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
4847
 
4848
;; t/r must come after r/r, lest reload will try to reload stuff like
4849
;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
4850
;; ??? This allows moves from macl to fpul to be recognized, but these moves
4851
;; will require a reload.
4852
;; ??? We can't include f/f because we need the proper FPSCR setting when
4853
;; TARGET_FMOVD is in effect, and mode switching is done before reload.
4854
(define_insn "movsi_ie"
4855
  [(set (match_operand:SI 0 "general_movdst_operand"
4856
            "=r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
4857
        (match_operand:SI 1 "general_movsrc_operand"
4858
         "Q,rI08,I20,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
4859
  "(TARGET_SH2E || TARGET_SH2A)
4860
   && (register_operand (operands[0], SImode)
4861
       || register_operand (operands[1], SImode))"
4862
  "@
4863
        mov.l   %1,%0
4864
        mov     %1,%0
4865
        movi20  %1,%0
4866
        cmp/pl  %1
4867
        mov.l   %1,%0
4868
        sts     %1,%0
4869
        sts     %1,%0
4870
        movt    %0
4871
        mov.l   %1,%0
4872
        sts.l   %1,%0
4873
        sts.l   %1,%0
4874
        lds     %1,%0
4875
        lds     %1,%0
4876
        lds.l   %1,%0
4877
        lds.l   %1,%0
4878
        lds.l   %1,%0
4879
        sts.l   %1,%0
4880
        fake    %1,%0
4881
        lds     %1,%0
4882
        sts     %1,%0
4883
        fsts    fpul,%0
4884
        flds    %1,fpul
4885
        fmov    %1,%0
4886
        ! move optimized away"
4887
  [(set_attr "type" "pcload_si,move,move,*,load_si,mac_gp,prget,move,store,store,pstore,move,prset,load,pload,load,store,pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
4888
   (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
4889
   (set_attr "length" "*,*,4,*,4,*,*,*,4,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")])
4890
 
4891
(define_insn "movsi_i_lowpart"
4892
  [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
4893
        (match_operand:SI 1 "general_movsrc_operand" "Q,rI08,mr,x,l,t,r,i"))]
4894
   "TARGET_SH1
4895
    && (register_operand (operands[0], SImode)
4896
        || register_operand (operands[1], SImode))"
4897
  "@
4898
        mov.l   %1,%0
4899
        mov     %1,%0
4900
        mov.l   %1,%0
4901
        sts     %1,%0
4902
        sts     %1,%0
4903
        movt    %0
4904
        mov.l   %1,%0
4905
        fake    %1,%0"
4906
  [(set_attr "type" "pcload,move,load,move,prget,move,store,pcload")])
4907
 
4908
(define_insn_and_split "load_ra"
4909
  [(set (match_operand:SI 0 "general_movdst_operand" "")
4910
        (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
4911
  "TARGET_SH1"
4912
  "#"
4913
  "&& ! currently_expanding_to_rtl"
4914
  [(set (match_dup 0) (match_dup 1))]
4915
  "
4916
{
4917
  if (TARGET_SHCOMPACT && current_function_has_nonlocal_label)
4918
    operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
4919
}")
4920
 
4921
;; The '?'s in the following constraints may not reflect the time taken
4922
;; to perform the move. They are there to discourage the use of floating-
4923
;; point registers for storing integer values.
4924
(define_insn "*movsi_media"
4925
  [(set (match_operand:SI 0 "general_movdst_operand"
4926
                "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
4927
        (match_operand:SI 1 "general_movsrc_operand"
4928
         "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
4929
  "TARGET_SHMEDIA_FPU
4930
   && (register_operand (operands[0], SImode)
4931
       || sh_register_operand (operands[1], SImode)
4932
       || GET_CODE (operands[1]) == TRUNCATE)"
4933
  "@
4934
        add.l   %1, r63, %0
4935
        movi    %1, %0
4936
        #
4937
        ld%M1.l %m1, %0
4938
        st%M0.l %m0, %N1
4939
        fld%M1.s        %m1, %0
4940
        fst%M0.s        %m0, %1
4941
        fmov.ls %N1, %0
4942
        fmov.sl %1, %0
4943
        fmov.s  %1, %0
4944
        ptabs   %1, %0
4945
        gettr   %1, %0
4946
        pt      %1, %0"
4947
  [(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")
4948
   (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
4949
   (set (attr "highpart")
4950
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4951
               (const_string "user")]
4952
              (const_string "ignore")))])
4953
 
4954
(define_insn "*movsi_media_nofpu"
4955
  [(set (match_operand:SI 0 "general_movdst_operand"
4956
                "=r,r,r,r,m,*b,r,*b")
4957
        (match_operand:SI 1 "general_movsrc_operand"
4958
         "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
4959
  "TARGET_SHMEDIA
4960
   && (register_operand (operands[0], SImode)
4961
       || sh_register_operand (operands[1], SImode)
4962
       || GET_CODE (operands[1]) == TRUNCATE)"
4963
  "@
4964
        add.l   %1, r63, %0
4965
        movi    %1, %0
4966
        #
4967
        ld%M1.l %m1, %0
4968
        st%M0.l %m0, %N1
4969
        ptabs   %1, %0
4970
        gettr   %1, %0
4971
        pt      %1, %0"
4972
  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
4973
   (set_attr "length" "4,4,8,4,4,4,4,12")
4974
   (set (attr "highpart")
4975
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4976
               (const_string "user")]
4977
              (const_string "ignore")))])
4978
 
4979
(define_expand "movsi_const"
4980
  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
4981
        (const:SI (sign_extend:SI
4982
                   (truncate:HI
4983
                    (ashiftrt:SI
4984
                     (match_operand:DI 1 "immediate_operand" "s")
4985
                     (const_int 16))))))
4986
   (set (match_dup 0)
4987
        (ior:SI (ashift:SI (match_dup 0) (const_int 16))
4988
                (const:SI
4989
                  (zero_extend:SI
4990
                   (truncate:HI (match_dup 1))))))]
4991
  "TARGET_SHMEDIA && reload_completed
4992
   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
4993
  "
4994
{
4995
  if (GET_CODE (operands[1]) == LABEL_REF
4996
      && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
4997
    LABEL_NUSES (XEXP (operands[1], 0)) += 2;
4998
  else if (GOTOFF_P (operands[1]))
4999
    {
5000
      rtx unspec = XEXP (operands[1], 0);
5001
 
5002
      if (! UNSPEC_GOTOFF_P (unspec))
5003
        {
5004
          unspec = XEXP (unspec, 0);
5005
          if (! UNSPEC_GOTOFF_P (unspec))
5006
            abort ();
5007
        }
5008
      if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
5009
          && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
5010
        LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
5011
    }
5012
}")
5013
 
5014
(define_expand "movsi_const_16bit"
5015
  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5016
        (const:SI (sign_extend:SI
5017
                   (truncate:HI
5018
                    (match_operand:DI 1 "immediate_operand" "s")))))]
5019
  "TARGET_SHMEDIA && flag_pic && reload_completed
5020
   && GET_CODE (operands[1]) == SYMBOL_REF"
5021
  "")
5022
 
5023
(define_split
5024
  [(set (match_operand:SI 0 "arith_reg_dest" "")
5025
        (match_operand:SI 1 "immediate_operand" ""))]
5026
  "TARGET_SHMEDIA && reload_completed
5027
   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5028
  [(const_int 0)]
5029
  "
5030
{
5031
  rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
5032
 
5033
  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
5034
                                        REG_NOTES (insn));
5035
 
5036
  DONE;
5037
}")
5038
 
5039
(define_split
5040
  [(set (match_operand:SI 0 "register_operand" "")
5041
        (match_operand:SI 1 "immediate_operand" ""))]
5042
  "TARGET_SHMEDIA && reload_completed
5043
   && ((GET_CODE (operands[1]) == CONST_INT
5044
        && ! CONST_OK_FOR_I16 (INTVAL (operands[1])))
5045
       || GET_CODE (operands[1]) == CONST_DOUBLE)"
5046
  [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5047
 
5048
(define_expand "movsi"
5049
  [(set (match_operand:SI 0 "general_movdst_operand" "")
5050
        (match_operand:SI 1 "general_movsrc_operand" ""))]
5051
  ""
5052
  "{ if (prepare_move_operands (operands, SImode)) DONE; }")
5053
 
5054
(define_expand "ic_invalidate_line"
5055
  [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
5056
                                (match_dup 1)] UNSPEC_ICACHE)
5057
              (clobber (scratch:SI))])]
5058
  "TARGET_HARD_SH4 || TARGET_SH5"
5059
  "
5060
{
5061
  if (TARGET_SHMEDIA)
5062
    {
5063
      emit_insn (gen_ic_invalidate_line_media (operands[0]));
5064
      DONE;
5065
    }
5066
  else if (TARGET_SHCOMPACT)
5067
    {
5068
      operands[1] = function_symbol (NULL, \"__ic_invalidate\", SFUNC_STATIC);
5069
      operands[1] = force_reg (Pmode, operands[1]);
5070
      emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
5071
      DONE;
5072
    }
5073
  else if (TARGET_SH4A_ARCH)
5074
    {
5075
      emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
5076
      DONE;
5077
    }
5078
  operands[0] = force_reg (Pmode, operands[0]);
5079
  operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
5080
                                                               Pmode)));
5081
}")
5082
 
5083
;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
5084
;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
5085
;; the requirement *1*00 for associative address writes.  The alignment of
5086
;; %0 implies that its least significant bit is cleared,
5087
;; thus we clear the V bit of a matching entry if there is one.
5088
(define_insn "ic_invalidate_line_i"
5089
  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
5090
                     (match_operand:SI 1 "register_operand" "r")]
5091
                     UNSPEC_ICACHE)
5092
   (clobber (match_scratch:SI 2 "=&r"))]
5093
  "TARGET_HARD_SH4"
5094
  "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
5095
  [(set_attr "length" "8")
5096
   (set_attr "type" "cwb")])
5097
 
5098
(define_insn "ic_invalidate_line_sh4a"
5099
  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
5100
                    UNSPEC_ICACHE)]
5101
  "TARGET_SH4A_ARCH"
5102
  "ocbwb\\t@%0\;synco\;icbi\\t@%0"
5103
  [(set_attr "length" "16")
5104
   (set_attr "type" "cwb")])
5105
 
5106
;; ??? could make arg 0 an offsettable memory operand to allow to save
5107
;; an add in the code that calculates the address.
5108
(define_insn "ic_invalidate_line_media"
5109
  [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
5110
                    UNSPEC_ICACHE)]
5111
  "TARGET_SHMEDIA"
5112
  "ocbwb        %0,0\;synco\;icbi       %0, 0\;synci"
5113
  [(set_attr "length" "16")
5114
   (set_attr "type" "invalidate_line_media")])
5115
 
5116
(define_insn "ic_invalidate_line_compact"
5117
  [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5118
                     (match_operand:SI 1 "register_operand" "r")]
5119
                    UNSPEC_ICACHE)
5120
   (clobber (reg:SI PR_REG))]
5121
  "TARGET_SHCOMPACT"
5122
  "jsr @%1%#"
5123
  [(set_attr "type" "sfunc")
5124
   (set_attr "needs_delay_slot" "yes")])
5125
 
5126
(define_expand "initialize_trampoline"
5127
  [(match_operand:SI 0 "" "")
5128
   (match_operand:SI 1 "" "")
5129
   (match_operand:SI 2 "" "")]
5130
  "TARGET_SHCOMPACT"
5131
  "
5132
{
5133
  rtx sfun, tramp;
5134
 
5135
  tramp = force_reg (Pmode, operands[0]);
5136
  sfun = force_reg (Pmode, function_symbol (NULL, \"__init_trampoline\",
5137
                                            SFUNC_STATIC));
5138
  emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
5139
  emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
5140
 
5141
  emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
5142
  DONE;
5143
}")
5144
 
5145
(define_insn "initialize_trampoline_compact"
5146
  [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5147
                     (match_operand:SI 1 "register_operand" "r")
5148
                     (reg:SI R2_REG) (reg:SI R3_REG)]
5149
                    UNSPEC_INIT_TRAMP)
5150
 
5151
   (clobber (reg:SI PR_REG))]
5152
  "TARGET_SHCOMPACT"
5153
  "jsr @%1%#"
5154
  [(set_attr "type" "sfunc")
5155
   (set_attr "needs_delay_slot" "yes")])
5156
 
5157
(define_insn "movqi_i"
5158
  [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,r,l")
5159
        (match_operand:QI 1 "general_movsrc_operand"  "ri,m,r,t,l,r"))]
5160
  "TARGET_SH1
5161
   && (arith_reg_operand (operands[0], QImode)
5162
       || arith_reg_operand (operands[1], QImode))"
5163
  "@
5164
        mov     %1,%0
5165
        mov.b   %1,%0
5166
        mov.b   %1,%0
5167
        movt    %0
5168
        sts     %1,%0
5169
        lds     %1,%0"
5170
 [(set_attr "type" "move,load,store,move,move,move")])
5171
 
5172
(define_insn "*movqi_media"
5173
  [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
5174
        (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
5175
  "TARGET_SHMEDIA
5176
   && (arith_reg_operand (operands[0], QImode)
5177
       || extend_reg_or_0_operand (operands[1], QImode))"
5178
  "@
5179
        add.l   %1, r63, %0
5180
        movi    %1, %0
5181
        ld%M1.ub        %m1, %0
5182
        st%M0.b %m0, %N1"
5183
  [(set_attr "type" "arith_media,arith_media,load_media,store_media")
5184
   (set (attr "highpart")
5185
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5186
               (const_string "user")]
5187
              (const_string "ignore")))])
5188
 
5189
(define_expand "movqi"
5190
  [(set (match_operand:QI 0 "general_operand" "")
5191
        (match_operand:QI 1 "general_operand"  ""))]
5192
  ""
5193
  "{ if (prepare_move_operands (operands, QImode)) DONE; }")
5194
 
5195
(define_expand "reload_inqi"
5196
  [(set (match_operand:SI 2 "" "=&r")
5197
        (match_operand:QI 1 "inqhi_operand" ""))
5198
   (set (match_operand:QI 0 "arith_reg_operand" "=r")
5199
        (truncate:QI (match_dup 3)))]
5200
  "TARGET_SHMEDIA"
5201
  "
5202
{
5203
  rtx inner = XEXP (operands[1], 0);
5204
  int regno = REGNO (inner);
5205
 
5206
  regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5207
  operands[1] = gen_rtx_REG (SImode, regno);
5208
  operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5209
}")
5210
 
5211
/* When storing r0, we have to avoid reg+reg addressing.  */
5212
(define_insn "movhi_i"
5213
  [(set (match_operand:HI 0 "general_movdst_operand"   "=r,r,r,r,m,r,l,r")
5214
        (match_operand:HI 1 "general_movsrc_operand" "Q,rI08,m,t,r,l,r,i"))]
5215
  "TARGET_SH1
5216
   && (arith_reg_operand (operands[0], HImode)
5217
       || arith_reg_operand (operands[1], HImode))
5218
   && (GET_CODE (operands[0]) != MEM
5219
       || GET_CODE (XEXP (operands[0], 0)) != PLUS
5220
       || GET_CODE (XEXP (XEXP (operands[0], 0), 1)) != REG
5221
       || ! refers_to_regno_p (R0_REG, R0_REG + 1, operands[1], (rtx *)0))"
5222
  "@
5223
        mov.w   %1,%0
5224
        mov     %1,%0
5225
        mov.w   %1,%0
5226
        movt    %0
5227
        mov.w   %1,%0
5228
        sts     %1,%0
5229
        lds     %1,%0
5230
        fake    %1,%0"
5231
  [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
5232
 
5233
(define_insn "*movhi_media"
5234
  [(set (match_operand:HI 0 "general_movdst_operand"     "=r,r,r,r,m")
5235
        (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
5236
  "TARGET_SHMEDIA
5237
   && (arith_reg_operand (operands[0], HImode)
5238
       || arith_reg_or_0_operand (operands[1], HImode))"
5239
  "@
5240
        add.l   %1, r63, %0
5241
        movi    %1, %0
5242
        #
5243
        ld%M1.w %m1, %0
5244
        st%M0.w %m0, %N1"
5245
  [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
5246
   (set (attr "highpart")
5247
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5248
               (const_string "user")]
5249
              (const_string "ignore")))])
5250
 
5251
(define_split
5252
  [(set (match_operand:HI 0 "register_operand" "")
5253
        (match_operand:HI 1 "immediate_operand" ""))]
5254
  "TARGET_SHMEDIA && reload_completed
5255
   && ! CONST_OK_FOR_I16 (INTVAL (operands[1]))"
5256
  [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5257
 
5258
(define_expand "movhi"
5259
  [(set (match_operand:HI 0 "general_movdst_operand" "")
5260
        (match_operand:HI 1 "general_movsrc_operand"  ""))]
5261
  ""
5262
  "{ if (prepare_move_operands (operands, HImode)) DONE; }")
5263
 
5264
(define_expand "reload_inhi"
5265
  [(set (match_operand:SI 2 "" "=&r")
5266
        (match_operand:HI 1 "inqhi_operand" ""))
5267
   (set (match_operand:HI 0 "arith_reg_operand" "=r")
5268
        (truncate:HI (match_dup 3)))]
5269
  "TARGET_SHMEDIA"
5270
  "
5271
{
5272
  rtx inner = XEXP (operands[1], 0);
5273
  int regno = REGNO (inner);
5274
 
5275
  regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5276
  operands[1] = gen_rtx_REG (SImode, regno);
5277
  operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5278
}")
5279
 
5280
;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
5281
;; compiled with -m2 -ml -O3 -funroll-loops
5282
(define_insn "*movdi_i"
5283
  [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
5284
        (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
5285
  "TARGET_SH1
5286
   && (arith_reg_operand (operands[0], DImode)
5287
       || arith_reg_operand (operands[1], DImode))"
5288
  "* return output_movedouble (insn, operands, DImode);"
5289
  [(set_attr "length" "4")
5290
   (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
5291
 
5292
;; If the output is a register and the input is memory or a register, we have
5293
;; to be careful and see which word needs to be loaded first.
5294
 
5295
(define_split
5296
  [(set (match_operand:DI 0 "general_movdst_operand" "")
5297
        (match_operand:DI 1 "general_movsrc_operand" ""))]
5298
  "TARGET_SH1 && reload_completed"
5299
  [(set (match_dup 2) (match_dup 3))
5300
   (set (match_dup 4) (match_dup 5))]
5301
  "
5302
{
5303
  int regno;
5304
 
5305
  if ((GET_CODE (operands[0]) == MEM
5306
       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
5307
      || (GET_CODE (operands[1]) == MEM
5308
          && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
5309
    FAIL;
5310
 
5311
  switch (GET_CODE (operands[0]))
5312
    {
5313
    case REG:
5314
      regno = REGNO (operands[0]);
5315
      break;
5316
    case SUBREG:
5317
      regno = subreg_regno (operands[0]);
5318
      break;
5319
    case MEM:
5320
      regno = -1;
5321
      break;
5322
    default:
5323
      gcc_unreachable ();
5324
    }
5325
 
5326
  if (regno == -1
5327
      || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
5328
    {
5329
      operands[2] = operand_subword (operands[0], 0, 0, DImode);
5330
      operands[3] = operand_subword (operands[1], 0, 0, DImode);
5331
      operands[4] = operand_subword (operands[0], 1, 0, DImode);
5332
      operands[5] = operand_subword (operands[1], 1, 0, DImode);
5333
    }
5334
  else
5335
    {
5336
      operands[2] = operand_subword (operands[0], 1, 0, DImode);
5337
      operands[3] = operand_subword (operands[1], 1, 0, DImode);
5338
      operands[4] = operand_subword (operands[0], 0, 0, DImode);
5339
      operands[5] = operand_subword (operands[1], 0, 0, DImode);
5340
    }
5341
 
5342
  if (operands[2] == 0 || operands[3] == 0
5343
      || operands[4] == 0 || operands[5] == 0)
5344
    FAIL;
5345
}")
5346
 
5347
;; The '?'s in the following constraints may not reflect the time taken
5348
;; to perform the move. They are there to discourage the use of floating-
5349
;; point registers for storing integer values.
5350
(define_insn "*movdi_media"
5351
  [(set (match_operand:DI 0 "general_movdst_operand"
5352
                 "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
5353
        (match_operand:DI 1 "general_movsrc_operand"
5354
         "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5355
  "TARGET_SHMEDIA_FPU
5356
   && (register_operand (operands[0], DImode)
5357
       || sh_register_operand (operands[1], DImode))"
5358
  "@
5359
        add     %1, r63, %0
5360
        movi    %1, %0
5361
        #
5362
        ld%M1.q %m1, %0
5363
        st%M0.q %m0, %N1
5364
        fld%M1.d        %m1, %0
5365
        fst%M0.d        %m0, %1
5366
        fmov.qd %N1, %0
5367
        fmov.dq %1, %0
5368
        fmov.d  %1, %0
5369
        ptabs   %1, %0
5370
        gettr   %1, %0
5371
        pt      %1, %0"
5372
  [(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")
5373
   (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
5374
 
5375
(define_insn "*movdi_media_nofpu"
5376
  [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
5377
        (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
5378
  "TARGET_SHMEDIA
5379
   && (register_operand (operands[0], DImode)
5380
       || sh_register_operand (operands[1], DImode))"
5381
  "@
5382
        add     %1, r63, %0
5383
        movi    %1, %0
5384
        #
5385
        ld%M1.q %m1, %0
5386
        st%M0.q %m0, %N1
5387
        ptabs   %1, %0
5388
        gettr   %1, %0
5389
        pt      %1, %0"
5390
  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5391
   (set_attr "length" "4,4,16,4,4,4,4,*")])
5392
 
5393
(define_insn "*movdi_media_I16"
5394
  [(set (match_operand:DI 0 "ext_dest_operand" "=r")
5395
        (match_operand:DI 1 "const_int_operand" "I16"))]
5396
  "TARGET_SHMEDIA && reload_completed"
5397
  "movi %1, %0"
5398
  [(set_attr "type" "arith_media")
5399
   (set_attr "length" "4")])
5400
 
5401
(define_split
5402
  [(set (match_operand:DI 0 "arith_reg_dest" "")
5403
        (match_operand:DI 1 "immediate_operand" ""))]
5404
  "TARGET_SHMEDIA && reload_completed
5405
   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5406
  [(set (match_dup 0) (match_dup 1))]
5407
  "
5408
{
5409
  rtx insn;
5410
 
5411
  if (TARGET_SHMEDIA64)
5412
    insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
5413
  else
5414
    insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
5415
 
5416
  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
5417
                                        REG_NOTES (insn));
5418
 
5419
  DONE;
5420
}")
5421
 
5422
(define_expand "movdi_const"
5423
  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5424
        (const:DI (sign_extend:DI
5425
                   (truncate:HI
5426
                    (ashiftrt:DI
5427
                     (match_operand:DI 1 "immediate_operand" "s")
5428
                     (const_int 48))))))
5429
   (set (match_dup 0)
5430
        (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5431
                (const:DI
5432
                 (zero_extend:DI
5433
                  (truncate:HI
5434
                   (ashiftrt:SI
5435
                    (match_dup 1)
5436
                    (const_int 32)))))))
5437
   (set (match_dup 0)
5438
        (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5439
                (const:DI
5440
                 (zero_extend:DI
5441
                  (truncate:HI
5442
                   (ashiftrt:SI
5443
                    (match_dup 1)
5444
                    (const_int 16)))))))
5445
   (set (match_dup 0)
5446
        (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5447
                (const:DI
5448
                 (zero_extend:DI
5449
                  (truncate:HI
5450
                   (match_dup 1))))))]
5451
  "TARGET_SHMEDIA64 && reload_completed
5452
   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5453
  "
5454
{
5455
  sh_mark_label (operands[1], 4);
5456
}")
5457
 
5458
(define_expand "movdi_const_32bit"
5459
  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5460
        (const:DI (sign_extend:DI
5461
                   (truncate:HI
5462
                    (ashiftrt:DI
5463
                     (match_operand:DI 1 "immediate_operand" "s")
5464
                     (const_int 16))))))
5465
   (set (match_dup 0)
5466
        (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5467
                (const:DI
5468
                 (zero_extend:DI
5469
                  (truncate:HI
5470
                   (match_dup 1))))))]
5471
  "TARGET_SHMEDIA32 && reload_completed
5472
   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5473
  "
5474
{
5475
  sh_mark_label (operands[1], 2);
5476
}")
5477
 
5478
(define_expand "movdi_const_16bit"
5479
  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5480
        (const:DI (sign_extend:DI
5481
                   (truncate:HI
5482
                    (match_operand:DI 1 "immediate_operand" "s")))))]
5483
  "TARGET_SHMEDIA && flag_pic && reload_completed
5484
   && GET_CODE (operands[1]) == SYMBOL_REF"
5485
  "")
5486
 
5487
(define_split
5488
  [(set (match_operand:DI 0 "ext_dest_operand" "")
5489
        (match_operand:DI 1 "immediate_operand" ""))]
5490
  "TARGET_SHMEDIA && reload_completed
5491
   && GET_CODE (operands[1]) == CONST_INT
5492
   && ! CONST_OK_FOR_I16 (INTVAL (operands[1]))"
5493
  [(set (match_dup 0) (match_dup 2))
5494
   (match_dup 1)]
5495
  "
5496
{
5497
  unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
5498
  unsigned HOST_WIDE_INT low = val;
5499
  unsigned HOST_WIDE_INT high = val;
5500
  unsigned HOST_WIDE_INT sign;
5501
  unsigned HOST_WIDE_INT val2 = val ^ (val-1);
5502
 
5503
  /* Zero-extend the 16 least-significant bits.  */
5504
  low &= 0xffff;
5505
 
5506
  /* Arithmetic shift right the word by 16 bits.  */
5507
  high >>= 16;
5508
  if (GET_CODE (operands[0]) == SUBREG
5509
      && GET_MODE (SUBREG_REG (operands[0])) == SImode)
5510
    {
5511
      high &= 0xffff;
5512
      high ^= 0x8000;
5513
      high -= 0x8000;
5514
    }
5515
  else
5516
    {
5517
      sign = 1;
5518
      sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5519
      high ^= sign;
5520
      high -= sign;
5521
    }
5522
  do
5523
    {
5524
      /* If we can't generate the constant with a two-insn movi / shori
5525
         sequence, try some other strategies.  */
5526
      if (! CONST_OK_FOR_I16 (high))
5527
        {
5528
          /* Try constant load / left shift.  We know VAL != 0.  */
5529
          val2 = val ^ (val-1);
5530
          if (val2 > 0x1ffff)
5531
            {
5532
              int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
5533
 
5534
              if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
5535
                  || (! CONST_OK_FOR_I16 (high >> 16)
5536
                      && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
5537
                {
5538
                  val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
5539
                  operands[1] = gen_ashldi3_media (operands[0], operands[0],
5540
                                                   GEN_INT (trailing_zeroes));
5541
                  break;
5542
                }
5543
            }
5544
          /* Try constant load / right shift.  */
5545
          val2 = (val >> 15) + 1;
5546
          if (val2 == (val2 & -val2))
5547
            {
5548
              int shift = 49 - exact_log2 (val2);
5549
 
5550
              val2 = trunc_int_for_mode (val << shift, DImode);
5551
              if (CONST_OK_FOR_I16 (val2))
5552
                {
5553
                  operands[1] = gen_lshrdi3_media (operands[0], operands[0],
5554
                                                   GEN_INT (shift));
5555
                  break;
5556
                }
5557
            }
5558
          /* Try mperm.w .  */
5559
          val2 = val & 0xffff;
5560
          if ((val >> 16 & 0xffff) == val2
5561
              && (val >> 32 & 0xffff) == val2
5562
              && (val >> 48 & 0xffff) == val2)
5563
            {
5564
              val2 = (HOST_WIDE_INT) val >> 48;
5565
              operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
5566
              operands[1] = gen_mperm_w0 (operands[1], operands[1]);
5567
              break;
5568
            }
5569
          /* Try movi / mshflo.l  */
5570
          val2 = (HOST_WIDE_INT) val >> 32;
5571
          if (val2 == ((unsigned HOST_WIDE_INT)
5572
                        trunc_int_for_mode (val, SImode)))
5573
            {
5574
              operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5575
                                             operands[0]);
5576
              break;
5577
            }
5578
          /* Try movi / mshflo.l w/ r63.  */
5579
          val2 = val + ((HOST_WIDE_INT) -1 << 32);
5580
          if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
5581
            {
5582
              operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5583
                                             const0_rtx);
5584
              break;
5585
            }
5586
        }
5587
      val2 = high;
5588
      operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
5589
    }
5590
  while (0);
5591
  operands[2] = GEN_INT (val2);
5592
}")
5593
 
5594
(define_split
5595
  [(set (match_operand:DI 0 "ext_dest_operand" "")
5596
        (match_operand:DI 1 "immediate_operand" ""))]
5597
  "TARGET_SHMEDIA && reload_completed
5598
   && GET_CODE (operands[1]) == CONST_DOUBLE"
5599
  [(set (match_dup 0) (match_dup 2))
5600
  (set (match_dup 0)
5601
       (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
5602
  "
5603
{
5604
  unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
5605
  unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
5606
  unsigned HOST_WIDE_INT val = low;
5607
  unsigned HOST_WIDE_INT sign;
5608
 
5609
  /* Zero-extend the 16 least-significant bits.  */
5610
  val &= 0xffff;
5611
  operands[1] = GEN_INT (val);
5612
 
5613
  /* Arithmetic shift right the double-word by 16 bits.  */
5614
  low >>= 16;
5615
  low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
5616
  high >>= 16;
5617
  sign = 1;
5618
  sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5619
  high ^= sign;
5620
  high -= sign;
5621
 
5622
  /* This will only be true if high is a sign-extension of low, i.e.,
5623
     it must be either 0 or (unsigned)-1, and be zero iff the
5624
     most-significant bit of low is set.  */
5625
  if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
5626
    operands[2] = GEN_INT (low);
5627
  else
5628
    operands[2] = immed_double_const (low, high, DImode);
5629
}")
5630
 
5631
(define_insn "shori_media"
5632
  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5633
        (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
5634
                           (const_int 16))
5635
                (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
5636
  "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
5637
  "@
5638
        shori   %u2, %0
5639
        #"
5640
  [(set_attr "type" "arith_media,*")])
5641
 
5642
(define_insn "*shori_media_si"
5643
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5644
        (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5645
                           (const_int 16))
5646
                (match_operand:SI 2 "immediate_operand" "K16Csu")))]
5647
  "TARGET_SHMEDIA"
5648
  "shori        %u2, %0")
5649
 
5650
(define_expand "movdi"
5651
  [(set (match_operand:DI 0 "general_movdst_operand" "")
5652
        (match_operand:DI 1 "general_movsrc_operand" ""))]
5653
  ""
5654
  "{ if (prepare_move_operands (operands, DImode)) DONE; }")
5655
 
5656
(define_insn "movdf_media"
5657
  [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
5658
        (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
5659
  "TARGET_SHMEDIA_FPU
5660
   && (register_operand (operands[0], DFmode)
5661
       || sh_register_operand (operands[1], DFmode))"
5662
  "@
5663
        fmov.d  %1, %0
5664
        fmov.qd %N1, %0
5665
        fmov.dq %1, %0
5666
        add     %1, r63, %0
5667
        #
5668
        fld%M1.d        %m1, %0
5669
        fst%M0.d        %m0, %1
5670
        ld%M1.q %m1, %0
5671
        st%M0.q %m0, %N1"
5672
  [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
5673
 
5674
(define_insn "movdf_media_nofpu"
5675
  [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
5676
        (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
5677
  "TARGET_SHMEDIA
5678
   && (register_operand (operands[0], DFmode)
5679
       || sh_register_operand (operands[1], DFmode))"
5680
  "@
5681
        add     %1, r63, %0
5682
        #
5683
        ld%M1.q %m1, %0
5684
        st%M0.q %m0, %N1"
5685
  [(set_attr "type" "arith_media,*,load_media,store_media")])
5686
 
5687
(define_split
5688
  [(set (match_operand:DF 0 "arith_reg_dest" "")
5689
        (match_operand:DF 1 "immediate_operand" ""))]
5690
  "TARGET_SHMEDIA && reload_completed"
5691
  [(set (match_dup 3) (match_dup 2))]
5692
  "
5693
{
5694
  int endian = WORDS_BIG_ENDIAN ? 1 : 0;
5695
  long values[2];
5696
  REAL_VALUE_TYPE value;
5697
 
5698
  REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
5699
  REAL_VALUE_TO_TARGET_DOUBLE (value, values);
5700
 
5701
  if (HOST_BITS_PER_WIDE_INT >= 64)
5702
    operands[2] = immed_double_const ((unsigned long) values[endian]
5703
                                      | ((HOST_WIDE_INT) values[1 - endian]
5704
                                         << 32), 0, DImode);
5705
  else
5706
    {
5707
      gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
5708
      operands[2] = immed_double_const (values[endian], values[1 - endian],
5709
                                        DImode);
5710
    }
5711
 
5712
  operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
5713
}")
5714
 
5715
;; ??? This should be a define expand.
5716
 
5717
(define_insn "movdf_k"
5718
  [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
5719
        (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
5720
  "TARGET_SH1
5721
   && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
5722
       /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
5723
       || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
5724
       || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
5725
   && (arith_reg_operand (operands[0], DFmode)
5726
       || arith_reg_operand (operands[1], DFmode))"
5727
  "* return output_movedouble (insn, operands, DFmode);"
5728
  [(set_attr "length" "4")
5729
   (set_attr "type" "move,pcload,load,store")])
5730
 
5731
;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
5732
;; However, the d/F/c/z alternative cannot be split directly; it is converted
5733
;; with special code in machine_dependent_reorg into a load of the R0_REG and
5734
;; the d/m/c/X alternative, which is split later into single-precision
5735
;; instructions.  And when not optimizing, no splits are done before fixing
5736
;; up pcloads, so we need usable length information for that.
5737
(define_insn "movdf_i4"
5738
  [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
5739
        (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
5740
   (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
5741
   (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
5742
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
5743
   && (arith_reg_operand (operands[0], DFmode)
5744
       || arith_reg_operand (operands[1], DFmode))"
5745
  "@
5746
        fmov    %1,%0
5747
        #
5748
        #
5749
        fmov.d  %1,%0
5750
        fmov.d  %1,%0
5751
        #
5752
        #
5753
        #
5754
        #
5755
        #"
5756
  [(set_attr_alternative "length"
5757
     [(if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 4))
5758
      (const_int 4)
5759
      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5760
      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5761
      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5762
      (const_int 4)
5763
      (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
5764
      ;; We can't use 4-byte push/pop on SHcompact, so we have to
5765
      ;; increment or decrement r15 explicitly.
5766
      (if_then_else
5767
       (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
5768
       (const_int 10) (const_int 8))
5769
      (if_then_else
5770
       (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
5771
       (const_int 10) (const_int 8))])
5772
   (set_attr "type" "fmove,move,pcfload,fload,store,pcload,load,store,load,fload")
5773
   (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
5774
   (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
5775
                                           (const_string "double")
5776
                                           (const_string "none")))])
5777
 
5778
;; Moving DFmode between fp/general registers through memory
5779
;; (the top of the stack) is faster than moving through fpul even for
5780
;; little endian.  Because the type of an instruction is important for its
5781
;; scheduling,  it is beneficial to split these operations, rather than
5782
;; emitting them in one single chunk, even if this will expose a stack
5783
;; use that will prevent scheduling of other stack accesses beyond this
5784
;; instruction.
5785
(define_split
5786
  [(set (match_operand:DF 0 "register_operand" "")
5787
        (match_operand:DF 1 "register_operand" ""))
5788
   (use (match_operand:PSI 2 "fpscr_operand" ""))
5789
   (clobber (match_scratch:SI 3 "=X"))]
5790
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
5791
   && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
5792
  [(const_int 0)]
5793
  "
5794
{
5795
  rtx insn, tos;
5796
 
5797
  if (TARGET_SH5 && true_regnum (operands[1]) < 16)
5798
    {
5799
      emit_move_insn (stack_pointer_rtx,
5800
                      plus_constant (stack_pointer_rtx, -8));
5801
      tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
5802
    }
5803
  else
5804
    tos = gen_tmp_stack_mem (DFmode,
5805
                             gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
5806
  insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
5807
  if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
5808
    REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
5809
  if (TARGET_SH5 && true_regnum (operands[0]) < 16)
5810
    tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
5811
  else
5812
    tos = gen_tmp_stack_mem (DFmode,
5813
                             gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
5814
  insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
5815
  if (TARGET_SH5 && true_regnum (operands[0]) < 16)
5816
    emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
5817
  else
5818
    REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
5819
  DONE;
5820
}")
5821
 
5822
;; local-alloc sometimes allocates scratch registers even when not required,
5823
;; so we must be prepared to handle these.
5824
 
5825
;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
5826
(define_split
5827
  [(set (match_operand:DF 0 "general_movdst_operand" "")
5828
        (match_operand:DF 1 "general_movsrc_operand"  ""))
5829
   (use (match_operand:PSI 2 "fpscr_operand" ""))
5830
   (clobber (match_scratch:SI 3 ""))]
5831
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
5832
   && reload_completed
5833
   && true_regnum (operands[0]) < 16
5834
   && true_regnum (operands[1]) < 16"
5835
  [(set (match_dup 0) (match_dup 1))]
5836
  "
5837
{
5838
  /* If this was a reg <-> mem operation with base + index reg addressing,
5839
     we have to handle this in a special way.  */
5840
  rtx mem = operands[0];
5841
  int store_p = 1;
5842
  if (! memory_operand (mem, DFmode))
5843
    {
5844
      mem = operands[1];
5845
      store_p = 0;
5846
    }
5847
  if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
5848
    mem = SUBREG_REG (mem);
5849
  if (GET_CODE (mem) == MEM)
5850
    {
5851
      rtx addr = XEXP (mem, 0);
5852
      if (GET_CODE (addr) == PLUS
5853
          && GET_CODE (XEXP (addr, 0)) == REG
5854
          && GET_CODE (XEXP (addr, 1)) == REG)
5855
        {
5856
          int offset;
5857
          rtx reg0 = gen_rtx_REG (Pmode, 0);
5858
          rtx regop = operands[store_p], word0 ,word1;
5859
 
5860
          if (GET_CODE (regop) == SUBREG)
5861
            alter_subreg (®op);
5862
          if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
5863
            offset = 2;
5864
          else
5865
            offset = 4;
5866
          mem = copy_rtx (mem);
5867
          PUT_MODE (mem, SImode);
5868
          word0 = gen_rtx_SUBREG (SImode, regop, 0);
5869
          alter_subreg (&word0);
5870
          word1 = gen_rtx_SUBREG (SImode, regop, 4);
5871
          alter_subreg (&word1);
5872
          if (store_p || ! refers_to_regno_p (REGNO (word0),
5873
                                              REGNO (word0) + 1, addr, 0))
5874
            {
5875
              emit_insn (store_p
5876
                         ? gen_movsi_ie (mem, word0)
5877
                         : gen_movsi_ie (word0, mem));
5878
              emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
5879
              mem = copy_rtx (mem);
5880
              emit_insn (store_p
5881
                         ? gen_movsi_ie (mem, word1)
5882
                         : gen_movsi_ie (word1, mem));
5883
              emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
5884
            }
5885
          else
5886
            {
5887
              emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
5888
              emit_insn (gen_movsi_ie (word1, mem));
5889
              emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
5890
              mem = copy_rtx (mem);
5891
              emit_insn (gen_movsi_ie (word0, mem));
5892
            }
5893
          DONE;
5894
        }
5895
    }
5896
}")
5897
 
5898
;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
5899
(define_split
5900
  [(set (match_operand:DF 0 "register_operand" "")
5901
        (match_operand:DF 1 "memory_operand"  ""))
5902
   (use (match_operand:PSI 2 "fpscr_operand" ""))
5903
   (clobber (reg:SI R0_REG))]
5904
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
5905
  [(parallel [(set (match_dup 0) (match_dup 1))
5906
              (use (match_dup 2))
5907
              (clobber (scratch:SI))])]
5908
  "")
5909
 
5910
(define_expand "reload_indf__frn"
5911
  [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
5912
                   (match_operand:DF 1 "immediate_operand" "FQ"))
5913
              (use (reg:PSI FPSCR_REG))
5914
              (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
5915
  "TARGET_SH1"
5916
  "")
5917
 
5918
(define_expand "reload_outdf__RnFRm"
5919
  [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
5920
                   (match_operand:DF 1 "register_operand" "af,r"))
5921
              (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
5922
  "TARGET_SH1"
5923
  "")
5924
 
5925
;; Simplify no-op moves.
5926
(define_split
5927
  [(set (match_operand:SF 0 "register_operand" "")
5928
        (match_operand:SF 1 "register_operand" ""))
5929
   (use (match_operand:PSI 2 "fpscr_operand" ""))
5930
   (clobber (match_scratch:SI 3 ""))]
5931
  "TARGET_SH2E && reload_completed
5932
   && true_regnum (operands[0]) == true_regnum (operands[1])"
5933
  [(set (match_dup 0) (match_dup 0))]
5934
  "")
5935
 
5936
;; fmovd substitute post-reload splits
5937
(define_split
5938
  [(set (match_operand:DF 0 "register_operand" "")
5939
        (match_operand:DF 1 "register_operand" ""))
5940
   (use (match_operand:PSI 2 "fpscr_operand" ""))
5941
   (clobber (match_scratch:SI 3 ""))]
5942
  "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
5943
   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
5944
   && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
5945
  [(const_int 0)]
5946
  "
5947
{
5948
  int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
5949
  emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
5950
                           gen_rtx_REG (SFmode, src), operands[2]));
5951
  emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
5952
                           gen_rtx_REG (SFmode, src + 1), operands[2]));
5953
  DONE;
5954
}")
5955
 
5956
(define_split
5957
  [(set (match_operand:DF 0 "register_operand" "")
5958
        (mem:DF (match_operand:SI 1 "register_operand" "")))
5959
   (use (match_operand:PSI 2 "fpscr_operand" ""))
5960
   (clobber (match_scratch:SI 3 ""))]
5961
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
5962
   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
5963
   && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
5964
  [(const_int 0)]
5965
  "
5966
{
5967
  int regno = true_regnum (operands[0]);
5968
  rtx insn;
5969
  rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
5970
  rtx mem2
5971
    = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
5972
  insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
5973
                                           regno + !! TARGET_LITTLE_ENDIAN),
5974
                                  mem2, operands[2]));
5975
  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[1], NULL_RTX);
5976
  insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
5977
                                               regno + ! TARGET_LITTLE_ENDIAN),
5978
                                  change_address (mem, SFmode, NULL_RTX),
5979
                                  operands[2]));
5980
  DONE;
5981
}")
5982
 
5983
(define_split
5984
  [(set (match_operand:DF 0 "register_operand" "")
5985
        (match_operand:DF 1 "memory_operand" ""))
5986
   (use (match_operand:PSI 2 "fpscr_operand" ""))
5987
   (clobber (match_scratch:SI 3 ""))]
5988
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
5989
   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
5990
  [(const_int 0)]
5991
  "
5992
{
5993
  int regno = true_regnum (operands[0]);
5994
  rtx addr, insn, adjust = NULL_RTX;
5995
  rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
5996
  rtx reg0 = gen_rtx_REG (SFmode, regno + !! TARGET_LITTLE_ENDIAN);
5997
  rtx reg1 = gen_rtx_REG (SFmode, regno + ! TARGET_LITTLE_ENDIAN);
5998
 
5999
  operands[1] = copy_rtx (mem2);
6000
  addr = XEXP (mem2, 0);
6001
  if (GET_CODE (addr) != POST_INC)
6002
    {
6003
      /* If we have to modify the stack pointer, the value that we have
6004
         read with post-increment might be modified by an interrupt,
6005
         so write it back.  */
6006
      if (REGNO (addr) == STACK_POINTER_REGNUM)
6007
        adjust = gen_push_e (reg0);
6008
      else
6009
        adjust = gen_addsi3 (addr, addr, GEN_INT (-4));
6010
      XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
6011
    }
6012
  addr = XEXP (addr, 0);
6013
  insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
6014
  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6015
  insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6016
  if (adjust)
6017
    emit_insn (adjust);
6018
  else
6019
    REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6020
  DONE;
6021
}")
6022
 
6023
(define_split
6024
  [(set (match_operand:DF 0 "memory_operand" "")
6025
        (match_operand:DF 1 "register_operand" ""))
6026
   (use (match_operand:PSI 2 "fpscr_operand" ""))
6027
   (clobber (match_scratch:SI 3 ""))]
6028
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6029
   && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6030
  [(const_int 0)]
6031
  "
6032
{
6033
  int regno = true_regnum (operands[1]);
6034
  rtx insn, addr, adjust = NULL_RTX;
6035
 
6036
  operands[0] = copy_rtx (operands[0]);
6037
  PUT_MODE (operands[0], SFmode);
6038
  insn = emit_insn (gen_movsf_ie (operands[0],
6039
                                  gen_rtx_REG (SFmode,
6040
                                           regno + ! TARGET_LITTLE_ENDIAN),
6041
                                  operands[2]));
6042
  operands[0] = copy_rtx (operands[0]);
6043
  addr = XEXP (operands[0], 0);
6044
  if (GET_CODE (addr) != PRE_DEC)
6045
    {
6046
      adjust = gen_addsi3 (addr, addr, GEN_INT (4));
6047
      emit_insn_before (adjust, insn);
6048
      XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
6049
    }
6050
  addr = XEXP (addr, 0);
6051
  if (! adjust)
6052
    REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6053
  insn = emit_insn (gen_movsf_ie (operands[0],
6054
                                  gen_rtx_REG (SFmode,
6055
                                           regno + !! TARGET_LITTLE_ENDIAN),
6056
                                  operands[2]));
6057
  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6058
  DONE;
6059
}")
6060
 
6061
;; If the output is a register and the input is memory or a register, we have
6062
;; to be careful and see which word needs to be loaded first.
6063
 
6064
(define_split
6065
  [(set (match_operand:DF 0 "general_movdst_operand" "")
6066
        (match_operand:DF 1 "general_movsrc_operand" ""))]
6067
  "TARGET_SH1 && reload_completed"
6068
  [(set (match_dup 2) (match_dup 3))
6069
   (set (match_dup 4) (match_dup 5))]
6070
  "
6071
{
6072
  int regno;
6073
 
6074
  if ((GET_CODE (operands[0]) == MEM
6075
       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
6076
      || (GET_CODE (operands[1]) == MEM
6077
          && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
6078
    FAIL;
6079
 
6080
  switch (GET_CODE (operands[0]))
6081
    {
6082
    case REG:
6083
      regno = REGNO (operands[0]);
6084
      break;
6085
    case SUBREG:
6086
      regno = subreg_regno (operands[0]);
6087
      break;
6088
    case MEM:
6089
      regno = -1;
6090
      break;
6091
    default:
6092
      gcc_unreachable ();
6093
    }
6094
 
6095
  if (regno == -1
6096
      || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
6097
    {
6098
      operands[2] = operand_subword (operands[0], 0, 0, DFmode);
6099
      operands[3] = operand_subword (operands[1], 0, 0, DFmode);
6100
      operands[4] = operand_subword (operands[0], 1, 0, DFmode);
6101
      operands[5] = operand_subword (operands[1], 1, 0, DFmode);
6102
    }
6103
  else
6104
    {
6105
      operands[2] = operand_subword (operands[0], 1, 0, DFmode);
6106
      operands[3] = operand_subword (operands[1], 1, 0, DFmode);
6107
      operands[4] = operand_subword (operands[0], 0, 0, DFmode);
6108
      operands[5] = operand_subword (operands[1], 0, 0, DFmode);
6109
    }
6110
 
6111
  if (operands[2] == 0 || operands[3] == 0
6112
      || operands[4] == 0 || operands[5] == 0)
6113
    FAIL;
6114
}")
6115
 
6116
;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is
6117
;; used only once, let combine add in the index again.
6118
 
6119
(define_split
6120
  [(set (match_operand:SI 0 "register_operand" "")
6121
        (match_operand:SI 1 "" ""))
6122
   (clobber (match_operand 2 "register_operand" ""))]
6123
  "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6124
   && ALLOW_INDEXED_ADDRESS"
6125
  [(use (reg:SI R0_REG))]
6126
  "
6127
{
6128
  rtx addr, reg, const_int;
6129
 
6130
  if (GET_CODE (operands[1]) != MEM)
6131
    FAIL;
6132
  addr = XEXP (operands[1], 0);
6133
  if (GET_CODE (addr) != PLUS)
6134
    FAIL;
6135
  reg = XEXP (addr, 0);
6136
  const_int = XEXP (addr, 1);
6137
  if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6138
         && GET_CODE (const_int) == CONST_INT))
6139
    FAIL;
6140
  emit_move_insn (operands[2], const_int);
6141
  emit_move_insn (operands[0],
6142
                  change_address (operands[1], VOIDmode,
6143
                                  gen_rtx_PLUS (SImode, reg, operands[2])));
6144
  DONE;
6145
}")
6146
 
6147
(define_split
6148
  [(set (match_operand:SI 1 "" "")
6149
        (match_operand:SI 0 "register_operand" ""))
6150
   (clobber (match_operand 2 "register_operand" ""))]
6151
  "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6152
   && ALLOW_INDEXED_ADDRESS"
6153
  [(use (reg:SI R0_REG))]
6154
  "
6155
{
6156
  rtx addr, reg, const_int;
6157
 
6158
  if (GET_CODE (operands[1]) != MEM)
6159
    FAIL;
6160
  addr = XEXP (operands[1], 0);
6161
  if (GET_CODE (addr) != PLUS)
6162
    FAIL;
6163
  reg = XEXP (addr, 0);
6164
  const_int = XEXP (addr, 1);
6165
  if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6166
         && GET_CODE (const_int) == CONST_INT))
6167
    FAIL;
6168
  emit_move_insn (operands[2], const_int);
6169
  emit_move_insn (change_address (operands[1], VOIDmode,
6170
                                  gen_rtx_PLUS (SImode, reg, operands[2])),
6171
                  operands[0]);
6172
  DONE;
6173
}")
6174
 
6175
(define_expand "movdf"
6176
  [(set (match_operand:DF 0 "general_movdst_operand" "")
6177
        (match_operand:DF 1 "general_movsrc_operand" ""))]
6178
  ""
6179
  "
6180
{
6181
  if (prepare_move_operands (operands, DFmode)) DONE;
6182
  if (TARGET_SHMEDIA)
6183
    {
6184
      if (TARGET_SHMEDIA_FPU)
6185
        emit_insn (gen_movdf_media (operands[0], operands[1]));
6186
      else
6187
        emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
6188
      DONE;
6189
    }
6190
  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
6191
    {
6192
      emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
6193
      DONE;
6194
    }
6195
}")
6196
 
6197
;;This is incompatible with the way gcc uses subregs.
6198
;;(define_insn "movv2sf_i"
6199
;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
6200
;;      (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
6201
;;  "TARGET_SHMEDIA_FPU
6202
;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
6203
;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
6204
;;  "@
6205
;;      #
6206
;;      fld%M1.p        %m1, %0
6207
;;      fst%M0.p        %m0, %1"
6208
;;  [(set_attr "type" "*,fload_media,fstore_media")])
6209
 
6210
(define_insn_and_split "movv2sf_i"
6211
  [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6212
        (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6213
  "TARGET_SHMEDIA_FPU"
6214
  "#"
6215
  "TARGET_SHMEDIA_FPU && reload_completed"
6216
  [(set (match_dup 0) (match_dup 1))]
6217
  "
6218
{
6219
  operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
6220
  operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
6221
}")
6222
 
6223
(define_expand "movv2sf"
6224
  [(set (match_operand:V2SF 0 "general_movdst_operand" "")
6225
        (match_operand:V2SF 1 "nonimmediate_operand" ""))]
6226
  "TARGET_SHMEDIA_FPU"
6227
  "
6228
{
6229
  if (prepare_move_operands (operands, V2SFmode))
6230
    DONE;
6231
}")
6232
 
6233
(define_expand "addv2sf3"
6234
  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6235
   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6236
   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6237
  "TARGET_SHMEDIA_FPU"
6238
  "
6239
{
6240
  sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
6241
  DONE;
6242
}")
6243
 
6244
(define_expand "subv2sf3"
6245
  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6246
   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6247
   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6248
  "TARGET_SHMEDIA_FPU"
6249
  "
6250
{
6251
  sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
6252
  DONE;
6253
}")
6254
 
6255
(define_expand "mulv2sf3"
6256
  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6257
   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6258
   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6259
  "TARGET_SHMEDIA_FPU"
6260
  "
6261
{
6262
  sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
6263
  DONE;
6264
}")
6265
 
6266
(define_expand "divv2sf3"
6267
  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6268
   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6269
   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6270
  "TARGET_SHMEDIA_FPU"
6271
  "
6272
{
6273
  sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
6274
  DONE;
6275
}")
6276
 
6277
(define_insn_and_split "*movv4sf_i"
6278
  [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6279
        (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6280
  "TARGET_SHMEDIA_FPU"
6281
  "#"
6282
  "&& reload_completed"
6283
  [(const_int 0)]
6284
  "
6285
{
6286
  int i;
6287
 
6288
  for (i = 0; i < 4/2; i++)
6289
    {
6290
      rtx x, y;
6291
 
6292
      if (GET_CODE (operands[0]) == MEM)
6293
        x = adjust_address (operands[0], V2SFmode,
6294
                            i * GET_MODE_SIZE (V2SFmode));
6295
      else
6296
        x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
6297
 
6298
      if (GET_CODE (operands[1]) == MEM)
6299
        y = adjust_address (operands[1], V2SFmode,
6300
                            i * GET_MODE_SIZE (V2SFmode));
6301
      else
6302
        y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
6303
 
6304
      emit_insn (gen_movv2sf_i (x, y));
6305
    }
6306
 
6307
  DONE;
6308
}"
6309
  [(set_attr "length" "8")])
6310
 
6311
(define_expand "movv4sf"
6312
  [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
6313
        (match_operand:V4SF 1 "general_operand" ""))]
6314
  "TARGET_SHMEDIA_FPU"
6315
  "
6316
{
6317
  if (prepare_move_operands (operands, V4SFmode))
6318
    DONE;
6319
}")
6320
 
6321
(define_insn_and_split "*movv16sf_i"
6322
  [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6323
        (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6324
  "TARGET_SHMEDIA_FPU"
6325
  "#"
6326
  "&& reload_completed"
6327
  [(const_int 0)]
6328
  "
6329
{
6330
  int i;
6331
 
6332
  for (i = 0; i < 16/2; i++)
6333
    {
6334
      rtx x,y;
6335
 
6336
      if (GET_CODE (operands[0]) == MEM)
6337
        x = adjust_address (operands[0], V2SFmode,
6338
                            i * GET_MODE_SIZE (V2SFmode));
6339
      else
6340
        {
6341
          x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
6342
          alter_subreg (&x);
6343
        }
6344
 
6345
      if (GET_CODE (operands[1]) == MEM)
6346
        y = adjust_address (operands[1], V2SFmode,
6347
                            i * GET_MODE_SIZE (V2SFmode));
6348
      else
6349
        {
6350
          y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
6351
          alter_subreg (&y);
6352
        }
6353
 
6354
      emit_insn (gen_movv2sf_i (x, y));
6355
    }
6356
 
6357
  DONE;
6358
}"
6359
  [(set_attr "length" "32")])
6360
 
6361
(define_expand "movv16sf"
6362
  [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6363
        (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6364
  "TARGET_SHMEDIA_FPU"
6365
  "
6366
{
6367
  if (prepare_move_operands (operands, V16SFmode))
6368
    DONE;
6369
}")
6370
 
6371
(define_insn "movsf_media"
6372
  [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
6373
        (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
6374
  "TARGET_SHMEDIA_FPU
6375
   && (register_operand (operands[0], SFmode)
6376
       || sh_register_operand (operands[1], SFmode))"
6377
  "@
6378
        fmov.s  %1, %0
6379
        fmov.ls %N1, %0
6380
        fmov.sl %1, %0
6381
        add.l   %1, r63, %0
6382
        #
6383
        fld%M1.s        %m1, %0
6384
        fst%M0.s        %m0, %1
6385
        ld%M1.l %m1, %0
6386
        st%M0.l %m0, %N1"
6387
  [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
6388
   (set (attr "highpart")
6389
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
6390
               (const_string "user")]
6391
              (const_string "ignore")))])
6392
 
6393
(define_insn "movsf_media_nofpu"
6394
  [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
6395
        (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
6396
  "TARGET_SHMEDIA
6397
   && (register_operand (operands[0], SFmode)
6398
       || sh_register_operand (operands[1], SFmode))"
6399
  "@
6400
        add.l   %1, r63, %0
6401
        #
6402
        ld%M1.l %m1, %0
6403
        st%M0.l %m0, %N1"
6404
  [(set_attr "type" "arith_media,*,load_media,store_media")
6405
   (set (attr "highpart")
6406
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
6407
               (const_string "user")]
6408
              (const_string "ignore")))])
6409
 
6410
(define_split
6411
  [(set (match_operand:SF 0 "arith_reg_dest" "")
6412
        (match_operand:SF 1 "immediate_operand" ""))]
6413
  "TARGET_SHMEDIA && reload_completed
6414
   && ! FP_REGISTER_P (true_regnum (operands[0]))"
6415
  [(set (match_dup 3) (match_dup 2))]
6416
  "
6417
{
6418
  long values;
6419
  REAL_VALUE_TYPE value;
6420
 
6421
  REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
6422
  REAL_VALUE_TO_TARGET_SINGLE (value, values);
6423
  operands[2] = GEN_INT (values);
6424
 
6425
  operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6426
}")
6427
 
6428
(define_insn "movsf_i"
6429
  [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
6430
        (match_operand:SF 1 "general_movsrc_operand"  "r,G,FQ,mr,r,r,l"))]
6431
  "TARGET_SH1
6432
   && (! TARGET_SH2E
6433
       /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
6434
       || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
6435
       || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
6436
   && (arith_reg_operand (operands[0], SFmode)
6437
       || arith_reg_operand (operands[1], SFmode))"
6438
  "@
6439
        mov     %1,%0
6440
        mov     #0,%0
6441
        mov.l   %1,%0
6442
        mov.l   %1,%0
6443
        mov.l   %1,%0
6444
        lds     %1,%0
6445
        sts     %1,%0"
6446
  [(set_attr "type" "move,move,pcload,load,store,move,move")])
6447
 
6448
;; We may not split the ry/yr/XX alternatives to movsi_ie, since
6449
;; update_flow_info would not know where to put REG_EQUAL notes
6450
;; when the destination changes mode.
6451
(define_insn "movsf_ie"
6452
  [(set (match_operand:SF 0 "general_movdst_operand"
6453
         "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
6454
        (match_operand:SF 1 "general_movsrc_operand"
6455
          "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
6456
   (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"))
6457
   (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
6458
 
6459
  "TARGET_SH2E
6460
   && (arith_reg_operand (operands[0], SFmode)
6461
       || arith_reg_operand (operands[1], SFmode)
6462
       || arith_reg_operand (operands[3], SImode)
6463
       || (fpul_operand (operands[0], SFmode)
6464
           && memory_operand (operands[1], SFmode)
6465
           && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
6466
       || (fpul_operand (operands[1], SFmode)
6467
           && memory_operand (operands[0], SFmode)
6468
           && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
6469
  "@
6470
        fmov    %1,%0
6471
        mov     %1,%0
6472
        fldi0   %0
6473
        fldi1   %0
6474
        #
6475
        fmov.s  %1,%0
6476
        fmov.s  %1,%0
6477
        mov.l   %1,%0
6478
        mov.l   %1,%0
6479
        mov.l   %1,%0
6480
        fsts    fpul,%0
6481
        flds    %1,fpul
6482
        lds.l   %1,%0
6483
        #
6484
        sts     %1,%0
6485
        lds     %1,%0
6486
        sts.l   %1,%0
6487
        lds.l   %1,%0
6488
        ! move optimized away"
6489
  [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,store,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,store,load,nil")
6490
   (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
6491
   (set_attr "length" "*,*,*,*,4,4,4,*,*,*,2,2,2,4,2,2,2,2,0")
6492
   (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
6493
                                           (const_string "single")
6494
                                           (const_string "none")))])
6495
 
6496
(define_split
6497
  [(set (match_operand:SF 0 "register_operand" "")
6498
        (match_operand:SF 1 "register_operand" ""))
6499
   (use (match_operand:PSI 2 "fpscr_operand" ""))
6500
   (clobber (reg:SI FPUL_REG))]
6501
  "TARGET_SH1"
6502
  [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
6503
              (use (match_dup 2))
6504
              (clobber (scratch:SI))])
6505
   (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
6506
              (use (match_dup 2))
6507
              (clobber (scratch:SI))])]
6508
  "")
6509
 
6510
(define_expand "movsf"
6511
  [(set (match_operand:SF 0 "general_movdst_operand" "")
6512
        (match_operand:SF 1 "general_movsrc_operand" ""))]
6513
  ""
6514
  "
6515
{
6516
  if (prepare_move_operands (operands, SFmode))
6517
    DONE;
6518
  if (TARGET_SHMEDIA)
6519
    {
6520
      if (TARGET_SHMEDIA_FPU)
6521
        emit_insn (gen_movsf_media (operands[0], operands[1]));
6522
      else
6523
        emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
6524
      DONE;
6525
    }
6526
  if (TARGET_SH2E)
6527
    {
6528
      emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
6529
      DONE;
6530
    }
6531
}")
6532
 
6533
(define_insn "mov_nop"
6534
  [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
6535
  "TARGET_SH2E"
6536
  ""
6537
  [(set_attr "length" "0")
6538
   (set_attr "type" "nil")])
6539
 
6540
(define_expand "reload_insf__frn"
6541
  [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
6542
                   (match_operand:SF 1 "immediate_operand" "FQ"))
6543
              (use (reg:PSI FPSCR_REG))
6544
              (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6545
  "TARGET_SH1"
6546
  "")
6547
 
6548
(define_expand "reload_insi__i_fpul"
6549
  [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
6550
                   (match_operand:SI 1 "immediate_operand" "i"))
6551
              (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6552
  "TARGET_SH1"
6553
  "")
6554
 
6555
(define_expand "ptabs"
6556
  [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
6557
  "TARGET_SHMEDIA"
6558
  "
6559
{
6560
  if (!TARGET_PT_FIXED)
6561
    {
6562
      rtx eq = operands[1];
6563
 
6564
      /* ??? For canonical RTL we really should remove any CONST from EQ
6565
         before wrapping it in the AND, and finally wrap the EQ into a
6566
         const if is constant.  However, for reload we must expose the
6567
         input register or symbolic constant, and we can't have
6568
         different insn structures outside of the operands for different
6569
         alternatives of the same pattern.  */
6570
      eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
6571
                       GEN_INT (3));
6572
      operands[1]
6573
        = (gen_rtx_IF_THEN_ELSE
6574
            (PDImode,
6575
             eq,
6576
             gen_rtx_MEM (PDImode, operands[1]),
6577
             gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
6578
                            PDImode, operands[1])));
6579
    }
6580
}")
6581
 
6582
;; expanded by ptabs expander.
6583
(define_insn "*extendsipdi_media"
6584
  [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
6585
        (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
6586
                                                          "r,Csy")
6587
                                      (const_int 3))
6588
                              (const_int 3))
6589
                          (mem:PDI (match_dup 1))
6590
                          (sign_extend:PDI (match_dup 1))))]
6591
  "TARGET_SHMEDIA && !TARGET_PT_FIXED"
6592
  "@
6593
        ptabs   %1, %0
6594
        pt      %1, %0"
6595
  [(set_attr "type"   "ptabs_media,pt_media")
6596
   (set_attr "length" "4,*")])
6597
 
6598
(define_insn "*truncdipdi_media"
6599
  [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
6600
        (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
6601
                                                          "r,Csy")
6602
                                      (const_int 3))
6603
                              (const_int 3))
6604
                          (mem:PDI (match_dup 1))
6605
                          (truncate:PDI (match_dup 1))))]
6606
  "TARGET_SHMEDIA && !TARGET_PT_FIXED"
6607
  "@
6608
        ptabs   %1, %0
6609
        pt      %1, %0"
6610
  [(set_attr "type"   "ptabs_media,pt_media")
6611
   (set_attr "length" "4,*")])
6612
 
6613
(define_insn "*movsi_y"
6614
  [(set (match_operand:SI 0 "register_operand" "=y,y")
6615
        (match_operand:SI 1 "immediate_operand" "Qi,I08"))
6616
   (clobber (match_scratch:SI 2 "=&z,r"))]
6617
  "TARGET_SH2E
6618
   && (reload_in_progress || reload_completed)"
6619
  "#"
6620
  [(set_attr "length" "4")
6621
   (set_attr "type" "pcload,move")])
6622
 
6623
(define_split
6624
  [(set (match_operand:SI 0 "register_operand" "")
6625
        (match_operand:SI 1 "immediate_operand" ""))
6626
   (clobber (match_operand:SI 2 "register_operand" ""))]
6627
  "TARGET_SH1"
6628
  [(set (match_dup 2) (match_dup 1))
6629
   (set (match_dup 0) (match_dup 2))]
6630
  "")
6631
 
6632
(define_split
6633
  [(set (match_operand:SI 0 "register_operand" "")
6634
        (match_operand:SI 1 "memory_operand" ""))
6635
   (clobber (reg:SI R0_REG))]
6636
  "TARGET_SH1"
6637
  [(set (match_dup 0) (match_dup 1))]
6638
  "")
6639
 
6640
;; ------------------------------------------------------------------------
6641
;; Define the real conditional branch instructions.
6642
;; ------------------------------------------------------------------------
6643
 
6644
(define_insn "branch_true"
6645
  [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
6646
                           (label_ref (match_operand 0 "" ""))
6647
                           (pc)))]
6648
  "TARGET_SH1"
6649
  "* return output_branch (1, insn, operands);"
6650
  [(set_attr "type" "cbranch")])
6651
 
6652
(define_insn "branch_false"
6653
  [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
6654
                           (label_ref (match_operand 0 "" ""))
6655
                           (pc)))]
6656
  "TARGET_SH1"
6657
  "* return output_branch (0, insn, operands);"
6658
  [(set_attr "type" "cbranch")])
6659
 
6660
;; Patterns to prevent reorg from re-combining a condbranch with a branch
6661
;; which destination is too far away.
6662
;; The const_int_operand is distinct for each branch target; it avoids
6663
;; unwanted matches with redundant_insn.
6664
(define_insn "block_branch_redirect"
6665
  [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
6666
  "TARGET_SH1"
6667
  ""
6668
  [(set_attr "length" "0")])
6669
 
6670
;; This one has the additional purpose to record a possible scratch register
6671
;; for the following branch.
6672
;; ??? Unfortunately, just setting the scratch register is not good enough,
6673
;; because the insn then might be deemed dead and deleted.  And we can't
6674
;; make the use in the jump insn explicit because that would disable
6675
;; delay slot scheduling from the target.
6676
(define_insn "indirect_jump_scratch"
6677
  [(set (match_operand:SI 0 "register_operand" "=r")
6678
        (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
6679
   (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
6680
  "TARGET_SH1"
6681
  ""
6682
  [(set_attr "length" "0")])
6683
 
6684
;; This one is used to preemt an insn from beyond the bra / braf / jmp
6685
;; being pulled into the delay slot of a condbranch that has been made to
6686
;; jump around the unconditional jump because it was out of range.
6687
(define_insn "stuff_delay_slot"
6688
  [(set (pc)
6689
        (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)] UNSPEC_BBR))
6690
   (set (reg:SI T_REG) (match_operand:SI 1 "const_int_operand" ""))]
6691
  "TARGET_SH1"
6692
  ""
6693
  [(set_attr "length" "0")
6694
   (set_attr "cond_delay_slot" "yes")])
6695
 
6696
;; Conditional branch insns
6697
 
6698
(define_expand "beq_media"
6699
  [(set (pc)
6700
        (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r")
6701
                          (match_operand:DI 2 "arith_operand" "r,I06"))
6702
                      (match_operand 0 "" "")
6703
                      (pc)))]
6704
  "TARGET_SHMEDIA"
6705
  "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6706
 
6707
(define_insn "*beq_media_i"
6708
  [(set (pc)
6709
        (if_then_else (match_operator 3 "equality_comparison_operator"
6710
                        [(match_operand:DI 1 "arith_reg_operand" "r,r")
6711
                         (match_operand:DI 2 "arith_operand" "r,I06")])
6712
                      (match_operand 0 "target_operand" "b,b")
6713
                      (pc)))]
6714
  "TARGET_SHMEDIA"
6715
  "@
6716
        b%o3%'  %1, %2, %0%>
6717
        b%o3i%' %1, %2, %0%>"
6718
  [(set_attr "type" "cbranch_media")])
6719
 
6720
(define_insn "*beq_media_i32"
6721
  [(set (pc)
6722
        (if_then_else (match_operator 3 "equality_comparison_operator"
6723
                        [(match_operand:SI 1 "arith_reg_operand" "r,r")
6724
                         (match_operand:SI 2 "arith_operand" "r,I06")])
6725
                      (match_operand 0 "target_operand" "b,b")
6726
                      (pc)))]
6727
  "TARGET_SHMEDIA"
6728
  "@
6729
        b%o3%'  %1, %2, %0%>
6730
        b%o3i%' %1, %2, %0%>"
6731
  [(set_attr "type" "cbranch_media")])
6732
 
6733
(define_expand "bne_media"
6734
  [(set (pc)
6735
        (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r")
6736
                          (match_operand:DI 2 "arith_operand" "r,I06"))
6737
                      (match_operand 0 "" "")
6738
                      (pc)))]
6739
  "TARGET_SHMEDIA"
6740
  "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6741
 
6742
(define_expand "bgt_media"
6743
  [(set (pc)
6744
        (if_then_else (gt (match_operand:DI 1 "arith_reg_or_0_operand" "")
6745
                          (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6746
                      (match_operand 0 "" "")
6747
                      (pc)))]
6748
  "TARGET_SHMEDIA"
6749
  "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6750
 
6751
(define_expand "bge_media"
6752
  [(set (pc)
6753
        (if_then_else (ge (match_operand:DI 1 "arith_reg_or_0_operand" "")
6754
                          (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6755
                      (match_operand 0 "" "")
6756
                      (pc)))]
6757
  "TARGET_SHMEDIA"
6758
  "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6759
 
6760
(define_expand "bgtu_media"
6761
  [(set (pc)
6762
        (if_then_else (gtu (match_operand:DI 1 "arith_reg_or_0_operand" "")
6763
                           (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6764
                      (match_operand 0 "" "")
6765
                      (pc)))]
6766
  "TARGET_SHMEDIA"
6767
  "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6768
 
6769
(define_expand "bgeu_media"
6770
  [(set (pc)
6771
        (if_then_else (geu (match_operand:DI 1 "arith_reg_or_0_operand" "")
6772
                           (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6773
                      (match_operand 0 "" "")
6774
                      (pc)))]
6775
  "TARGET_SHMEDIA"
6776
  "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6777
 
6778
(define_insn "*bgt_media_i"
6779
  [(set (pc)
6780
        (if_then_else (match_operator 3 "greater_comparison_operator"
6781
                        [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
6782
                         (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
6783
                      (match_operand 0 "target_operand" "b")
6784
                      (pc)))]
6785
  "TARGET_SHMEDIA"
6786
  "b%o3%'       %N1, %N2, %0%>"
6787
  [(set_attr "type" "cbranch_media")])
6788
 
6789
(define_insn "*bgt_media_i32"
6790
  [(set (pc)
6791
        (if_then_else (match_operator 3 "greater_comparison_operator"
6792
                        [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
6793
                         (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
6794
                      (match_operand 0 "target_operand" "b")
6795
                      (pc)))]
6796
  "TARGET_SHMEDIA"
6797
  "b%o3%'       %N1, %N2, %0%>"
6798
  [(set_attr "type" "cbranch_media")])
6799
 
6800
;; These are only needed to make invert_jump() happy - otherwise, jump
6801
;; optimization will be silently disabled.
6802
(define_insn "*blt_media_i"
6803
  [(set (pc)
6804
        (if_then_else (match_operator 3 "less_comparison_operator"
6805
                        [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
6806
                         (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
6807
                      (match_operand 0 "target_operand" "b")
6808
                      (pc)))]
6809
  "TARGET_SHMEDIA"
6810
  "b%o3%'       %N2, %N1, %0%>"
6811
  [(set_attr "type" "cbranch_media")])
6812
 
6813
(define_insn "*blt_media_i32"
6814
  [(set (pc)
6815
        (if_then_else (match_operator 3 "less_comparison_operator"
6816
                        [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
6817
                         (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
6818
                      (match_operand 0 "target_operand" "b")
6819
                      (pc)))]
6820
  "TARGET_SHMEDIA"
6821
  "b%o3%'       %N2, %N1, %0%>"
6822
  [(set_attr "type" "cbranch_media")])
6823
 
6824
(define_expand "beq"
6825
  [(set (pc)
6826
        (if_then_else (ne (reg:SI T_REG) (const_int 0))
6827
                      (label_ref (match_operand 0 "" ""))
6828
                      (pc)))]
6829
  ""
6830
  "
6831
{
6832
  if (TARGET_SHMEDIA)
6833
    {
6834
      enum machine_mode mode = GET_MODE (sh_compare_op0);
6835
 
6836
      if (mode != DImode && mode != SImode)
6837
        {
6838
          rtx tmp = gen_reg_rtx (DImode);
6839
 
6840
          emit_insn (gen_seq (tmp));
6841
          emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
6842
          DONE;
6843
        }
6844
 
6845
      sh_compare_op0 = force_reg (mode, sh_compare_op0);
6846
      if (CONSTANT_P (sh_compare_op1)
6847
          && (GET_CODE (sh_compare_op1) != CONST_INT
6848
              || ! CONST_OK_FOR_I06 (INTVAL (sh_compare_op1))))
6849
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
6850
      emit_jump_insn (gen_beq_media (operands[0],
6851
                                     sh_compare_op0, sh_compare_op1));
6852
      DONE;
6853
    }
6854
 
6855
  from_compare (operands, EQ);
6856
}")
6857
 
6858
(define_expand "bne"
6859
  [(set (pc)
6860
        (if_then_else (eq (reg:SI T_REG) (const_int 0))
6861
                      (label_ref (match_operand 0 "" ""))
6862
                      (pc)))]
6863
  ""
6864
  "
6865
{
6866
  if (TARGET_SHMEDIA)
6867
    {
6868
      enum machine_mode mode = GET_MODE (sh_compare_op0);
6869
 
6870
      if (mode != DImode && mode != SImode)
6871
        {
6872
          rtx tmp = gen_reg_rtx (DImode);
6873
 
6874
          emit_insn (gen_seq (tmp));
6875
          emit_jump_insn (gen_beq_media (operands[0], tmp, const0_rtx));
6876
          DONE;
6877
        }
6878
 
6879
      sh_compare_op0 = force_reg (mode, sh_compare_op0);
6880
      if (CONSTANT_P (sh_compare_op1)
6881
          && (GET_CODE (sh_compare_op1) != CONST_INT
6882
              || ! CONST_OK_FOR_I06 (INTVAL (sh_compare_op1))))
6883
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
6884
      emit_jump_insn (gen_bne_media (operands[0],
6885
                                     sh_compare_op0, sh_compare_op1));
6886
      DONE;
6887
    }
6888
 
6889
  from_compare (operands, EQ);
6890
}")
6891
 
6892
(define_expand "bgt"
6893
  [(set (pc)
6894
        (if_then_else (ne (reg:SI T_REG) (const_int 0))
6895
                      (label_ref (match_operand 0 "" ""))
6896
                      (pc)))]
6897
  ""
6898
  "
6899
{
6900
  if (TARGET_SHMEDIA)
6901
    {
6902
      enum machine_mode mode = GET_MODE (sh_compare_op0);
6903
 
6904
      if (mode != DImode && mode != SImode)
6905
        {
6906
          rtx tmp = gen_reg_rtx (DImode);
6907
 
6908
          emit_insn (gen_sgt (tmp));
6909
          emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
6910
          DONE;
6911
        }
6912
 
6913
      if (sh_compare_op0 != const0_rtx)
6914
        sh_compare_op0 = force_reg (mode, sh_compare_op0);
6915
      if (sh_compare_op1 != const0_rtx)
6916
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
6917
      emit_jump_insn (gen_bgt_media (operands[0],
6918
                                     sh_compare_op0, sh_compare_op1));
6919
      DONE;
6920
    }
6921
 
6922
  from_compare (operands, GT);
6923
}")
6924
 
6925
(define_expand "blt"
6926
  [(set (pc)
6927
        (if_then_else (eq (reg:SI T_REG) (const_int 0))
6928
                      (label_ref (match_operand 0 "" ""))
6929
                      (pc)))]
6930
  ""
6931
  "
6932
{
6933
  if (TARGET_SHMEDIA)
6934
    {
6935
      enum machine_mode mode = GET_MODE (sh_compare_op0);
6936
 
6937
      if (mode != DImode && mode != SImode)
6938
        {
6939
          rtx tmp = gen_reg_rtx (DImode);
6940
 
6941
          emit_insn (gen_slt (tmp));
6942
          emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
6943
          DONE;
6944
        }
6945
 
6946
      if (sh_compare_op0 != const0_rtx)
6947
        sh_compare_op0 = force_reg (mode, sh_compare_op0);
6948
      if (sh_compare_op1 != const0_rtx)
6949
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
6950
      emit_jump_insn (gen_bgt_media (operands[0],
6951
                                     sh_compare_op1, sh_compare_op0));
6952
      DONE;
6953
    }
6954
 
6955
  if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
6956
    {
6957
      rtx tmp = sh_compare_op0;
6958
      sh_compare_op0 = sh_compare_op1;
6959
      sh_compare_op1 = tmp;
6960
      emit_insn (gen_bgt (operands[0]));
6961
      DONE;
6962
    }
6963
  from_compare (operands, GE);
6964
}")
6965
 
6966
(define_expand "ble"
6967
  [(set (pc)
6968
        (if_then_else (eq (reg:SI T_REG) (const_int 0))
6969
                      (label_ref (match_operand 0 "" ""))
6970
                      (pc)))]
6971
  ""
6972
  "
6973
{
6974
  if (TARGET_SHMEDIA)
6975
    {
6976
      enum machine_mode mode = GET_MODE (sh_compare_op0);
6977
 
6978
      if (mode != DImode && mode != SImode)
6979
        {
6980
          rtx tmp = gen_reg_rtx (DImode);
6981
 
6982
          emit_insn (gen_sle (tmp));
6983
          emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
6984
          DONE;
6985
        }
6986
 
6987
      if (sh_compare_op0 != const0_rtx)
6988
        sh_compare_op0 = force_reg (mode, sh_compare_op0);
6989
      if (sh_compare_op1 != const0_rtx)
6990
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
6991
      emit_jump_insn (gen_bge_media (operands[0],
6992
                                     sh_compare_op1, sh_compare_op0));
6993
      DONE;
6994
    }
6995
 
6996
  if (TARGET_SH2E
6997
      && TARGET_IEEE
6998
      && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
6999
    {
7000
      rtx tmp = sh_compare_op0;
7001
      sh_compare_op0 = sh_compare_op1;
7002
      sh_compare_op1 = tmp;
7003
      emit_insn (gen_bge (operands[0]));
7004
      DONE;
7005
    }
7006
  from_compare (operands, GT);
7007
}")
7008
 
7009
(define_expand "bge"
7010
  [(set (pc)
7011
        (if_then_else (ne (reg:SI T_REG) (const_int 0))
7012
                      (label_ref (match_operand 0 "" ""))
7013
                      (pc)))]
7014
  ""
7015
  "
7016
{
7017
  if (TARGET_SHMEDIA)
7018
    {
7019
      enum machine_mode mode = GET_MODE (sh_compare_op0);
7020
 
7021
      if (mode != DImode && mode != SImode)
7022
        {
7023
          rtx tmp = gen_reg_rtx (DImode);
7024
 
7025
          emit_insn (gen_sge (tmp));
7026
          emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
7027
          DONE;
7028
        }
7029
 
7030
      if (sh_compare_op0 != const0_rtx)
7031
        sh_compare_op0 = force_reg (mode, sh_compare_op0);
7032
      if (sh_compare_op1 != const0_rtx)
7033
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
7034
      emit_jump_insn (gen_bge_media (operands[0],
7035
                                     sh_compare_op0, sh_compare_op1));
7036
      DONE;
7037
    }
7038
 
7039
  if (TARGET_SH2E
7040
      && ! TARGET_IEEE
7041
      && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
7042
    {
7043
      rtx tmp = sh_compare_op0;
7044
      sh_compare_op0 = sh_compare_op1;
7045
      sh_compare_op1 = tmp;
7046
      emit_insn (gen_ble (operands[0]));
7047
      DONE;
7048
    }
7049
  from_compare (operands, GE);
7050
}")
7051
 
7052
(define_expand "bgtu"
7053
  [(set (pc)
7054
        (if_then_else (ne (reg:SI T_REG) (const_int 0))
7055
                      (label_ref (match_operand 0 "" ""))
7056
                      (pc)))]
7057
  ""
7058
  "
7059
{
7060
  if (TARGET_SHMEDIA)
7061
    {
7062
      enum machine_mode mode = GET_MODE (sh_compare_op0);
7063
 
7064
      if (sh_compare_op0 != const0_rtx)
7065
        sh_compare_op0 = force_reg (mode, sh_compare_op0);
7066
      if (sh_compare_op1 != const0_rtx)
7067
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
7068
      emit_jump_insn (gen_bgtu_media (operands[0],
7069
                                      sh_compare_op0, sh_compare_op1));
7070
      DONE;
7071
    }
7072
 
7073
  from_compare (operands, GTU);
7074
}")
7075
 
7076
(define_expand "bltu"
7077
  [(set (pc)
7078
        (if_then_else (eq (reg:SI T_REG) (const_int 0))
7079
                      (label_ref (match_operand 0 "" ""))
7080
                      (pc)))]
7081
  ""
7082
  "
7083
{
7084
  if (TARGET_SHMEDIA)
7085
    {
7086
      enum machine_mode mode = GET_MODE (sh_compare_op0);
7087
 
7088
      if (sh_compare_op0 != const0_rtx)
7089
        sh_compare_op0 = force_reg (mode, sh_compare_op0);
7090
      if (sh_compare_op1 != const0_rtx)
7091
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
7092
      emit_jump_insn (gen_bgtu_media (operands[0],
7093
                                      sh_compare_op1, sh_compare_op0));
7094
      DONE;
7095
    }
7096
 
7097
  from_compare (operands, GEU);
7098
}")
7099
 
7100
(define_expand "bgeu"
7101
  [(set (pc)
7102
        (if_then_else (ne (reg:SI T_REG) (const_int 0))
7103
                      (label_ref (match_operand 0 "" ""))
7104
                      (pc)))]
7105
  ""
7106
  "
7107
{
7108
  if (TARGET_SHMEDIA)
7109
    {
7110
      enum machine_mode mode = GET_MODE (sh_compare_op0);
7111
 
7112
      if (sh_compare_op0 != const0_rtx)
7113
        sh_compare_op0 = force_reg (mode, sh_compare_op0);
7114
      if (sh_compare_op1 != const0_rtx)
7115
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
7116
      emit_jump_insn (gen_bgeu_media (operands[0],
7117
                                      sh_compare_op0, sh_compare_op1));
7118
      DONE;
7119
    }
7120
 
7121
  from_compare (operands, GEU);
7122
}")
7123
 
7124
(define_expand "bleu"
7125
  [(set (pc)
7126
        (if_then_else (eq (reg:SI T_REG) (const_int 0))
7127
                      (label_ref (match_operand 0 "" ""))
7128
                      (pc)))]
7129
  ""
7130
  "
7131
{
7132
  if (TARGET_SHMEDIA)
7133
    {
7134
      enum machine_mode mode = GET_MODE (sh_compare_op0);
7135
 
7136
      if (sh_compare_op0 != const0_rtx)
7137
        sh_compare_op0 = force_reg (mode, sh_compare_op0);
7138
      if (sh_compare_op1 != const0_rtx)
7139
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
7140
      emit_jump_insn (gen_bgeu_media (operands[0],
7141
                                      sh_compare_op1, sh_compare_op0));
7142
      DONE;
7143
    }
7144
 
7145
  from_compare (operands, GTU);
7146
}")
7147
 
7148
(define_expand "bunordered"
7149
  [(set (match_dup 1) (unordered:SI (match_dup 2) (match_dup 3)))
7150
   (set (pc)
7151
        (if_then_else (ne (match_dup 1) (const_int 0))
7152
                      (match_operand 0 "" "")
7153
                      (pc)))]
7154
  "TARGET_SHMEDIA"
7155
  "
7156
{
7157
  operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);
7158
  operands[1] = gen_reg_rtx (SImode);
7159
  operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7160
  operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
7161
}")
7162
 
7163
;; combiner splitter for test-and-branch on single bit in register.  This
7164
;; is endian dependent because the non-paradoxical subreg looks different
7165
;; on big endian.
7166
(define_split
7167
  [(set (pc)
7168
        (if_then_else
7169
          (match_operator 3 "equality_comparison_operator"
7170
            [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1
7171
                                                      "extend_reg_operand" "")
7172
                                                    0)
7173
                                         (const_int 1)
7174
                                         (match_operand 2
7175
                                          "const_int_operand" "")) 0)
7176
             (const_int 0)])
7177
          (match_operand 0 "target_operand" "")
7178
          (pc)))
7179
   (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
7180
  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
7181
  [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
7182
   (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
7183
 
7184
  "
7185
{
7186
  operands[5] = GEN_INT (31 - INTVAL (operands[2]));
7187
  operands[6] = (GET_CODE (operands[3]) == EQ
7188
                 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
7189
                 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
7190
}")
7191
 
7192
;; ------------------------------------------------------------------------
7193
;; Jump and linkage insns
7194
;; ------------------------------------------------------------------------
7195
 
7196
(define_insn "jump_compact"
7197
  [(set (pc)
7198
        (label_ref (match_operand 0 "" "")))]
7199
  "TARGET_SH1"
7200
  "*
7201
{
7202
  /* The length is 16 if the delay slot is unfilled.  */
7203
  if (get_attr_length(insn) > 4)
7204
    return output_far_jump(insn, operands[0]);
7205
  else
7206
    return   \"bra      %l0%#\";
7207
}"
7208
  [(set_attr "type" "jump")
7209
   (set_attr "needs_delay_slot" "yes")])
7210
 
7211
;; ??? It would be much saner to explicitly use the scratch register
7212
;; in the jump insn, and have indirect_jump_scratch only set it,
7213
;; but fill_simple_delay_slots would refuse to do delay slot filling
7214
;; from the target then, as it uses simplejump_p.
7215
;;(define_insn "jump_compact_far"
7216
;;  [(set (pc)
7217
;;      (label_ref (match_operand 0 "" "")))
7218
;;   (use (match_operand 1 "register_operand" "r")]
7219
;;  "TARGET_SH1"
7220
;;  "* return output_far_jump(insn, operands[0], operands[1]);"
7221
;;  [(set_attr "type" "jump")
7222
;;   (set_attr "needs_delay_slot" "yes")])
7223
 
7224
(define_insn "jump_media"
7225
  [(set (pc)
7226
        (match_operand 0 "target_operand" "b"))]
7227
  "TARGET_SHMEDIA"
7228
  "blink        %0, r63%>"
7229
  [(set_attr "type" "jump_media")])
7230
 
7231
(define_expand "jump"
7232
  [(set (pc)
7233
        (label_ref (match_operand 0 "" "")))]
7234
  ""
7235
  "
7236
{
7237
  if (TARGET_SH1)
7238
    emit_jump_insn (gen_jump_compact (operands[0]));
7239
  else if (TARGET_SHMEDIA)
7240
    {
7241
      if (reload_in_progress || reload_completed)
7242
        FAIL;
7243
      emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode,
7244
                                                         operands[0])));
7245
    }
7246
  DONE;
7247
}")
7248
 
7249
(define_insn "force_mode_for_call"
7250
  [(use (reg:PSI FPSCR_REG))]
7251
  "TARGET_SHCOMPACT"
7252
  ""
7253
  [(set_attr "length" "0")
7254
   (set (attr "fp_mode")
7255
        (if_then_else (eq_attr "fpu_single" "yes")
7256
                      (const_string "single") (const_string "double")))])
7257
 
7258
(define_insn "calli"
7259
  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7260
         (match_operand 1 "" ""))
7261
   (use (reg:PSI FPSCR_REG))
7262
   (clobber (reg:SI PR_REG))]
7263
  "TARGET_SH1"
7264
  "jsr  @%0%#"
7265
  [(set_attr "type" "call")
7266
   (set (attr "fp_mode")
7267
        (if_then_else (eq_attr "fpu_single" "yes")
7268
                      (const_string "single") (const_string "double")))
7269
   (set_attr "needs_delay_slot" "yes")
7270
   (set_attr "fp_set" "unknown")])
7271
 
7272
;; This is a pc-rel call, using bsrf, for use with PIC.
7273
 
7274
(define_insn "calli_pcrel"
7275
  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7276
         (match_operand 1 "" ""))
7277
   (use (reg:PSI FPSCR_REG))
7278
   (use (reg:SI PIC_REG))
7279
   (use (match_operand 2 "" ""))
7280
   (clobber (reg:SI PR_REG))]
7281
  "TARGET_SH2"
7282
  "bsrf %0\\n%O2:%#"
7283
  [(set_attr "type" "call")
7284
   (set (attr "fp_mode")
7285
        (if_then_else (eq_attr "fpu_single" "yes")
7286
                      (const_string "single") (const_string "double")))
7287
   (set_attr "needs_delay_slot" "yes")
7288
   (set_attr "fp_set" "unknown")])
7289
 
7290
(define_insn_and_split "call_pcrel"
7291
  [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7292
         (match_operand 1 "" ""))
7293
   (use (reg:PSI FPSCR_REG))
7294
   (use (reg:SI PIC_REG))
7295
   (clobber (reg:SI PR_REG))
7296
   (clobber (match_scratch:SI 2 "=r"))]
7297
  "TARGET_SH2"
7298
  "#"
7299
  "reload_completed"
7300
  [(const_int 0)]
7301
  "
7302
{
7303
  rtx lab = PATTERN (gen_call_site ());
7304
 
7305
  if (SYMBOL_REF_LOCAL_P (operands[0]))
7306
    emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7307
  else
7308
    emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
7309
  emit_call_insn (gen_calli_pcrel (operands[2], operands[1], lab));
7310
  DONE;
7311
}"
7312
  [(set_attr "type" "call")
7313
   (set (attr "fp_mode")
7314
        (if_then_else (eq_attr "fpu_single" "yes")
7315
                      (const_string "single") (const_string "double")))
7316
   (set_attr "needs_delay_slot" "yes")
7317
   (set_attr "fp_set" "unknown")])
7318
 
7319
(define_insn "call_compact"
7320
  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7321
         (match_operand 1 "" ""))
7322
   (match_operand 2 "immediate_operand" "n")
7323
   (use (reg:SI R0_REG))
7324
   (use (reg:SI R1_REG))
7325
   (use (reg:PSI FPSCR_REG))
7326
   (clobber (reg:SI PR_REG))]
7327
  "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7328
  "jsr  @%0%#"
7329
  [(set_attr "type" "call")
7330
   (set (attr "fp_mode")
7331
        (if_then_else (eq_attr "fpu_single" "yes")
7332
                      (const_string "single") (const_string "double")))
7333
   (set_attr "needs_delay_slot" "yes")])
7334
 
7335
(define_insn "call_compact_rettramp"
7336
  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7337
         (match_operand 1 "" ""))
7338
   (match_operand 2 "immediate_operand" "n")
7339
   (use (reg:SI R0_REG))
7340
   (use (reg:SI R1_REG))
7341
   (use (reg:PSI FPSCR_REG))
7342
   (clobber (reg:SI R10_REG))
7343
   (clobber (reg:SI PR_REG))]
7344
  "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7345
  "jsr  @%0%#"
7346
  [(set_attr "type" "call")
7347
   (set (attr "fp_mode")
7348
        (if_then_else (eq_attr "fpu_single" "yes")
7349
                      (const_string "single") (const_string "double")))
7350
   (set_attr "needs_delay_slot" "yes")])
7351
 
7352
(define_insn "call_media"
7353
  [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
7354
         (match_operand 1 "" ""))
7355
   (clobber (reg:DI PR_MEDIA_REG))]
7356
  "TARGET_SHMEDIA"
7357
  "blink        %0, r18"
7358
  [(set_attr "type" "jump_media")])
7359
 
7360
(define_insn "call_valuei"
7361
  [(set (match_operand 0 "" "=rf")
7362
        (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7363
              (match_operand 2 "" "")))
7364
   (use (reg:PSI FPSCR_REG))
7365
   (clobber (reg:SI PR_REG))]
7366
  "TARGET_SH1"
7367
  "jsr  @%1%#"
7368
  [(set_attr "type" "call")
7369
   (set (attr "fp_mode")
7370
        (if_then_else (eq_attr "fpu_single" "yes")
7371
                      (const_string "single") (const_string "double")))
7372
   (set_attr "needs_delay_slot" "yes")
7373
   (set_attr "fp_set" "unknown")])
7374
 
7375
(define_insn "call_valuei_pcrel"
7376
  [(set (match_operand 0 "" "=rf")
7377
        (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7378
              (match_operand 2 "" "")))
7379
   (use (reg:PSI FPSCR_REG))
7380
   (use (reg:SI PIC_REG))
7381
   (use (match_operand 3 "" ""))
7382
   (clobber (reg:SI PR_REG))]
7383
  "TARGET_SH2"
7384
  "bsrf %1\\n%O3:%#"
7385
  [(set_attr "type" "call")
7386
   (set (attr "fp_mode")
7387
        (if_then_else (eq_attr "fpu_single" "yes")
7388
                      (const_string "single") (const_string "double")))
7389
   (set_attr "needs_delay_slot" "yes")
7390
   (set_attr "fp_set" "unknown")])
7391
 
7392
(define_insn_and_split "call_value_pcrel"
7393
  [(set (match_operand 0 "" "=rf")
7394
        (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7395
              (match_operand 2 "" "")))
7396
   (use (reg:PSI FPSCR_REG))
7397
   (use (reg:SI PIC_REG))
7398
   (clobber (reg:SI PR_REG))
7399
   (clobber (match_scratch:SI 3 "=r"))]
7400
  "TARGET_SH2"
7401
  "#"
7402
  "reload_completed"
7403
  [(const_int 0)]
7404
  "
7405
{
7406
  rtx lab = PATTERN (gen_call_site ());
7407
 
7408
  if (SYMBOL_REF_LOCAL_P (operands[1]))
7409
    emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
7410
  else
7411
    emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
7412
  emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
7413
                                         operands[2], lab));
7414
  DONE;
7415
}"
7416
  [(set_attr "type" "call")
7417
   (set (attr "fp_mode")
7418
        (if_then_else (eq_attr "fpu_single" "yes")
7419
                      (const_string "single") (const_string "double")))
7420
   (set_attr "needs_delay_slot" "yes")
7421
   (set_attr "fp_set" "unknown")])
7422
 
7423
(define_insn "call_value_compact"
7424
  [(set (match_operand 0 "" "=rf")
7425
        (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7426
              (match_operand 2 "" "")))
7427
   (match_operand 3 "immediate_operand" "n")
7428
   (use (reg:SI R0_REG))
7429
   (use (reg:SI R1_REG))
7430
   (use (reg:PSI FPSCR_REG))
7431
   (clobber (reg:SI PR_REG))]
7432
  "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7433
  "jsr  @%1%#"
7434
  [(set_attr "type" "call")
7435
   (set (attr "fp_mode")
7436
        (if_then_else (eq_attr "fpu_single" "yes")
7437
                      (const_string "single") (const_string "double")))
7438
   (set_attr "needs_delay_slot" "yes")])
7439
 
7440
(define_insn "call_value_compact_rettramp"
7441
  [(set (match_operand 0 "" "=rf")
7442
        (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7443
              (match_operand 2 "" "")))
7444
   (match_operand 3 "immediate_operand" "n")
7445
   (use (reg:SI R0_REG))
7446
   (use (reg:SI R1_REG))
7447
   (use (reg:PSI FPSCR_REG))
7448
   (clobber (reg:SI R10_REG))
7449
   (clobber (reg:SI PR_REG))]
7450
  "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7451
  "jsr  @%1%#"
7452
  [(set_attr "type" "call")
7453
   (set (attr "fp_mode")
7454
        (if_then_else (eq_attr "fpu_single" "yes")
7455
                      (const_string "single") (const_string "double")))
7456
   (set_attr "needs_delay_slot" "yes")])
7457
 
7458
(define_insn "call_value_media"
7459
  [(set (match_operand 0 "" "=rf")
7460
        (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
7461
              (match_operand 2 "" "")))
7462
   (clobber (reg:DI PR_MEDIA_REG))]
7463
  "TARGET_SHMEDIA"
7464
  "blink        %1, r18"
7465
  [(set_attr "type" "jump_media")])
7466
 
7467
(define_expand "call"
7468
  [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7469
                            (match_operand 1 "" ""))
7470
              (match_operand 2 "" "")
7471
              (use (reg:PSI FPSCR_REG))
7472
              (clobber (reg:SI PR_REG))])]
7473
  ""
7474
  "
7475
{
7476
  if (TARGET_SHMEDIA)
7477
    {
7478
      operands[0] = shmedia_prepare_call_address (operands[0], 0);
7479
      emit_call_insn (gen_call_media (operands[0], operands[1]));
7480
      DONE;
7481
    }
7482
  else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
7483
    {
7484
      rtx cookie_rtx = operands[2];
7485
      long cookie = INTVAL (cookie_rtx);
7486
      rtx func = XEXP (operands[0], 0);
7487
      rtx r0, r1;
7488
 
7489
      if (flag_pic)
7490
        {
7491
          if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7492
            {
7493
              rtx reg = gen_reg_rtx (Pmode);
7494
 
7495
              emit_insn (gen_symGOTPLT2reg (reg, func));
7496
              func = reg;
7497
            }
7498
          else
7499
            func = legitimize_pic_address (func, Pmode, 0);
7500
        }
7501
 
7502
      r0 = gen_rtx_REG (SImode, R0_REG);
7503
      r1 = gen_rtx_REG (SImode, R1_REG);
7504
 
7505
      /* Since such a call function may use all call-clobbered
7506
         registers, we force a mode switch earlier, so that we don't
7507
         run out of registers when adjusting fpscr for the call.  */
7508
      emit_insn (gen_force_mode_for_call ());
7509
 
7510
      operands[0]
7511
        = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7512
                           SFUNC_GOT);
7513
      operands[0] = force_reg (SImode, operands[0]);
7514
 
7515
      emit_move_insn (r0, func);
7516
      emit_move_insn (r1, cookie_rtx);
7517
 
7518
      if (cookie & CALL_COOKIE_RET_TRAMP (1))
7519
        emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
7520
                                                   operands[2]));
7521
      else
7522
        emit_call_insn (gen_call_compact (operands[0], operands[1],
7523
                                          operands[2]));
7524
 
7525
      DONE;
7526
    }
7527
  else if (TARGET_SHCOMPACT && flag_pic
7528
           && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7529
           && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7530
    {
7531
      rtx reg = gen_reg_rtx (Pmode);
7532
 
7533
      emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
7534
      XEXP (operands[0], 0) = reg;
7535
    }
7536
  if (flag_pic && TARGET_SH2
7537
      && GET_CODE (operands[0]) == MEM
7538
      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
7539
    {
7540
      emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
7541
      DONE;
7542
    }
7543
  else
7544
  {
7545
    operands[0] = force_reg (SImode, XEXP (operands[0], 0));
7546
    operands[1] = operands[2];
7547
  }
7548
 
7549
  emit_call_insn (gen_calli (operands[0], operands[1]));
7550
  DONE;
7551
}")
7552
 
7553
(define_insn "call_pop_compact"
7554
  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7555
         (match_operand 1 "" ""))
7556
   (match_operand 2 "immediate_operand" "n")
7557
   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7558
                                 (match_operand 3 "immediate_operand" "n")))
7559
   (use (reg:SI R0_REG))
7560
   (use (reg:SI R1_REG))
7561
   (use (reg:PSI FPSCR_REG))
7562
   (clobber (reg:SI PR_REG))]
7563
  "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7564
  "jsr  @%0%#"
7565
  [(set_attr "type" "call")
7566
   (set (attr "fp_mode")
7567
        (if_then_else (eq_attr "fpu_single" "yes")
7568
                      (const_string "single") (const_string "double")))
7569
   (set_attr "needs_delay_slot" "yes")])
7570
 
7571
(define_insn "call_pop_compact_rettramp"
7572
  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7573
         (match_operand 1 "" ""))
7574
   (match_operand 2 "immediate_operand" "n")
7575
   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7576
                                 (match_operand 3 "immediate_operand" "n")))
7577
   (use (reg:SI R0_REG))
7578
   (use (reg:SI R1_REG))
7579
   (use (reg:PSI FPSCR_REG))
7580
   (clobber (reg:SI R10_REG))
7581
   (clobber (reg:SI PR_REG))]
7582
  "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7583
  "jsr  @%0%#"
7584
  [(set_attr "type" "call")
7585
   (set (attr "fp_mode")
7586
        (if_then_else (eq_attr "fpu_single" "yes")
7587
                      (const_string "single") (const_string "double")))
7588
   (set_attr "needs_delay_slot" "yes")])
7589
 
7590
(define_expand "call_pop"
7591
  [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7592
                    (match_operand 1 "" ""))
7593
             (match_operand 2 "" "")
7594
             (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7595
                                           (match_operand 3 "" "")))])]
7596
  "TARGET_SHCOMPACT"
7597
  "
7598
{
7599
  rtx cookie_rtx;
7600
  long cookie;
7601
  rtx func;
7602
  rtx r0, r1;
7603
 
7604
  gcc_assert (operands[2] && INTVAL (operands[2]));
7605
  cookie_rtx = operands[2];
7606
  cookie = INTVAL (cookie_rtx);
7607
  func = XEXP (operands[0], 0);
7608
 
7609
  if (flag_pic)
7610
    {
7611
      if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7612
        {
7613
          rtx reg = gen_reg_rtx (Pmode);
7614
          emit_insn (gen_symGOTPLT2reg (reg, func));
7615
          func = reg;
7616
        }
7617
      else
7618
        func = legitimize_pic_address (func, Pmode, 0);
7619
    }
7620
 
7621
  r0 = gen_rtx_REG (SImode, R0_REG);
7622
  r1 = gen_rtx_REG (SImode, R1_REG);
7623
 
7624
  /* Since such a call function may use all call-clobbered
7625
     registers, we force a mode switch earlier, so that we don't
7626
     run out of registers when adjusting fpscr for the call.  */
7627
  emit_insn (gen_force_mode_for_call ());
7628
 
7629
  operands[0] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7630
                                 SFUNC_GOT);
7631
  operands[0] = force_reg (SImode, operands[0]);
7632
 
7633
  emit_move_insn (r0, func);
7634
  emit_move_insn (r1, cookie_rtx);
7635
 
7636
  if (cookie & CALL_COOKIE_RET_TRAMP (1))
7637
    emit_call_insn (gen_call_pop_compact_rettramp
7638
                     (operands[0], operands[1], operands[2], operands[3]));
7639
  else
7640
    emit_call_insn (gen_call_pop_compact
7641
                     (operands[0], operands[1], operands[2], operands[3]));
7642
 
7643
  DONE;
7644
}")
7645
 
7646
(define_expand "call_value"
7647
  [(parallel [(set (match_operand 0 "arith_reg_operand" "")
7648
                   (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
7649
                                 (match_operand 2 "" "")))
7650
              (match_operand 3 "" "")
7651
              (use (reg:PSI FPSCR_REG))
7652
              (clobber (reg:SI PR_REG))])]
7653
  ""
7654
  "
7655
{
7656
  if (TARGET_SHMEDIA)
7657
    {
7658
      operands[1] = shmedia_prepare_call_address (operands[1], 0);
7659
      emit_call_insn (gen_call_value_media (operands[0], operands[1],
7660
                                            operands[2]));
7661
      DONE;
7662
    }
7663
  else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
7664
    {
7665
      rtx cookie_rtx = operands[3];
7666
      long cookie = INTVAL (cookie_rtx);
7667
      rtx func = XEXP (operands[1], 0);
7668
      rtx r0, r1;
7669
 
7670
      if (flag_pic)
7671
        {
7672
          if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7673
            {
7674
              rtx reg = gen_reg_rtx (Pmode);
7675
 
7676
              emit_insn (gen_symGOTPLT2reg (reg, func));
7677
              func = reg;
7678
            }
7679
          else
7680
            func = legitimize_pic_address (func, Pmode, 0);
7681
        }
7682
 
7683
      r0 = gen_rtx_REG (SImode, R0_REG);
7684
      r1 = gen_rtx_REG (SImode, R1_REG);
7685
 
7686
      /* Since such a call function may use all call-clobbered
7687
         registers, we force a mode switch earlier, so that we don't
7688
         run out of registers when adjusting fpscr for the call.  */
7689
      emit_insn (gen_force_mode_for_call ());
7690
 
7691
      operands[1]
7692
        = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7693
                           SFUNC_GOT);
7694
      operands[1] = force_reg (SImode, operands[1]);
7695
 
7696
      emit_move_insn (r0, func);
7697
      emit_move_insn (r1, cookie_rtx);
7698
 
7699
      if (cookie & CALL_COOKIE_RET_TRAMP (1))
7700
        emit_call_insn (gen_call_value_compact_rettramp (operands[0],
7701
                                                         operands[1],
7702
                                                         operands[2],
7703
                                                         operands[3]));
7704
      else
7705
        emit_call_insn (gen_call_value_compact (operands[0], operands[1],
7706
                                                operands[2], operands[3]));
7707
 
7708
      DONE;
7709
    }
7710
  else if (TARGET_SHCOMPACT && flag_pic
7711
           && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7712
           && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
7713
    {
7714
      rtx reg = gen_reg_rtx (Pmode);
7715
 
7716
      emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
7717
      XEXP (operands[1], 0) = reg;
7718
    }
7719
  if (flag_pic && TARGET_SH2
7720
      && GET_CODE (operands[1]) == MEM
7721
      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
7722
    {
7723
      emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
7724
                                            operands[2]));
7725
      DONE;
7726
    }
7727
  else
7728
    operands[1] = force_reg (SImode, XEXP (operands[1], 0));
7729
 
7730
  emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
7731
  DONE;
7732
}")
7733
 
7734
(define_insn "sibcalli"
7735
  [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
7736
         (match_operand 1 "" ""))
7737
   (use (reg:PSI FPSCR_REG))
7738
   (return)]
7739
  "TARGET_SH1"
7740
  "jmp  @%0%#"
7741
  [(set_attr "needs_delay_slot" "yes")
7742
   (set (attr "fp_mode")
7743
        (if_then_else (eq_attr "fpu_single" "yes")
7744
                      (const_string "single") (const_string "double")))
7745
   (set_attr "type" "jump_ind")])
7746
 
7747
(define_insn "sibcalli_pcrel"
7748
  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
7749
         (match_operand 1 "" ""))
7750
   (use (match_operand 2 "" ""))
7751
   (use (reg:PSI FPSCR_REG))
7752
   (return)]
7753
  "TARGET_SH2"
7754
  "braf %0\\n%O2:%#"
7755
  [(set_attr "needs_delay_slot" "yes")
7756
   (set (attr "fp_mode")
7757
        (if_then_else (eq_attr "fpu_single" "yes")
7758
                      (const_string "single") (const_string "double")))
7759
   (set_attr "type" "jump_ind")])
7760
 
7761
;; This uses an unspec to describe that the symbol_ref is very close.
7762
(define_insn "sibcalli_thunk"
7763
  [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
7764
                             UNSPEC_THUNK))
7765
         (match_operand 1 "" ""))
7766
   (use (reg:PSI FPSCR_REG))
7767
   (return)]
7768
  "TARGET_SH1"
7769
  "bra  %O0"
7770
  [(set_attr "needs_delay_slot" "yes")
7771
   (set (attr "fp_mode")
7772
        (if_then_else (eq_attr "fpu_single" "yes")
7773
                      (const_string "single") (const_string "double")))
7774
   (set_attr "type" "jump")
7775
   (set_attr "length" "2")])
7776
 
7777
(define_insn_and_split "sibcall_pcrel"
7778
  [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7779
         (match_operand 1 "" ""))
7780
   (use (reg:PSI FPSCR_REG))
7781
   (clobber (match_scratch:SI 2 "=k"))
7782
   (return)]
7783
  "TARGET_SH2"
7784
  "#"
7785
  "reload_completed"
7786
  [(const_int 0)]
7787
  "
7788
{
7789
  rtx lab = PATTERN (gen_call_site ());
7790
  rtx call_insn;
7791
 
7792
  emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7793
  call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
7794
                                                  lab));
7795
  SIBLING_CALL_P (call_insn) = 1;
7796
  DONE;
7797
}"
7798
  [(set_attr "needs_delay_slot" "yes")
7799
   (set (attr "fp_mode")
7800
        (if_then_else (eq_attr "fpu_single" "yes")
7801
                      (const_string "single") (const_string "double")))
7802
   (set_attr "type" "jump_ind")])
7803
 
7804
(define_insn "sibcall_compact"
7805
  [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
7806
         (match_operand 1 "" ""))
7807
   (return)
7808
   (use (match_operand:SI 2 "register_operand" "z,x"))
7809
   (use (reg:SI R1_REG))
7810
   (use (reg:PSI FPSCR_REG))
7811
   ;; We want to make sure the `x' above will only match MACH_REG
7812
   ;; because sibcall_epilogue may clobber MACL_REG.
7813
   (clobber (reg:SI MACL_REG))]
7814
  "TARGET_SHCOMPACT"
7815
  "@
7816
        jmp     @%0%#
7817
        jmp     @%0\\n  sts     %2, r0"
7818
  [(set_attr "needs_delay_slot" "yes,no")
7819
   (set_attr "length" "2,4")
7820
   (set (attr "fp_mode") (const_string "single"))
7821
   (set_attr "type" "jump_ind")])
7822
 
7823
(define_insn "sibcall_media"
7824
  [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
7825
         (match_operand 1 "" ""))
7826
   (use (reg:SI PR_MEDIA_REG))
7827
   (return)]
7828
  "TARGET_SHMEDIA"
7829
  "blink        %0, r63"
7830
  [(set_attr "type" "jump_media")])
7831
 
7832
(define_expand "sibcall"
7833
  [(parallel
7834
    [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7835
           (match_operand 1 "" ""))
7836
     (match_operand 2 "" "")
7837
     (use (reg:PSI FPSCR_REG))
7838
     (return)])]
7839
  ""
7840
  "
7841
{
7842
  if (TARGET_SHMEDIA)
7843
    {
7844
      operands[0] = shmedia_prepare_call_address (operands[0], 1);
7845
      emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
7846
      DONE;
7847
    }
7848
  else if (TARGET_SHCOMPACT && operands[2]
7849
           && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
7850
    {
7851
      rtx cookie_rtx = operands[2];
7852
      long cookie = INTVAL (cookie_rtx);
7853
      rtx func = XEXP (operands[0], 0);
7854
      rtx mach, r1;
7855
 
7856
      if (flag_pic)
7857
        {
7858
          if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7859
            {
7860
              rtx reg = gen_reg_rtx (Pmode);
7861
 
7862
              emit_insn (gen_symGOT2reg (reg, func));
7863
              func = reg;
7864
            }
7865
          else
7866
            func = legitimize_pic_address (func, Pmode, 0);
7867
        }
7868
 
7869
      /* FIXME: if we could tell whether all argument registers are
7870
         already taken, we could decide whether to force the use of
7871
         MACH_REG or to stick to R0_REG.  Unfortunately, there's no
7872
         simple way to tell.  We could use the CALL_COOKIE, but we
7873
         can't currently tell a register used for regular argument
7874
         passing from one that is unused.  If we leave it up to reload
7875
         to decide which register to use, it seems to always choose
7876
         R0_REG, which leaves no available registers in SIBCALL_REGS
7877
         to hold the address of the trampoline.  */
7878
      mach = gen_rtx_REG (SImode, MACH_REG);
7879
      r1 = gen_rtx_REG (SImode, R1_REG);
7880
 
7881
      /* Since such a call function may use all call-clobbered
7882
         registers, we force a mode switch earlier, so that we don't
7883
         run out of registers when adjusting fpscr for the call.  */
7884
      emit_insn (gen_force_mode_for_call ());
7885
 
7886
      operands[0]
7887
        = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7888
                           SFUNC_GOT);
7889
      operands[0] = force_reg (SImode, operands[0]);
7890
 
7891
      /* We don't need a return trampoline, since the callee will
7892
         return directly to the upper caller.  */
7893
      if (cookie & CALL_COOKIE_RET_TRAMP (1))
7894
        {
7895
          cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
7896
          cookie_rtx = GEN_INT (cookie);
7897
        }
7898
 
7899
      emit_move_insn (mach, func);
7900
      emit_move_insn (r1, cookie_rtx);
7901
 
7902
      emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
7903
      DONE;
7904
    }
7905
  else if (TARGET_SHCOMPACT && flag_pic
7906
           && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7907
           && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7908
    {
7909
      rtx reg = gen_reg_rtx (Pmode);
7910
 
7911
      emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
7912
      XEXP (operands[0], 0) = reg;
7913
    }
7914
  if (flag_pic && TARGET_SH2
7915
      && GET_CODE (operands[0]) == MEM
7916
      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7917
      /* The PLT needs the PIC register, but the epilogue would have
7918
         to restore it, so we can only use PC-relative PIC calls for
7919
         static functions.  */
7920
      && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7921
    {
7922
      emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
7923
      DONE;
7924
    }
7925
  else
7926
    operands[0] = force_reg (SImode, XEXP (operands[0], 0));
7927
 
7928
  emit_call_insn (gen_sibcalli (operands[0], operands[1]));
7929
  DONE;
7930
}")
7931
 
7932
(define_expand "sibcall_value"
7933
  [(set (match_operand 0 "" "")
7934
        (call (match_operand 1 "" "")
7935
              (match_operand 2 "" "")))
7936
   (match_operand 3 "" "")]
7937
  ""
7938
  "
7939
{
7940
  emit_call_insn (gen_sibcall (operands[1], operands[2], operands[3]));
7941
  DONE;
7942
}")
7943
 
7944
(define_insn "call_value_pop_compact"
7945
  [(set (match_operand 0 "" "=rf")
7946
        (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7947
              (match_operand 2 "" "")))
7948
   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7949
                                 (match_operand 4 "immediate_operand" "n")))
7950
   (match_operand 3 "immediate_operand" "n")
7951
   (use (reg:SI R0_REG))
7952
   (use (reg:SI R1_REG))
7953
   (use (reg:PSI FPSCR_REG))
7954
   (clobber (reg:SI PR_REG))]
7955
  "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7956
  "jsr  @%1%#"
7957
  [(set_attr "type" "call")
7958
   (set (attr "fp_mode")
7959
        (if_then_else (eq_attr "fpu_single" "yes")
7960
                      (const_string "single") (const_string "double")))
7961
   (set_attr "needs_delay_slot" "yes")])
7962
 
7963
(define_insn "call_value_pop_compact_rettramp"
7964
  [(set (match_operand 0 "" "=rf")
7965
        (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7966
              (match_operand 2 "" "")))
7967
   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7968
                                 (match_operand 4 "immediate_operand" "n")))
7969
   (match_operand 3 "immediate_operand" "n")
7970
   (use (reg:SI R0_REG))
7971
   (use (reg:SI R1_REG))
7972
   (use (reg:PSI FPSCR_REG))
7973
   (clobber (reg:SI R10_REG))
7974
   (clobber (reg:SI PR_REG))]
7975
  "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7976
  "jsr  @%1%#"
7977
  [(set_attr "type" "call")
7978
   (set (attr "fp_mode")
7979
        (if_then_else (eq_attr "fpu_single" "yes")
7980
                      (const_string "single") (const_string "double")))
7981
   (set_attr "needs_delay_slot" "yes")])
7982
 
7983
(define_expand "call_value_pop"
7984
  [(parallel [(set (match_operand 0 "arith_reg_operand" "")
7985
                   (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
7986
                                 (match_operand 2 "" "")))
7987
              (match_operand 3 "" "")
7988
              (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7989
                                            (match_operand 4 "" "")))])]
7990
  "TARGET_SHCOMPACT"
7991
  "
7992
{
7993
  rtx cookie_rtx;
7994
  long cookie;
7995
  rtx func;
7996
  rtx r0, r1;
7997
 
7998
  gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
7999
  cookie_rtx = operands[3];
8000
  cookie = INTVAL (cookie_rtx);
8001
  func = XEXP (operands[1], 0);
8002
 
8003
  if (flag_pic)
8004
    {
8005
      if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8006
        {
8007
          rtx reg = gen_reg_rtx (Pmode);
8008
 
8009
          emit_insn (gen_symGOTPLT2reg (reg, func));
8010
          func = reg;
8011
        }
8012
      else
8013
        func = legitimize_pic_address (func, Pmode, 0);
8014
    }
8015
 
8016
  r0 = gen_rtx_REG (SImode, R0_REG);
8017
  r1 = gen_rtx_REG (SImode, R1_REG);
8018
 
8019
  /* Since such a call function may use all call-clobbered
8020
     registers, we force a mode switch earlier, so that we don't
8021
     run out of registers when adjusting fpscr for the call.  */
8022
  emit_insn (gen_force_mode_for_call ());
8023
 
8024
  operands[1] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8025
                                 SFUNC_GOT);
8026
  operands[1] = force_reg (SImode, operands[1]);
8027
 
8028
  emit_move_insn (r0, func);
8029
  emit_move_insn (r1, cookie_rtx);
8030
 
8031
  if (cookie & CALL_COOKIE_RET_TRAMP (1))
8032
    emit_call_insn (gen_call_value_pop_compact_rettramp
8033
                        (operands[0], operands[1], operands[2],
8034
                         operands[3], operands[4]));
8035
  else
8036
    emit_call_insn (gen_call_value_pop_compact
8037
                        (operands[0], operands[1], operands[2],
8038
                         operands[3], operands[4]));
8039
 
8040
  DONE;
8041
}")
8042
 
8043
(define_expand "sibcall_epilogue"
8044
  [(return)]
8045
  ""
8046
  "
8047
{
8048
  sh_expand_epilogue (1);
8049
  if (TARGET_SHCOMPACT)
8050
    {
8051
      rtx insn, set;
8052
 
8053
      /* If epilogue clobbers r0, preserve it in macl.  */
8054
      for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
8055
        if ((set = single_set (insn))
8056
            && GET_CODE (SET_DEST (set)) == REG
8057
            && REGNO (SET_DEST (set)) == R0_REG)
8058
          {
8059
            rtx r0 = gen_rtx_REG (SImode, R0_REG);
8060
            rtx tmp = gen_rtx_REG (SImode, MACL_REG);
8061
            rtx i;
8062
 
8063
            /* We can't tell at this point whether the sibcall is a
8064
               sibcall_compact and, if it is, whether it uses r0 or
8065
               mach as operand 2, so let the instructions that
8066
               preserve r0 be optimized away if r0 turns out to be
8067
               dead.  */
8068
            i = emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
8069
            REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
8070
                                               REG_NOTES (i));
8071
            i = emit_move_insn (r0, tmp);
8072
            REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
8073
                                               REG_NOTES (i));
8074
            break;
8075
          }
8076
    }
8077
  DONE;
8078
}")
8079
 
8080
(define_insn "indirect_jump_compact"
8081
  [(set (pc)
8082
        (match_operand:SI 0 "arith_reg_operand" "r"))]
8083
  "TARGET_SH1"
8084
  "jmp  @%0%#"
8085
  [(set_attr "needs_delay_slot" "yes")
8086
   (set_attr "type" "jump_ind")])
8087
 
8088
(define_expand "indirect_jump"
8089
  [(set (pc)
8090
        (match_operand 0 "register_operand" ""))]
8091
  ""
8092
  "
8093
{
8094
  if (GET_MODE (operands[0]) != Pmode)
8095
    operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
8096
}")
8097
 
8098
;; The use of operand 1 / 2 helps us distinguish case table jumps
8099
;; which can be present in structured code from indirect jumps which can not
8100
;; be present in structured code.  This allows -fprofile-arcs to work.
8101
 
8102
;; For SH1 processors.
8103
(define_insn "casesi_jump_1"
8104
  [(set (pc)
8105
        (match_operand:SI 0 "register_operand" "r"))
8106
   (use (label_ref (match_operand 1 "" "")))]
8107
  "TARGET_SH1"
8108
  "jmp  @%0%#"
8109
  [(set_attr "needs_delay_slot" "yes")
8110
   (set_attr "type" "jump_ind")])
8111
 
8112
;; For all later processors.
8113
(define_insn "casesi_jump_2"
8114
  [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
8115
                      (label_ref (match_operand 1 "" ""))))
8116
   (use (label_ref (match_operand 2 "" "")))]
8117
  "TARGET_SH2
8118
   && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
8119
  "braf %0%#"
8120
  [(set_attr "needs_delay_slot" "yes")
8121
   (set_attr "type" "jump_ind")])
8122
 
8123
(define_insn "casesi_jump_media"
8124
  [(set (pc) (match_operand 0 "target_reg_operand" "b"))
8125
   (use (label_ref (match_operand 1 "" "")))]
8126
  "TARGET_SHMEDIA"
8127
  "blink        %0, r63"
8128
  [(set_attr "type" "jump_media")])
8129
 
8130
;; Call subroutine returning any type.
8131
;; ??? This probably doesn't work.
8132
 
8133
(define_expand "untyped_call"
8134
  [(parallel [(call (match_operand 0 "" "")
8135
                    (const_int 0))
8136
              (match_operand 1 "" "")
8137
              (match_operand 2 "" "")])]
8138
  "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
8139
  "
8140
{
8141
  int i;
8142
 
8143
  emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
8144
 
8145
  for (i = 0; i < XVECLEN (operands[2], 0); i++)
8146
    {
8147
      rtx set = XVECEXP (operands[2], 0, i);
8148
      emit_move_insn (SET_DEST (set), SET_SRC (set));
8149
    }
8150
 
8151
  /* The optimizer does not know that the call sets the function value
8152
     registers we stored in the result block.  We avoid problems by
8153
     claiming that all hard registers are used and clobbered at this
8154
     point.  */
8155
  emit_insn (gen_blockage ());
8156
 
8157
  DONE;
8158
}")
8159
 
8160
;; ------------------------------------------------------------------------
8161
;; Misc insns
8162
;; ------------------------------------------------------------------------
8163
 
8164
(define_insn "dect"
8165
  [(set (reg:SI T_REG)
8166
        (eq:SI (match_operand:SI 0 "arith_reg_dest" "+r") (const_int 1)))
8167
   (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
8168
  "TARGET_SH2"
8169
  "dt   %0"
8170
  [(set_attr "type" "arith")])
8171
 
8172
(define_insn "nop"
8173
  [(const_int 0)]
8174
  ""
8175
  "nop")
8176
 
8177
;; Load address of a label. This is only generated by the casesi expand,
8178
;; and by machine_dependent_reorg (fixing up fp moves).
8179
;; This must use unspec, because this only works for labels that are
8180
;; within range,
8181
 
8182
(define_insn "mova"
8183
  [(set (reg:SI R0_REG)
8184
        (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
8185
  "TARGET_SH1"
8186
  "mova %O0,r0"
8187
  [(set_attr "in_delay_slot" "no")
8188
   (set_attr "type" "arith")])
8189
 
8190
;; machine_dependent_reorg will make this a `mova'.
8191
(define_insn "mova_const"
8192
  [(set (reg:SI R0_REG)
8193
        (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
8194
  "TARGET_SH1"
8195
  "#"
8196
  [(set_attr "in_delay_slot" "no")
8197
   (set_attr "type" "arith")])
8198
 
8199
(define_expand "GOTaddr2picreg"
8200
  [(set (reg:SI R0_REG)
8201
        (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
8202
                   UNSPEC_MOVA))
8203
   (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
8204
   (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
8205
  "" "
8206
{
8207
  operands[0] = gen_rtx_REG (Pmode, PIC_REG);
8208
  operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
8209
 
8210
  if (TARGET_SHMEDIA)
8211
    {
8212
      rtx tr = gen_rtx_REG (Pmode, TR0_REG);
8213
      rtx pic = operands[0];
8214
      rtx lab = PATTERN (gen_call_site ());
8215
      rtx insn, equiv;
8216
 
8217
      equiv = operands[1];
8218
      operands[1] = gen_rtx_MINUS (Pmode,
8219
                                   operands[1],
8220
                                   gen_rtx_CONST
8221
                                   (Pmode,
8222
                                    gen_rtx_MINUS (Pmode,
8223
                                                   gen_rtx_CONST (Pmode,
8224
                                                                  lab),
8225
                                                   pc_rtx)));
8226
      operands[1] = gen_sym2PIC (operands[1]);
8227
      PUT_MODE (operands[1], Pmode);
8228
 
8229
      if (Pmode == SImode)
8230
        {
8231
          emit_insn (gen_movsi_const (pic, operands[1]));
8232
          emit_insn (gen_ptrel_si (tr, pic, lab));
8233
        }
8234
      else
8235
        {
8236
          emit_insn (gen_movdi_const (pic, operands[1]));
8237
          emit_insn (gen_ptrel_di (tr, pic, lab));
8238
        }
8239
 
8240
      insn = emit_move_insn (operands[0], tr);
8241
 
8242
      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, equiv,
8243
                                            REG_NOTES (insn));
8244
 
8245
      DONE;
8246
    }
8247
}
8248
")
8249
 
8250
(define_insn "*ptb"
8251
  [(set (match_operand 0 "target_reg_operand" "=b")
8252
        (const (unspec [(match_operand 1 "" "Csy")]
8253
                             UNSPEC_DATALABEL)))]
8254
  "TARGET_SHMEDIA && flag_pic
8255
   && EXTRA_CONSTRAINT_Csy (operands[1])"
8256
  "ptb/u        datalabel %1, %0"
8257
  [(set_attr "type" "ptabs_media")
8258
   (set_attr "length" "*")])
8259
 
8260
(define_insn "ptrel_si"
8261
  [(set (match_operand:SI 0 "target_reg_operand" "=b")
8262
        (plus:SI (match_operand:SI 1 "register_operand" "r")
8263
              (pc)))
8264
   (match_operand:SI 2 "" "")]
8265
  "TARGET_SHMEDIA"
8266
  "%O2: ptrel/u %1, %0"
8267
  [(set_attr "type" "ptabs_media")])
8268
 
8269
(define_insn "ptrel_di"
8270
  [(set (match_operand:DI 0 "target_reg_operand" "=b")
8271
        (plus:DI (match_operand:DI 1 "register_operand" "r")
8272
              (pc)))
8273
   (match_operand:DI 2 "" "")]
8274
  "TARGET_SHMEDIA"
8275
  "%O2: ptrel/u %1, %0"
8276
  [(set_attr "type" "ptabs_media")])
8277
 
8278
(define_expand "builtin_setjmp_receiver"
8279
  [(match_operand 0 "" "")]
8280
  "flag_pic"
8281
  "
8282
{
8283
  emit_insn (gen_GOTaddr2picreg ());
8284
  DONE;
8285
}")
8286
 
8287
(define_expand "call_site"
8288
  [(unspec [(match_dup 0)] UNSPEC_CALLER)]
8289
  "TARGET_SH1"
8290
  "
8291
{
8292
  static HOST_WIDE_INT i = 0;
8293
  operands[0] = GEN_INT (i);
8294
  i++;
8295
}")
8296
 
8297
(define_expand "sym_label2reg"
8298
  [(set (match_operand:SI 0 "" "")
8299
        (const:SI (minus:SI
8300
                   (const:SI
8301
                    (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC))
8302
                   (const:SI
8303
                    (plus:SI
8304
                     (match_operand:SI 2 "" "")
8305
                     (const_int 2))))))]
8306
  "TARGET_SH1" "")
8307
 
8308
(define_expand "symGOT_load"
8309
  [(set (match_dup 2) (match_operand 1 "" ""))
8310
   (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
8311
   (set (match_operand 0 "" "") (mem (match_dup 3)))]
8312
  ""
8313
  "
8314
{
8315
  rtx insn, mem;
8316
 
8317
  operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
8318
  operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
8319
 
8320
  if (TARGET_SHMEDIA)
8321
    {
8322
      rtx reg = operands[2];
8323
 
8324
      if (Pmode == DImode)
8325
        {
8326
          if (flag_pic > 1)
8327
            emit_insn (gen_movdi_const_32bit (reg, operands[1]));
8328
          else
8329
            emit_insn (gen_movdi_const_16bit (reg, operands[1]));
8330
        }
8331
      else
8332
        {
8333
          if (flag_pic > 1)
8334
            emit_insn (gen_movsi_const (reg, operands[1]));
8335
          else
8336
            emit_insn (gen_movsi_const_16bit (reg, operands[1]));
8337
        }
8338
    }
8339
  else
8340
    emit_move_insn (operands[2], operands[1]);
8341
 
8342
  emit_move_insn (operands[3], gen_rtx_PLUS (Pmode,
8343
                                             operands[2],
8344
                                             gen_rtx_REG (Pmode, PIC_REG)));
8345
 
8346
  /* When stack protector inserts codes after the result is set to
8347
     R0, @(rX, r12) will cause a spill failure for R0.  Don't schedule
8348
     insns to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
8349
     when rX is a GOT address for the guard symbol.  Ugly but doesn't
8350
     matter because this is a rare situation.  */
8351
  if (!TARGET_SHMEDIA
8352
      && flag_stack_protect
8353
      && GET_CODE (operands[1]) == CONST
8354
      && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
8355
      && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
8356
      && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
8357
                 \"__stack_chk_guard\") == 0)
8358
    emit_insn (gen_blockage ());
8359
 
8360
  /* N.B. This is not constant for a GOTPLT relocation.  */
8361
  mem = gen_rtx_MEM (Pmode, operands[3]);
8362
  MEM_NOTRAP_P (mem) = 1;
8363
  /* ??? Should we have a special alias set for the GOT?  */
8364
  insn = emit_move_insn (operands[0], mem);
8365
 
8366
  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, XVECEXP (XEXP (operands[1],
8367
                                                                  0), 0, 0),
8368
                                        REG_NOTES (insn));
8369
 
8370
  DONE;
8371
}")
8372
 
8373
(define_expand "sym2GOT"
8374
  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
8375
  ""
8376
  "")
8377
 
8378
(define_expand "symGOT2reg"
8379
  [(match_operand 0 "" "") (match_operand 1 "" "")]
8380
  ""
8381
  "
8382
{
8383
  rtx gotsym, insn;
8384
 
8385
  gotsym = gen_sym2GOT (operands[1]);
8386
  PUT_MODE (gotsym, Pmode);
8387
  insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
8388
 
8389
  MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
8390
 
8391
  DONE;
8392
}")
8393
 
8394
(define_expand "symGOTPLT2reg"
8395
  [(match_operand 0 "" "") (match_operand 1 "" "")]
8396
  ""
8397
  "
8398
{
8399
  rtx pltsym = gen_rtx_CONST (Pmode,
8400
                              gen_rtx_UNSPEC (Pmode,
8401
                                              gen_rtvec (1, operands[1]),
8402
                                              UNSPEC_GOTPLT));
8403
  emit_insn (gen_symGOT_load (operands[0], pltsym));
8404
  DONE;
8405
}")
8406
 
8407
(define_expand "sym2GOTOFF"
8408
  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
8409
  ""
8410
  "")
8411
 
8412
(define_expand "symGOTOFF2reg"
8413
  [(match_operand 0 "" "") (match_operand 1 "" "")]
8414
  ""
8415
  "
8416
{
8417
  rtx gotoffsym, insn;
8418
  rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
8419
 
8420
  gotoffsym = gen_sym2GOTOFF (operands[1]);
8421
  PUT_MODE (gotoffsym, Pmode);
8422
  emit_move_insn (t, gotoffsym);
8423
  insn = emit_move_insn (operands[0],
8424
                         gen_rtx_PLUS (Pmode, t,
8425
                                       gen_rtx_REG (Pmode, PIC_REG)));
8426
 
8427
  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
8428
                                        REG_NOTES (insn));
8429
 
8430
  DONE;
8431
}")
8432
 
8433
(define_expand "symPLT_label2reg"
8434
  [(set (match_operand:SI 0 "" "")
8435
        (const:SI (minus:SI
8436
                   (const:SI
8437
                    (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
8438
                   (const:SI
8439
                    (minus:SI
8440
                     (const:SI (plus:SI
8441
                                (match_operand:SI 2 "" "")
8442
                                (const_int 2)))
8443
                     (const:SI (unspec:SI [(pc)] UNSPEC_PIC)))))))
8444
   ;; Even though the PIC register is not really used by the call
8445
   ;; sequence in which this is expanded, the PLT code assumes the PIC
8446
   ;; register is set, so we must not skip its initialization.  Since
8447
   ;; we only use this expand as part of calling sequences, and never
8448
   ;; to take the address of a function, this is the best point to
8449
   ;; insert the (use).  Using the PLT to take the address of a
8450
   ;; function would be wrong, not only because the PLT entry could
8451
   ;; then be called from a function that doesn't initialize the PIC
8452
   ;; register to the proper GOT, but also because pointers to the
8453
   ;; same function might not compare equal, should they be set by
8454
   ;; different shared libraries.
8455
   (use (reg:SI PIC_REG))]
8456
  "TARGET_SH1"
8457
  "")
8458
 
8459
(define_expand "sym2PIC"
8460
  [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
8461
  ""
8462
  "")
8463
 
8464
;; TLS code generation.
8465
;; ??? this should be a define_insn_and_split
8466
;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
8467
;; 
8468
;; for details.
8469
 
8470
(define_insn "tls_global_dynamic"
8471
  [(set (match_operand:SI 0 "register_operand" "=&z")
8472
        (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8473
                                  UNSPEC_TLSGD))
8474
              (const_int 0)))
8475
   (use (reg:PSI FPSCR_REG))
8476
   (use (reg:SI PIC_REG))
8477
   (clobber (reg:SI PR_REG))
8478
   (clobber (scratch:SI))]
8479
  "TARGET_SH1"
8480
  "*
8481
{
8482
  return \"\\
8483
mov.l\\t1f,r4\\n\\
8484
\\tmova\\t2f,r0\\n\\
8485
\\tmov.l\\t2f,r1\\n\\
8486
\\tadd\\tr0,r1\\n\\
8487
\\tjsr\\t@r1\\n\\
8488
\\tadd\\tr12,r4\\n\\
8489
\\tbra\\t3f\\n\\
8490
\\tnop\\n\\
8491
\\t.align\\t2\\n\\
8492
1:\\t.long\\t%a1@TLSGD\\n\\
8493
2:\\t.long\\t__tls_get_addr@PLT\\n\\
8494
3:\";
8495
}"
8496
  [(set_attr "type" "tls_load")
8497
   (set_attr "length" "26")])
8498
 
8499
(define_insn "tls_local_dynamic"
8500
  [(set (match_operand:SI 0 "register_operand" "=&z")
8501
        (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8502
                                  UNSPEC_TLSLDM))
8503
              (const_int 0)))
8504
   (use (reg:PSI FPSCR_REG))
8505
   (use (reg:SI PIC_REG))
8506
   (clobber (reg:SI PR_REG))
8507
   (clobber (scratch:SI))]
8508
  "TARGET_SH1"
8509
  "*
8510
{
8511
  return \"\\
8512
mov.l\\t1f,r4\\n\\
8513
\\tmova\\t2f,r0\\n\\
8514
\\tmov.l\\t2f,r1\\n\\
8515
\\tadd\\tr0,r1\\n\\
8516
\\tjsr\\t@r1\\n\\
8517
\\tadd\\tr12,r4\\n\\
8518
\\tbra\\t3f\\n\\
8519
\\tnop\\n\\
8520
\\t.align\\t2\\n\\
8521
1:\\t.long\\t%a1@TLSLDM\\n\\
8522
2:\\t.long\\t__tls_get_addr@PLT\\n\\
8523
3:\";
8524
}"
8525
  [(set_attr "type" "tls_load")
8526
   (set_attr "length" "26")])
8527
 
8528
(define_expand "sym2DTPOFF"
8529
  [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
8530
  ""
8531
  "")
8532
 
8533
(define_expand "symDTPOFF2reg"
8534
  [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
8535
  ""
8536
  "
8537
{
8538
  rtx dtpoffsym, insn;
8539
  rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
8540
 
8541
  dtpoffsym = gen_sym2DTPOFF (operands[1]);
8542
  PUT_MODE (dtpoffsym, Pmode);
8543
  emit_move_insn (t, dtpoffsym);
8544
  insn = emit_move_insn (operands[0],
8545
                         gen_rtx_PLUS (Pmode, t, operands[2]));
8546
  DONE;
8547
}")
8548
 
8549
(define_expand "sym2GOTTPOFF"
8550
  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
8551
  ""
8552
  "")
8553
 
8554
(define_insn "tls_initial_exec"
8555
  [(set (match_operand:SI 0 "register_operand" "=&r")
8556
        (unspec:SI [(match_operand:SI 1 "" "")]
8557
                    UNSPEC_TLSIE))
8558
   (use (reg:SI GBR_REG))
8559
   (use (reg:SI PIC_REG))
8560
   (clobber (reg:SI R0_REG))]
8561
  ""
8562
  "*
8563
{
8564
  return \"\\
8565
mov.l\\t1f,r0\\n\\
8566
\\tstc\\tgbr,%0\\n\\
8567
\\tmov.l\\t@(r0,r12),r0\\n\\
8568
\\tbra\\t2f\\n\\
8569
\\tadd\\tr0,%0\\n\\
8570
\\t.align\\t2\\n\\
8571
1:\\t.long\\t%a1\\n\\
8572
2:\";
8573
}"
8574
  [(set_attr "type" "tls_load")
8575
   (set_attr "length" "16")])
8576
 
8577
(define_expand "sym2TPOFF"
8578
  [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
8579
  ""
8580
  "")
8581
 
8582
(define_expand "symTPOFF2reg"
8583
  [(match_operand 0 "" "") (match_operand 1 "" "")]
8584
  ""
8585
  "
8586
{
8587
  rtx tpoffsym, insn;
8588
 
8589
  tpoffsym = gen_sym2TPOFF (operands[1]);
8590
  PUT_MODE (tpoffsym, Pmode);
8591
  insn = emit_move_insn (operands[0], tpoffsym);
8592
  DONE;
8593
}")
8594
 
8595
(define_insn "load_gbr"
8596
  [(set (match_operand:SI 0 "register_operand" "") (reg:SI GBR_REG))
8597
   (use (reg:SI GBR_REG))]
8598
  ""
8599
  "stc  gbr,%0"
8600
  [(set_attr "type" "tls_load")])
8601
 
8602
;; case instruction for switch statements.
8603
 
8604
;; Operand 0 is index
8605
;; operand 1 is the minimum bound
8606
;; operand 2 is the maximum bound - minimum bound + 1
8607
;; operand 3 is CODE_LABEL for the table;
8608
;; operand 4 is the CODE_LABEL to go to if index out of range.
8609
 
8610
(define_expand "casesi"
8611
  [(match_operand:SI 0 "arith_reg_operand" "")
8612
   (match_operand:SI 1 "arith_reg_operand" "")
8613
   (match_operand:SI 2 "arith_reg_operand" "")
8614
   (match_operand 3 "" "") (match_operand 4 "" "")]
8615
  ""
8616
  "
8617
{
8618
  rtx reg = gen_reg_rtx (SImode);
8619
  rtx reg2 = gen_reg_rtx (SImode);
8620
  if (TARGET_SHMEDIA)
8621
    {
8622
      rtx reg = gen_reg_rtx (DImode);
8623
      rtx reg2 = gen_reg_rtx (DImode);
8624
      rtx reg3 = gen_reg_rtx (Pmode);
8625
      rtx reg4 = gen_reg_rtx (Pmode);
8626
      rtx reg5 = gen_reg_rtx (Pmode);
8627
      rtx load;
8628
 
8629
      operands[0] = convert_modes (DImode, SImode, operands[0], 0);
8630
      operands[1] = convert_modes (DImode, SImode, operands[1], 0);
8631
      operands[2] = convert_modes (DImode, SImode, operands[2], 1);
8632
 
8633
      emit_jump_insn (gen_bgt_media (operands[4], operands[1], operands[0]));
8634
      emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
8635
      emit_jump_insn (gen_bgtu_media (operands[4], reg, operands[2]));
8636
      emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
8637
      emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
8638
                                               (Pmode, operands[3])));
8639
      /* Messy: can we subreg to clean this up? */
8640
      if (Pmode == DImode)
8641
        load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
8642
      else
8643
        load = gen_casesi_load_media (reg4,
8644
                                      gen_rtx_SUBREG (DImode, reg3, 0),
8645
                                      reg2, operands[3]);
8646
      PUT_MODE (SET_SRC (load), Pmode);
8647
      emit_insn (load);
8648
      /* ??? The following add could be eliminated if we used ptrel.  */
8649
      emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
8650
      emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
8651
      emit_barrier ();
8652
      DONE;
8653
    }
8654
  operands[1] = copy_to_mode_reg (SImode, operands[1]);
8655
  operands[2] = copy_to_mode_reg (SImode, operands[2]);
8656
  /* If optimizing, casesi_worker depends on the mode of the instruction
8657
     before label it 'uses' - operands[3].  */
8658
  emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
8659
                           reg));
8660
  emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
8661
  if (TARGET_SH2)
8662
    emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
8663
  else
8664
    emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
8665
  /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
8666
     operands[3], but to lab.  We will fix this up in
8667
     machine_dependent_reorg.  */
8668
  emit_barrier ();
8669
  DONE;
8670
}")
8671
 
8672
(define_expand "casesi_0"
8673
  [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
8674
   (set (match_dup 4) (minus:SI (match_dup 4)
8675
                                (match_operand:SI 1 "arith_operand" "")))
8676
   (set (reg:SI T_REG)
8677
        (gtu:SI (match_dup 4)
8678
                (match_operand:SI 2 "arith_reg_operand" "")))
8679
   (set (pc)
8680
        (if_then_else (ne (reg:SI T_REG)
8681
                          (const_int 0))
8682
                      (label_ref (match_operand 3 "" ""))
8683
                      (pc)))]
8684
  "TARGET_SH1"
8685
  "")
8686
 
8687
;; ??? reload might clobber r0 if we use it explicitly in the RTL before
8688
;; reload; using a R0_REGS pseudo reg is likely to give poor code.
8689
;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
8690
 
8691
(define_insn "casesi_worker_0"
8692
  [(set (match_operand:SI 0 "register_operand" "=r,r")
8693
        (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
8694
                 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8695
   (clobber (match_scratch:SI 3 "=X,1"))
8696
   (clobber (match_scratch:SI 4 "=&z,z"))]
8697
  "TARGET_SH1"
8698
  "#")
8699
 
8700
(define_split
8701
  [(set (match_operand:SI 0 "register_operand" "")
8702
        (unspec:SI [(match_operand:SI 1 "register_operand" "")
8703
                    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8704
   (clobber (match_scratch:SI 3 ""))
8705
   (clobber (match_scratch:SI 4 ""))]
8706
  "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
8707
  [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
8708
   (parallel [(set (match_dup 0)
8709
              (unspec:SI [(reg:SI R0_REG) (match_dup 1)
8710
                          (label_ref (match_dup 2))] UNSPEC_CASESI))
8711
              (clobber (match_dup 3))])
8712
   (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
8713
  "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
8714
 
8715
(define_split
8716
  [(set (match_operand:SI 0 "register_operand" "")
8717
        (unspec:SI [(match_operand:SI 1 "register_operand" "")
8718
                    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8719
   (clobber (match_scratch:SI 3 ""))
8720
   (clobber (match_scratch:SI 4 ""))]
8721
  "TARGET_SH2 && reload_completed"
8722
  [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
8723
   (parallel [(set (match_dup 0)
8724
              (unspec:SI [(reg:SI R0_REG) (match_dup 1)
8725
                          (label_ref (match_dup 2))] UNSPEC_CASESI))
8726
              (clobber (match_dup 3))])]
8727
  "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
8728
 
8729
(define_insn "casesi_worker_1"
8730
  [(set (match_operand:SI 0 "register_operand" "=r,r")
8731
        (unspec:SI [(reg:SI R0_REG)
8732
                    (match_operand:SI 1 "register_operand" "0,r")
8733
                    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8734
   (clobber (match_scratch:SI 3 "=X,1"))]
8735
  "TARGET_SH1"
8736
  "*
8737
{
8738
  rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8739
 
8740
  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8741
 
8742
  switch (GET_MODE (diff_vec))
8743
    {
8744
    case SImode:
8745
      return \"shll2    %1\;mov.l       @(r0,%1),%0\";
8746
    case HImode:
8747
      return \"add      %1,%1\;mov.w    @(r0,%1),%0\";
8748
    case QImode:
8749
      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8750
        return \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
8751
      return \"mov.b    @(r0,%1),%0\";
8752
    default:
8753
      gcc_unreachable ();
8754
    }
8755
}"
8756
  [(set_attr "length" "4")])
8757
 
8758
(define_insn "casesi_worker_2"
8759
  [(set (match_operand:SI 0 "register_operand" "=r,r")
8760
        (unspec:SI [(reg:SI R0_REG)
8761
                    (match_operand:SI 1 "register_operand" "0,r")
8762
                    (label_ref (match_operand 2 "" ""))
8763
                    (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
8764
   (clobber (match_operand:SI 4 "" "=X,1"))]
8765
  "TARGET_SH2 && reload_completed && flag_pic"
8766
  "*
8767
{
8768
  rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8769
  const char *load;
8770
 
8771
  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8772
 
8773
  switch (GET_MODE (diff_vec))
8774
    {
8775
    case SImode:
8776
      output_asm_insn (\"shll2    %1\", operands);
8777
      load = \"mov.l    @(r0,%1),%0\"; break;
8778
    case HImode:
8779
      output_asm_insn (\"add    %1,%1\", operands);
8780
      load = \"mov.w    @(r0,%1),%0\"; break;
8781
    case QImode:
8782
      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8783
        load = \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
8784
      else
8785
        load = \"mov.b  @(r0,%1),%0\";
8786
      break;
8787
    default:
8788
      gcc_unreachable ();
8789
    }
8790
  output_asm_insn (\"add\tr0,%1\;mova\t%O3,r0\\n\", operands);
8791
  return load;
8792
}"
8793
  [(set_attr "length" "8")])
8794
 
8795
(define_insn "casesi_shift_media"
8796
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
8797
        (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
8798
                   (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
8799
                    UNSPEC_CASESI)))]
8800
  "TARGET_SHMEDIA"
8801
  "*
8802
{
8803
  rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8804
 
8805
  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8806
 
8807
  switch (GET_MODE (diff_vec))
8808
    {
8809
    case SImode:
8810
      return \"shlli    %1, 2, %0\";
8811
    case HImode:
8812
      return \"shlli    %1, 1, %0\";
8813
    case QImode:
8814
      if (rtx_equal_p (operands[0], operands[1]))
8815
        return \"\";
8816
      return \"add      %1, r63, %0\";
8817
    default:
8818
      gcc_unreachable ();
8819
    }
8820
}"
8821
  [(set_attr "type" "arith_media")])
8822
 
8823
(define_insn "casesi_load_media"
8824
  [(set (match_operand 0 "any_arith_reg_dest" "=r")
8825
        (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
8826
                         (match_operand:DI 2 "arith_reg_operand" "r")
8827
                         (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
8828
  "TARGET_SHMEDIA"
8829
  "*
8830
{
8831
  rtx diff_vec = PATTERN (next_real_insn (operands[3]));
8832
 
8833
  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8834
 
8835
  switch (GET_MODE (diff_vec))
8836
    {
8837
    case SImode:
8838
      return \"ldx.l    %1, %2, %0\";
8839
    case HImode:
8840
#if 0
8841
      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8842
        return \"ldx.uw %1, %2, %0\";
8843
#endif
8844
      return \"ldx.w    %1, %2, %0\";
8845
    case QImode:
8846
      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8847
        return \"ldx.ub %1, %2, %0\";
8848
      return \"ldx.b    %1, %2, %0\";
8849
    default:
8850
      gcc_unreachable ();
8851
    }
8852
}"
8853
  [(set_attr "type" "load_media")])
8854
 
8855
(define_expand "return"
8856
  [(return)]
8857
  "reload_completed && ! sh_need_epilogue ()"
8858
  "
8859
{
8860
  if (TARGET_SHMEDIA)
8861
    {
8862
      emit_jump_insn (gen_return_media ());
8863
      DONE;
8864
    }
8865
 
8866
  if (TARGET_SHCOMPACT
8867
      && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
8868
    {
8869
      emit_jump_insn (gen_shcompact_return_tramp ());
8870
      DONE;
8871
    }
8872
}")
8873
 
8874
(define_insn "*return_i"
8875
  [(return)]
8876
  "TARGET_SH1 && ! (TARGET_SHCOMPACT
8877
                    && (current_function_args_info.call_cookie
8878
                        & CALL_COOKIE_RET_TRAMP (1)))
8879
   && reload_completed
8880
   && lookup_attribute (\"trap_exit\",
8881
                        DECL_ATTRIBUTES (current_function_decl)) == NULL_TREE"
8882
  "%@   %#"
8883
  [(set_attr "type" "return")
8884
   (set_attr "needs_delay_slot" "yes")])
8885
 
8886
;; trapa has no delay slot.
8887
(define_insn "*return_trapa"
8888
  [(return)]
8889
  "TARGET_SH1 && !TARGET_SHCOMPACT
8890
   && reload_completed"
8891
  "%@"
8892
  [(set_attr "type" "return")])
8893
 
8894
(define_expand "shcompact_return_tramp"
8895
  [(return)]
8896
  "TARGET_SHCOMPACT
8897
   && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
8898
  "
8899
{
8900
  rtx reg = gen_rtx_REG (Pmode, R0_REG);
8901
 
8902
  function_symbol (reg, \"__GCC_shcompact_return_trampoline\", SFUNC_STATIC);
8903
  emit_jump_insn (gen_shcompact_return_tramp_i ());
8904
  DONE;
8905
}")
8906
 
8907
(define_insn "shcompact_return_tramp_i"
8908
  [(parallel [(return) (use (reg:SI R0_REG))])]
8909
  "TARGET_SHCOMPACT
8910
   && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
8911
  "jmp  @r0%#"
8912
  [(set_attr "type" "jump_ind")
8913
   (set_attr "needs_delay_slot" "yes")])
8914
 
8915
(define_insn "return_media_i"
8916
  [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
8917
  "TARGET_SHMEDIA && reload_completed"
8918
  "blink        %0, r63"
8919
  [(set_attr "type" "jump_media")])
8920
 
8921
(define_insn "return_media_rte"
8922
  [(return)]
8923
  "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
8924
  "rte"
8925
  [(set_attr "type" "jump_media")])
8926
 
8927
(define_expand "return_media"
8928
  [(return)]
8929
  "TARGET_SHMEDIA && reload_completed"
8930
  "
8931
{
8932
  int tr_regno = sh_media_register_for_return ();
8933
  rtx tr;
8934
 
8935
  if (current_function_interrupt)
8936
    {
8937
      emit_jump_insn (gen_return_media_rte ());
8938
      DONE;
8939
    }
8940
  if (tr_regno < 0)
8941
    {
8942
      rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
8943
 
8944
      gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
8945
      tr_regno = TR0_REG;
8946
      tr = gen_rtx_REG (Pmode, tr_regno);
8947
      emit_move_insn (tr, r18);
8948
    }
8949
  else
8950
    tr = gen_rtx_REG (Pmode, tr_regno);
8951
 
8952
  emit_jump_insn (gen_return_media_i (tr));
8953
  DONE;
8954
}")
8955
 
8956
(define_insn "shcompact_preserve_incoming_args"
8957
  [(set (match_operand:SI 0 "register_operand" "+r")
8958
        (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
8959
  "TARGET_SHCOMPACT"
8960
  ""
8961
  [(set_attr "length" "0")])
8962
 
8963
(define_insn "shcompact_incoming_args"
8964
  [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
8965
   (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
8966
   (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
8967
   (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
8968
   (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
8969
   (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
8970
   (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
8971
   (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
8972
   (set (mem:BLK (reg:SI MACL_REG))
8973
        (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
8974
   (use (reg:SI R0_REG))
8975
   (clobber (reg:SI R0_REG))
8976
   (clobber (reg:SI MACL_REG))
8977
   (clobber (reg:SI MACH_REG))
8978
   (clobber (reg:SI PR_REG))]
8979
  "TARGET_SHCOMPACT"
8980
  "jsr  @r0%#"
8981
  [(set_attr "needs_delay_slot" "yes")])
8982
 
8983
(define_insn "shmedia_save_restore_regs_compact"
8984
  [(set (reg:SI SP_REG)
8985
        (plus:SI (reg:SI SP_REG)
8986
                 (match_operand:SI 0 "immediate_operand" "i")))
8987
   (use (reg:SI R0_REG))
8988
   (clobber (reg:SI PR_REG))]
8989
  "TARGET_SHCOMPACT
8990
   && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
8991
       || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
8992
  "jsr @r0%#"
8993
  [(set_attr "needs_delay_slot" "yes")])
8994
 
8995
(define_expand "prologue"
8996
  [(const_int 0)]
8997
  ""
8998
  "sh_expand_prologue (); DONE;")
8999
 
9000
(define_expand "epilogue"
9001
  [(return)]
9002
  ""
9003
  "
9004
{
9005
  sh_expand_epilogue (0);
9006
  emit_jump_insn (gen_return ());
9007
  DONE;
9008
}")
9009
 
9010
(define_expand "eh_return"
9011
  [(use (match_operand 0 "register_operand" ""))]
9012
  ""
9013
{
9014
  rtx ra = operands[0];
9015
 
9016
  if (TARGET_SHMEDIA64)
9017
    emit_insn (gen_eh_set_ra_di (ra));
9018
  else
9019
    emit_insn (gen_eh_set_ra_si (ra));
9020
 
9021
  DONE;
9022
})
9023
 
9024
;; Clobber the return address on the stack.  We can't expand this
9025
;; until we know where it will be put in the stack frame.
9026
 
9027
(define_insn "eh_set_ra_si"
9028
  [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
9029
   (clobber (match_scratch:SI 1 "=&r"))]
9030
  "! TARGET_SHMEDIA64"
9031
  "#")
9032
 
9033
(define_insn "eh_set_ra_di"
9034
  [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
9035
   (clobber (match_scratch:DI 1 "=&r"))]
9036
  "TARGET_SHMEDIA64"
9037
  "#")
9038
 
9039
(define_split
9040
  [(unspec [(match_operand 0 "register_operand" "")] UNSPEC_EH_RETURN)
9041
   (clobber (match_scratch 1 ""))]
9042
  "reload_completed"
9043
  [(const_int 0)]
9044
  "
9045
{
9046
  sh_set_return_address (operands[0], operands[1]);
9047
  DONE;
9048
}")
9049
 
9050
(define_insn "blockage"
9051
  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
9052
  ""
9053
  ""
9054
  [(set_attr "length" "0")])
9055
 
9056
;; ------------------------------------------------------------------------
9057
;; Scc instructions
9058
;; ------------------------------------------------------------------------
9059
 
9060
(define_insn "movt"
9061
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9062
        (eq:SI (reg:SI T_REG) (const_int 1)))]
9063
  "TARGET_SH1"
9064
  "movt %0"
9065
  [(set_attr "type" "arith")])
9066
 
9067
(define_expand "seq"
9068
  [(set (match_operand:SI 0 "arith_reg_dest" "")
9069
        (match_dup 1))]
9070
  ""
9071
  "
9072
{
9073
  if (TARGET_SHMEDIA)
9074
    {
9075
      rtx reg;
9076
 
9077
      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9078
      if (sh_compare_op1 != const0_rtx)
9079
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9080
                                    ? GET_MODE (sh_compare_op0)
9081
                                    : GET_MODE (sh_compare_op1),
9082
                                    sh_compare_op1);
9083
      if (GET_MODE_SIZE (GET_MODE (operands[0])) <= 4)
9084
        {
9085
          if (GET_MODE (operands[0]) != SImode)
9086
            operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
9087
 
9088
          switch (GET_MODE (sh_compare_op0))
9089
            {
9090
            case SImode:
9091
              emit_insn (gen_cmpeqsi_media (operands[0],
9092
                                              sh_compare_op0, sh_compare_op1));
9093
              break;
9094
 
9095
            case DImode:
9096
              emit_insn (gen_cmpeqdi_media (operands[0],
9097
                                              sh_compare_op0, sh_compare_op1));
9098
              break;
9099
 
9100
            case SFmode:
9101
              if (! TARGET_SHMEDIA_FPU)
9102
                FAIL;
9103
              emit_insn (gen_cmpeqsf_media (operands[0],
9104
                                              sh_compare_op0, sh_compare_op1));
9105
              break;
9106
 
9107
            case DFmode:
9108
              if (! TARGET_SHMEDIA_FPU)
9109
                FAIL;
9110
              emit_insn (gen_cmpeqdf_media (operands[0],
9111
                                              sh_compare_op0, sh_compare_op1));
9112
              break;
9113
 
9114
            default:
9115
              FAIL;
9116
            }
9117
          DONE;
9118
        }
9119
 
9120
      reg = operands[0];
9121
      if (GET_MODE (operands[0]) != SImode)
9122
        reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9123
                             : gen_reg_rtx (SImode);
9124
 
9125
      switch (GET_MODE (sh_compare_op0))
9126
        {
9127
        case SImode:
9128
          emit_insn (gen_cmpeqsi_media (reg,
9129
                                        sh_compare_op0, sh_compare_op1));
9130
          break;
9131
 
9132
        case DImode:
9133
          emit_insn (gen_cmpeqdi_media (reg,
9134
                                        sh_compare_op0, sh_compare_op1));
9135
          break;
9136
 
9137
        case SFmode:
9138
          if (! TARGET_SHMEDIA_FPU)
9139
            FAIL;
9140
          emit_insn (gen_cmpeqsf_media (reg,
9141
                                        sh_compare_op0, sh_compare_op1));
9142
          break;
9143
 
9144
        case DFmode:
9145
          if (! TARGET_SHMEDIA_FPU)
9146
            FAIL;
9147
          emit_insn (gen_cmpeqdf_media (reg,
9148
                                        sh_compare_op0, sh_compare_op1));
9149
          break;
9150
 
9151
        default:
9152
          FAIL;
9153
        }
9154
 
9155
      if (GET_MODE (operands[0]) == DImode)
9156
        emit_insn (gen_extendsidi2 (operands[0], reg));
9157
 
9158
      DONE;
9159
    }
9160
  if (sh_expand_t_scc (EQ, operands[0]))
9161
    DONE;
9162
  if (! currently_expanding_to_rtl)
9163
    FAIL;
9164
  operands[1] = prepare_scc_operands (EQ);
9165
}")
9166
 
9167
(define_expand "slt"
9168
  [(set (match_operand:SI 0 "arith_reg_operand" "")
9169
        (match_dup 1))]
9170
  ""
9171
  "
9172
{
9173
  if (TARGET_SHMEDIA)
9174
    {
9175
      rtx reg;
9176
 
9177
      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9178
      if (sh_compare_op1 != const0_rtx)
9179
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9180
                                    ? GET_MODE (sh_compare_op0)
9181
                                    : GET_MODE (sh_compare_op1),
9182
                                    sh_compare_op1);
9183
 
9184
      reg = operands[0];
9185
      if (GET_MODE (operands[0]) != SImode)
9186
        reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9187
                             : gen_reg_rtx (SImode);
9188
 
9189
      switch (GET_MODE (sh_compare_op0))
9190
        {
9191
        case SImode:
9192
          emit_insn (gen_cmpgtsi_media (reg,
9193
                                        sh_compare_op1, sh_compare_op0));
9194
          break;
9195
 
9196
        case DImode:
9197
          emit_insn (gen_cmpgtdi_media (reg,
9198
                                        sh_compare_op1, sh_compare_op0));
9199
          break;
9200
 
9201
        case SFmode:
9202
          if (! TARGET_SHMEDIA_FPU)
9203
            FAIL;
9204
          emit_insn (gen_cmpgtsf_media (reg,
9205
                                        sh_compare_op1, sh_compare_op0));
9206
          break;
9207
 
9208
        case DFmode:
9209
          if (! TARGET_SHMEDIA_FPU)
9210
            FAIL;
9211
          emit_insn (gen_cmpgtdf_media (reg,
9212
                                        sh_compare_op1, sh_compare_op0));
9213
          break;
9214
 
9215
        default:
9216
          FAIL;
9217
        }
9218
 
9219
      if (GET_MODE (operands[0]) == DImode)
9220
        emit_insn (gen_extendsidi2 (operands[0], reg));
9221
 
9222
      DONE;
9223
    }
9224
  if (! currently_expanding_to_rtl)
9225
    FAIL;
9226
  operands[1] = prepare_scc_operands (LT);
9227
}")
9228
 
9229
(define_expand "sle"
9230
  [(match_operand:SI 0 "arith_reg_operand" "")]
9231
  ""
9232
  "
9233
{
9234
  rtx tmp = sh_compare_op0;
9235
 
9236
  if (TARGET_SHMEDIA)
9237
    {
9238
      rtx reg;
9239
 
9240
      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9241
      if (sh_compare_op1 != const0_rtx)
9242
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9243
                                    ? GET_MODE (sh_compare_op0)
9244
                                    : GET_MODE (sh_compare_op1),
9245
                                    sh_compare_op1);
9246
 
9247
      reg = operands[0];
9248
      if (GET_MODE (operands[0]) != SImode)
9249
        reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9250
                             : gen_reg_rtx (SImode);
9251
 
9252
      switch (GET_MODE (sh_compare_op0))
9253
        {
9254
        case SImode:
9255
          {
9256
            tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9257
 
9258
            emit_insn (gen_cmpgtsi_media (tmp,
9259
                                          sh_compare_op0, sh_compare_op1));
9260
            emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9261
            break;
9262
          }
9263
 
9264
        case DImode:
9265
          {
9266
            tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9267
 
9268
            emit_insn (gen_cmpgtdi_media (tmp,
9269
                                          sh_compare_op0, sh_compare_op1));
9270
            emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9271
            break;
9272
          }
9273
 
9274
        case SFmode:
9275
          if (! TARGET_SHMEDIA_FPU)
9276
            FAIL;
9277
          emit_insn (gen_cmpgesf_media (reg,
9278
                                        sh_compare_op1, sh_compare_op0));
9279
          break;
9280
 
9281
        case DFmode:
9282
          if (! TARGET_SHMEDIA_FPU)
9283
            FAIL;
9284
          emit_insn (gen_cmpgedf_media (reg,
9285
                                        sh_compare_op1, sh_compare_op0));
9286
          break;
9287
 
9288
        default:
9289
          FAIL;
9290
        }
9291
 
9292
      if (GET_MODE (operands[0]) == DImode)
9293
        emit_insn (gen_extendsidi2 (operands[0], reg));
9294
 
9295
      DONE;
9296
    }
9297
 
9298
  sh_compare_op0 = sh_compare_op1;
9299
  sh_compare_op1 = tmp;
9300
  emit_insn (gen_sge (operands[0]));
9301
  DONE;
9302
}")
9303
 
9304
(define_expand "sgt"
9305
  [(set (match_operand:SI 0 "arith_reg_operand" "")
9306
        (match_dup 1))]
9307
  ""
9308
  "
9309
{
9310
  if (TARGET_SHMEDIA)
9311
    {
9312
      rtx reg;
9313
 
9314
      reg = operands[0];
9315
      if (GET_MODE (operands[0]) != SImode)
9316
        reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9317
                             : gen_reg_rtx (SImode);
9318
      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9319
      if (sh_compare_op1 != const0_rtx)
9320
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9321
                                    ? GET_MODE (sh_compare_op0)
9322
                                    : GET_MODE (sh_compare_op1),
9323
                                    sh_compare_op1);
9324
 
9325
      switch (GET_MODE (sh_compare_op0))
9326
        {
9327
        case SImode:
9328
          emit_insn (gen_cmpgtsi_media (reg,
9329
                                        sh_compare_op0, sh_compare_op1));
9330
          break;
9331
 
9332
        case DImode:
9333
          emit_insn (gen_cmpgtdi_media (reg,
9334
                                        sh_compare_op0, sh_compare_op1));
9335
          break;
9336
 
9337
        case SFmode:
9338
          if (! TARGET_SHMEDIA_FPU)
9339
            FAIL;
9340
          emit_insn (gen_cmpgtsf_media (reg,
9341
                                        sh_compare_op0, sh_compare_op1));
9342
          break;
9343
 
9344
        case DFmode:
9345
          if (! TARGET_SHMEDIA_FPU)
9346
            FAIL;
9347
          emit_insn (gen_cmpgtdf_media (reg,
9348
                                        sh_compare_op0, sh_compare_op1));
9349
          break;
9350
 
9351
        default:
9352
          FAIL;
9353
        }
9354
 
9355
      if (GET_MODE (operands[0]) == DImode)
9356
        emit_insn (gen_extendsidi2 (operands[0], reg));
9357
 
9358
      DONE;
9359
    }
9360
  if (! currently_expanding_to_rtl)
9361
    FAIL;
9362
  operands[1] = prepare_scc_operands (GT);
9363
}")
9364
 
9365
(define_expand "sge"
9366
  [(set (match_operand:SI 0 "arith_reg_operand" "")
9367
        (match_dup 1))]
9368
  ""
9369
  "
9370
{
9371
  if (TARGET_SHMEDIA)
9372
    {
9373
      rtx reg;
9374
      enum machine_mode mode = GET_MODE (sh_compare_op0);
9375
 
9376
      if ((mode) == VOIDmode)
9377
        mode = GET_MODE (sh_compare_op1);
9378
      reg = operands[0];
9379
      if (GET_MODE (operands[0]) != SImode)
9380
        reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9381
                             : gen_reg_rtx (SImode);
9382
      sh_compare_op0 = force_reg (mode, sh_compare_op0);
9383
      if (sh_compare_op1 != const0_rtx)
9384
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
9385
 
9386
      switch (mode)
9387
        {
9388
        case SImode:
9389
          {
9390
            rtx tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9391
 
9392
            emit_insn (gen_cmpgtsi_media (tmp,
9393
                                          sh_compare_op1, sh_compare_op0));
9394
            emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9395
            break;
9396
          }
9397
 
9398
        case DImode:
9399
          {
9400
            rtx tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9401
 
9402
            emit_insn (gen_cmpgtdi_media (tmp,
9403
                                          sh_compare_op1, sh_compare_op0));
9404
            emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9405
            break;
9406
          }
9407
 
9408
        case SFmode:
9409
          if (! TARGET_SHMEDIA_FPU)
9410
            FAIL;
9411
          emit_insn (gen_cmpgesf_media (reg,
9412
                                        sh_compare_op0, sh_compare_op1));
9413
          break;
9414
 
9415
        case DFmode:
9416
          if (! TARGET_SHMEDIA_FPU)
9417
            FAIL;
9418
          emit_insn (gen_cmpgedf_media (reg,
9419
                                        sh_compare_op0, sh_compare_op1));
9420
          break;
9421
 
9422
        default:
9423
          FAIL;
9424
        }
9425
 
9426
      if (GET_MODE (operands[0]) == DImode)
9427
        emit_insn (gen_extendsidi2 (operands[0], reg));
9428
 
9429
      DONE;
9430
    }
9431
 
9432
  if (! currently_expanding_to_rtl)
9433
    FAIL;
9434
  if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
9435
    {
9436
      if (TARGET_IEEE)
9437
        {
9438
          rtx lab = gen_label_rtx ();
9439
          prepare_scc_operands (EQ);
9440
          emit_jump_insn (gen_branch_true (lab));
9441
          prepare_scc_operands (GT);
9442
          emit_label (lab);
9443
          emit_insn (gen_movt (operands[0]));
9444
        }
9445
      else
9446
        emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT)));
9447
      DONE;
9448
    }
9449
  operands[1] = prepare_scc_operands (GE);
9450
}")
9451
 
9452
(define_expand "sgtu"
9453
  [(set (match_operand:SI 0 "arith_reg_operand" "")
9454
        (match_dup 1))]
9455
  ""
9456
  "
9457
{
9458
  if (TARGET_SHMEDIA)
9459
    {
9460
      rtx reg;
9461
 
9462
      reg = operands[0];
9463
      if (GET_MODE (operands[0]) == DImode)
9464
        reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9465
                             : gen_reg_rtx (SImode);
9466
      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9467
      if (sh_compare_op1 != const0_rtx)
9468
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9469
                                    ? GET_MODE (sh_compare_op0)
9470
                                    : GET_MODE (sh_compare_op1),
9471
                                    sh_compare_op1);
9472
 
9473
      emit_insn (gen_cmpgtudi_media (reg,
9474
                                     sh_compare_op0, sh_compare_op1));
9475
      if (GET_MODE (operands[0]) == DImode)
9476
        emit_insn (gen_extendsidi2 (operands[0], reg));
9477
 
9478
      DONE;
9479
    }
9480
  if (! currently_expanding_to_rtl)
9481
    FAIL;
9482
  operands[1] = prepare_scc_operands (GTU);
9483
}")
9484
 
9485
(define_expand "sltu"
9486
  [(set (match_operand:SI 0 "arith_reg_operand" "")
9487
        (match_dup 1))]
9488
  ""
9489
  "
9490
{
9491
  if (TARGET_SHMEDIA)
9492
    {
9493
      rtx reg;
9494
 
9495
      reg = operands[0];
9496
      if (GET_MODE (operands[0]) == DImode)
9497
        reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9498
                             : gen_reg_rtx (SImode);
9499
      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9500
      if (sh_compare_op1 != const0_rtx)
9501
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9502
                                    ? GET_MODE (sh_compare_op0)
9503
                                    : GET_MODE (sh_compare_op1),
9504
                                    sh_compare_op1);
9505
 
9506
      emit_insn (gen_cmpgtudi_media (reg,
9507
                                     sh_compare_op1, sh_compare_op0));
9508
      if (GET_MODE (operands[0]) == DImode)
9509
        emit_insn (gen_extendsidi2 (operands[0], reg));
9510
 
9511
      DONE;
9512
    }
9513
  if (! currently_expanding_to_rtl)
9514
    FAIL;
9515
  operands[1] = prepare_scc_operands (LTU);
9516
}")
9517
 
9518
(define_expand "sleu"
9519
  [(set (match_operand:SI 0 "arith_reg_operand" "")
9520
        (match_dup 1))]
9521
  ""
9522
  "
9523
{
9524
  if (TARGET_SHMEDIA)
9525
    {
9526
      rtx tmp, reg;
9527
 
9528
      reg = operands[0];
9529
      if (GET_MODE (operands[0]) != SImode)
9530
        reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9531
                             : gen_reg_rtx (SImode);
9532
      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9533
      if (sh_compare_op1 != const0_rtx)
9534
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9535
                                    ? GET_MODE (sh_compare_op0)
9536
                                    : GET_MODE (sh_compare_op1),
9537
                                    sh_compare_op1);
9538
 
9539
      tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9540
 
9541
      emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1));
9542
      emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9543
      if (GET_MODE (operands[0]) == DImode)
9544
        emit_insn (gen_extendsidi2 (operands[0], reg));
9545
 
9546
      DONE;
9547
    }
9548
  if (! currently_expanding_to_rtl)
9549
    FAIL;
9550
  operands[1] = prepare_scc_operands (LEU);
9551
}")
9552
 
9553
(define_expand "sgeu"
9554
  [(set (match_operand:SI 0 "arith_reg_operand" "")
9555
        (match_dup 1))]
9556
  ""
9557
  "
9558
{
9559
  if (TARGET_SHMEDIA)
9560
    {
9561
      rtx tmp, reg;
9562
 
9563
      reg = operands[0];
9564
      if (GET_MODE (operands[0]) != SImode)
9565
        reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9566
                             : gen_reg_rtx (SImode);
9567
      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9568
      if (sh_compare_op1 != const0_rtx)
9569
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9570
                                    ? GET_MODE (sh_compare_op0)
9571
                                    : GET_MODE (sh_compare_op1),
9572
                                    sh_compare_op1);
9573
 
9574
      tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode);
9575
 
9576
      emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0));
9577
      emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9578
      if (GET_MODE (operands[0]) == DImode)
9579
        emit_insn (gen_extendsidi2 (operands[0], reg));
9580
 
9581
      DONE;
9582
    }
9583
 
9584
  if (! currently_expanding_to_rtl)
9585
    FAIL;
9586
  operands[1] = prepare_scc_operands (GEU);
9587
}")
9588
 
9589
;; sne moves the complement of the T reg to DEST like this:
9590
;;      cmp/eq ...
9591
;;      mov    #-1,temp
9592
;;      negc   temp,dest
9593
;;   This is better than xoring compare result with 1 because it does
9594
;;   not require r0 and further, the -1 may be CSE-ed or lifted out of a
9595
;;   loop.
9596
 
9597
(define_expand "sne"
9598
  [(set (match_dup 2) (const_int -1))
9599
   (parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
9600
                   (neg:SI (plus:SI (match_dup 1)
9601
                                    (match_dup 2))))
9602
              (set (reg:SI T_REG)
9603
                   (ne:SI (ior:SI (match_dup 1) (match_dup 2))
9604
                          (const_int 0)))])]
9605
  ""
9606
  "
9607
{
9608
  if (TARGET_SHMEDIA)
9609
    {
9610
      rtx tmp, reg;
9611
 
9612
      reg = operands[0];
9613
      if (GET_MODE (operands[0]) != SImode)
9614
        reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9615
                             : gen_reg_rtx (SImode);
9616
      if (! TARGET_SHMEDIA_FPU
9617
          && GET_MODE (sh_compare_op0) != DImode
9618
          && GET_MODE (sh_compare_op0) != SImode)
9619
        FAIL;
9620
 
9621
      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9622
      if (sh_compare_op1 != const0_rtx)
9623
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9624
                                    ? GET_MODE (sh_compare_op0)
9625
                                    : GET_MODE (sh_compare_op1),
9626
                                    sh_compare_op1);
9627
 
9628
      tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9629
 
9630
      emit_insn (gen_seq (tmp));
9631
      emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9632
      if (GET_MODE (operands[0]) == DImode)
9633
        emit_insn (gen_extendsidi2 (operands[0], reg));
9634
 
9635
      DONE;
9636
    }
9637
 
9638
  if (sh_expand_t_scc (NE, operands[0]))
9639
    DONE;
9640
  if (! currently_expanding_to_rtl)
9641
    FAIL;
9642
  operands[1] = prepare_scc_operands (EQ);
9643
  operands[2] = gen_reg_rtx (SImode);
9644
}")
9645
 
9646
(define_expand "sunordered"
9647
  [(set (match_operand:SI 0 "arith_reg_operand" "")
9648
        (unordered:SI (match_dup 1) (match_dup 2)))]
9649
  "TARGET_SHMEDIA_FPU"
9650
  "
9651
{
9652
  operands[1] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9653
  operands[2] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
9654
}")
9655
 
9656
;; Use the same trick for FP sle / sge
9657
 
9658
;; Apart from the constant use and the T setting, this is like movt,
9659
;; except that it uses the logically negated value of T, i.e.
9660
;; operand[0] := T ? 0 : 1.
9661
(define_expand "movnegt"
9662
  [(set (match_dup 2) (const_int -1))
9663
   (parallel [(set (match_operand 0 "" "")
9664
                   (neg:SI (plus:SI (match_dup 1)
9665
                                    (match_dup 2))))
9666
              (set (reg:SI T_REG)
9667
                   (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2))
9668
                          (const_int 0)))])]
9669
  "TARGET_SH1"
9670
  "operands[2] = gen_reg_rtx (SImode);")
9671
 
9672
;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
9673
;; This prevents a regression that occurred when we switched from xor to
9674
;; mov/neg for sne.
9675
 
9676
(define_split
9677
  [(set (match_operand:SI 0 "arith_reg_dest" "")
9678
        (plus:SI (reg:SI T_REG)
9679
                 (const_int -1)))]
9680
  "TARGET_SH1"
9681
  [(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1)))
9682
   (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
9683
  "")
9684
 
9685
;; -------------------------------------------------------------------------
9686
;; Instructions to cope with inline literal tables
9687
;; -------------------------------------------------------------------------
9688
 
9689
; 2 byte integer in line
9690
 
9691
(define_insn "consttable_2"
9692
 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9693
                    (match_operand 1 "" "")]
9694
                   UNSPECV_CONST2)]
9695
 ""
9696
 "*
9697
{
9698
  if (operands[1] != const0_rtx)
9699
    assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
9700
  return \"\";
9701
}"
9702
 [(set_attr "length" "2")
9703
 (set_attr "in_delay_slot" "no")])
9704
 
9705
; 4 byte integer in line
9706
 
9707
(define_insn "consttable_4"
9708
 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9709
                    (match_operand 1 "" "")]
9710
                   UNSPECV_CONST4)]
9711
 ""
9712
 "*
9713
{
9714
  if (operands[1] != const0_rtx)
9715
    assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
9716
  return \"\";
9717
}"
9718
 [(set_attr "length" "4")
9719
  (set_attr "in_delay_slot" "no")])
9720
 
9721
; 8 byte integer in line
9722
 
9723
(define_insn "consttable_8"
9724
 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9725
                    (match_operand 1 "" "")]
9726
                   UNSPECV_CONST8)]
9727
 ""
9728
 "*
9729
{
9730
  if (operands[1] != const0_rtx)
9731
    assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
9732
  return \"\";
9733
}"
9734
 [(set_attr "length" "8")
9735
  (set_attr "in_delay_slot" "no")])
9736
 
9737
; 4 byte floating point
9738
 
9739
(define_insn "consttable_sf"
9740
 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
9741
                    (match_operand 1 "" "")]
9742
                   UNSPECV_CONST4)]
9743
 ""
9744
 "*
9745
{
9746
  if (operands[1] != const0_rtx)
9747
    {
9748
      REAL_VALUE_TYPE d;
9749
      REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9750
      assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
9751
    }
9752
  return \"\";
9753
}"
9754
 [(set_attr "length" "4")
9755
  (set_attr "in_delay_slot" "no")])
9756
 
9757
; 8 byte floating point
9758
 
9759
(define_insn "consttable_df"
9760
 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
9761
                    (match_operand 1 "" "")]
9762
                   UNSPECV_CONST8)]
9763
 ""
9764
 "*
9765
{
9766
  if (operands[1] != const0_rtx)
9767
    {
9768
      REAL_VALUE_TYPE d;
9769
      REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9770
      assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
9771
    }
9772
  return \"\";
9773
}"
9774
 [(set_attr "length" "8")
9775
  (set_attr "in_delay_slot" "no")])
9776
 
9777
;; Alignment is needed for some constant tables; it may also be added for
9778
;; Instructions at the start of loops, or after unconditional branches.
9779
;; ??? We would get more accurate lengths if we did instruction
9780
;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
9781
;; here is too conservative.
9782
 
9783
; align to a two byte boundary
9784
 
9785
(define_expand "align_2"
9786
 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
9787
 ""
9788
 "")
9789
 
9790
; align to a four byte boundary
9791
;; align_4 and align_log are instructions for the starts of loops, or
9792
;; after unconditional branches, which may take up extra room.
9793
 
9794
(define_expand "align_4"
9795
 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
9796
 ""
9797
 "")
9798
 
9799
; align to a cache line boundary
9800
 
9801
(define_insn "align_log"
9802
 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
9803
 ""
9804
 ""
9805
 [(set_attr "length" "0")
9806
  (set_attr "in_delay_slot" "no")])
9807
 
9808
; emitted at the end of the literal table, used to emit the
9809
; 32bit branch labels if needed.
9810
 
9811
(define_insn "consttable_end"
9812
  [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
9813
  ""
9814
  "* return output_jump_label_table ();"
9815
  [(set_attr "in_delay_slot" "no")])
9816
 
9817
; emitted at the end of the window in the literal table.
9818
 
9819
(define_insn "consttable_window_end"
9820
  [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
9821
  ""
9822
  ""
9823
  [(set_attr "length" "0")
9824
   (set_attr "in_delay_slot" "no")])
9825
 
9826
;; -------------------------------------------------------------------------
9827
;; Misc
9828
;; -------------------------------------------------------------------------
9829
 
9830
;; String/block move insn.
9831
 
9832
(define_expand "movmemsi"
9833
  [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
9834
                   (mem:BLK (match_operand:BLK 1 "" "")))
9835
              (use (match_operand:SI 2 "nonmemory_operand" ""))
9836
              (use (match_operand:SI 3 "immediate_operand" ""))
9837
              (clobber (reg:SI PR_REG))
9838
              (clobber (reg:SI R4_REG))
9839
              (clobber (reg:SI R5_REG))
9840
              (clobber (reg:SI R0_REG))])]
9841
  "TARGET_SH1 && ! TARGET_SH5"
9842
  "
9843
{
9844
  if(expand_block_move (operands))
9845
     DONE;
9846
  else FAIL;
9847
}")
9848
 
9849
(define_insn "block_move_real"
9850
  [(parallel [(set (mem:BLK (reg:SI R4_REG))
9851
                   (mem:BLK (reg:SI R5_REG)))
9852
              (use (match_operand:SI 0 "arith_reg_operand" "r"))
9853
              (clobber (reg:SI PR_REG))
9854
              (clobber (reg:SI R0_REG))])]
9855
  "TARGET_SH1 && ! TARGET_HARD_SH4"
9856
  "jsr  @%0%#"
9857
  [(set_attr "type" "sfunc")
9858
   (set_attr "needs_delay_slot" "yes")])
9859
 
9860
(define_insn "block_lump_real"
9861
  [(parallel [(set (mem:BLK (reg:SI R4_REG))
9862
                   (mem:BLK (reg:SI R5_REG)))
9863
              (use (match_operand:SI 0 "arith_reg_operand" "r"))
9864
              (use (reg:SI R6_REG))
9865
              (clobber (reg:SI PR_REG))
9866
              (clobber (reg:SI T_REG))
9867
              (clobber (reg:SI R4_REG))
9868
              (clobber (reg:SI R5_REG))
9869
              (clobber (reg:SI R6_REG))
9870
              (clobber (reg:SI R0_REG))])]
9871
  "TARGET_SH1 && ! TARGET_HARD_SH4"
9872
  "jsr  @%0%#"
9873
  [(set_attr "type" "sfunc")
9874
   (set_attr "needs_delay_slot" "yes")])
9875
 
9876
(define_insn "block_move_real_i4"
9877
  [(parallel [(set (mem:BLK (reg:SI R4_REG))
9878
                   (mem:BLK (reg:SI R5_REG)))
9879
              (use (match_operand:SI 0 "arith_reg_operand" "r"))
9880
              (clobber (reg:SI PR_REG))
9881
              (clobber (reg:SI R0_REG))
9882
              (clobber (reg:SI R1_REG))
9883
              (clobber (reg:SI R2_REG))])]
9884
  "TARGET_HARD_SH4"
9885
  "jsr  @%0%#"
9886
  [(set_attr "type" "sfunc")
9887
   (set_attr "needs_delay_slot" "yes")])
9888
 
9889
(define_insn "block_lump_real_i4"
9890
  [(parallel [(set (mem:BLK (reg:SI R4_REG))
9891
                   (mem:BLK (reg:SI R5_REG)))
9892
              (use (match_operand:SI 0 "arith_reg_operand" "r"))
9893
              (use (reg:SI R6_REG))
9894
              (clobber (reg:SI PR_REG))
9895
              (clobber (reg:SI T_REG))
9896
              (clobber (reg:SI R4_REG))
9897
              (clobber (reg:SI R5_REG))
9898
              (clobber (reg:SI R6_REG))
9899
              (clobber (reg:SI R0_REG))
9900
              (clobber (reg:SI R1_REG))
9901
              (clobber (reg:SI R2_REG))
9902
              (clobber (reg:SI R3_REG))])]
9903
  "TARGET_HARD_SH4"
9904
  "jsr  @%0%#"
9905
  [(set_attr "type" "sfunc")
9906
   (set_attr "needs_delay_slot" "yes")])
9907
 
9908
;; -------------------------------------------------------------------------
9909
;; Floating point instructions.
9910
;; -------------------------------------------------------------------------
9911
 
9912
;; ??? All patterns should have a type attribute.
9913
 
9914
(define_expand "movpsi"
9915
  [(set (match_operand:PSI 0 "register_operand" "")
9916
        (match_operand:PSI 1 "general_movsrc_operand" ""))]
9917
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9918
  "")
9919
 
9920
;; The c / m alternative is a fake to guide reload to load directly into
9921
;; fpscr, since reload doesn't know how to use post-increment.
9922
;; GO_IF_LEGITIMATE_ADDRESS guards about bogus addresses before reload,
9923
;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
9924
;; predicate after reload.
9925
;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
9926
;; like a mac -> gpr move.
9927
(define_insn "fpu_switch"
9928
  [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
9929
        (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
9930
  "TARGET_SH2E
9931
   && (! reload_completed
9932
       || true_regnum (operands[0]) != FPSCR_REG
9933
       || GET_CODE (operands[1]) != MEM
9934
       || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
9935
  "@
9936
        ! precision stays the same
9937
        lds.l   %1,fpscr
9938
        mov.l   %1,%0
9939
        #
9940
        lds     %1,fpscr
9941
        mov     %1,%0
9942
        mov.l   %1,%0
9943
        sts     fpscr,%0
9944
        sts.l   fpscr,%0"
9945
  [(set_attr "length" "0,2,2,4,2,2,2,2,2")
9946
   (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,store")])
9947
 
9948
(define_peephole2
9949
  [(set (reg:PSI FPSCR_REG)
9950
        (mem:PSI (match_operand:SI 0 "register_operand" "")))]
9951
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
9952
  [(const_int 0)]
9953
{
9954
  rtx fpscr, mem, new_insn;
9955
 
9956
  fpscr = SET_DEST (PATTERN (curr_insn));
9957
  mem = SET_SRC (PATTERN (curr_insn));
9958
  mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
9959
 
9960
  new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
9961
  REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
9962
  DONE;
9963
})
9964
 
9965
(define_split
9966
  [(set (reg:PSI FPSCR_REG)
9967
        (mem:PSI (match_operand:SI 0 "register_operand" "")))]
9968
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
9969
   && (flag_peephole2 ? flow2_completed : reload_completed)"
9970
  [(const_int 0)]
9971
{
9972
  rtx fpscr, mem, new_insn;
9973
 
9974
  fpscr = SET_DEST (PATTERN (curr_insn));
9975
  mem = SET_SRC (PATTERN (curr_insn));
9976
  mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
9977
 
9978
  new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
9979
  REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
9980
 
9981
  if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
9982
    emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
9983
  DONE;
9984
})
9985
 
9986
;; ??? This uses the fp unit, but has no type indicating that.
9987
;; If we did that, this would either give a bogus latency or introduce
9988
;; a bogus FIFO constraint.
9989
;; Since this insn is currently only used for prologues/epilogues,
9990
;; it is probably best to claim no function unit, which matches the
9991
;; current setting.
9992
(define_insn "toggle_sz"
9993
  [(set (reg:PSI FPSCR_REG)
9994
        (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
9995
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9996
  "fschg"
9997
  [(set_attr "type" "fp") (set_attr "fp_set" "unknown")])
9998
 
9999
;; There's no way we can use it today, since optimize mode switching
10000
;; doesn't enable us to know from which mode we're switching to the
10001
;; mode it requests, to tell whether we can use a relative mode switch
10002
;; (like toggle_pr) or an absolute switch (like loading fpscr from
10003
;; memory).
10004
(define_insn "toggle_pr"
10005
  [(set (reg:PSI FPSCR_REG)
10006
        (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
10007
  "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
10008
  "fpchg"
10009
  [(set_attr "type" "fp")])
10010
 
10011
(define_expand "addsf3"
10012
  [(set (match_operand:SF 0 "arith_reg_operand" "")
10013
        (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
10014
                 (match_operand:SF 2 "arith_reg_operand" "")))]
10015
  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10016
  "
10017
{
10018
  if (TARGET_SH2E)
10019
    {
10020
      expand_sf_binop (&gen_addsf3_i, operands);
10021
      DONE;
10022
    }
10023
}")
10024
 
10025
(define_insn "*addsf3_media"
10026
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10027
        (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10028
                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10029
  "TARGET_SHMEDIA_FPU"
10030
  "fadd.s       %1, %2, %0"
10031
  [(set_attr "type" "fparith_media")])
10032
 
10033
(define_insn_and_split "unary_sf_op"
10034
  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10035
        (vec_select:V2SF
10036
         (vec_concat:V2SF
10037
          (vec_select:SF
10038
           (match_dup 0)
10039
           (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
10040
          (match_operator:SF 2 "unary_float_operator"
10041
            [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10042
                            (parallel [(match_operand 4
10043
                                        "const_int_operand" "n")]))]))
10044
         (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
10045
  "TARGET_SHMEDIA_FPU"
10046
  "#"
10047
  "TARGET_SHMEDIA_FPU && reload_completed"
10048
  [(set (match_dup 5) (match_dup 6))]
10049
  "
10050
{
10051
  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10052
  rtx op1 = gen_rtx_REG (SFmode,
10053
                         (true_regnum (operands[1])
10054
                          + (INTVAL (operands[4]) ^ endian)));
10055
 
10056
  operands[7] = gen_rtx_REG (SFmode,
10057
                             (true_regnum (operands[0])
10058
                              + (INTVAL (operands[3]) ^ endian)));
10059
  operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
10060
}"
10061
  [(set_attr "type" "fparith_media")])
10062
 
10063
(define_insn_and_split "binary_sf_op"
10064
  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10065
        (vec_select:V2SF
10066
         (vec_concat:V2SF
10067
          (vec_select:SF
10068
           (match_dup 0)
10069
           (parallel [(match_operand 7 "const_int_operand" "n")]))
10070
          (match_operator:SF 3 "binary_float_operator"
10071
            [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10072
                            (parallel [(match_operand 5
10073
                                        "const_int_operand" "n")]))
10074
             (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
10075
                            (parallel [(match_operand 6
10076
                                        "const_int_operand" "n")]))]))
10077
         (parallel [(match_dup 7) (match_operand 4 "const_int_operand" "n")])))]
10078
  "TARGET_SHMEDIA_FPU && INTVAL (operands[4]) != INTVAL (operands[7])"
10079
  "#"
10080
  "&& reload_completed"
10081
  [(set (match_dup 8) (match_dup 9))]
10082
  "
10083
{
10084
  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10085
  rtx op1 = gen_rtx_REG (SFmode,
10086
                         (true_regnum (operands[1])
10087
                          + (INTVAL (operands[5]) ^ endian)));
10088
  rtx op2 = gen_rtx_REG (SFmode,
10089
                         (true_regnum (operands[2])
10090
                          + (INTVAL (operands[6]) ^ endian)));
10091
 
10092
  operands[8] = gen_rtx_REG (SFmode,
10093
                             (true_regnum (operands[0])
10094
                              + (INTVAL (operands[4]) ^ endian)));
10095
  operands[9] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
10096
}"
10097
  [(set_attr "type" "fparith_media")])
10098
 
10099
(define_insn "addsf3_i"
10100
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10101
        (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10102
                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10103
   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10104
  "TARGET_SH2E"
10105
  "fadd %2,%0"
10106
  [(set_attr "type" "fp")
10107
   (set_attr "fp_mode" "single")])
10108
 
10109
(define_expand "subsf3"
10110
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10111
        (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10112
                  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
10113
  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10114
  "
10115
{
10116
  if (TARGET_SH2E)
10117
    {
10118
      expand_sf_binop (&gen_subsf3_i, operands);
10119
      DONE;
10120
    }
10121
}")
10122
 
10123
(define_insn "*subsf3_media"
10124
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10125
        (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10126
                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10127
  "TARGET_SHMEDIA_FPU"
10128
  "fsub.s       %1, %2, %0"
10129
  [(set_attr "type" "fparith_media")])
10130
 
10131
(define_insn "subsf3_i"
10132
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10133
        (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
10134
                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10135
   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10136
  "TARGET_SH2E"
10137
  "fsub %2,%0"
10138
  [(set_attr "type" "fp")
10139
   (set_attr "fp_mode" "single")])
10140
 
10141
;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
10142
;; register in feeding fp instructions.  Thus, we cannot generate fmac for
10143
;; mixed-precision SH4 targets.  To allow it to be still generated for the
10144
;; SH3E, we use a separate insn for SH3E mulsf3.
10145
 
10146
(define_expand "mulsf3"
10147
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10148
        (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10149
                 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
10150
  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10151
  "
10152
{
10153
  if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10154
    expand_sf_binop (&gen_mulsf3_i4, operands);
10155
  else if (TARGET_SH2E)
10156
    emit_insn (gen_mulsf3_ie (operands[0], operands[1], operands[2]));
10157
  if (! TARGET_SHMEDIA)
10158
    DONE;
10159
}")
10160
 
10161
(define_insn "*mulsf3_media"
10162
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10163
        (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10164
                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10165
  "TARGET_SHMEDIA_FPU"
10166
  "fmul.s       %1, %2, %0"
10167
  [(set_attr "type" "fparith_media")])
10168
 
10169
(define_insn "mulsf3_i4"
10170
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10171
        (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10172
                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10173
   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10174
  "TARGET_SH2E"
10175
  "fmul %2,%0"
10176
  [(set_attr "type" "fp")
10177
   (set_attr "fp_mode" "single")])
10178
 
10179
(define_insn "mulsf3_ie"
10180
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10181
        (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10182
                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10183
  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10184
  "fmul %2,%0"
10185
  [(set_attr "type" "fp")])
10186
 
10187
(define_insn "mac_media"
10188
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10189
        (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10190
                          (match_operand:SF 2 "fp_arith_reg_operand" "f"))
10191
                 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
10192
  "TARGET_SHMEDIA_FPU"
10193
  "fmac.s %1, %2, %0"
10194
  [(set_attr "type" "fparith_media")])
10195
 
10196
(define_insn "*macsf3"
10197
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10198
        (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
10199
                          (match_operand:SF 2 "fp_arith_reg_operand" "f"))
10200
                 (match_operand:SF 3 "arith_reg_operand" "0")))
10201
   (use (match_operand:PSI 4 "fpscr_operand" "c"))]
10202
  "TARGET_SH2E && ! TARGET_SH4"
10203
  "fmac fr0,%2,%0"
10204
  [(set_attr "type" "fp")
10205
   (set_attr "fp_mode" "single")])
10206
 
10207
(define_expand "divsf3"
10208
  [(set (match_operand:SF 0 "arith_reg_operand" "")
10209
        (div:SF (match_operand:SF 1 "arith_reg_operand" "")
10210
                (match_operand:SF 2 "arith_reg_operand" "")))]
10211
  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10212
  "
10213
{
10214
  if (TARGET_SH2E)
10215
    {
10216
      expand_sf_binop (&gen_divsf3_i, operands);
10217
      DONE;
10218
    }
10219
}")
10220
 
10221
(define_insn "*divsf3_media"
10222
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10223
        (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10224
                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10225
  "TARGET_SHMEDIA_FPU"
10226
  "fdiv.s       %1, %2, %0"
10227
  [(set_attr "type" "fdiv_media")])
10228
 
10229
(define_insn "divsf3_i"
10230
  [(set (match_operand:SF 0 "arith_reg_dest" "=f")
10231
        (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
10232
                 (match_operand:SF 2 "arith_reg_operand" "f")))
10233
   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10234
  "TARGET_SH2E"
10235
  "fdiv %2,%0"
10236
  [(set_attr "type" "fdiv")
10237
   (set_attr "fp_mode" "single")])
10238
 
10239
(define_insn "floatdisf2"
10240
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10241
        (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10242
  "TARGET_SHMEDIA_FPU"
10243
  "float.qs %1, %0"
10244
  [(set_attr "type" "fpconv_media")])
10245
 
10246
(define_expand "floatsisf2"
10247
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10248
        (float:SF (match_operand:SI 1 "fpul_operand" "")))]
10249
  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10250
  "
10251
{
10252
  if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10253
    {
10254
      emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10255
      DONE;
10256
    }
10257
}")
10258
 
10259
(define_insn "*floatsisf2_media"
10260
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10261
        (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10262
  "TARGET_SHMEDIA_FPU"
10263
  "float.ls     %1, %0"
10264
  [(set_attr "type" "fpconv_media")])
10265
 
10266
(define_insn "floatsisf2_i4"
10267
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10268
        (float:SF (match_operand:SI 1 "fpul_operand" "y")))
10269
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10270
  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10271
  "float        %1,%0"
10272
  [(set_attr "type" "fp")
10273
   (set_attr "fp_mode" "single")])
10274
 
10275
(define_insn "*floatsisf2_ie"
10276
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10277
        (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
10278
  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10279
  "float        %1,%0"
10280
  [(set_attr "type" "fp")])
10281
 
10282
(define_insn "fix_truncsfdi2"
10283
  [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10284
        (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10285
  "TARGET_SHMEDIA_FPU"
10286
  "ftrc.sq %1, %0"
10287
  [(set_attr "type" "fpconv_media")])
10288
 
10289
(define_expand "fix_truncsfsi2"
10290
  [(set (match_operand:SI 0 "fpul_operand" "=y")
10291
        (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10292
  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10293
  "
10294
{
10295
  if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10296
    {
10297
      emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10298
      DONE;
10299
    }
10300
}")
10301
 
10302
(define_insn "*fix_truncsfsi2_media"
10303
  [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10304
        (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10305
  "TARGET_SHMEDIA_FPU"
10306
  "ftrc.sl      %1, %0"
10307
  [(set_attr "type" "fpconv_media")])
10308
 
10309
(define_insn "fix_truncsfsi2_i4"
10310
  [(set (match_operand:SI 0 "fpul_operand" "=y")
10311
        (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10312
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10313
  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10314
  "ftrc %1,%0"
10315
  [(set_attr "type" "ftrc_s")
10316
   (set_attr "fp_mode" "single")])
10317
 
10318
;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
10319
;; fix_truncsfsi2_i4.
10320
;; (define_insn "fix_truncsfsi2_i4_2"
10321
;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10322
;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10323
;;   (use (reg:PSI FPSCR_REG))
10324
;;   (clobber (reg:SI FPUL_REG))]
10325
;;  "TARGET_SH4"
10326
;;  "#"
10327
;;  [(set_attr "length" "4")
10328
;;   (set_attr "fp_mode" "single")])
10329
 
10330
;;(define_split
10331
;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10332
;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10333
;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
10334
;;   (clobber (reg:SI FPUL_REG))]
10335
;;  "TARGET_SH4"
10336
;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10337
;;            (use (match_dup 2))])
10338
;;   (set (match_dup 0) (reg:SI FPUL_REG))])
10339
 
10340
(define_insn "*fixsfsi"
10341
  [(set (match_operand:SI 0 "fpul_operand" "=y")
10342
        (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10343
  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10344
  "ftrc %1,%0"
10345
  [(set_attr "type" "fp")])
10346
 
10347
(define_insn "cmpgtsf_t"
10348
  [(set (reg:SI T_REG)
10349
        (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10350
               (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10351
  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10352
  "fcmp/gt      %1,%0"
10353
  [(set_attr "type" "fp")
10354
   (set_attr "fp_mode" "single")])
10355
 
10356
(define_insn "cmpeqsf_t"
10357
  [(set (reg:SI T_REG)
10358
        (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10359
               (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10360
  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10361
  "fcmp/eq      %1,%0"
10362
  [(set_attr "type" "fp")
10363
   (set_attr "fp_mode" "single")])
10364
 
10365
(define_insn "ieee_ccmpeqsf_t"
10366
  [(set (reg:SI T_REG)
10367
        (ior:SI (reg:SI T_REG)
10368
                (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10369
                       (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
10370
  "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10371
  "* return output_ieee_ccmpeq (insn, operands);"
10372
  [(set_attr "length" "4")])
10373
 
10374
 
10375
(define_insn "cmpgtsf_t_i4"
10376
  [(set (reg:SI T_REG)
10377
        (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10378
               (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10379
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10380
  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10381
  "fcmp/gt      %1,%0"
10382
  [(set_attr "type" "fp")
10383
   (set_attr "fp_mode" "single")])
10384
 
10385
(define_insn "cmpeqsf_t_i4"
10386
  [(set (reg:SI T_REG)
10387
        (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10388
               (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10389
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10390
  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10391
  "fcmp/eq      %1,%0"
10392
  [(set_attr "type" "fp")
10393
   (set_attr "fp_mode" "single")])
10394
 
10395
(define_insn "*ieee_ccmpeqsf_t_4"
10396
  [(set (reg:SI T_REG)
10397
        (ior:SI (reg:SI T_REG)
10398
                (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10399
                       (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
10400
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10401
  "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10402
  "* return output_ieee_ccmpeq (insn, operands);"
10403
  [(set_attr "length" "4")
10404
   (set_attr "fp_mode" "single")])
10405
 
10406
(define_insn "cmpeqsf_media"
10407
  [(set (match_operand:SI 0 "register_operand" "=r")
10408
        (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10409
               (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10410
  "TARGET_SHMEDIA_FPU"
10411
  "fcmpeq.s     %1, %2, %0"
10412
  [(set_attr "type" "fcmp_media")])
10413
 
10414
(define_insn "cmpgtsf_media"
10415
  [(set (match_operand:SI 0 "register_operand" "=r")
10416
        (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10417
               (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10418
  "TARGET_SHMEDIA_FPU"
10419
  "fcmpgt.s     %1, %2, %0"
10420
  [(set_attr "type" "fcmp_media")])
10421
 
10422
(define_insn "cmpgesf_media"
10423
  [(set (match_operand:SI 0 "register_operand" "=r")
10424
        (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10425
               (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10426
  "TARGET_SHMEDIA_FPU"
10427
  "fcmpge.s     %1, %2, %0"
10428
  [(set_attr "type" "fcmp_media")])
10429
 
10430
(define_insn "cmpunsf_media"
10431
  [(set (match_operand:SI 0 "register_operand" "=r")
10432
        (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10433
                      (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10434
  "TARGET_SHMEDIA_FPU"
10435
  "fcmpun.s     %1, %2, %0"
10436
  [(set_attr "type" "fcmp_media")])
10437
 
10438
(define_expand "cmpsf"
10439
  [(set (reg:SI T_REG)
10440
        (compare (match_operand:SF 0 "arith_operand" "")
10441
                 (match_operand:SF 1 "arith_operand" "")))]
10442
  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10443
  "
10444
{
10445
  sh_compare_op0 = operands[0];
10446
  sh_compare_op1 = operands[1];
10447
  DONE;
10448
}")
10449
 
10450
(define_expand "negsf2"
10451
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10452
        (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10453
  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10454
  "
10455
{
10456
  if (TARGET_SH2E)
10457
    {
10458
      expand_sf_unop (&gen_negsf2_i, operands);
10459
      DONE;
10460
    }
10461
}")
10462
 
10463
(define_insn "*negsf2_media"
10464
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10465
        (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10466
  "TARGET_SHMEDIA_FPU"
10467
  "fneg.s       %1, %0"
10468
  [(set_attr "type" "fmove_media")])
10469
 
10470
(define_insn "negsf2_i"
10471
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10472
        (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10473
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10474
  "TARGET_SH2E"
10475
  "fneg %0"
10476
  [(set_attr "type" "fmove")
10477
   (set_attr "fp_mode" "single")])
10478
 
10479
(define_expand "sqrtsf2"
10480
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10481
        (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10482
  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
10483
  "
10484
{
10485
  if (TARGET_SH3E)
10486
    {
10487
      expand_sf_unop (&gen_sqrtsf2_i, operands);
10488
      DONE;
10489
    }
10490
}")
10491
 
10492
(define_insn "*sqrtsf2_media"
10493
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10494
        (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10495
  "TARGET_SHMEDIA_FPU"
10496
  "fsqrt.s      %1, %0"
10497
  [(set_attr "type" "fdiv_media")])
10498
 
10499
(define_insn "sqrtsf2_i"
10500
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10501
        (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10502
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10503
  "TARGET_SH3E"
10504
  "fsqrt        %0"
10505
  [(set_attr "type" "fdiv")
10506
   (set_attr "fp_mode" "single")])
10507
 
10508
(define_insn "rsqrtsf2"
10509
  [(set (match_operand:SF 0 "register_operand" "=f")
10510
        (div:SF (match_operand:SF 1 "immediate_operand" "i")
10511
                (sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
10512
   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10513
  "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10514
   && operands[1] == CONST1_RTX (SFmode)"
10515
  "fsrra        %0"
10516
  [(set_attr "type" "fsrra")
10517
   (set_attr "fp_mode" "single")])
10518
 
10519
(define_insn "fsca"
10520
  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10521
        (vec_concat:V2SF
10522
         (unspec:SF [(mult:SF
10523
                      (float:SF (match_operand:SI 1 "fpul_operand" "y"))
10524
                      (match_operand:SF 2 "immediate_operand" "i"))
10525
                    ] UNSPEC_FSINA)
10526
         (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
10527
                    ] UNSPEC_FCOSA)))
10528
   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10529
  "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10530
   && operands[2] == sh_fsca_int2sf ()"
10531
  "fsca fpul,%d0"
10532
  [(set_attr "type" "fsca")
10533
   (set_attr "fp_mode" "single")])
10534
 
10535
(define_expand "sinsf2"
10536
  [(set (match_operand:SF 0 "nonimmediate_operand" "")
10537
        (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10538
                   UNSPEC_FSINA))]
10539
  "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10540
  "
10541
{
10542
  rtx scaled = gen_reg_rtx (SFmode);
10543
  rtx truncated = gen_reg_rtx (SImode);
10544
  rtx fsca = gen_reg_rtx (V2SFmode);
10545
  rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10546
 
10547
  emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10548
  emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10549
  emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10550
                          get_fpscr_rtx ()));
10551
  emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 0));
10552
  DONE;
10553
}")
10554
 
10555
(define_expand "cossf2"
10556
  [(set (match_operand:SF 0 "nonimmediate_operand" "")
10557
        (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10558
                   UNSPEC_FCOSA))]
10559
  "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10560
  "
10561
{
10562
  rtx scaled = gen_reg_rtx (SFmode);
10563
  rtx truncated = gen_reg_rtx (SImode);
10564
  rtx fsca = gen_reg_rtx (V2SFmode);
10565
  rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10566
 
10567
  emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10568
  emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10569
  emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10570
                          get_fpscr_rtx ()));
10571
  emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
10572
  DONE;
10573
}")
10574
 
10575
(define_expand "sindf2"
10576
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10577
        (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10578
                   UNSPEC_FSINA))]
10579
  "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10580
  "
10581
{
10582
  rtx scaled = gen_reg_rtx (DFmode);
10583
  rtx truncated = gen_reg_rtx (SImode);
10584
  rtx fsca = gen_reg_rtx (V2SFmode);
10585
  rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10586
  rtx sfresult = gen_reg_rtx (SFmode);
10587
 
10588
  emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10589
  emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10590
  emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10591
                          get_fpscr_rtx ()));
10592
  emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 0));
10593
  emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10594
  DONE;
10595
}")
10596
 
10597
(define_expand "cosdf2"
10598
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10599
        (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10600
                   UNSPEC_FCOSA))]
10601
  "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10602
  "
10603
{
10604
  rtx scaled = gen_reg_rtx (DFmode);
10605
  rtx truncated = gen_reg_rtx (SImode);
10606
  rtx fsca = gen_reg_rtx (V2SFmode);
10607
  rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10608
  rtx sfresult = gen_reg_rtx (SFmode);
10609
 
10610
  emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10611
  emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10612
  emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10613
                          get_fpscr_rtx ()));
10614
  emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 4));
10615
  emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10616
  DONE;
10617
}")
10618
 
10619
(define_expand "abssf2"
10620
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10621
        (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10622
  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10623
  "
10624
{
10625
  if (TARGET_SH2E)
10626
    {
10627
      expand_sf_unop (&gen_abssf2_i, operands);
10628
      DONE;
10629
    }
10630
}")
10631
 
10632
(define_insn "*abssf2_media"
10633
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10634
        (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10635
  "TARGET_SHMEDIA_FPU"
10636
  "fabs.s       %1, %0"
10637
  [(set_attr "type" "fmove_media")])
10638
 
10639
(define_insn "abssf2_i"
10640
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10641
        (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10642
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10643
  "TARGET_SH2E"
10644
  "fabs %0"
10645
  [(set_attr "type" "fmove")
10646
   (set_attr "fp_mode" "single")])
10647
 
10648
(define_expand "adddf3"
10649
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10650
        (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10651
                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10652
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10653
  "
10654
{
10655
  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10656
    {
10657
      expand_df_binop (&gen_adddf3_i, operands);
10658
      DONE;
10659
    }
10660
}")
10661
 
10662
(define_insn "*adddf3_media"
10663
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10664
        (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10665
                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10666
  "TARGET_SHMEDIA_FPU"
10667
  "fadd.d       %1, %2, %0"
10668
  [(set_attr "type" "dfparith_media")])
10669
 
10670
(define_insn "adddf3_i"
10671
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10672
        (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10673
                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10674
   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10675
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10676
  "fadd %2,%0"
10677
  [(set_attr "type" "dfp_arith")
10678
   (set_attr "fp_mode" "double")])
10679
 
10680
(define_expand "subdf3"
10681
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10682
        (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10683
                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10684
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10685
  "
10686
{
10687
  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10688
    {
10689
      expand_df_binop (&gen_subdf3_i, operands);
10690
      DONE;
10691
    }
10692
}")
10693
 
10694
(define_insn "*subdf3_media"
10695
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10696
        (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10697
                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10698
  "TARGET_SHMEDIA_FPU"
10699
  "fsub.d       %1, %2, %0"
10700
  [(set_attr "type" "dfparith_media")])
10701
 
10702
(define_insn "subdf3_i"
10703
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10704
        (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10705
                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10706
   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10707
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10708
  "fsub %2,%0"
10709
  [(set_attr "type" "dfp_arith")
10710
   (set_attr "fp_mode" "double")])
10711
 
10712
(define_expand "muldf3"
10713
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10714
        (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10715
                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10716
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10717
  "
10718
{
10719
  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10720
    {
10721
      expand_df_binop (&gen_muldf3_i, operands);
10722
      DONE;
10723
    }
10724
}")
10725
 
10726
(define_insn "*muldf3_media"
10727
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10728
        (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10729
                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10730
  "TARGET_SHMEDIA_FPU"
10731
  "fmul.d       %1, %2, %0"
10732
  [(set_attr "type" "dfmul_media")])
10733
 
10734
(define_insn "muldf3_i"
10735
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10736
        (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10737
                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10738
   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10739
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10740
  "fmul %2,%0"
10741
  [(set_attr "type" "dfp_arith")
10742
   (set_attr "fp_mode" "double")])
10743
 
10744
(define_expand "divdf3"
10745
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10746
        (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10747
                (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10748
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10749
  "
10750
{
10751
  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10752
    {
10753
      expand_df_binop (&gen_divdf3_i, operands);
10754
      DONE;
10755
    }
10756
}")
10757
 
10758
(define_insn "*divdf3_media"
10759
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10760
        (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10761
                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10762
  "TARGET_SHMEDIA_FPU"
10763
  "fdiv.d       %1, %2, %0"
10764
  [(set_attr "type" "dfdiv_media")])
10765
 
10766
(define_insn "divdf3_i"
10767
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10768
        (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10769
                (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10770
   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10771
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10772
  "fdiv %2,%0"
10773
  [(set_attr "type" "dfdiv")
10774
   (set_attr "fp_mode" "double")])
10775
 
10776
(define_insn "floatdidf2"
10777
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10778
        (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10779
  "TARGET_SHMEDIA_FPU"
10780
  "float.qd     %1, %0"
10781
  [(set_attr "type" "dfpconv_media")])
10782
 
10783
(define_expand "floatsidf2"
10784
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10785
        (float:DF (match_operand:SI 1 "fpul_operand" "")))]
10786
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10787
  "
10788
{
10789
  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10790
    {
10791
      emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
10792
                                      get_fpscr_rtx ()));
10793
      DONE;
10794
    }
10795
}")
10796
 
10797
(define_insn "*floatsidf2_media"
10798
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10799
        (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10800
  "TARGET_SHMEDIA_FPU"
10801
  "float.ld     %1, %0"
10802
  [(set_attr "type" "dfpconv_media")])
10803
 
10804
(define_insn "floatsidf2_i"
10805
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10806
        (float:DF (match_operand:SI 1 "fpul_operand" "y")))
10807
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10808
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10809
  "float        %1,%0"
10810
  [(set_attr "type" "dfp_conv")
10811
   (set_attr "fp_mode" "double")])
10812
 
10813
(define_insn "fix_truncdfdi2"
10814
  [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10815
        (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10816
  "TARGET_SHMEDIA_FPU"
10817
  "ftrc.dq      %1, %0"
10818
  [(set_attr "type" "dfpconv_media")])
10819
 
10820
(define_expand "fix_truncdfsi2"
10821
  [(set (match_operand:SI 0 "fpul_operand" "")
10822
        (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
10823
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10824
  "
10825
{
10826
  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10827
    {
10828
      emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
10829
                                          get_fpscr_rtx ()));
10830
      DONE;
10831
    }
10832
}")
10833
 
10834
(define_insn "*fix_truncdfsi2_media"
10835
  [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10836
        (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10837
  "TARGET_SHMEDIA_FPU"
10838
  "ftrc.dl      %1, %0"
10839
  [(set_attr "type" "dfpconv_media")])
10840
 
10841
(define_insn "fix_truncdfsi2_i"
10842
  [(set (match_operand:SI 0 "fpul_operand" "=y")
10843
        (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
10844
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10845
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10846
  "ftrc %1,%0"
10847
  [(set_attr "type" "dfp_conv")
10848
   (set_attr "dfp_comp" "no")
10849
   (set_attr "fp_mode" "double")])
10850
 
10851
;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
10852
;; fix_truncdfsi2_i.
10853
;; (define_insn "fix_truncdfsi2_i4"
10854
;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10855
;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
10856
;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
10857
;;    (clobber (reg:SI FPUL_REG))]
10858
;;   "TARGET_SH4"
10859
;;   "#"
10860
;;   [(set_attr "length" "4")
10861
;;    (set_attr "fp_mode" "double")])
10862
;;
10863
;; (define_split
10864
;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10865
;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
10866
;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
10867
;;    (clobber (reg:SI FPUL_REG))]
10868
;;   "TARGET_SH4"
10869
;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10870
;;            (use (match_dup 2))])
10871
;;    (set (match_dup 0) (reg:SI FPUL_REG))])
10872
 
10873
(define_insn "cmpgtdf_t"
10874
  [(set (reg:SI T_REG)
10875
        (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
10876
               (match_operand:DF 1 "arith_reg_operand" "f")))
10877
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10878
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10879
  "fcmp/gt      %1,%0"
10880
  [(set_attr "type" "dfp_cmp")
10881
   (set_attr "fp_mode" "double")])
10882
 
10883
(define_insn "cmpeqdf_t"
10884
  [(set (reg:SI T_REG)
10885
        (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
10886
               (match_operand:DF 1 "arith_reg_operand" "f")))
10887
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10888
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10889
  "fcmp/eq      %1,%0"
10890
  [(set_attr "type" "dfp_cmp")
10891
   (set_attr "fp_mode" "double")])
10892
 
10893
(define_insn "*ieee_ccmpeqdf_t"
10894
  [(set (reg:SI T_REG)
10895
        (ior:SI (reg:SI T_REG)
10896
                (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
10897
                       (match_operand:DF 1 "arith_reg_operand" "f"))))
10898
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10899
  "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10900
  "* return output_ieee_ccmpeq (insn, operands);"
10901
  [(set_attr "length" "4")
10902
   (set_attr "fp_mode" "double")])
10903
 
10904
(define_insn "cmpeqdf_media"
10905
  [(set (match_operand:SI 0 "register_operand" "=r")
10906
        (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10907
               (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10908
  "TARGET_SHMEDIA_FPU"
10909
  "fcmpeq.d     %1,%2,%0"
10910
  [(set_attr "type" "fcmp_media")])
10911
 
10912
(define_insn "cmpgtdf_media"
10913
  [(set (match_operand:SI 0 "register_operand" "=r")
10914
        (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10915
               (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10916
  "TARGET_SHMEDIA_FPU"
10917
  "fcmpgt.d     %1,%2,%0"
10918
  [(set_attr "type" "fcmp_media")])
10919
 
10920
(define_insn "cmpgedf_media"
10921
  [(set (match_operand:SI 0 "register_operand" "=r")
10922
        (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10923
               (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10924
  "TARGET_SHMEDIA_FPU"
10925
  "fcmpge.d     %1,%2,%0"
10926
  [(set_attr "type" "fcmp_media")])
10927
 
10928
(define_insn "cmpundf_media"
10929
  [(set (match_operand:SI 0 "register_operand" "=r")
10930
        (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10931
                      (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10932
  "TARGET_SHMEDIA_FPU"
10933
  "fcmpun.d     %1,%2,%0"
10934
  [(set_attr "type" "fcmp_media")])
10935
 
10936
(define_expand "cmpdf"
10937
  [(set (reg:SI T_REG)
10938
        (compare (match_operand:DF 0 "arith_operand" "")
10939
                 (match_operand:DF 1 "arith_operand" "")))]
10940
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10941
  "
10942
{
10943
  sh_compare_op0 = operands[0];
10944
  sh_compare_op1 = operands[1];
10945
  DONE;
10946
}")
10947
 
10948
(define_expand "negdf2"
10949
  [(set (match_operand:DF 0 "arith_reg_operand" "")
10950
        (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
10951
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10952
  "
10953
{
10954
  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10955
    {
10956
      expand_df_unop (&gen_negdf2_i, operands);
10957
      DONE;
10958
    }
10959
}")
10960
 
10961
(define_insn "*negdf2_media"
10962
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10963
        (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10964
  "TARGET_SHMEDIA_FPU"
10965
  "fneg.d       %1, %0"
10966
  [(set_attr "type" "fmove_media")])
10967
 
10968
(define_insn "negdf2_i"
10969
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10970
        (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
10971
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10972
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10973
  "fneg %0"
10974
  [(set_attr "type" "fmove")
10975
   (set_attr "fp_mode" "double")])
10976
 
10977
(define_expand "sqrtdf2"
10978
  [(set (match_operand:DF 0 "arith_reg_operand" "")
10979
        (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
10980
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10981
  "
10982
{
10983
  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10984
    {
10985
      expand_df_unop (&gen_sqrtdf2_i, operands);
10986
      DONE;
10987
    }
10988
}")
10989
 
10990
(define_insn "*sqrtdf2_media"
10991
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10992
        (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10993
  "TARGET_SHMEDIA_FPU"
10994
  "fsqrt.d      %1, %0"
10995
  [(set_attr "type" "dfdiv_media")])
10996
 
10997
(define_insn "sqrtdf2_i"
10998
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10999
        (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11000
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11001
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11002
  "fsqrt        %0"
11003
  [(set_attr "type" "dfdiv")
11004
   (set_attr "fp_mode" "double")])
11005
 
11006
(define_expand "absdf2"
11007
  [(set (match_operand:DF 0 "arith_reg_operand" "")
11008
        (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
11009
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11010
  "
11011
{
11012
  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11013
    {
11014
      expand_df_unop (&gen_absdf2_i, operands);
11015
      DONE;
11016
    }
11017
}")
11018
 
11019
(define_insn "*absdf2_media"
11020
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11021
        (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11022
  "TARGET_SHMEDIA_FPU"
11023
  "fabs.d       %1, %0"
11024
  [(set_attr "type" "fmove_media")])
11025
 
11026
(define_insn "absdf2_i"
11027
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11028
        (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11029
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11030
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11031
  "fabs %0"
11032
  [(set_attr "type" "fmove")
11033
   (set_attr "fp_mode" "double")])
11034
 
11035
(define_expand "extendsfdf2"
11036
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
11037
        (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
11038
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11039
  "
11040
{
11041
  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11042
    {
11043
      emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
11044
                                        get_fpscr_rtx ()));
11045
      DONE;
11046
    }
11047
}")
11048
 
11049
(define_insn "*extendsfdf2_media"
11050
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11051
        (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
11052
  "TARGET_SHMEDIA_FPU"
11053
  "fcnv.sd      %1, %0"
11054
  [(set_attr "type" "dfpconv_media")])
11055
 
11056
(define_insn "extendsfdf2_i4"
11057
  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11058
        (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
11059
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11060
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11061
  "fcnvsd  %1,%0"
11062
  [(set_attr "type" "fp")
11063
   (set_attr "fp_mode" "double")])
11064
 
11065
(define_expand "truncdfsf2"
11066
  [(set (match_operand:SF 0 "fpul_operand" "")
11067
        (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
11068
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11069
  "
11070
{
11071
  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11072
    {
11073
      emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
11074
                                       get_fpscr_rtx ()));
11075
      DONE;
11076
    }
11077
}")
11078
 
11079
(define_insn "*truncdfsf2_media"
11080
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11081
        (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11082
  "TARGET_SHMEDIA_FPU"
11083
  "fcnv.ds      %1, %0"
11084
  [(set_attr "type" "dfpconv_media")])
11085
 
11086
(define_insn "truncdfsf2_i4"
11087
  [(set (match_operand:SF 0 "fpul_operand" "=y")
11088
        (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
11089
   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11090
  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11091
  "fcnvds  %1,%0"
11092
  [(set_attr "type" "fp")
11093
   (set_attr "fp_mode" "double")])
11094
 
11095
;; Bit field extract patterns.  These give better code for packed bitfields,
11096
;; because they allow auto-increment addresses to be generated.
11097
 
11098
(define_expand "insv"
11099
  [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
11100
                         (match_operand:SI 1 "immediate_operand" "")
11101
                         (match_operand:SI 2 "immediate_operand" ""))
11102
        (match_operand:SI 3 "general_operand" ""))]
11103
  "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
11104
  "
11105
{
11106
  rtx addr_target, orig_address, shift_reg, qi_val;
11107
  HOST_WIDE_INT bitsize, size, v = 0;
11108
  rtx x = operands[3];
11109
 
11110
  /* ??? expmed doesn't care for non-register predicates.  */
11111
  if (! memory_operand (operands[0], VOIDmode)
11112
      || ! immediate_operand (operands[1], VOIDmode)
11113
      || ! immediate_operand (operands[2], VOIDmode)
11114
      || ! general_operand (x, VOIDmode))
11115
    FAIL;
11116
  /* If this isn't a 16 / 24 / 32 bit field, or if
11117
     it doesn't start on a byte boundary, then fail.  */
11118
  bitsize = INTVAL (operands[1]);
11119
  if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
11120
      || (INTVAL (operands[2]) % 8) != 0)
11121
    FAIL;
11122
 
11123
  size = bitsize / 8;
11124
  orig_address = XEXP (operands[0], 0);
11125
  shift_reg = gen_reg_rtx (SImode);
11126
  if (GET_CODE (x) == CONST_INT)
11127
    {
11128
      v = INTVAL (x);
11129
      qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
11130
    }
11131
  else
11132
    {
11133
      emit_insn (gen_movsi (shift_reg, operands[3]));
11134
      qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11135
    }
11136
  addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1));
11137
 
11138
  operands[0] = replace_equiv_address (operands[0], addr_target);
11139
  emit_insn (gen_movqi (operands[0], qi_val));
11140
 
11141
  while (size -= 1)
11142
    {
11143
      if (GET_CODE (x) == CONST_INT)
11144
        qi_val
11145
          = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
11146
      else
11147
        {
11148
          emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
11149
          qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11150
        }
11151
      emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
11152
      emit_insn (gen_movqi (operands[0], qi_val));
11153
    }
11154
 
11155
  DONE;
11156
}")
11157
 
11158
(define_insn "movua"
11159
  [(set (match_operand:SI 0 "register_operand" "=z")
11160
        (sign_extract:SI (match_operand:SI 1 "unaligned_load_operand" "Sua>")
11161
                         (const_int 32) (const_int 0)))]
11162
  "TARGET_SH4A_ARCH"
11163
  "movua.l      %1,%0"
11164
  [(set_attr "type" "movua")])
11165
 
11166
;; We shouldn't need this, but cse replaces increments with references
11167
;; to other regs before flow has a chance to create post_inc
11168
;; addressing modes, and only postreload's cse_move2add brings the
11169
;; increments back to a usable form.
11170
(define_peephole2
11171
  [(set (match_operand:SI 0 "register_operand" "")
11172
        (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
11173
                         (const_int 32) (const_int 0)))
11174
   (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11175
  "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
11176
  [(set (match_operand:SI 0 "register_operand" "")
11177
        (sign_extract:SI (mem:SI (post_inc:SI
11178
                                  (match_operand:SI 1 "register_operand" "")))
11179
                         (const_int 32) (const_int 0)))]
11180
  "")
11181
 
11182
(define_expand "extv"
11183
  [(set (match_operand:SI 0 "register_operand" "")
11184
        (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11185
                         (match_operand 2 "const_int_operand" "")
11186
                         (match_operand 3 "const_int_operand" "")))]
11187
  "TARGET_SH4A_ARCH"
11188
{
11189
  if (TARGET_SH4A_ARCH
11190
      && INTVAL (operands[2]) == 32
11191
      && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11192
      && GET_CODE (operands[1]) == MEM && MEM_ALIGN (operands[1]) < 32)
11193
    {
11194
      emit_insn (gen_movua (operands[0],
11195
                            adjust_address (operands[1], SImode, 0)));
11196
      DONE;
11197
    }
11198
 
11199
  FAIL;
11200
})
11201
 
11202
(define_expand "extzv"
11203
  [(set (match_operand:SI 0 "register_operand" "")
11204
        (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11205
                         (match_operand 2 "const_int_operand" "")
11206
                         (match_operand 3 "const_int_operand" "")))]
11207
  "TARGET_SH4A_ARCH"
11208
{
11209
  if (TARGET_SH4A_ARCH
11210
      && INTVAL (operands[2]) == 32
11211
      && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11212
      && GET_CODE (operands[1]) == MEM && MEM_ALIGN (operands[1]) < 32)
11213
    {
11214
      emit_insn (gen_movua (operands[0],
11215
                            adjust_address (operands[1], SImode, 0)));
11216
      DONE;
11217
    }
11218
 
11219
  FAIL;
11220
})
11221
 
11222
 
11223
;; -------------------------------------------------------------------------
11224
;; Peepholes
11225
;; -------------------------------------------------------------------------
11226
 
11227
;; This matches cases where a stack pointer increment at the start of the
11228
;; epilogue combines with a stack slot read loading the return value.
11229
 
11230
(define_peephole
11231
  [(set (match_operand:SI 0 "arith_reg_operand" "")
11232
        (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
11233
   (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11234
  "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
11235
  "mov.l        @%1+,%0")
11236
 
11237
;; See the comment on the dt combiner pattern above.
11238
 
11239
(define_peephole
11240
  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11241
        (plus:SI (match_dup 0)
11242
                 (const_int -1)))
11243
   (set (reg:SI T_REG)
11244
        (eq:SI (match_dup 0)
11245
               (const_int 0)))]
11246
  "TARGET_SH2"
11247
  "dt   %0")
11248
 
11249
;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
11250
;; to `mov #k,r0; mov.l @(r0,r15),rn'.  These sequences are generated by
11251
;; reload when the constant is too large for a reg+offset address.
11252
 
11253
;; ??? We would get much better code if this was done in reload.  This would
11254
;; require modifying find_reloads_address to recognize that if the constant
11255
;; is out-of-range for an immediate add, then we get better code by reloading
11256
;; the constant into a register than by reloading the sum into a register,
11257
;; since the former is one instruction shorter if the address does not need
11258
;; to be offsettable.  Unfortunately this does not work, because there is
11259
;; only one register, r0, that can be used as an index register.  This register
11260
;; is also the function return value register.  So, if we try to force reload
11261
;; to use double-reg addresses, then we end up with some instructions that
11262
;; need to use r0 twice.  The only way to fix this is to change the calling
11263
;; convention so that r0 is not used to return values.
11264
 
11265
(define_peephole
11266
  [(set (match_operand:SI 0 "register_operand" "=r")
11267
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11268
   (set (mem:SI (match_dup 0))
11269
        (match_operand:SI 2 "general_movsrc_operand" ""))]
11270
  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11271
  "mov.l        %2,@(%0,%1)")
11272
 
11273
(define_peephole
11274
  [(set (match_operand:SI 0 "register_operand" "=r")
11275
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11276
   (set (match_operand:SI 2 "general_movdst_operand" "")
11277
        (mem:SI (match_dup 0)))]
11278
  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11279
  "mov.l        @(%0,%1),%2")
11280
 
11281
(define_peephole
11282
  [(set (match_operand:SI 0 "register_operand" "=r")
11283
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11284
   (set (mem:HI (match_dup 0))
11285
        (match_operand:HI 2 "general_movsrc_operand" ""))]
11286
  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11287
  "mov.w        %2,@(%0,%1)")
11288
 
11289
(define_peephole
11290
  [(set (match_operand:SI 0 "register_operand" "=r")
11291
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11292
   (set (match_operand:HI 2 "general_movdst_operand" "")
11293
        (mem:HI (match_dup 0)))]
11294
  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11295
  "mov.w        @(%0,%1),%2")
11296
 
11297
(define_peephole
11298
  [(set (match_operand:SI 0 "register_operand" "=r")
11299
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11300
   (set (mem:QI (match_dup 0))
11301
        (match_operand:QI 2 "general_movsrc_operand" ""))]
11302
  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11303
  "mov.b        %2,@(%0,%1)")
11304
 
11305
(define_peephole
11306
  [(set (match_operand:SI 0 "register_operand" "=r")
11307
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11308
   (set (match_operand:QI 2 "general_movdst_operand" "")
11309
        (mem:QI (match_dup 0)))]
11310
  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11311
  "mov.b        @(%0,%1),%2")
11312
 
11313
(define_peephole
11314
  [(set (match_operand:SI 0 "register_operand" "=r")
11315
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11316
   (set (mem:SF (match_dup 0))
11317
        (match_operand:SF 2 "general_movsrc_operand" ""))]
11318
  "TARGET_SH1 && REGNO (operands[0]) == 0
11319
   && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
11320
       || (GET_CODE (operands[2]) == SUBREG
11321
           && REGNO (SUBREG_REG (operands[2])) < 16))
11322
   && reg_unused_after (operands[0], insn)"
11323
  "mov.l        %2,@(%0,%1)")
11324
 
11325
(define_peephole
11326
  [(set (match_operand:SI 0 "register_operand" "=r")
11327
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11328
   (set (match_operand:SF 2 "general_movdst_operand" "")
11329
 
11330
        (mem:SF (match_dup 0)))]
11331
  "TARGET_SH1 && REGNO (operands[0]) == 0
11332
   && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
11333
       || (GET_CODE (operands[2]) == SUBREG
11334
           && REGNO (SUBREG_REG (operands[2])) < 16))
11335
   && reg_unused_after (operands[0], insn)"
11336
  "mov.l        @(%0,%1),%2")
11337
 
11338
(define_peephole
11339
  [(set (match_operand:SI 0 "register_operand" "=r")
11340
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11341
   (set (mem:SF (match_dup 0))
11342
        (match_operand:SF 2 "general_movsrc_operand" ""))]
11343
  "TARGET_SH2E && REGNO (operands[0]) == 0
11344
   && ((GET_CODE (operands[2]) == REG
11345
        && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11346
       || (GET_CODE (operands[2]) == SUBREG
11347
           && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11348
   && reg_unused_after (operands[0], insn)"
11349
  "fmov{.s|}    %2,@(%0,%1)")
11350
 
11351
(define_peephole
11352
  [(set (match_operand:SI 0 "register_operand" "=r")
11353
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11354
   (set (match_operand:SF 2 "general_movdst_operand" "")
11355
 
11356
        (mem:SF (match_dup 0)))]
11357
  "TARGET_SH2E && REGNO (operands[0]) == 0
11358
   && ((GET_CODE (operands[2]) == REG
11359
        && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11360
       || (GET_CODE (operands[2]) == SUBREG
11361
           && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11362
   && reg_unused_after (operands[0], insn)"
11363
  "fmov{.s|}    @(%0,%1),%2")
11364
 
11365
;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).  */
11366
(define_insn "sp_switch_1"
11367
  [(const_int 1) (match_operand:SI 0 "symbol_ref_operand" "s")]
11368
  "TARGET_SH1"
11369
  "*
11370
{
11371
  output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", operands);
11372
  output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", operands);
11373
  return \"mov r0,r15\";
11374
}"
11375
  [(set_attr "length" "10")])
11376
 
11377
;; Switch back to the original stack for interrupt functions with the
11378
;; sp_switch attribute.  */
11379
(define_insn "sp_switch_2"
11380
  [(const_int 2)]
11381
  "TARGET_SH1"
11382
  "mov.l @r15+,r15\;mov.l @r15+,r0"
11383
  [(set_attr "length" "4")])
11384
 
11385
;; Integer vector moves
11386
 
11387
(define_expand "movv8qi"
11388
  [(set (match_operand:V8QI 0 "general_movdst_operand" "")
11389
        (match_operand:V8QI 1 "general_movsrc_operand" ""))]
11390
  "TARGET_SHMEDIA"
11391
  "{ if (prepare_move_operands (operands, V8QImode)) DONE; }")
11392
 
11393
(define_insn "movv8qi_i"
11394
  [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
11395
        (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11396
  "TARGET_SHMEDIA
11397
   && (register_operand (operands[0], V8QImode)
11398
       || sh_register_operand (operands[1], V8QImode))"
11399
  "@
11400
        add     %1, r63, %0
11401
        movi    %1, %0
11402
        #
11403
        ld%M1.q %m1, %0
11404
        st%M0.q %m0, %N1"
11405
  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11406
   (set_attr "length" "4,4,16,4,4")])
11407
 
11408
(define_split
11409
  [(set (match_operand:V8QI 0 "arith_reg_dest" "")
11410
        (subreg:V8QI (const_int 0) 0))]
11411
  "TARGET_SHMEDIA"
11412
  [(set (match_dup 0)
11413
        (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
11414
                            (const_int 0) (const_int 0) (const_int 0)
11415
                            (const_int 0) (const_int 0)]))])
11416
 
11417
(define_split
11418
  [(set (match_operand 0 "arith_reg_dest" "")
11419
        (match_operand 1 "sh_rep_vec" ""))]
11420
  "TARGET_SHMEDIA && reload_completed
11421
   && GET_MODE (operands[0]) == GET_MODE (operands[1])
11422
   && sh_vector_mode_supported_p (GET_MODE (operands[0]))
11423
   && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
11424
   && (XVECEXP (operands[1], 0, 0) != const0_rtx
11425
       || XVECEXP (operands[1], 0, 1) != const0_rtx)
11426
   && (XVECEXP (operands[1], 0, 0) != constm1_rtx
11427
       || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
11428
  [(set (match_dup 0) (match_dup 1))
11429
   (match_dup 2)]
11430
  "
11431
{
11432
  int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
11433
  rtx elt1 = XVECEXP (operands[1], 0, 1);
11434
 
11435
  if (unit_size > 2)
11436
    operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
11437
  else
11438
    {
11439
      if (unit_size < 2)
11440
        operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
11441
      operands[2] = gen_mperm_w0 (operands[0], operands[0]);
11442
    }
11443
  operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
11444
  operands[1] = XVECEXP (operands[1], 0, 0);
11445
  if (unit_size < 2)
11446
    {
11447
      if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (elt1) == CONST_INT)
11448
        operands[1]
11449
          = GEN_INT (TARGET_LITTLE_ENDIAN
11450
                     ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
11451
                     : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
11452
      else
11453
        {
11454
          operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
11455
          operands[1]
11456
            = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
11457
        }
11458
    }
11459
}")
11460
 
11461
(define_split
11462
  [(set (match_operand 0 "arith_reg_dest" "")
11463
        (match_operand 1 "sh_const_vec" ""))]
11464
  "TARGET_SHMEDIA && reload_completed
11465
   && GET_MODE (operands[0]) == GET_MODE (operands[1])
11466
   && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
11467
  [(set (match_dup 0) (match_dup 1))]
11468
  "
11469
{
11470
  rtx v = operands[1];
11471
  enum machine_mode new_mode
11472
    = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
11473
 
11474
  operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
11475
  operands[1]
11476
    = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
11477
}")
11478
 
11479
(define_expand "movv2hi"
11480
  [(set (match_operand:V2HI 0 "general_movdst_operand" "")
11481
        (match_operand:V2HI 1 "general_movsrc_operand" ""))]
11482
  "TARGET_SHMEDIA"
11483
  "{ if (prepare_move_operands (operands, V2HImode)) DONE; }")
11484
 
11485
(define_insn "movv2hi_i"
11486
  [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
11487
        (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11488
  "TARGET_SHMEDIA
11489
   && (register_operand (operands[0], V2HImode)
11490
       || sh_register_operand (operands[1], V2HImode))"
11491
  "@
11492
        add.l   %1, r63, %0
11493
        movi    %1, %0
11494
        #
11495
        ld%M1.l %m1, %0
11496
        st%M0.l %m0, %N1"
11497
  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11498
   (set_attr "length" "4,4,16,4,4")
11499
   (set (attr "highpart")
11500
        (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
11501
               (const_string "user")]
11502
              (const_string "ignore")))])
11503
 
11504
(define_expand "movv4hi"
11505
  [(set (match_operand:V4HI 0 "general_movdst_operand" "")
11506
        (match_operand:V4HI 1 "general_movsrc_operand" ""))]
11507
  "TARGET_SHMEDIA"
11508
  "{ if (prepare_move_operands (operands, V4HImode)) DONE; }")
11509
 
11510
(define_insn "movv4hi_i"
11511
  [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
11512
        (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11513
  "TARGET_SHMEDIA
11514
   && (register_operand (operands[0], V4HImode)
11515
       || sh_register_operand (operands[1], V4HImode))"
11516
  "@
11517
        add     %1, r63, %0
11518
        movi    %1, %0
11519
        #
11520
        ld%M1.q %m1, %0
11521
        st%M0.q %m0, %N1"
11522
  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11523
   (set_attr "length" "4,4,16,4,4")
11524
   (set_attr "highpart" "depend")])
11525
 
11526
(define_expand "movv2si"
11527
  [(set (match_operand:V2SI 0 "general_movdst_operand" "")
11528
        (match_operand:V2SI 1 "general_movsrc_operand" ""))]
11529
  "TARGET_SHMEDIA"
11530
  "{ if (prepare_move_operands (operands, V2SImode)) DONE; }")
11531
 
11532
(define_insn "movv2si_i"
11533
  [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
11534
        (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11535
  "TARGET_SHMEDIA
11536
   && (register_operand (operands[0], V2SImode)
11537
       || sh_register_operand (operands[1], V2SImode))"
11538
  "@
11539
        add     %1, r63, %0
11540
        #
11541
        #
11542
        ld%M1.q %m1, %0
11543
        st%M0.q %m0, %N1"
11544
  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11545
   (set_attr "length" "4,4,16,4,4")
11546
   (set_attr "highpart" "depend")])
11547
 
11548
;; Multimedia Intrinsics
11549
 
11550
(define_insn "absv2si2"
11551
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11552
        (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
11553
  "TARGET_SHMEDIA"
11554
  "mabs.l       %1, %0"
11555
  [(set_attr "type" "mcmp_media")
11556
   (set_attr "highpart" "depend")])
11557
 
11558
(define_insn "absv4hi2"
11559
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11560
        (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
11561
  "TARGET_SHMEDIA"
11562
  "mabs.w       %1, %0"
11563
  [(set_attr "type" "mcmp_media")
11564
   (set_attr "highpart" "depend")])
11565
 
11566
(define_insn "addv2si3"
11567
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11568
        (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
11569
                   (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11570
  "TARGET_SHMEDIA"
11571
  "madd.l       %1, %2, %0"
11572
  [(set_attr "type" "arith_media")
11573
   (set_attr "highpart" "depend")])
11574
 
11575
(define_insn "addv4hi3"
11576
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11577
        (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
11578
                   (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11579
  "TARGET_SHMEDIA"
11580
  "madd.w       %1, %2, %0"
11581
  [(set_attr "type" "arith_media")
11582
   (set_attr "highpart" "depend")])
11583
 
11584
(define_insn_and_split "addv2hi3"
11585
  [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
11586
        (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
11587
                   (match_operand:V2HI 2 "extend_reg_operand" "r")))]
11588
  "TARGET_SHMEDIA"
11589
  "#"
11590
  "TARGET_SHMEDIA"
11591
  [(const_int 0)]
11592
  "
11593
{
11594
  rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
11595
  rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
11596
  rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
11597
  rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
11598
  rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
11599
 
11600
  emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
11601
  emit_insn (gen_truncdisi2 (si_dst, di_dst));
11602
  DONE;
11603
}"
11604
  [(set_attr "highpart" "must_split")])
11605
 
11606
(define_insn "ssaddv2si3"
11607
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11608
        (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
11609
                      (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11610
  "TARGET_SHMEDIA"
11611
  "madds.l      %1, %2, %0"
11612
  [(set_attr "type" "mcmp_media")
11613
   (set_attr "highpart" "depend")])
11614
 
11615
(define_insn "usaddv8qi3"
11616
  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11617
        (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
11618
                      (match_operand:V8QI 2 "arith_reg_operand" "r")))]
11619
  "TARGET_SHMEDIA"
11620
  "madds.ub     %1, %2, %0"
11621
  [(set_attr "type" "mcmp_media")
11622
   (set_attr "highpart" "depend")])
11623
 
11624
(define_insn "ssaddv4hi3"
11625
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11626
        (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
11627
                      (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11628
  "TARGET_SHMEDIA"
11629
  "madds.w      %1, %2, %0"
11630
  [(set_attr "type" "mcmp_media")
11631
   (set_attr "highpart" "depend")])
11632
 
11633
(define_insn "negcmpeqv8qi"
11634
  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11635
        (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
11636
                           (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
11637
  "TARGET_SHMEDIA"
11638
  "mcmpeq.b     %N1, %N2, %0"
11639
  [(set_attr "type" "mcmp_media")
11640
   (set_attr "highpart" "depend")])
11641
 
11642
(define_insn "negcmpeqv2si"
11643
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11644
        (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
11645
                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11646
  "TARGET_SHMEDIA"
11647
  "mcmpeq.l     %N1, %N2, %0"
11648
  [(set_attr "type" "mcmp_media")
11649
   (set_attr "highpart" "depend")])
11650
 
11651
(define_insn "negcmpeqv4hi"
11652
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11653
        (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
11654
                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11655
  "TARGET_SHMEDIA"
11656
  "mcmpeq.w     %N1, %N2, %0"
11657
  [(set_attr "type" "mcmp_media")
11658
   (set_attr "highpart" "depend")])
11659
 
11660
(define_insn "negcmpgtuv8qi"
11661
  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11662
        (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
11663
                            (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
11664
  "TARGET_SHMEDIA"
11665
  "mcmpgt.ub    %N1, %N2, %0"
11666
  [(set_attr "type" "mcmp_media")
11667
   (set_attr "highpart" "depend")])
11668
 
11669
(define_insn "negcmpgtv2si"
11670
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11671
        (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
11672
                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11673
  "TARGET_SHMEDIA"
11674
  "mcmpgt.l     %N1, %N2, %0"
11675
  [(set_attr "type" "mcmp_media")
11676
   (set_attr "highpart" "depend")])
11677
 
11678
(define_insn "negcmpgtv4hi"
11679
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11680
        (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
11681
                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11682
  "TARGET_SHMEDIA"
11683
  "mcmpgt.w     %N1, %N2, %0"
11684
  [(set_attr "type" "mcmp_media")
11685
   (set_attr "highpart" "depend")])
11686
 
11687
(define_insn "mcmv"
11688
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11689
        (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11690
                        (match_operand:DI 2 "arith_reg_operand" "r"))
11691
                (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
11692
                        (not:DI (match_dup 2)))))]
11693
  "TARGET_SHMEDIA"
11694
  "mcmv %N1, %2, %0"
11695
  [(set_attr "type" "arith_media")
11696
   (set_attr "highpart" "depend")])
11697
 
11698
(define_insn "mcnvs_lw"
11699
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11700
        (vec_concat:V4HI
11701
         (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
11702
         (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11703
  "TARGET_SHMEDIA"
11704
  "mcnvs.lw     %N1, %N2, %0"
11705
  [(set_attr "type" "mcmp_media")])
11706
 
11707
(define_insn "mcnvs_wb"
11708
  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11709
        (vec_concat:V8QI
11710
         (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
11711
         (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11712
  "TARGET_SHMEDIA"
11713
  "mcnvs.wb     %N1, %N2, %0"
11714
  [(set_attr "type" "mcmp_media")])
11715
 
11716
(define_insn "mcnvs_wub"
11717
  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11718
        (vec_concat:V8QI
11719
         (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
11720
         (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11721
  "TARGET_SHMEDIA"
11722
  "mcnvs.wub    %N1, %N2, %0"
11723
  [(set_attr "type" "mcmp_media")])
11724
 
11725
(define_insn "mextr_rl"
11726
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11727
        (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11728
                             (match_operand:HI 3 "mextr_bit_offset" "i"))
11729
               (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
11730
                          (match_operand:HI 4 "mextr_bit_offset" "i"))))]
11731
  "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
11732
  "*
11733
{
11734
  static char templ[21];
11735
 
11736
  sprintf (templ, \"mextr%d\\t%%N1, %%N2, %%0\",
11737
           (int) INTVAL (operands[3]) >> 3);
11738
  return templ;
11739
}"
11740
  [(set_attr "type" "arith_media")])
11741
 
11742
(define_insn "*mextr_lr"
11743
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11744
        (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11745
                           (match_operand:HI 3 "mextr_bit_offset" "i"))
11746
               (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
11747
                            (match_operand:HI 4 "mextr_bit_offset" "i"))))]
11748
  "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
11749
  "*
11750
{
11751
  static char templ[21];
11752
 
11753
  sprintf (templ, \"mextr%d\\t%%N2, %%N1, %%0\",
11754
           (int) INTVAL (operands[4]) >> 3);
11755
  return templ;
11756
}"
11757
  [(set_attr "type" "arith_media")])
11758
 
11759
; mextrN can be modelled with vec_select / vec_concat, but the selection
11760
; vector then varies depending on endianness.
11761
(define_expand "mextr1"
11762
  [(match_operand:DI 0 "arith_reg_dest" "")
11763
   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11764
   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11765
  "TARGET_SHMEDIA"
11766
  "
11767
{
11768
  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11769
                           GEN_INT (1 * 8), GEN_INT (7 * 8)));
11770
  DONE;
11771
}")
11772
 
11773
(define_expand "mextr2"
11774
  [(match_operand:DI 0 "arith_reg_dest" "")
11775
   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11776
   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11777
  "TARGET_SHMEDIA"
11778
  "
11779
{
11780
  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11781
                           GEN_INT (2 * 8), GEN_INT (6 * 8)));
11782
  DONE;
11783
}")
11784
 
11785
(define_expand "mextr3"
11786
  [(match_operand:DI 0 "arith_reg_dest" "")
11787
   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11788
   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11789
  "TARGET_SHMEDIA"
11790
  "
11791
{
11792
  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11793
                           GEN_INT (3 * 8), GEN_INT (5 * 8)));
11794
  DONE;
11795
}")
11796
 
11797
(define_expand "mextr4"
11798
  [(match_operand:DI 0 "arith_reg_dest" "")
11799
   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11800
   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11801
  "TARGET_SHMEDIA"
11802
  "
11803
{
11804
  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11805
                           GEN_INT (4 * 8), GEN_INT (4 * 8)));
11806
  DONE;
11807
}")
11808
 
11809
(define_expand "mextr5"
11810
  [(match_operand:DI 0 "arith_reg_dest" "")
11811
   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11812
   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11813
  "TARGET_SHMEDIA"
11814
  "
11815
{
11816
  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11817
                           GEN_INT (5 * 8), GEN_INT (3 * 8)));
11818
  DONE;
11819
}")
11820
 
11821
(define_expand "mextr6"
11822
  [(match_operand:DI 0 "arith_reg_dest" "")
11823
   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11824
   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11825
  "TARGET_SHMEDIA"
11826
  "
11827
{
11828
  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11829
                           GEN_INT (6 * 8), GEN_INT (2 * 8)));
11830
  DONE;
11831
}")
11832
 
11833
(define_expand "mextr7"
11834
  [(match_operand:DI 0 "arith_reg_dest" "")
11835
   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11836
   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11837
  "TARGET_SHMEDIA"
11838
  "
11839
{
11840
  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11841
                           GEN_INT (7 * 8), GEN_INT (1 * 8)));
11842
  DONE;
11843
}")
11844
 
11845
(define_expand "mmacfx_wl"
11846
  [(match_operand:V2SI 0 "arith_reg_dest" "")
11847
   (match_operand:V2HI 1 "extend_reg_operand" "")
11848
   (match_operand:V2HI 2 "extend_reg_operand" "")
11849
   (match_operand:V2SI 3 "arith_reg_operand" "")]
11850
  "TARGET_SHMEDIA"
11851
  "
11852
{
11853
  emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
11854
                              operands[1], operands[2]));
11855
  DONE;
11856
}")
11857
 
11858
;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
11859
;; is depend
11860
(define_insn "mmacfx_wl_i"
11861
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11862
        (ss_plus:V2SI
11863
         (match_operand:V2SI 1 "arith_reg_operand" "0")
11864
         (ss_truncate:V2SI
11865
          (ashift:V2DI
11866
           (sign_extend:V2DI
11867
            (mult:V2SI
11868
             (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
11869
             (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
11870
           (const_int 1)))))]
11871
  "TARGET_SHMEDIA"
11872
  "mmacfx.wl    %2, %3, %0"
11873
  [(set_attr "type" "mac_media")
11874
   (set_attr "highpart" "depend")])
11875
 
11876
(define_expand "mmacnfx_wl"
11877
  [(match_operand:V2SI 0 "arith_reg_dest" "")
11878
   (match_operand:V2HI 1 "extend_reg_operand" "")
11879
   (match_operand:V2HI 2 "extend_reg_operand" "")
11880
   (match_operand:V2SI 3 "arith_reg_operand" "")]
11881
  "TARGET_SHMEDIA"
11882
  "
11883
{
11884
  emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
11885
                               operands[1], operands[2]));
11886
  DONE;
11887
}")
11888
 
11889
(define_insn "mmacnfx_wl_i"
11890
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11891
        (ss_minus:V2SI
11892
         (match_operand:V2SI 1 "arith_reg_operand" "0")
11893
         (ss_truncate:V2SI
11894
          (ashift:V2DI
11895
           (sign_extend:V2DI
11896
            (mult:V2SI
11897
             (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
11898
             (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
11899
           (const_int 1)))))]
11900
  "TARGET_SHMEDIA"
11901
  "mmacnfx.wl   %2, %3, %0"
11902
  [(set_attr "type" "mac_media")
11903
   (set_attr "highpart" "depend")])
11904
 
11905
(define_insn "mulv2si3"
11906
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11907
        (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
11908
                   (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11909
  "TARGET_SHMEDIA"
11910
  "mmul.l       %1, %2, %0"
11911
  [(set_attr "type" "d2mpy_media")
11912
   (set_attr "highpart" "depend")])
11913
 
11914
(define_insn "mulv4hi3"
11915
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11916
        (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
11917
                   (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11918
  "TARGET_SHMEDIA"
11919
  "mmul.w       %1, %2, %0"
11920
  [(set_attr "type" "dmpy_media")
11921
   (set_attr "highpart" "depend")])
11922
 
11923
(define_insn "mmulfx_l"
11924
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11925
        (ss_truncate:V2SI
11926
         (ashiftrt:V2DI
11927
          (mult:V2DI
11928
           (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
11929
           (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
11930
          (const_int 31))))]
11931
  "TARGET_SHMEDIA"
11932
  "mmulfx.l     %1, %2, %0"
11933
  [(set_attr "type" "d2mpy_media")
11934
   (set_attr "highpart" "depend")])
11935
 
11936
(define_insn "mmulfx_w"
11937
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11938
        (ss_truncate:V4HI
11939
         (ashiftrt:V4SI
11940
          (mult:V4SI
11941
           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
11942
           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
11943
          (const_int 15))))]
11944
  "TARGET_SHMEDIA"
11945
  "mmulfx.w     %1, %2, %0"
11946
  [(set_attr "type" "dmpy_media")
11947
   (set_attr "highpart" "depend")])
11948
 
11949
(define_insn "mmulfxrp_w"
11950
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11951
        (ss_truncate:V4HI
11952
         (ashiftrt:V4SI
11953
          (plus:V4SI
11954
           (mult:V4SI
11955
            (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
11956
            (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
11957
           (const_int 16384))
11958
          (const_int 15))))]
11959
  "TARGET_SHMEDIA"
11960
  "mmulfxrp.w   %1, %2, %0"
11961
  [(set_attr "type" "dmpy_media")
11962
   (set_attr "highpart" "depend")])
11963
 
11964
 
11965
(define_expand "mmulhi_wl"
11966
  [(match_operand:V2SI 0 "arith_reg_dest" "")
11967
   (match_operand:V4HI 1 "arith_reg_operand" "")
11968
   (match_operand:V4HI 2 "arith_reg_operand" "")]
11969
  "TARGET_SHMEDIA"
11970
  "
11971
{
11972
  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
11973
             (operands[0], operands[1], operands[2]));
11974
  DONE;
11975
}")
11976
 
11977
(define_expand "mmullo_wl"
11978
  [(match_operand:V2SI 0 "arith_reg_dest" "")
11979
   (match_operand:V4HI 1 "arith_reg_operand" "")
11980
   (match_operand:V4HI 2 "arith_reg_operand" "")]
11981
  "TARGET_SHMEDIA"
11982
  "
11983
{
11984
  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
11985
             (operands[0], operands[1], operands[2]));
11986
  DONE;
11987
}")
11988
 
11989
(define_insn "mmul23_wl"
11990
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11991
        (vec_select:V2SI
11992
         (mult:V4SI
11993
          (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
11994
          (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
11995
         (parallel [(const_int 2) (const_int 3)])))]
11996
  "TARGET_SHMEDIA"
11997
  "* return (TARGET_LITTLE_ENDIAN
11998
             ? \"mmulhi.wl      %1, %2, %0\"
11999
             : \"mmullo.wl      %1, %2, %0\");"
12000
  [(set_attr "type" "dmpy_media")
12001
   (set (attr "highpart")
12002
        (cond [(eq_attr "endian" "big") (const_string "ignore")]
12003
         (const_string "user")))])
12004
 
12005
(define_insn "mmul01_wl"
12006
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12007
        (vec_select:V2SI
12008
         (mult:V4SI
12009
          (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12010
          (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12011
         (parallel [(const_int 0) (const_int 1)])))]
12012
  "TARGET_SHMEDIA"
12013
  "* return (TARGET_LITTLE_ENDIAN
12014
             ? \"mmullo.wl      %1, %2, %0\"
12015
             : \"mmulhi.wl      %1, %2, %0\");"
12016
  [(set_attr "type" "dmpy_media")
12017
   (set (attr "highpart")
12018
        (cond [(eq_attr "endian" "little") (const_string "ignore")]
12019
         (const_string "user")))])
12020
 
12021
 
12022
(define_expand "mmulsum_wq"
12023
  [(match_operand:DI 0 "arith_reg_dest" "")
12024
   (match_operand:V4HI 1 "arith_reg_operand" "")
12025
   (match_operand:V4HI 2 "arith_reg_operand" "")
12026
   (match_operand:DI 3 "arith_reg_operand" "")]
12027
  "TARGET_SHMEDIA"
12028
  "
12029
{
12030
  emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
12031
                               operands[1], operands[2]));
12032
  DONE;
12033
}")
12034
 
12035
(define_insn "mmulsum_wq_i"
12036
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12037
        (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
12038
         (plus:DI
12039
          (plus:DI
12040
           (vec_select:DI
12041
            (mult:V4DI
12042
             (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
12043
             (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
12044
            (parallel [(const_int 0)]))
12045
           (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12046
                                     (sign_extend:V4DI (match_dup 3)))
12047
                          (parallel [(const_int 1)])))
12048
          (plus:DI
12049
           (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12050
                                     (sign_extend:V4DI (match_dup 3)))
12051
                          (parallel [(const_int 2)]))
12052
           (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12053
                                     (sign_extend:V4DI (match_dup 3)))
12054
                          (parallel [(const_int 3)]))))))]
12055
  "TARGET_SHMEDIA"
12056
  "mmulsum.wq   %2, %3, %0"
12057
  [(set_attr "type" "mac_media")])
12058
 
12059
(define_expand "mperm_w"
12060
  [(match_operand:V4HI 0 "arith_reg_dest" "=r")
12061
   (match_operand:V4HI 1 "arith_reg_operand" "r")
12062
   (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
12063
  "TARGET_SHMEDIA"
12064
  "
12065
{
12066
  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
12067
             (operands[0], operands[1], operands[2]));
12068
  DONE;
12069
}")
12070
 
12071
; This use of vec_select isn't exactly correct according to rtl.texi
12072
; (because not constant), but it seems a straightforward extension.
12073
(define_insn "mperm_w_little"
12074
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12075
        (vec_select:V4HI
12076
         (match_operand:V4HI 1 "arith_reg_operand" "r")
12077
         (parallel
12078
          [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
12079
                            (const_int 2) (const_int 0))
12080
           (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
12081
           (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
12082
           (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
12083
  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
12084
  "mperm.w      %1, %N2, %0"
12085
  [(set_attr "type" "arith_media")])
12086
 
12087
(define_insn "mperm_w_big"
12088
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12089
        (vec_select:V4HI
12090
         (match_operand:V4HI 1 "arith_reg_operand" "r")
12091
         (parallel
12092
          [(zero_extract:QI (not:QI (match_operand:QI 2
12093
                                     "extend_reg_or_0_operand" "rZ"))
12094
                            (const_int 2) (const_int 0))
12095
           (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
12096
           (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
12097
           (zero_extract:QI (not:QI (match_dup 2))
12098
                            (const_int 2) (const_int 6))])))]
12099
  "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
12100
  "mperm.w      %1, %N2, %0"
12101
  [(set_attr "type" "arith_media")])
12102
 
12103
(define_insn "mperm_w0"
12104
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12105
        (vec_duplicate:V4HI (truncate:HI (match_operand 1
12106
                                          "trunc_hi_operand" "r"))))]
12107
  "TARGET_SHMEDIA"
12108
  "mperm.w      %1, r63, %0"
12109
  [(set_attr "type" "arith_media")
12110
   (set_attr "highpart" "ignore")])
12111
 
12112
(define_expand "msad_ubq"
12113
  [(match_operand:DI 0 "arith_reg_dest" "")
12114
   (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
12115
   (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
12116
   (match_operand:DI 3 "arith_reg_operand" "")]
12117
  "TARGET_SHMEDIA"
12118
  "
12119
{
12120
  emit_insn (gen_msad_ubq_i (operands[0], operands[3],
12121
                             operands[1], operands[2]));
12122
  DONE;
12123
}")
12124
 
12125
(define_insn "msad_ubq_i"
12126
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12127
        (plus:DI
12128
         (plus:DI
12129
          (plus:DI
12130
           (plus:DI
12131
            (match_operand:DI 1 "arith_reg_operand" "0")
12132
            (abs:DI (vec_select:DI
12133
                     (minus:V8DI
12134
                      (zero_extend:V8DI
12135
                       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12136
                      (zero_extend:V8DI
12137
                       (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
12138
                     (parallel [(const_int 0)]))))
12139
           (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12140
                                              (zero_extend:V8DI (match_dup 3)))
12141
                                  (parallel [(const_int 1)]))))
12142
          (plus:DI
12143
           (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12144
                                              (zero_extend:V8DI (match_dup 3)))
12145
                                  (parallel [(const_int 2)])))
12146
           (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12147
                                              (zero_extend:V8DI (match_dup 3)))
12148
                                  (parallel [(const_int 3)])))))
12149
         (plus:DI
12150
          (plus:DI
12151
           (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12152
                                              (zero_extend:V8DI (match_dup 3)))
12153
                                  (parallel [(const_int 4)])))
12154
           (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12155
                                              (zero_extend:V8DI (match_dup 3)))
12156
                                  (parallel [(const_int 5)]))))
12157
          (plus:DI
12158
           (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12159
                                              (zero_extend:V8DI (match_dup 3)))
12160
                                  (parallel [(const_int 6)])))
12161
           (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12162
                                              (zero_extend:V8DI (match_dup 3)))
12163
                                  (parallel [(const_int 7)])))))))]
12164
  "TARGET_SHMEDIA"
12165
  "msad.ubq     %N2, %N3, %0"
12166
  [(set_attr "type" "mac_media")])
12167
 
12168
(define_insn "mshalds_l"
12169
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12170
        (ss_truncate:V2SI
12171
         (ashift:V2DI
12172
          (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12173
          (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12174
                  (const_int 31)))))]
12175
  "TARGET_SHMEDIA"
12176
  "mshalds.l    %1, %2, %0"
12177
  [(set_attr "type" "mcmp_media")
12178
   (set_attr "highpart" "depend")])
12179
 
12180
(define_insn "mshalds_w"
12181
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12182
        (ss_truncate:V4HI
12183
         (ashift:V4SI
12184
          (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12185
          (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12186
                  (const_int 15)))))]
12187
  "TARGET_SHMEDIA"
12188
  "mshalds.w    %1, %2, %0"
12189
  [(set_attr "type" "mcmp_media")
12190
   (set_attr "highpart" "depend")])
12191
 
12192
(define_insn "ashrv2si3"
12193
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12194
        (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12195
                       (match_operand:DI 2 "arith_reg_operand" "r")))]
12196
  "TARGET_SHMEDIA"
12197
  "mshard.l     %1, %2, %0"
12198
  [(set_attr "type" "arith_media")
12199
   (set_attr "highpart" "depend")])
12200
 
12201
(define_insn "ashrv4hi3"
12202
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12203
        (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12204
                       (match_operand:DI 2 "arith_reg_operand" "r")))]
12205
  "TARGET_SHMEDIA"
12206
  "mshard.w     %1, %2, %0"
12207
  [(set_attr "type" "arith_media")
12208
   (set_attr "highpart" "depend")])
12209
 
12210
(define_insn "mshards_q"
12211
  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
12212
        (ss_truncate:HI
12213
         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
12214
                      (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
12215
  "TARGET_SHMEDIA"
12216
  "mshards.q    %1, %N2, %0"
12217
  [(set_attr "type" "mcmp_media")])
12218
 
12219
(define_expand "mshfhi_b"
12220
  [(match_operand:V8QI 0 "arith_reg_dest" "")
12221
   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12222
   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12223
  "TARGET_SHMEDIA"
12224
  "
12225
{
12226
  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
12227
             (operands[0], operands[1], operands[2]));
12228
  DONE;
12229
}")
12230
 
12231
(define_expand "mshflo_b"
12232
  [(match_operand:V8QI 0 "arith_reg_dest" "")
12233
   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12234
   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12235
  "TARGET_SHMEDIA"
12236
  "
12237
{
12238
  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
12239
             (operands[0], operands[1], operands[2]));
12240
  DONE;
12241
}")
12242
 
12243
(define_insn "mshf4_b"
12244
  [(set
12245
    (match_operand:V8QI 0 "arith_reg_dest" "=r")
12246
    (vec_select:V8QI
12247
     (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12248
                       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12249
     (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
12250
                (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
12251
  "TARGET_SHMEDIA"
12252
  "* return (TARGET_LITTLE_ENDIAN
12253
             ? \"mshfhi.b       %N1, %N2, %0\"
12254
             : \"mshflo.b       %N1, %N2, %0\");"
12255
  [(set_attr "type" "arith_media")
12256
   (set (attr "highpart")
12257
        (cond [(eq_attr "endian" "big") (const_string "ignore")]
12258
         (const_string "user")))])
12259
 
12260
(define_insn "mshf0_b"
12261
  [(set
12262
    (match_operand:V8QI 0 "arith_reg_dest" "=r")
12263
    (vec_select:V8QI
12264
     (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12265
                       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12266
     (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
12267
                (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
12268
  "TARGET_SHMEDIA"
12269
  "* return (TARGET_LITTLE_ENDIAN
12270
             ? \"mshflo.b       %N1, %N2, %0\"
12271
             : \"mshfhi.b       %N1, %N2, %0\");"
12272
  [(set_attr "type" "arith_media")
12273
   (set (attr "highpart")
12274
        (cond [(eq_attr "endian" "little") (const_string "ignore")]
12275
         (const_string "user")))])
12276
 
12277
(define_expand "mshfhi_l"
12278
  [(match_operand:V2SI 0 "arith_reg_dest" "")
12279
   (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12280
   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12281
  "TARGET_SHMEDIA"
12282
  "
12283
{
12284
  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
12285
             (operands[0], operands[1], operands[2]));
12286
  DONE;
12287
}")
12288
 
12289
(define_expand "mshflo_l"
12290
  [(match_operand:V2SI 0 "arith_reg_dest" "")
12291
   (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12292
   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12293
  "TARGET_SHMEDIA"
12294
  "
12295
{
12296
  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
12297
             (operands[0], operands[1], operands[2]));
12298
  DONE;
12299
}")
12300
 
12301
(define_insn "mshf4_l"
12302
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12303
        (vec_select:V2SI
12304
         (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12305
                          (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12306
         (parallel [(const_int 1) (const_int 3)])))]
12307
  "TARGET_SHMEDIA"
12308
  "* return (TARGET_LITTLE_ENDIAN
12309
             ? \"mshfhi.l       %N1, %N2, %0\"
12310
             : \"mshflo.l       %N1, %N2, %0\");"
12311
  [(set_attr "type" "arith_media")
12312
   (set (attr "highpart")
12313
        (cond [(eq_attr "endian" "big") (const_string "ignore")]
12314
         (const_string "user")))])
12315
 
12316
(define_insn "mshf0_l"
12317
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12318
        (vec_select:V2SI
12319
         (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12320
                          (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12321
         (parallel [(const_int 0) (const_int 2)])))]
12322
  "TARGET_SHMEDIA"
12323
  "* return (TARGET_LITTLE_ENDIAN
12324
             ? \"mshflo.l       %N1, %N2, %0\"
12325
             : \"mshfhi.l       %N1, %N2, %0\");"
12326
  [(set_attr "type" "arith_media")
12327
   (set (attr "highpart")
12328
        (cond [(eq_attr "endian" "little") (const_string "ignore")]
12329
         (const_string "user")))])
12330
 
12331
(define_expand "mshfhi_w"
12332
  [(match_operand:V4HI 0 "arith_reg_dest" "")
12333
   (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12334
   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12335
  "TARGET_SHMEDIA"
12336
  "
12337
{
12338
  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
12339
             (operands[0], operands[1], operands[2]));
12340
  DONE;
12341
}")
12342
 
12343
(define_expand "mshflo_w"
12344
  [(match_operand:V4HI 0 "arith_reg_dest" "")
12345
   (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12346
   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12347
  "TARGET_SHMEDIA"
12348
  "
12349
{
12350
  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
12351
             (operands[0], operands[1], operands[2]));
12352
  DONE;
12353
}")
12354
 
12355
(define_insn "mshf4_w"
12356
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12357
        (vec_select:V4HI
12358
         (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12359
                          (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12360
         (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
12361
  "TARGET_SHMEDIA"
12362
  "* return (TARGET_LITTLE_ENDIAN
12363
             ? \"mshfhi.w       %N1, %N2, %0\"
12364
             : \"mshflo.w       %N1, %N2, %0\");"
12365
  [(set_attr "type" "arith_media")
12366
   (set (attr "highpart")
12367
        (cond [(eq_attr "endian" "big") (const_string "ignore")]
12368
         (const_string "user")))])
12369
 
12370
(define_insn "mshf0_w"
12371
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12372
        (vec_select:V4HI
12373
         (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12374
                          (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12375
         (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
12376
  "TARGET_SHMEDIA"
12377
  "* return (TARGET_LITTLE_ENDIAN
12378
             ? \"mshflo.w       %N1, %N2, %0\"
12379
             : \"mshfhi.w       %N1, %N2, %0\");"
12380
  [(set_attr "type" "arith_media")
12381
   (set (attr "highpart")
12382
        (cond [(eq_attr "endian" "little") (const_string "ignore")]
12383
         (const_string "user")))])
12384
 
12385
(define_insn "mshflo_w_x"
12386
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12387
        (vec_select:V4HI
12388
         (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
12389
                          (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
12390
         (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
12391
  "TARGET_SHMEDIA"
12392
  "mshflo.w     %N1, %N2, %0"
12393
  [(set_attr "type" "arith_media")
12394
   (set_attr "highpart" "ignore")])
12395
 
12396
/* These are useful to expand ANDs and as combiner patterns.  */
12397
(define_insn_and_split "mshfhi_l_di"
12398
  [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
12399
        (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
12400
                             (const_int 32))
12401
                (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
12402
                        (const_int -4294967296))))]
12403
  "TARGET_SHMEDIA"
12404
  "@
12405
        mshfhi.l        %N1, %N2, %0
12406
        #"
12407
  "TARGET_SHMEDIA && reload_completed
12408
   && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12409
  [(set (match_dup 3) (match_dup 4))
12410
   (set (match_dup 5) (match_dup 6))]
12411
  "
12412
{
12413
  operands[3] = gen_lowpart (SImode, operands[0]);
12414
  operands[4] = gen_highpart (SImode, operands[1]);
12415
  operands[5] = gen_highpart (SImode, operands[0]);
12416
  operands[6] = gen_highpart (SImode, operands[2]);
12417
}"
12418
  [(set_attr "type" "arith_media")])
12419
 
12420
(define_insn "*mshfhi_l_di_rev"
12421
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12422
        (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12423
                        (const_int -4294967296))
12424
                (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12425
                             (const_int 32))))]
12426
  "TARGET_SHMEDIA"
12427
  "mshfhi.l     %N2, %N1, %0"
12428
  [(set_attr "type" "arith_media")])
12429
 
12430
(define_split
12431
  [(set (match_operand:DI 0 "arith_reg_dest" "")
12432
        (ior:DI (zero_extend:DI (match_operand:SI 1
12433
                                              "extend_reg_or_0_operand" ""))
12434
                (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
12435
                        (const_int -4294967296))))
12436
   (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
12437
  "TARGET_SHMEDIA"
12438
  [(const_int 0)]
12439
  "
12440
{
12441
  emit_insn (gen_ashldi3_media (operands[3],
12442
                                simplify_gen_subreg (DImode, operands[1],
12443
                                                     SImode, 0),
12444
                                GEN_INT (32)));
12445
  emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
12446
  DONE;
12447
}")
12448
 
12449
(define_insn "mshflo_l_di"
12450
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12451
        (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12452
                        (const_int 4294967295))
12453
                (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12454
                           (const_int 32))))]
12455
 
12456
  "TARGET_SHMEDIA"
12457
  "mshflo.l     %N1, %N2, %0"
12458
  [(set_attr "type" "arith_media")
12459
   (set_attr "highpart" "ignore")])
12460
 
12461
(define_insn "*mshflo_l_di_rev"
12462
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12463
        (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12464
                           (const_int 32))
12465
                (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12466
                        (const_int 4294967295))))]
12467
 
12468
  "TARGET_SHMEDIA"
12469
  "mshflo.l     %N2, %N1, %0"
12470
  [(set_attr "type" "arith_media")
12471
   (set_attr "highpart" "ignore")])
12472
 
12473
;; Combiner pattern for trampoline initialization.
12474
(define_insn_and_split "*double_shori"
12475
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12476
        (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
12477
                           (const_int 32))
12478
                (match_operand:DI 2 "const_int_operand" "n")))]
12479
  "TARGET_SHMEDIA
12480
   && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
12481
  "#"
12482
  "rtx_equal_p (operands[0], operands[1])"
12483
  [(const_int 0)]
12484
  "
12485
{
12486
  HOST_WIDE_INT v = INTVAL (operands[2]);
12487
 
12488
  emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
12489
  emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
12490
  DONE;
12491
}"
12492
  [(set_attr "highpart" "ignore")])
12493
 
12494
 
12495
(define_insn "*mshflo_l_di_x"
12496
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12497
        (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
12498
                                 "rZ"))
12499
                (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12500
                           (const_int 32))))]
12501
 
12502
  "TARGET_SHMEDIA"
12503
  "mshflo.l     %N1, %N2, %0"
12504
  [(set_attr "type" "arith_media")
12505
   (set_attr "highpart" "ignore")])
12506
 
12507
(define_insn_and_split "concat_v2sf"
12508
  [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
12509
;;      (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
12510
        (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
12511
                         (match_operand:SF 2 "register_operand" "rZ,f,f")))]
12512
 
12513
  "TARGET_SHMEDIA"
12514
  "@
12515
        mshflo.l        %N1, %N2, %0
12516
        #
12517
        #"
12518
  "TARGET_SHMEDIA && reload_completed
12519
   && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12520
  [(set (match_dup 3) (match_dup 1))
12521
   (set (match_dup 4) (match_dup 2))]
12522
  "
12523
{
12524
  operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
12525
  operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
12526
}"
12527
  [(set_attr "type" "arith_media")
12528
   (set_attr "highpart" "ignore")])
12529
 
12530
(define_insn "*mshflo_l_di_x_rev"
12531
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12532
        (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12533
                           (const_int 32))
12534
                (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
12535
 
12536
  "TARGET_SHMEDIA"
12537
  "mshflo.l     %N2, %N1, %0"
12538
  [(set_attr "type" "arith_media")
12539
   (set_attr "highpart" "ignore")])
12540
 
12541
(define_insn "ashlv2si3"
12542
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12543
        (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12544
                     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12545
  "TARGET_SHMEDIA"
12546
  "mshlld.l     %1, %2, %0"
12547
  [(set_attr "type" "arith_media")
12548
   (set_attr "highpart" "depend")])
12549
 
12550
(define_split
12551
  [(set (match_operand 0 "any_register_operand" "")
12552
        (match_operator 3 "shift_operator"
12553
          [(match_operand 1 "any_register_operand" "")
12554
           (match_operand 2 "shift_count_reg_operand" "")]))]
12555
  "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
12556
  [(set (match_dup 0) (match_dup 3))]
12557
  "
12558
{
12559
  rtx count = operands[2];
12560
  enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
12561
 
12562
  while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
12563
         || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
12564
         || GET_CODE (count) == TRUNCATE)
12565
    count = XEXP (count, 0);
12566
  inner_mode = GET_MODE (count);
12567
  count = simplify_gen_subreg (outer_mode, count, inner_mode,
12568
                               subreg_lowpart_offset (outer_mode, inner_mode));
12569
  operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
12570
                                operands[1], count);
12571
}")
12572
 
12573
(define_insn "ashlv4hi3"
12574
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12575
        (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12576
                     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12577
  "TARGET_SHMEDIA"
12578
  "mshlld.w     %1, %2, %0"
12579
  [(set_attr "type" "arith_media")
12580
   (set_attr "highpart" "depend")])
12581
 
12582
(define_insn "lshrv2si3"
12583
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12584
        (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12585
                     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12586
  "TARGET_SHMEDIA"
12587
  "mshlrd.l     %1, %2, %0"
12588
  [(set_attr "type" "arith_media")
12589
   (set_attr "highpart" "depend")])
12590
 
12591
(define_insn "lshrv4hi3"
12592
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12593
        (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12594
                       (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12595
  "TARGET_SHMEDIA"
12596
  "mshlrd.w     %1, %2, %0"
12597
  [(set_attr "type" "arith_media")
12598
   (set_attr "highpart" "depend")])
12599
 
12600
(define_insn "subv2si3"
12601
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12602
        (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12603
                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12604
  "TARGET_SHMEDIA"
12605
  "msub.l       %N1, %2, %0"
12606
  [(set_attr "type" "arith_media")
12607
   (set_attr "highpart" "depend")])
12608
 
12609
(define_insn "subv4hi3"
12610
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12611
        (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12612
                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12613
  "TARGET_SHMEDIA"
12614
  "msub.w       %N1, %2, %0"
12615
  [(set_attr "type" "arith_media")
12616
   (set_attr "highpart" "depend")])
12617
 
12618
(define_insn_and_split "subv2hi3"
12619
  [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
12620
        (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
12621
                   (match_operand:V2HI 2 "arith_reg_operand" "r")))]
12622
  "TARGET_SHMEDIA"
12623
  "#"
12624
  "TARGET_SHMEDIA"
12625
  [(const_int 0)]
12626
  "
12627
{
12628
  rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
12629
  rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
12630
  rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
12631
  rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
12632
  rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
12633
 
12634
  emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
12635
  emit_insn (gen_truncdisi2 (si_dst, di_dst));
12636
  DONE;
12637
}"
12638
  [(set_attr "highpart" "must_split")])
12639
 
12640
(define_insn "sssubv2si3"
12641
  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12642
        (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12643
                       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12644
  "TARGET_SHMEDIA"
12645
  "msubs.l      %N1, %2, %0"
12646
  [(set_attr "type" "mcmp_media")
12647
   (set_attr "highpart" "depend")])
12648
 
12649
(define_insn "ussubv8qi3"
12650
  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12651
        (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12652
                       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
12653
  "TARGET_SHMEDIA"
12654
  "msubs.ub     %N1, %2, %0"
12655
  [(set_attr "type" "mcmp_media")
12656
   (set_attr "highpart" "depend")])
12657
 
12658
(define_insn "sssubv4hi3"
12659
  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12660
        (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12661
                       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12662
  "TARGET_SHMEDIA"
12663
  "msubs.w      %N1, %2, %0"
12664
  [(set_attr "type" "mcmp_media")
12665
   (set_attr "highpart" "depend")])
12666
 
12667
;; Floating Point Intrinsics
12668
 
12669
(define_insn "fcosa_s"
12670
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12671
        (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
12672
                   UNSPEC_FCOSA))]
12673
  "TARGET_SHMEDIA"
12674
  "fcosa.s      %1, %0"
12675
  [(set_attr "type" "atrans_media")])
12676
 
12677
(define_insn "fsina_s"
12678
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12679
        (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
12680
                   UNSPEC_FSINA))]
12681
  "TARGET_SHMEDIA"
12682
  "fsina.s      %1, %0"
12683
  [(set_attr "type" "atrans_media")])
12684
 
12685
(define_insn "fipr"
12686
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12687
        (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
12688
                                                    "fp_arith_reg_operand" "f")
12689
                                                   (match_operand:V4SF 2
12690
                                                    "fp_arith_reg_operand" "f"))
12691
                                         (parallel [(const_int 0)]))
12692
                          (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12693
                                         (parallel [(const_int 1)])))
12694
                 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12695
                                         (parallel [(const_int 2)]))
12696
                          (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12697
                                         (parallel [(const_int 3)])))))]
12698
  "TARGET_SHMEDIA"
12699
  "fipr.s       %1, %2, %0"
12700
  [(set_attr "type" "fparith_media")])
12701
 
12702
(define_insn "fsrra_s"
12703
  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12704
        (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
12705
                   UNSPEC_FSRRA))]
12706
  "TARGET_SHMEDIA"
12707
  "fsrra.s      %1, %0"
12708
  [(set_attr "type" "atrans_media")])
12709
 
12710
(define_insn "ftrv"
12711
  [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
12712
        (plus:V4SF
12713
         (plus:V4SF
12714
          (mult:V4SF
12715
           (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
12716
                            (parallel [(const_int 0) (const_int 5)
12717
                                       (const_int 10) (const_int 15)]))
12718
           (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
12719
          (mult:V4SF
12720
           (vec_select:V4SF (match_dup 1)
12721
                            (parallel [(const_int 4) (const_int 9)
12722
                                       (const_int 14) (const_int 3)]))
12723
           (vec_select:V4SF (match_dup 2)
12724
                            (parallel [(const_int 1) (const_int 2)
12725
                                       (const_int 3) (const_int 0)]))))
12726
         (plus:V4SF
12727
          (mult:V4SF
12728
           (vec_select:V4SF (match_dup 1)
12729
                            (parallel [(const_int 8) (const_int 13)
12730
                                       (const_int 2) (const_int 7)]))
12731
           (vec_select:V4SF (match_dup 2)
12732
                            (parallel [(const_int 2) (const_int 3)
12733
                                       (const_int 0) (const_int 1)])))
12734
          (mult:V4SF
12735
           (vec_select:V4SF (match_dup 1)
12736
                            (parallel [(const_int 12) (const_int 1)
12737
                                       (const_int 6) (const_int 11)]))
12738
           (vec_select:V4SF (match_dup 2)
12739
                            (parallel [(const_int 3) (const_int 0)
12740
                                       (const_int 1) (const_int 2)]))))))]
12741
  "TARGET_SHMEDIA"
12742
  "ftrv.s %1, %2, %0"
12743
  [(set_attr "type" "fparith_media")])
12744
 
12745
(define_insn "ldhi_l"
12746
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12747
        (zero_extract:SI
12748
         (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
12749
                                  (const_int 3))
12750
                          (const_int -3)))
12751
         (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
12752
         (const_int 0)))]
12753
  "TARGET_SHMEDIA32"
12754
  "ldhi.l       %U1, %0"
12755
  [(set_attr "type" "load_media")])
12756
 
12757
(define_insn "ldhi_q"
12758
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12759
        (zero_extract:DI
12760
         (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
12761
                                  (const_int 7))
12762
                          (const_int -7)))
12763
         (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
12764
         (const_int 0)))]
12765
  "TARGET_SHMEDIA32"
12766
  "ldhi.q       %U1, %0"
12767
  [(set_attr "type" "load_media")])
12768
 
12769
(define_insn_and_split "*ldhi_q_comb0"
12770
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12771
        (zero_extract:DI
12772
         (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
12773
                                            "register_operand" "r")
12774
                                           (match_operand:SI 2
12775
                                            "ua_offset" "I06"))
12776
                                  (const_int 7))
12777
                          (const_int -7)))
12778
         (plus:SI (and:SI (match_dup 1) (const_int 7))
12779
                  (const_int 1))
12780
         (const_int 0)))]
12781
  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
12782
  "#"
12783
  ""
12784
  [(pc)]
12785
  "emit_insn (gen_ldhi_q (operands[0],
12786
                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
12787
   DONE;")
12788
 
12789
 
12790
(define_insn_and_split "*ldhi_q_comb1"
12791
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12792
        (zero_extract:DI
12793
         (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
12794
                                            "register_operand" "r")
12795
                                           (match_operand:SI 2
12796
                                            "ua_offset" "I06"))
12797
                                  (const_int 7))
12798
                          (const_int -7)))
12799
         (plus:SI (and:SI (plus:SI (match_dup 1)  (match_operand:SI 3
12800
                                                   "ua_offset" "I06"))
12801
                          (const_int 7))
12802
                  (const_int 1))
12803
         (const_int 0)))]
12804
  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
12805
   && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
12806
  "#"
12807
  ""
12808
  [(pc)]
12809
  "emit_insn (gen_ldhi_q (operands[0],
12810
                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
12811
   DONE;")
12812
 
12813
 
12814
(define_insn "ldlo_l"
12815
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12816
        (zero_extract:SI
12817
         (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
12818
                         (const_int -4)))
12819
         (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
12820
         (and:SI (match_dup 1) (const_int 3))))]
12821
  "TARGET_SHMEDIA32"
12822
  "ldlo.l       %U1, %0"
12823
  [(set_attr "type" "load_media")])
12824
 
12825
(define_insn "ldlo_q"
12826
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12827
        (zero_extract:DI
12828
         (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
12829
                         (const_int -8)))
12830
         (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
12831
         (and:SI (match_dup 1) (const_int 7))))]
12832
  "TARGET_SHMEDIA32"
12833
  "ldlo.q       %U1, %0"
12834
  [(set_attr "type" "load_media")])
12835
 
12836
(define_insn_and_split "*ldlo_q_comb0"
12837
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12838
        (zero_extract:DI
12839
         (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
12840
                                  (match_operand:SI 2 "ua_offset" "I06"))
12841
                         (const_int -8)))
12842
         (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
12843
         (and:SI (match_dup 1) (const_int 7))))]
12844
  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
12845
  "#"
12846
  ""
12847
  [(pc)]
12848
  "emit_insn (gen_ldlo_q (operands[0],
12849
                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
12850
   DONE;")
12851
 
12852
(define_insn_and_split "*ldlo_q_comb1"
12853
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12854
        (zero_extract:DI
12855
         (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
12856
                                  (match_operand:SI 2 "ua_offset" "I06"))
12857
                         (const_int -8)))
12858
         (minus:SI (const_int 8)
12859
                   (and:SI (plus:SI (match_dup 1)
12860
                                    (match_operand:SI 3 "ua_offset" "I06"))
12861
                           (const_int 7)))
12862
         (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
12863
  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
12864
   && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
12865
  "#"
12866
  ""
12867
  [(pc)]
12868
  "emit_insn (gen_ldlo_q (operands[0],
12869
                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
12870
   DONE;")
12871
 
12872
(define_insn "sthi_l"
12873
  [(set (zero_extract:SI
12874
         (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
12875
                                  (const_int 3))
12876
                          (const_int -3)))
12877
         (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
12878
         (const_int 0))
12879
        (match_operand:SI 1 "arith_reg_operand" "r"))]
12880
  "TARGET_SHMEDIA32"
12881
  "sthi.l       %U0, %1"
12882
  [(set_attr "type" "ustore_media")])
12883
 
12884
;; All unaligned stores are considered to be 'narrow' because they typically
12885
;; operate on less that a quadword, and when they operate on a full quadword,
12886
;; the vanilla store high / store low sequence will cause a stall if not
12887
;; scheduled apart.
12888
(define_insn "sthi_q"
12889
  [(set (zero_extract:DI
12890
         (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
12891
                                  (const_int 7))
12892
                          (const_int -7)))
12893
         (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
12894
         (const_int 0))
12895
        (match_operand:DI 1 "arith_reg_operand" "r"))]
12896
  "TARGET_SHMEDIA32"
12897
  "sthi.q       %U0, %1"
12898
  [(set_attr "type" "ustore_media")])
12899
 
12900
(define_insn_and_split "*sthi_q_comb0"
12901
  [(set (zero_extract:DI
12902
         (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
12903
                                            "register_operand" "r")
12904
                                           (match_operand:SI 1 "ua_offset"
12905
                                            "I06"))
12906
                                  (const_int 7))
12907
                          (const_int -7)))
12908
         (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
12909
         (const_int 0))
12910
        (match_operand:DI 2 "arith_reg_operand" "r"))]
12911
  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
12912
  "#"
12913
  ""
12914
  [(pc)]
12915
  "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
12916
                          operands[2]));
12917
   DONE;")
12918
 
12919
(define_insn_and_split "*sthi_q_comb1"
12920
  [(set (zero_extract:DI
12921
         (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
12922
                                            "register_operand" "r")
12923
                                           (match_operand:SI 1 "ua_offset"
12924
                                            "I06"))
12925
                                  (const_int 7))
12926
                          (const_int -7)))
12927
         (plus:SI (and:SI (plus:SI (match_dup 0)
12928
                                   (match_operand:SI 2 "ua_offset" "I06"))
12929
                          (const_int 7))
12930
                  (const_int 1))
12931
         (const_int 0))
12932
        (match_operand:DI 3 "arith_reg_operand" "r"))]
12933
  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
12934
   && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
12935
  "#"
12936
  ""
12937
  [(pc)]
12938
  "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
12939
                          operands[3]));
12940
   DONE;")
12941
 
12942
;; This is highpart user because the address is used as full 64 bit.
12943
(define_insn "stlo_l"
12944
  [(set (zero_extract:SI
12945
         (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
12946
                         (const_int -4)))
12947
         (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
12948
         (and:SI (match_dup 0) (const_int 3)))
12949
        (match_operand:SI 1 "arith_reg_operand" "r"))]
12950
  "TARGET_SHMEDIA32"
12951
  "stlo.l       %U0, %1"
12952
  [(set_attr "type" "ustore_media")])
12953
 
12954
(define_insn "stlo_q"
12955
  [(set (zero_extract:DI
12956
         (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
12957
                         (const_int -8)))
12958
         (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
12959
         (and:SI (match_dup 0) (const_int 7)))
12960
        (match_operand:DI 1 "arith_reg_operand" "r"))]
12961
  "TARGET_SHMEDIA32"
12962
  "stlo.q       %U0, %1"
12963
  [(set_attr "type" "ustore_media")])
12964
 
12965
(define_insn_and_split "*stlo_q_comb0"
12966
  [(set (zero_extract:DI
12967
         (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
12968
                                  (match_operand:SI 1 "ua_offset" "I06"))
12969
                         (const_int -8)))
12970
         (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
12971
         (and:SI (match_dup 0) (const_int 7)))
12972
        (match_operand:DI 2 "arith_reg_operand" "r"))]
12973
  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
12974
  "#"
12975
  ""
12976
  [(pc)]
12977
  "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
12978
                          operands[2]));
12979
   DONE;")
12980
 
12981
(define_insn_and_split "*stlo_q_comb1"
12982
  [(set (zero_extract:DI
12983
         (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
12984
                                  (match_operand:SI 1 "ua_offset" "I06"))
12985
                         (const_int -8)))
12986
         (minus:SI (const_int 8) (and:SI (plus:SI (match_dup 0)
12987
                                                  (match_operand:SI 2
12988
                                                   "ua_offset" "I06"))
12989
                                         (const_int 7)))
12990
         (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
12991
        (match_operand:DI 3 "arith_reg_operand" "r"))]
12992
  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
12993
  "#"
12994
  ""
12995
  [(pc)]
12996
  "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
12997
                          operands[3]));
12998
   DONE;")
12999
 
13000
(define_insn "ldhi_l64"
13001
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13002
        (zero_extract:SI
13003
         (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13004
                                  (const_int 3))
13005
                          (const_int -3)))
13006
         (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
13007
         (const_int 0)))]
13008
  "TARGET_SHMEDIA64"
13009
  "ldhi.l       %U1, %0"
13010
  [(set_attr "type" "load_media")])
13011
 
13012
(define_insn "ldhi_q64"
13013
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13014
        (zero_extract:DI
13015
         (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13016
                                  (const_int 7))
13017
                          (const_int -7)))
13018
         (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
13019
         (const_int 0)))]
13020
  "TARGET_SHMEDIA64"
13021
  "ldhi.q       %U1, %0"
13022
  [(set_attr "type" "load_media")])
13023
 
13024
(define_insn "ldlo_l64"
13025
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13026
        (zero_extract:SI
13027
         (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13028
                         (const_int -4)))
13029
         (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
13030
         (and:DI (match_dup 1) (const_int 3))))]
13031
  "TARGET_SHMEDIA64"
13032
  "ldlo.l       %U1, %0"
13033
  [(set_attr "type" "load_media")])
13034
 
13035
(define_insn "ldlo_q64"
13036
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13037
        (zero_extract:DI
13038
         (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13039
                         (const_int -8)))
13040
         (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
13041
         (and:DI (match_dup 1) (const_int 7))))]
13042
  "TARGET_SHMEDIA64"
13043
  "ldlo.q       %U1, %0"
13044
  [(set_attr "type" "load_media")])
13045
 
13046
(define_insn "sthi_l64"
13047
  [(set (zero_extract:SI
13048
         (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13049
                                  (const_int 3))
13050
                          (const_int -3)))
13051
         (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
13052
         (const_int 0))
13053
        (match_operand:SI 1 "arith_reg_operand" "r"))]
13054
  "TARGET_SHMEDIA64"
13055
  "sthi.l       %U0, %1"
13056
  [(set_attr "type" "ustore_media")])
13057
 
13058
(define_insn "sthi_q64"
13059
  [(set (zero_extract:DI
13060
         (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13061
                                  (const_int 7))
13062
                          (const_int -7)))
13063
         (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
13064
         (const_int 0))
13065
        (match_operand:DI 1 "arith_reg_operand" "r"))]
13066
  "TARGET_SHMEDIA64"
13067
  "sthi.q       %U0, %1"
13068
  [(set_attr "type" "ustore_media")])
13069
 
13070
(define_insn "stlo_l64"
13071
  [(set (zero_extract:SI
13072
         (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13073
                         (const_int -4)))
13074
         (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
13075
         (and:DI (match_dup 0) (const_int 3)))
13076
        (match_operand:SI 1 "arith_reg_operand" "r"))]
13077
  "TARGET_SHMEDIA64"
13078
  "stlo.l       %U0, %1"
13079
  [(set_attr "type" "ustore_media")])
13080
 
13081
(define_insn "stlo_q64"
13082
  [(set (zero_extract:DI
13083
         (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13084
                         (const_int -8)))
13085
         (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
13086
         (and:DI (match_dup 0) (const_int 7)))
13087
        (match_operand:DI 1 "arith_reg_operand" "r"))]
13088
  "TARGET_SHMEDIA64"
13089
  "stlo.q       %U0, %1"
13090
  [(set_attr "type" "ustore_media")])
13091
 
13092
(define_insn "nsb"
13093
  [(set (match_operand:QI 0 "arith_reg_dest" "=r")
13094
        (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13095
                   UNSPEC_NSB))]
13096
  "TARGET_SHMEDIA"
13097
  "nsb  %1, %0"
13098
  [(set_attr "type" "arith_media")])
13099
 
13100
(define_insn "nsbsi"
13101
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13102
        (zero_extend:SI
13103
         (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13104
                    UNSPEC_NSB)))]
13105
  "TARGET_SHMEDIA"
13106
  "nsb  %1, %0"
13107
  [(set_attr "type" "arith_media")])
13108
 
13109
(define_insn "nsbdi"
13110
  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13111
        (zero_extend:DI
13112
         (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13113
                    UNSPEC_NSB)))]
13114
  "TARGET_SHMEDIA"
13115
  "nsb  %1, %0"
13116
  [(set_attr "type" "arith_media")])
13117
 
13118
(define_expand "ffsdi2"
13119
  [(set (match_operand:DI 0 "arith_reg_dest" "")
13120
        (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
13121
  "TARGET_SHMEDIA"
13122
  "
13123
{
13124
  rtx scratch = gen_reg_rtx (DImode);
13125
  rtx last;
13126
 
13127
  emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
13128
  emit_insn (gen_xordi3 (scratch, operands[1], scratch));
13129
  emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
13130
  emit_insn (gen_nsbdi (scratch, scratch));
13131
  emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
13132
  emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
13133
  last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
13134
  REG_NOTES (last)
13135
    = gen_rtx_EXPR_LIST (REG_EQUAL,
13136
                         gen_rtx_FFS (DImode, operands[0]), REG_NOTES (last));
13137
  DONE;
13138
}")
13139
 
13140
(define_expand "ffssi2"
13141
  [(set (match_operand:SI 0 "arith_reg_dest" "")
13142
        (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
13143
  "TARGET_SHMEDIA"
13144
  "
13145
{
13146
  rtx scratch = gen_reg_rtx (SImode);
13147
  rtx discratch = gen_reg_rtx (DImode);
13148
  rtx last;
13149
 
13150
  emit_insn (gen_adddi3 (discratch,
13151
                         simplify_gen_subreg (DImode, operands[1], SImode, 0),
13152
                         constm1_rtx));
13153
  emit_insn (gen_andcdi3 (discratch,
13154
                          simplify_gen_subreg (DImode, operands[1], SImode, 0),
13155
                          discratch));
13156
  emit_insn (gen_nsbsi (scratch, discratch));
13157
  last = emit_insn (gen_subsi3 (operands[0],
13158
                                force_reg (SImode, GEN_INT (63)), scratch));
13159
  REG_NOTES (last)
13160
    = gen_rtx_EXPR_LIST (REG_EQUAL,
13161
                         gen_rtx_FFS (SImode, operands[0]), REG_NOTES (last));
13162
  DONE;
13163
}")
13164
 
13165
(define_insn "byterev"
13166
  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13167
        (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
13168
                         (parallel [(const_int 7) (const_int 6) (const_int 5)
13169
                                    (const_int 4) (const_int 3) (const_int 2)
13170
                                    (const_int 1) (const_int 0)])))]
13171
  "TARGET_SHMEDIA"
13172
  "byterev      %1, %0"
13173
  [(set_attr "type" "arith_media")])
13174
 
13175
(define_insn "*prefetch_media"
13176
  [(prefetch (match_operand:QI 0 "address_operand" "p")
13177
             (match_operand:SI 1 "const_int_operand" "n")
13178
             (match_operand:SI 2 "const_int_operand" "n"))]
13179
  "TARGET_SHMEDIA"
13180
  "*
13181
{
13182
  operands[0] = gen_rtx_MEM (QImode, operands[0]);
13183
  output_asm_insn (\"ld%M0.b    %m0,r63\", operands);
13184
  return \"\";
13185
}"
13186
  [(set_attr "type" "other")])
13187
 
13188
(define_insn "*prefetch_i4"
13189
  [(prefetch (match_operand:SI 0 "register_operand" "r")
13190
             (match_operand:SI 1 "const_int_operand" "n")
13191
             (match_operand:SI 2 "const_int_operand" "n"))]
13192
  "TARGET_HARD_SH4 || TARGET_SHCOMPACT"
13193
  "*
13194
{
13195
  return \"pref @%0\";
13196
}"
13197
  [(set_attr "type" "other")])
13198
 
13199
(define_expand "prefetch"
13200
  [(prefetch (match_operand 0 "address_operand" "p")
13201
             (match_operand:SI 1 "const_int_operand" "n")
13202
             (match_operand:SI 2 "const_int_operand" "n"))]
13203
  "TARGET_HARD_SH4 || TARGET_SH5"
13204
  "
13205
{
13206
  if (GET_MODE (operands[0]) != Pmode
13207
      || GET_CODE (operands[1]) != CONST_INT
13208
      || GET_CODE (operands[2]) != CONST_INT)
13209
    FAIL;
13210
  if (! TARGET_SHMEDIA)
13211
    operands[0] = force_reg (Pmode, operands[0]);
13212
}")
13213
 
13214
(define_insn "alloco_i"
13215
  [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
13216
        (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
13217
  "TARGET_SHMEDIA32"
13218
  "*
13219
{
13220
  rtx xops[2];
13221
 
13222
  if (GET_CODE (operands[0]) == PLUS)
13223
    {
13224
      xops[0] = XEXP (operands[0], 0);
13225
      xops[1] = XEXP (operands[0], 1);
13226
    }
13227
  else
13228
    {
13229
      xops[0] = operands[0];
13230
      xops[1] = const0_rtx;
13231
    }
13232
  output_asm_insn (\"alloco   %0, %1\", xops);
13233
  return \"\";
13234
}"
13235
  [(set_attr "type" "other")])
13236
 
13237
(define_split
13238
  [(set (match_operand 0 "any_register_operand" "")
13239
        (match_operand 1 "" ""))]
13240
  "TARGET_SHMEDIA && reload_completed"
13241
  [(set (match_dup 0) (match_dup 1))]
13242
  "
13243
{
13244
  int n_changes = 0;
13245
 
13246
  for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
13247
  if (!n_changes)
13248
    FAIL;
13249
}")
13250
 
13251
; Stack Protector Patterns
13252
 
13253
(define_expand "stack_protect_set"
13254
  [(set (match_operand 0 "memory_operand" "")
13255
        (match_operand 1 "memory_operand" ""))]
13256
  ""
13257
{
13258
  if (TARGET_SHMEDIA)
13259
    {
13260
      if (TARGET_SHMEDIA64)
13261
        emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
13262
      else
13263
        emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
13264
    }
13265
  else
13266
    emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
13267
 
13268
  DONE;
13269
})
13270
 
13271
(define_insn "stack_protect_set_si"
13272
  [(set (match_operand:SI 0 "memory_operand" "=m")
13273
        (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13274
   (set (match_scratch:SI 2 "=&r") (const_int 0))]
13275
  "!TARGET_SHMEDIA"
13276
  "mov.l\t%1, %2\;mov.l\t%2, %0\;mov\t#0, %2"
13277
  [(set_attr "type" "other")
13278
   (set_attr "length" "6")])
13279
 
13280
(define_insn "stack_protect_set_si_media"
13281
  [(set (match_operand:SI 0 "memory_operand" "=m")
13282
        (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13283
   (set (match_scratch:SI 2 "=&r") (const_int 0))]
13284
  "TARGET_SHMEDIA"
13285
  "ld%M1.l\t%m1, %2\;st%M0.l\t%m0, %2\;movi\t0, %2"
13286
  [(set_attr "type" "other")
13287
   (set_attr "length" "12")])
13288
 
13289
(define_insn "stack_protect_set_di_media"
13290
  [(set (match_operand:DI 0 "memory_operand" "=m")
13291
        (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13292
   (set (match_scratch:DI 2 "=&r") (const_int 0))]
13293
  "TARGET_SHMEDIA64"
13294
  "ld%M1.q\t%m1, %2\;st%M0.q\t%m0, %2\;movi\t0, %2"
13295
  [(set_attr "type" "other")
13296
   (set_attr "length" "12")])
13297
 
13298
(define_expand "stack_protect_test"
13299
  [(match_operand 0 "memory_operand" "")
13300
   (match_operand 1 "memory_operand" "")
13301
   (match_operand 2 "" "")]
13302
  ""
13303
{
13304
  if (TARGET_SHMEDIA)
13305
    {
13306
      rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
13307
 
13308
      if (TARGET_SHMEDIA64)
13309
        emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
13310
                                                    operands[1]));
13311
      else
13312
        emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
13313
                                                    operands[1]));
13314
 
13315
      emit_jump_insn (gen_bne_media (operands[2], tmp, const0_rtx));
13316
    }
13317
  else
13318
    {
13319
      emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
13320
      emit_jump_insn (gen_branch_true (operands[2]));
13321
    }
13322
 
13323
  DONE;
13324
})
13325
 
13326
(define_insn "stack_protect_test_si"
13327
  [(set (reg:SI T_REG)
13328
        (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
13329
                    (match_operand:SI 1 "memory_operand" "m")]
13330
                   UNSPEC_SP_TEST))
13331
  (set (match_scratch:SI 2 "=&r") (const_int 0))
13332
  (set (match_scratch:SI 3 "=&r") (const_int 0))]
13333
  "!TARGET_SHMEDIA"
13334
  "mov.l\t%0, %2\;mov.l\t%1, %3\;cmp/eq\t%2, %3\;mov\t#0, %2\;mov\t#0, %3"
13335
  [(set_attr "type" "other")
13336
   (set_attr "length" "10")])
13337
 
13338
(define_insn "stack_protect_test_si_media"
13339
  [(set (match_operand:SI 0 "register_operand" "=&r")
13340
        (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
13341
                    (match_operand:SI 2 "memory_operand" "m")]
13342
                   UNSPEC_SP_TEST))
13343
  (set (match_scratch:SI 3 "=&r") (const_int 0))]
13344
  "TARGET_SHMEDIA"
13345
  "ld%M1.l\t%m1, %0\;ld%M2.l\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13346
  [(set_attr "type" "other")
13347
   (set_attr "length" "16")])
13348
 
13349
(define_insn "stack_protect_test_di_media"
13350
  [(set (match_operand:DI 0 "register_operand" "=&r")
13351
        (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
13352
                    (match_operand:DI 2 "memory_operand" "m")]
13353
                   UNSPEC_SP_TEST))
13354
  (set (match_scratch:DI 3 "=&r") (const_int 0))]
13355
  "TARGET_SHMEDIA64"
13356
  "ld%M1.q\t%m1, %0\;ld%M2.q\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13357
  [(set_attr "type" "other")
13358
   (set_attr "length" "16")])

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.