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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [c6x/] [c6x.md] - Blame information for rev 867

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
;; Machine description for TI C6X.
2
;; Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc.
3
;; Contributed by Andrew Jenner 
4
;; Contributed by Bernd Schmidt 
5
;; Contributed by CodeSourcery.
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
;; Register names
25
 
26
(define_constants
27
  [(REG_A0 0)
28
   (REG_A1 1)
29
   (REG_A2 2)
30
   (REG_A3 3)
31
   (REG_A4 4)
32
   (REG_A5 5)
33
   (REG_A6 6)
34
   (REG_A7 7)
35
   (REG_A8 8)
36
   (REG_A9 9)
37
   (REG_A10 10)
38
   (REG_A11 11)
39
   (REG_A12 12)
40
   (REG_A13 13)
41
   (REG_A14 14)
42
   (REG_A15 15)
43
   (REG_A16 16)
44
   (REG_A17 17)
45
   (REG_A18 18)
46
   (REG_A19 19)
47
   (REG_A20 20)
48
   (REG_A21 21)
49
   (REG_A22 22)
50
   (REG_A23 23)
51
   (REG_A24 24)
52
   (REG_A25 25)
53
   (REG_A26 26)
54
   (REG_A27 27)
55
   (REG_A28 28)
56
   (REG_A29 29)
57
   (REG_A30 30)
58
   (REG_A31 31)
59
   (REG_B0 32)
60
   (REG_B1 33)
61
   (REG_B2 34)
62
   (REG_B3 35)
63
   (REG_B4 36)
64
   (REG_B5 37)
65
   (REG_B6 38)
66
   (REG_B7 39)
67
   (REG_B8 40)
68
   (REG_B9 41)
69
   (REG_B10 42)
70
   (REG_B11 43)
71
   (REG_B12 44)
72
   (REG_B13 45)
73
   (REG_B14 46)
74
   (REG_SP 47)
75
   (REG_B15 47)
76
   (REG_B16 48)
77
   (REG_B17 49)
78
   (REG_B18 50)
79
   (REG_B19 51)
80
   (REG_B20 52)
81
   (REG_B21 53)
82
   (REG_B22 54)
83
   (REG_B23 55)
84
   (REG_B24 56)
85
   (REG_B25 57)
86
   (REG_B26 58)
87
   (REG_B27 59)
88
   (REG_B28 60)
89
   (REG_B29 61)
90
   (REG_B30 62)
91
   (REG_B31 63)
92
   (REG_FRAME 64)
93
   (REG_ARGP 65)
94
   (REG_ILC 66)])
95
 
96
(define_c_enum "unspec" [
97
   UNSPEC_NOP
98
   UNSPEC_RCP
99
   UNSPEC_MISALIGNED_ACCESS
100
   UNSPEC_ADDKPC
101
   UNSPEC_SETUP_DSBT
102
   UNSPEC_LOAD_GOT
103
   UNSPEC_LOAD_SDATA
104
   UNSPEC_BITREV
105
   UNSPEC_GOTOFF
106
   UNSPEC_MVILC
107
   UNSPEC_REAL_JUMP
108
   UNSPEC_REAL_LOAD
109
   UNSPEC_REAL_MULT
110
   UNSPEC_JUMP_SHADOW
111
   UNSPEC_LOAD_SHADOW
112
   UNSPEC_MULT_SHADOW
113
   UNSPEC_EPILOGUE_BARRIER
114
   UNSPEC_ATOMIC
115
   UNSPEC_CLR
116
   UNSPEC_EXT
117
   UNSPEC_EXTU
118
   UNSPEC_SUBC
119
   UNSPEC_AVG
120
])
121
 
122
(define_c_enum "unspecv" [
123
   UNSPECV_BLOCKAGE
124
   UNSPECV_SPLOOP
125
   UNSPECV_SPKERNEL
126
   UNSPECV_EH_RETURN
127
   UNSPECV_CAS
128
])
129
 
130
;; -------------------------------------------------------------------------
131
;; Instruction attributes
132
;; -------------------------------------------------------------------------
133
 
134
(define_attr "cpu"
135
  "c62x,c64x,c64xp,c67x,c67xp,c674x"
136
  (const (symbol_ref "(enum attr_cpu)c6x_arch")))
137
 
138
;; Define a type for each insn which is used in the scheduling description.
139
;; These correspond to the types defined in chapter 4 of the C674x manual.
140
(define_attr "type"
141
  "unknown,single,mpy2,store,storen,mpy4,load,loadn,branch,call,callp,dp2,fp4,
142
   intdp,cmpdp,adddp,mpy,mpyi,mpyid,mpydp,mpyspdp,mpysp2dp,spkernel,sploop,
143
   mvilc,blockage,shadow,load_shadow,mult_shadow,atomic"
144
  (const_string "single"))
145
 
146
;; The register file used by an instruction's destination register.
147
;; The function destreg_file computes this; instructions can override the
148
;; attribute if they aren't a single_set.
149
(define_attr "dest_regfile"
150
  "unknown,any,a,b"
151
  (cond [(eq_attr "type" "single,load,mpy2,mpy4,dp2,fp4,intdp,cmpdp,adddp,mpy,mpyi,mpyid,mpydp,mpyspdp,mpysp2dp")
152
         (cond [(match_operand 0 "a_register" "") (const_string "a")
153
                (match_operand 0 "b_register" "") (const_string "b")]
154
               (const_string "unknown"))
155
         (eq_attr "type" "store")
156
                (cond [(match_operand 1 "a_register" "") (const_string "a")
157
                       (match_operand 1 "b_register" "") (const_string "b")]
158
               (const_string "unknown"))]
159
        (const_string "unknown")))
160
 
161
(define_attr "addr_regfile"
162
  "unknown,a,b"
163
  (const_string "unknown"))
164
 
165
(define_attr "cross"
166
  "n,y"
167
  (const_string "n"))
168
 
169
;; This describes the relationship between operands and register files.
170
;; For example, "sxs" means that operands 0 and 2 determine the side of
171
;; the machine, and operand 1 can optionally use the cross path.  "dt" and
172
;; "td" are used to describe loads and stores.
173
;; Used for register renaming in loops for improving modulo scheduling.
174
(define_attr "op_pattern"
175
  "unknown,dt,td,sx,sxs,ssx"
176
  (cond [(eq_attr "type" "load") (const_string "td")
177
         (eq_attr "type" "store") (const_string "dt")]
178
        (const_string "unknown")))
179
 
180
(define_attr "has_shadow"
181
  "n,y"
182
  (const_string "n"))
183
 
184
;; The number of cycles the instruction takes to finish.  Any cycles above
185
;; the first are delay slots.
186
(define_attr "cycles" ""
187
  (cond [(eq_attr "type" "branch,call") (const_int 6)
188
         (eq_attr "type" "load,loadn") (const_int 5)
189
         (eq_attr "type" "dp2") (const_int 2)
190
         (eq_attr "type" "mpy2") (const_int 2)
191
         (eq_attr "type" "mpy4") (const_int 4)
192
         (eq_attr "type" "fp4") (const_int 4)
193
         (eq_attr "type" "mvilc") (const_int 4)
194
         (eq_attr "type" "cmpdp") (const_int 2)
195
         (eq_attr "type" "intdp") (const_int 5)
196
         (eq_attr "type" "adddp") (const_int 7)
197
         (eq_attr "type" "mpydp") (const_int 10)
198
         (eq_attr "type" "mpyi") (const_int 9)
199
         (eq_attr "type" "mpyid") (const_int 10)
200
         (eq_attr "type" "mpyspdp") (const_int 7)
201
         (eq_attr "type" "mpysp2dp") (const_int 5)]
202
        (const_int 1)))
203
 
204
;; The number of cycles during which the instruction reserves functional
205
;; units.
206
(define_attr "reserve_cycles" ""
207
  (cond [(eq_attr "type" "cmpdp") (const_int 2)
208
         (eq_attr "type" "adddp") (const_int 2)
209
         (eq_attr "type" "mpydp") (const_int 4)
210
         (eq_attr "type" "mpyi") (const_int 4)
211
         (eq_attr "type" "mpyid") (const_int 4)
212
         (eq_attr "type" "mpyspdp") (const_int 2)]
213
        (const_int 1)))
214
 
215
(define_attr "predicable" "no,yes"
216
  (const_string "yes"))
217
 
218
(define_attr "enabled" "no,yes"
219
  (const_string "yes"))
220
 
221
;; Specify which units can be used by a given instruction.  Normally,
222
;; dest_regfile is used to select between the two halves of the machine.
223
;; D_ADDR is for load/store instructions; they use the D unit and use
224
;; addr_regfile to choose between D1 and D2.
225
 
226
(define_attr "units62"
227
  "unknown,d,d_addr,l,m,s,dl,ds,dls,ls"
228
  (const_string "unknown"))
229
 
230
(define_attr "units64"
231
  "unknown,d,d_addr,l,m,s,dl,ds,dls,ls"
232
  (const_string "unknown"))
233
 
234
(define_attr "units64p"
235
  "unknown,d,d_addr,l,m,s,dl,ds,dls,ls"
236
  (attr "units64"))
237
 
238
(define_attr "units67"
239
  "unknown,d,d_addr,l,m,s,dl,ds,dls,ls"
240
  (attr "units62"))
241
 
242
(define_attr "units67p"
243
  "unknown,d,d_addr,l,m,s,dl,ds,dls,ls"
244
  (attr "units67"))
245
 
246
(define_attr "units674"
247
  "unknown,d,d_addr,l,m,s,dl,ds,dls,ls"
248
  (attr "units64"))
249
 
250
(define_attr "units"
251
  "unknown,d,d_addr,l,m,s,dl,ds,dls,ls"
252
  (cond [(eq_attr "cpu" "c62x")
253
           (attr "units62")
254
         (eq_attr "cpu" "c67x")
255
           (attr "units67")
256
         (eq_attr "cpu" "c67xp")
257
           (attr "units67p")
258
         (eq_attr "cpu" "c64x")
259
           (attr "units64")
260
         (eq_attr "cpu" "c64xp")
261
           (attr "units64p")
262
         (eq_attr "cpu" "c674x")
263
           (attr "units674")
264
        ]
265
        (const_string "unknown")))
266
 
267
(define_automaton "c6x_1,c6x_2,c6x_m1,c6x_m2,c6x_t1,c6x_t2,c6x_branch")
268
(automata_option "no-comb-vect")
269
(automata_option "ndfa")
270
(automata_option "collapse-ndfa")
271
 
272
(define_query_cpu_unit "d1,l1,s1" "c6x_1")
273
(define_cpu_unit "x1" "c6x_1")
274
(define_cpu_unit "l1w,s1w" "c6x_1")
275
(define_query_cpu_unit "m1" "c6x_m1")
276
(define_cpu_unit "m1w" "c6x_m1")
277
(define_cpu_unit "t1" "c6x_t1")
278
(define_query_cpu_unit "d2,l2,s2" "c6x_2")
279
(define_cpu_unit "x2" "c6x_2")
280
(define_cpu_unit "l2w,s2w" "c6x_2")
281
(define_query_cpu_unit "m2" "c6x_m2")
282
(define_cpu_unit "m2w" "c6x_m2")
283
(define_cpu_unit "t2" "c6x_t2")
284
;; A special set of units used to identify specific reservations, rather than
285
;; just units.
286
(define_query_cpu_unit "fps1,fpl1,adddps1,adddpl1" "c6x_1")
287
(define_query_cpu_unit "fps2,fpl2,adddps2,adddpl2" "c6x_2")
288
 
289
;; There can be up to two branches in one cycle (on the .s1 and .s2
290
;; units), but some instructions must not be scheduled in parallel
291
;; with a branch.  We model this by reserving either br0 or br1 for a
292
;; normal branch, and both of them for an insn such as callp.
293
;; Another constraint is that two branches may only execute in parallel
294
;; if one uses an offset, and the other a register.  We can distinguish
295
;; these by the dest_regfile attribute; it is "any" iff the branch uses
296
;; an offset.  br0 is reserved for these, while br1 is reserved for
297
;; branches using a register.
298
(define_cpu_unit "br0,br1" "c6x_branch")
299
 
300
(include "c6x-sched.md")
301
 
302
;; Some reservations which aren't generated from c6x-sched.md.in
303
 
304
(define_insn_reservation "branch_s1any" 6
305
  (and (eq_attr "type" "branch")
306
       (and (eq_attr "cross" "n")
307
            (and (eq_attr "units" "s")
308
                 (eq_attr "dest_regfile" "any"))))
309
  "s1+s1w+br0")
310
 
311
;; For calls, we also reserve the units needed in the following cycles
312
;; to load the return address.  There are two options; using addkpc or
313
;; mvkh/mvkl.  The code in c6x_reorg knows whether to use one of these
314
;; or whether to use callp.  The actual insns are emitted only after
315
;; the final scheduling pass is complete.
316
;; We always reserve S2 for PC-relative call insns, since that allows
317
;; us to turn them into callp insns later on.
318
(define_insn_reservation "call_addkpc_s1any" 6
319
  (and (eq_attr "type" "call")
320
       (and (ne (symbol_ref "TARGET_INSNS_64") (const_int 0))
321
            (and (eq_attr "cross" "n")
322
                 (and (eq_attr "units" "s")
323
                      (eq_attr "dest_regfile" "any")))))
324
  "s2+s2w+br0,s2+s2w+br0+br1")
325
 
326
(define_insn_reservation "call_mvk_s1any" 6
327
  (and (eq_attr "type" "call")
328
       (and (eq (symbol_ref "TARGET_INSNS_64") (const_int 0))
329
            (and (eq_attr "cross" "n")
330
                 (and (eq_attr "units" "s")
331
                      (eq_attr "dest_regfile" "any")))))
332
  "s2+s2w+br0,s2+s2w,s2+s2w")
333
 
334
(define_reservation "all" "s1+s2+d1+d2+l1+l2+m1+m2")
335
 
336
(define_insn_reservation "callp_s1" 1
337
  (and (eq_attr "type" "callp") (eq_attr "dest_regfile" "a"))
338
  "s1+s1w,all*5")
339
 
340
(define_insn_reservation "callp_s2" 1
341
  (and (eq_attr "type" "callp") (eq_attr "dest_regfile" "b"))
342
  "s2+s2w,all*5")
343
 
344
;; Constraints
345
 
346
(include "constraints.md")
347
 
348
;; Predicates
349
 
350
(include "predicates.md")
351
 
352
;; General predication pattern.
353
 
354
(define_cond_exec
355
  [(match_operator 0 "eqne_operator"
356
    [(match_operand 1 "predicate_register" "AB")
357
     (const_int 0)])]
358
  ""
359
  "")
360
 
361
;; -------------------------------------------------------------------------
362
;; NOP instruction
363
;; -------------------------------------------------------------------------
364
 
365
(define_insn "nop"
366
  [(const_int 0)]
367
  ""
368
  "nop")
369
 
370
(define_insn "nop_count"
371
  [(unspec [(match_operand 0 "const_int_operand" "n")] UNSPEC_NOP)]
372
  ""
373
  "%|%.\\tnop\\t%0")
374
 
375
;; -------------------------------------------------------------------------
376
;; Move instructions
377
;; -------------------------------------------------------------------------
378
 
379
(define_mode_iterator QIHIM [QI HI])
380
(define_mode_iterator SIDIM [SI DI])
381
(define_mode_iterator SIDIVM [SI DI V2HI V4QI])
382
(define_mode_iterator VEC4M [V2HI V4QI])
383
(define_mode_iterator VEC8M [V2SI V4HI V8QI])
384
(define_mode_iterator SISFVM [SI SF V2HI V4QI])
385
(define_mode_iterator DIDFM [DI DF])
386
(define_mode_iterator DIDFVM [DI DF V2SI V4HI V8QI])
387
(define_mode_iterator SFDFM [SF DF])
388
(define_mode_iterator M32 [QI HI SI SF V2HI V4QI])
389
 
390
;; The C6X LO_SUM and HIGH are backwards - HIGH sets the low bits, and
391
;; LO_SUM adds in the high bits.  Fortunately these are opaque operations
392
;; so this does not matter.
393
(define_insn "movsi_lo_sum"
394
  [(set (match_operand:SI 0 "register_operand" "=ab")
395
        (lo_sum:SI (match_operand:SI 1 "register_operand" "0")
396
                   (match_operand:SI 2 "const_int_or_symbolic_operand" "i")))]
397
  "reload_completed"
398
  "%|%.\\tmvkh\\t%$\\t%2, %0"
399
  [(set_attr "units" "s")])
400
 
401
(define_insn "movsi_high"
402
  [(set (match_operand:SI 0 "register_operand" "=ab")
403
        (high:SI (match_operand:SI 1 "const_int_or_symbolic_operand" "i")))]
404
  "reload_completed"
405
  "%|%.\\tmvkl\\t%$\\t%1, %0"
406
  [(set_attr "units" "s")])
407
 
408
(define_insn "movsi_gotoff_lo_sum"
409
  [(set (match_operand:SI 0 "register_operand" "=ab")
410
        (lo_sum:SI (match_operand:SI 1 "register_operand" "0")
411
                   (unspec:SI [(match_operand:SI 2 "symbolic_operand" "S2")]
412
                              UNSPEC_GOTOFF)))]
413
  "flag_pic == 2"
414
  "%|%.\\tmvkh\\t%$\\t$dpr_got%2, %0"
415
  [(set_attr "units" "s")])
416
 
417
(define_insn "movsi_gotoff_high"
418
  [(set (match_operand:SI 0 "register_operand" "=ab")
419
        (high:SI (unspec:SI [(match_operand:SI 1 "symbolic_operand" "S2")]
420
                            UNSPEC_GOTOFF)))]
421
  "flag_pic == 2"
422
  "%|%.\\tmvkl\\t%$\\t$dpr_got%1, %0"
423
  [(set_attr "units" "s")])
424
 
425
;; Normally we'd represent this as a normal load insn, but we can't currently
426
;; represent the addressing mode.
427
(define_insn "load_got_gotoff"
428
  [(set (match_operand:SI 0 "register_operand" "=a,b")
429
        (unspec:SI [(match_operand:SI 1 "register_operand" "Z,Z")
430
                    (match_operand:SI 2 "register_operand" "b,b")]
431
                   UNSPEC_GOTOFF))]
432
  "flag_pic == 2"
433
  "%|%.\\tldw\\t%$\\t*+%1[%2], %0"
434
  [(set_attr "type" "load")
435
   (set_attr "units" "d_addr")
436
   (set_attr "dest_regfile" "a,b")
437
   (set_attr "addr_regfile" "b")])
438
 
439
(define_insn "*movstricthi_high"
440
  [(set (match_operand:SI 0 "register_operand" "+ab")
441
        (ior:SI (and:SI (match_dup 0) (const_int 65535))
442
                (ashift:SI (match_operand:SI 1 "const_int_operand" "IuB")
443
                           (const_int 16))))]
444
  "reload_completed"
445
  "%|%.\\tmvklh\\t%$\\t%1, %0"
446
  [(set_attr "units" "s")])
447
 
448
;; Break up SImode loads of immediate operands.
449
 
450
(define_split
451
  [(set (match_operand:SI 0 "register_operand" "")
452
        (match_operand:SI 1 "const_int_operand" ""))]
453
  "reload_completed
454
   && !satisfies_constraint_IsB (operands[1])"
455
  [(set (match_dup 0) (match_dup 2))
456
   (set (match_dup 0) (ior:SI (and:SI (match_dup 0) (const_int 65535))
457
                              (ashift:SI (match_dup 3) (const_int 16))))]
458
{
459
  HOST_WIDE_INT val = INTVAL (operands[1]);
460
  operands[2] = GEN_INT (trunc_int_for_mode (val, HImode));
461
  operands[3] = GEN_INT ((val >> 16) & 65535);
462
})
463
 
464
(define_split
465
  [(set (match_operand:VEC4M 0 "register_operand" "")
466
        (match_operand:VEC4M 1 "const_vector_operand" ""))]
467
  "reload_completed"
468
  [(set (match_dup 2) (match_dup 3))]
469
{
470
  unsigned HOST_WIDE_INT mask, val;
471
  enum machine_mode inner_mode = GET_MODE_INNER (mode);
472
  int i;
473
 
474
  val = 0;
475
  mask = GET_MODE_MASK (inner_mode);
476
  if (TARGET_BIG_ENDIAN)
477
    {
478
      for (i = 0; i < GET_MODE_NUNITS (mode); i++)
479
        {
480
          val <<= GET_MODE_BITSIZE (inner_mode);
481
          val |= INTVAL (CONST_VECTOR_ELT (operands[1], i)) & mask;
482
        }
483
    }
484
  else
485
    {
486
      i = GET_MODE_NUNITS (mode);
487
      while (i-- > 0)
488
        {
489
          val <<= GET_MODE_BITSIZE (inner_mode);
490
          val |= INTVAL (CONST_VECTOR_ELT (operands[1], i)) & mask;
491
        }
492
    }
493
  operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]));
494
  operands[3] = GEN_INT (trunc_int_for_mode (val, SImode));
495
})
496
 
497
(define_split
498
  [(set (match_operand:VEC8M 0 "register_operand" "")
499
        (match_operand:VEC8M 1 "const_vector_operand" ""))]
500
  "reload_completed"
501
  [(set (match_dup 2) (match_dup 3))
502
   (set (match_dup 4) (match_dup 5))]
503
{
504
  unsigned HOST_WIDE_INT mask;
505
  unsigned HOST_WIDE_INT val[2];
506
  rtx lo_half, hi_half;
507
  enum machine_mode inner_mode = GET_MODE_INNER (mode);
508
  int i, j;
509
 
510
  split_di (operands, 1, &lo_half, &hi_half);
511
 
512
  val[0] = val[1] = 0;
513
  mask = GET_MODE_MASK (inner_mode);
514
  if (TARGET_BIG_ENDIAN)
515
    {
516
      for (i = 0, j = 1; i < GET_MODE_NUNITS (mode); i++)
517
        {
518
          if (i * 2 == GET_MODE_NUNITS (mode))
519
            j--;
520
          val[j] <<= GET_MODE_BITSIZE (inner_mode);
521
          val[j] |= INTVAL (CONST_VECTOR_ELT (operands[1], i)) & mask;
522
        }
523
    }
524
  else
525
    {
526
      i = GET_MODE_NUNITS (mode);
527
      j = 1;
528
      while (i-- > 0)
529
        {
530
          val[j] <<= GET_MODE_BITSIZE (inner_mode);
531
          val[j] |= INTVAL (CONST_VECTOR_ELT (operands[1], i)) & mask;
532
          if (i * 2 == GET_MODE_NUNITS (mode))
533
            j--;
534
        }
535
    }
536
  operands[2] = lo_half;
537
  operands[3] = GEN_INT (trunc_int_for_mode (val[0], SImode));
538
  operands[4] = hi_half;
539
  operands[5] = GEN_INT (trunc_int_for_mode (val[1], SImode));
540
})
541
 
542
(define_split
543
  [(set (match_operand:SF 0 "register_operand" "")
544
        (match_operand:SF 1 "immediate_operand" ""))]
545
  "reload_completed"
546
  [(set (match_dup 2) (match_dup 3))
547
   (set (match_dup 2) (ior:SI (and:SI (match_dup 2) (const_int 65535))
548
                              (ashift:SI (match_dup 4) (const_int 16))))]
549
{
550
  long values;
551
  REAL_VALUE_TYPE value;
552
 
553
  gcc_assert (GET_CODE (operands[1]) == CONST_DOUBLE);
554
 
555
  REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
556
  REAL_VALUE_TO_TARGET_SINGLE (value, values);
557
 
558
  operands[2] = gen_rtx_REG (SImode, true_regnum (operands[0]));
559
  operands[3] = GEN_INT (trunc_int_for_mode (values, HImode));
560
  if (values >= -32768 && values < 32768)
561
    {
562
      emit_move_insn (operands[2], operands[3]);
563
      DONE;
564
    }
565
  operands[4] = GEN_INT ((values >> 16) & 65535);
566
})
567
 
568
(define_split
569
  [(set (match_operand:SI 0 "register_operand" "")
570
        (match_operand:SI 1 "symbolic_operand" ""))]
571
  "reload_completed
572
   && (!TARGET_INSNS_64PLUS
573
       || !sdata_symbolic_operand (operands[1], SImode))"
574
  [(set (match_dup 0) (high:SI (match_dup 1)))
575
   (set (match_dup 0) (lo_sum:SI (match_dup 0) (match_dup 1)))]
576
  "")
577
 
578
;; Normally, we represent the load of an sdata address as a normal
579
;; move of a SYMBOL_REF.  In DSBT mode, B14 is not constant, so we
580
;; should show the dependency.
581
(define_insn "load_sdata_pic"
582
  [(set (match_operand:SI 0 "register_operand" "=a,b")
583
        (plus:SI (match_operand:SI 1 "pic_register_operand" "Z,Z")
584
                 (unspec:SI [(match_operand:SI 2 "sdata_symbolic_operand" "S0,S0")]
585
                            UNSPEC_LOAD_SDATA)))]
586
  "flag_pic"
587
  "@
588
   %|%.\\tadda%D2\\t%$\\t%1, %2, %0
589
   %|%.\\tadda%D2\\t%$\\t%1, %2, %0"
590
  [(set_attr "units" "d")
591
   (set_attr "cross" "y,n")
592
   (set_attr "op_pattern" "unknown")
593
   (set_attr "predicable" "no")])
594
 
595
;; Move instruction patterns
596
 
597
(define_mode_attr LDST_SUFFIX [(QI "b") (HI "h")
598
                               (SI "w") (SF "w") (V2HI "w") (V4QI "w")
599
                               (DI "dw") (V2SI "dw") (V4HI "dw") (V8QI "dw")])
600
 
601
(define_insn "mov_insn"
602
 [(set (match_operand:QIHIM 0 "nonimmediate_operand"
603
        "=a,b, a, b, ab, ab,a,?a, b,?b, Q, R, R, Q")
604
       (match_operand:QIHIM 1 "general_operand"
605
         "a,b,?b,?a,Is5,IsB,Q, R, R, Q, a,?a, b,?b"))]
606
  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) == REG"
607
 "@
608
  %|%.\\tmv\\t%$\\t%1, %0
609
  %|%.\\tmv\\t%$\\t%1, %0
610
  %|%.\\tmv\\t%$\\t%1, %0
611
  %|%.\\tmv\\t%$\\t%1, %0
612
  %|%.\\tmvk\\t%$\\t%1, %0
613
  %|%.\\tmvk\\t%$\\t%1, %0
614
  %|%.\\tld\\t%$\\t%1, %0
615
  %|%.\\tld\\t%$\\t%1, %0
616
  %|%.\\tld\\t%$\\t%1, %0
617
  %|%.\\tld\\t%$\\t%1, %0
618
  %|%.\\tst\\t%$\\t%1, %0
619
  %|%.\\tst\\t%$\\t%1, %0
620
  %|%.\\tst\\t%$\\t%1, %0
621
  %|%.\\tst\\t%$\\t%1, %0"
622
  [(set_attr "type" "*,*,*,*,*,*,load,load,load,load,store,store,store,store")
623
   (set_attr "units62" "dls,dls,ls,ls,s,s,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr")
624
   (set_attr "units64" "dls,dls,ls,ls,dl,s,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr")
625
   (set_attr "op_pattern" "sx,sx,sx,sx,*,*,*,*,*,*,*,*,*,*")
626
   (set_attr "addr_regfile" "*,*,*,*,*,*,a,b,b,a,a,b,b,a")
627
   (set_attr "dest_regfile" "*,*,*,*,*,*,a,a,b,b,a,a,b,b")
628
   (set_attr "cross" "n,n,y,y,n,n,n,y,n,y,n,y,n,y")])
629
 
630
(define_insn "mov_insn"
631
 [(set (match_operand:SISFVM 0 "nonimmediate_operand"
632
        "=a,b, a, b, ab, ab,a,b,ab,a,?a, b,?b, Q, R, R, Q")
633
       (match_operand:SISFVM 1 "general_operand"
634
         "a,b,?b,?a,Is5,IsB,S0,S0,Si,Q, R, R, Q, a,?a, b,?b"))]
635
  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) == REG
636
    || (GET_CODE (operands[1]) == SUBREG && REG_P (SUBREG_REG (operands[1]))))"
637
 "@
638
  %|%.\\tmv\\t%$\\t%1, %0
639
  %|%.\\tmv\\t%$\\t%1, %0
640
  %|%.\\tmv\\t%$\\t%1, %0
641
  %|%.\\tmv\\t%$\\t%1, %0
642
  %|%.\\tmvk\\t%$\\t%1, %0
643
  %|%.\\tmvk\\t%$\\t%1, %0
644
  %|%.\\tadda%D1\\t%$\\tB14, %1, %0
645
  %|%.\\tadda%D1\\t%$\\tB14, %1, %0
646
  #
647
  %|%.\\tldw\\t%$\\t%1, %0
648
  %|%.\\tldw\\t%$\\t%1, %0
649
  %|%.\\tldw\\t%$\\t%1, %0
650
  %|%.\\tldw\\t%$\\t%1, %0
651
  %|%.\\tstw\\t%$\\t%1, %0
652
  %|%.\\tstw\\t%$\\t%1, %0
653
  %|%.\\tstw\\t%$\\t%1, %0
654
  %|%.\\tstw\\t%$\\t%1, %0"
655
  [(set_attr "type" "*,*,*,*,*,*,*,*,*,load,load,load,load,store,store,store,store")
656
   (set_attr "units62" "dls,dls,ls,ls,s,s,d,d,*,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr")
657
   (set_attr "units64" "dls,dls,ls,ls,dl,s,d,d,*,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr")
658
   (set_attr "op_pattern" "sx,sx,sx,sx,*,*,*,*,*,*,*,*,*,*,*,*,*")
659
   (set_attr "addr_regfile" "*,*,*,*,*,*,*,*,*,a,b,b,a,a,b,b,a")
660
   (set_attr "dest_regfile" "*,*,*,*,*,*,*,*,*,a,a,b,b,a,a,b,b")
661
   (set_attr "cross" "n,n,y,y,n,n,y,n,*,n,y,n,y,n,y,n,y")
662
   (set_attr "predicable" "yes,yes,yes,yes,yes,yes,no,no,yes,yes,yes,yes,yes,yes,yes,yes,yes")])
663
 
664
(define_insn "*mov_insn"
665
  [(set (match_operand:DIDFVM 0 "nonimmediate_operand"
666
         "=a,b, a, b,ab,a,?a, b,?b, Q, R, R, Q")
667
        (match_operand:DIDFVM 1 "general_operand"
668
          "a,b,?b,?a,iF,Q, R, R, Q, a,?a, b,?b"))]
669
  "(!MEM_P (operands[0]) || REG_P (operands[1])
670
    || (GET_CODE (operands[1]) == SUBREG && REG_P (SUBREG_REG (operands[1]))))"
671
{
672
  if (MEM_P (operands[1]) && TARGET_LDDW)
673
    return "%|%.\\tlddw\\t%$\\t%1, %0";
674
  if (MEM_P (operands[0]) && TARGET_STDW)
675
    return "%|%.\\tstdw\\t%$\\t%1, %0";
676
  if (TARGET_INSNS_64PLUS && REG_P (operands[0]) && REG_P (operands[1])
677
      && A_REGNO_P (REGNO (operands[0])) == A_REGNO_P (REGNO (operands[1])))
678
    return "%|%.\\tdmv\\t%$\\t%P1, %p1, %0";
679
  return "#";
680
}
681
  [(set_attr "units" "s,s,*,*,*,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr")
682
   (set_attr "addr_regfile" "*,*,*,*,*,a,b,b,a,a,b,b,a")
683
   (set_attr "dest_regfile" "*,*,*,*,*,a,a,b,b,a,a,b,b")
684
   (set_attr "type" "*,*,*,*,*,load,load,load,load,store,store,store,store")
685
   (set_attr "cross" "n,n,y,y,*,n,y,n,y,n,y,n,y")])
686
 
687
(define_split
688
  [(set (match_operand:DIDFVM 0 "nonimmediate_operand" "")
689
        (match_operand:DIDFVM 1 "general_operand" ""))]
690
  "reload_completed
691
   && !((MEM_P (operands[0]) && TARGET_STDW)
692
        || (MEM_P (operands[1]) && TARGET_LDDW))
693
   && !const_vector_operand (operands[1], mode)
694
   && !(TARGET_INSNS_64PLUS && REG_P (operands[0]) && REG_P (operands[1])
695
        && A_REGNO_P (REGNO (operands[0])) == A_REGNO_P (REGNO (operands[1])))"
696
  [(set (match_dup 2) (match_dup 3))
697
   (set (match_dup 4) (match_dup 5))]
698
{
699
  rtx lo_half[2], hi_half[2];
700
  split_di (operands, 2, lo_half, hi_half);
701
 
702
  /* We can't have overlap for a register-register move, but if
703
     memory is involved, we have to make sure we don't clobber the
704
     address.  */
705
  if (reg_overlap_mentioned_p (lo_half[0], hi_half[1]))
706
    {
707
      operands[2] = hi_half[0];
708
      operands[3] = hi_half[1];
709
      operands[4] = lo_half[0];
710
      operands[5] = lo_half[1];
711
    }
712
  else
713
    {
714
      operands[2] = lo_half[0];
715
      operands[3] = lo_half[1];
716
      operands[4] = hi_half[0];
717
      operands[5] = hi_half[1];
718
    }
719
})
720
 
721
(define_insn "real_load"
722
  [(unspec [(match_operand 0 "const_int_operand" "JA,JA,JB,JB")
723
            (match_operand:M32 1 "memory_operand" "Q,R,R,Q")]
724
           UNSPEC_REAL_LOAD)]
725
  ""
726
  "%|%.\\tld\\t%$\\t%1, %k0"
727
  [(set_attr "type" "load")
728
   (set_attr "units" "d_addr")
729
   (set_attr "addr_regfile" "a,b,b,a")
730
   (set_attr "dest_regfile" "a,a,b,b")
731
   (set_attr "cross" "n,y,n,y")])
732
 
733
(define_insn "real_load"
734
  [(unspec [(match_operand 0 "const_int_operand" "JA,JA,JB,JB")
735
            (match_operand:DIDFVM 1 "memory_operand" "Q,R,R,Q")]
736
           UNSPEC_REAL_LOAD)]
737
  "TARGET_LDDW"
738
  "%|%.\\tlddw\\t%$\\t%1, %K0"
739
  [(set_attr "type" "load")
740
   (set_attr "units" "d_addr")
741
   (set_attr "addr_regfile" "a,b,b,a")
742
   (set_attr "dest_regfile" "a,a,b,b")
743
   (set_attr "cross" "n,y,n,y")])
744
 
745
(define_insn "load_shadow"
746
  [(set (match_operand 0 "register_operand" "=ab")
747
        (unspec [(pc)] UNSPEC_LOAD_SHADOW))]
748
  ""
749
  ";; load to %0 occurs"
750
  [(set_attr "type" "load_shadow")])
751
 
752
(define_insn "mult_shadow"
753
  [(set (match_operand 0 "register_operand" "=ab")
754
        (unspec [(pc)] UNSPEC_MULT_SHADOW))]
755
  ""
756
  ";; multiplication occurs and stores to %0"
757
  [(set_attr "type" "mult_shadow")])
758
 
759
 
760
(define_mode_iterator MOV [QI HI SI SF DI DF V2HI V4QI V2SI V4HI V8QI])
761
 
762
(define_expand "mov"
763
  [(set (match_operand:MOV 0 "nonimmediate_operand" "")
764
        (match_operand:MOV 1 "general_operand" ""))]
765
  ""
766
{
767
  if (expand_move (operands, mode))
768
    DONE;
769
})
770
 
771
(define_expand "movmisalign"
772
  [(set (match_operand:SIDIVM 0 "nonimmediate_operand"        "")
773
        (unspec:SIDIVM [(match_operand:SIDIVM 1 "nonimmediate_operand" "")]
774
                       UNSPEC_MISALIGNED_ACCESS))]
775
  "TARGET_INSNS_64"
776
{
777
  if (memory_operand (operands[0], mode))
778
    {
779
      emit_insn (gen_movmisalign_store (operands[0], operands[1]));
780
      DONE;
781
    }
782
})
783
 
784
(define_insn_and_split "movmisalign_store"
785
  [(set (match_operand:SIDIVM 0 "memory_operand" "=W,Q,T,Q,T")
786
        (unspec:SIDIVM [(match_operand:SIDIVM 1 "register_operand" "r,a,b,b,a")]
787
                       UNSPEC_MISALIGNED_ACCESS))
788
   (clobber (match_scratch:SI 2 "=r,X,X,X,X"))]
789
  "TARGET_INSNS_64"
790
  "@
791
   #
792
   %|%.\\tstn\\t%$\\t%1, %0
793
   %|%.\\tstn\\t%$\\t%1, %0
794
   %|%.\\tstn\\t%$\\t%1, %0
795
   %|%.\\tstn\\t%$\\t%1, %0"
796
  "&& reload_completed && satisfies_constraint_W (operands[0])"
797
  [(parallel
798
    [(set (match_dup 3) (unspec:SIDIVM [(match_dup 1)] UNSPEC_MISALIGNED_ACCESS))
799
     (clobber (match_dup 4))])]
800
{
801
  rtx addr = XEXP (operands[0], 0);
802
  rtx tmpreg = operands[2];
803
 
804
  if (GET_CODE (addr) == PLUS && XEXP (addr, 0) == stack_pointer_rtx
805
      && GET_CODE (XEXP (addr, 1)) == CONST_INT)
806
    {
807
      unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1));
808
      val &= GET_MODE_SIZE (mode) - 1;
809
      if (val == 0)
810
        {
811
          emit_move_insn (operands[0], operands[1]);
812
          DONE;
813
        }
814
    }
815
  operands[3] = change_address (operands[0], mode, tmpreg);
816
  emit_move_insn (tmpreg, addr);
817
  operands[4] = gen_rtx_SCRATCH (SImode);
818
}
819
  [(set_attr "type" "storen")
820
   (set_attr "units" "d_addr")
821
   (set_attr "addr_regfile" "*,a,b,a,b")
822
   (set_attr "dest_regfile" "*,a,b,b,a")
823
   (set_attr "cross" "*,n,n,y,y")])
824
 
825
(define_insn_and_split "movmisalign_load"
826
  [(set (match_operand:SIDIVM 0 "register_operand" "=ab,a,b,b,a")
827
        (unspec:SIDIVM [(match_operand:SIDIVM 1 "memory_operand" "W,Q,T,Q,T")]
828
                       UNSPEC_MISALIGNED_ACCESS))]
829
  "TARGET_INSNS_64"
830
  "@
831
   #
832
   %|%.\\tldn\\t%$\\t%1, %0
833
   %|%.\\tldn\\t%$\\t%1, %0
834
   %|%.\\tldn\\t%$\\t%1, %0
835
   %|%.\\tldn\\t%$\\t%1, %0"
836
  "&& reload_completed && satisfies_constraint_W (operands[1])"
837
  [(set (match_dup 0) (unspec:SIDIVM [(match_dup 2)] UNSPEC_MISALIGNED_ACCESS))]
838
{
839
  rtx addr = XEXP (operands[1], 0);
840
  rtx tmpreg = (GET_MODE (operands[0]) == SImode ? operands[0]
841
                : operand_subword_force (operands[0], 0, DImode));
842
 
843
  if (GET_CODE (addr) == PLUS && XEXP (addr, 0) == stack_pointer_rtx
844
      && GET_CODE (XEXP (addr, 1)) == CONST_INT)
845
    {
846
      unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1));
847
      val &= GET_MODE_SIZE (mode) - 1;
848
      if (val == 0)
849
        {
850
          emit_move_insn (operands[0], operands[1]);
851
          DONE;
852
        }
853
    }
854
  operands[2] = change_address (operands[1], mode, tmpreg);
855
  emit_move_insn (tmpreg, addr);
856
}
857
  [(set_attr "type" "loadn")
858
   (set_attr "units" "d_addr")
859
   (set_attr "addr_regfile" "*,a,b,a,b")
860
   (set_attr "dest_regfile" "*,a,b,b,a")
861
   (set_attr "cross" "*,n,n,y,y")])
862
 
863
;;
864
 
865
;; -------------------------------------------------------------------------
866
;; Extensions/extractions
867
;; -------------------------------------------------------------------------
868
 
869
(define_code_iterator any_extract [zero_extract sign_extract])
870
(define_code_iterator any_ext [zero_extend sign_extend])
871
 
872
(define_code_attr ext_name [(zero_extend "zero_extend") (sign_extend "sign_extend")])
873
 
874
(define_code_attr u [(zero_extend "u") (sign_extend "")])
875
 
876
(define_code_attr z [(zero_extract "z") (sign_extract "")])
877
(define_code_attr zu [(zero_extract "u") (sign_extract "")])
878
 
879
(define_mode_attr ext_shift [(QI "24") (HI "16")])
880
 
881
(define_insn "si2"
882
 [(set (match_operand:SI 0 "register_operand" "=a,b,a,?a, b,?b")
883
       (any_ext:SI (match_operand:QIHIM 1 "nonimmediate_operand" "a,b,Q, R, R, Q")))]
884
  ""
885
 "@
886
  %|%.\\text\\t%$\\t%1, , , %0
887
  %|%.\\text\\t%$\\t%1, , , %0
888
  %|%.\\tld\\t%$\\t%1, %0
889
  %|%.\\tld\\t%$\\t%1, %0
890
  %|%.\\tld\\t%$\\t%1, %0
891
  %|%.\\tld\\t%$\\t%1, %0"
892
  [(set_attr "type" "*,*,load,load,load,load")
893
   (set_attr "units" "s,s,d_addr,d_addr,d_addr,d_addr")
894
   (set_attr "addr_regfile" "*,*,a,b,b,a")
895
   (set_attr "dest_regfile" "*,*,a,a,b,b")
896
   (set_attr "cross" "n,n,n,y,n,y")])
897
 
898
(define_insn "*extv_const"
899
  [(set (match_operand:SI 0 "nonimmediate_operand" "=a,b")
900
        (any_extract:SI (match_operand:SI 1 "register_operand" "a,b")
901
                        (match_operand:SI 2 "const_int_operand" "n,n")
902
                        (match_operand:SI 3 "const_int_operand" "n,n")))]
903
  "INTVAL (operands[3]) >= 0
904
   && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32"
905
{
906
  int pos = INTVAL (operands[3]);
907
  int len = INTVAL (operands[2]);
908
  rtx xop[4];
909
  xop[0] = operands[0];
910
  xop[1] = operands[1];
911
  xop[2] = GEN_INT (32 - pos - len);
912
  xop[3] = GEN_INT (32 - len);
913
 
914
  output_asm_insn ("%|%.\\text\\t%$\\t%1, %2, %3, %0", xop);
915
  return "";
916
}
917
  [(set_attr "units" "s")
918
   (set_attr "cross" "n")])
919
 
920
(define_expand "extv"
921
  [(set (match_operand:SI 0 "register_operand" "")
922
        (any_extract:SI (match_operand:SI 1 "register_operand" "")
923
                        (match_operand:SI 2 "const_int_operand" "")
924
                        (match_operand:SI 3 "const_int_operand" "")))]
925
  ""
926
{
927
   if (INTVAL (operands[2]) < 0
928
       || INTVAL (operands[2]) + INTVAL (operands[3]) > 32)
929
     FAIL;
930
})
931
 
932
(define_insn "real_"
933
  [(unspec [(match_operand 0 "const_int_operand" "JA,JA,JB,JB")
934
            (any_ext:SI (match_operand:QIHIM 1 "memory_operand" "Q,R,R,Q"))]
935
           UNSPEC_REAL_LOAD)]
936
  ""
937
  "%|%.\\tld\\t%$\\t%1, %k0"
938
  [(set_attr "type" "load")
939
   (set_attr "units" "d_addr")
940
   (set_attr "addr_regfile" "a,b,b,a")
941
   (set_attr "dest_regfile" "a,a,b,b")
942
   (set_attr "cross" "n,y,n,y")])
943
 
944
(define_insn "clrr"
945
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b")
946
        (unspec:SI [(match_operand:SI 1 "register_operand" "0,0,0,0")
947
                    (match_operand:SI 2 "register_operand" "a,b,?b,?a")
948
                    (match_operand:SI 3 "reg_or_const_int_operand" "ai,bi,a,b")]
949
                   UNSPEC_CLR))]
950
  ""
951
{
952
  if (CONST_INT_P (operands[2]))
953
    {
954
      rtx xops[4];
955
      int v1 = INTVAL (operands[2]);
956
      int v2 = (v1 >> 5) & 0x1f;
957
      v1 &= 0x1f;
958
      xops[0] = operands[0];
959
      xops[1] = operands[1];
960
      xops[2] = GEN_INT (v1);
961
      xops[3] = GEN_INT (v2);
962
      output_asm_insn ("%|%.\\tclr\\t%$\\t%1, %3, %2, %0", xops);
963
      return "";
964
    }
965
  return "%|%.\\tclr\\t%$\\t%2, %3, %0";
966
}
967
  [(set_attr "units" "s")
968
   (set_attr "cross" "n,n,y,y")])
969
 
970
(define_insn "extr"
971
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b")
972
        (unspec:SI [(match_operand:SI 1 "register_operand" "a,b,?b,?a")
973
                    (match_operand:SI 2 "reg_or_const_int_operand" "ai,bi,a,b")]
974
                   UNSPEC_EXT))]
975
  ""
976
{
977
  if (CONST_INT_P (operands[2]))
978
    {
979
      rtx xops[4];
980
      int v1 = INTVAL (operands[2]);
981
      int v2 = (v1 >> 5) & 0x1f;
982
      v1 &= 0x1f;
983
      xops[0] = operands[0];
984
      xops[1] = operands[1];
985
      xops[2] = GEN_INT (v1);
986
      xops[3] = GEN_INT (v2);
987
      output_asm_insn ("%|%.\\text\\t%$\\t%1, %3, %2, %0", xops);
988
      return "";
989
    }
990
  return "%|%.\\text\\t%$\\t%1, %2, %0";
991
}
992
  [(set_attr "units" "s")
993
   (set_attr "cross" "n,n,y,y")])
994
 
995
(define_insn "extru"
996
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b")
997
        (unspec:SI [(match_operand:SI 1 "register_operand" "a,b,?b,?a")
998
                    (match_operand:SI 2 "reg_or_const_int_operand" "ai,bi,a,b")]
999
                   UNSPEC_EXTU))]
1000
  ""
1001
{
1002
  if (CONST_INT_P (operands[2]))
1003
    {
1004
      rtx xops[4];
1005
      int v1 = INTVAL (operands[2]);
1006
      int v2 = (v1 >> 5) & 0x1f;
1007
      v1 &= 0x1f;
1008
      xops[0] = operands[0];
1009
      xops[1] = operands[1];
1010
      xops[2] = GEN_INT (v1);
1011
      xops[3] = GEN_INT (v2);
1012
      output_asm_insn ("%|%.\\textu\\t%$\\t%1, %3, %2, %0", xops);
1013
      return "";
1014
    }
1015
  return "%|%.\\textu\\t%$\\t%1, %2, %0";
1016
}
1017
  [(set_attr "units" "s")
1018
   (set_attr "cross" "n,y,n,y")])
1019
 
1020
;; -------------------------------------------------------------------------
1021
;; Compare instructions
1022
;; -------------------------------------------------------------------------
1023
 
1024
(define_insn "scmpsi_insn"
1025
  [(set (match_operand:SI 0 "register_operand" "=ab,a,b,a,b")
1026
        (match_operator:SI 1 "eqltgt_operator"
1027
           [(match_operand:SI 2 "register_operand" "ab,a,b,?b,?a")
1028
            (match_operand:SI 3 "reg_or_scst5_operand" "Is5,aIs5,bIs5,aIs5,bIs5")]))]
1029
  ""
1030
  "%|%.\\tcmp%C1\\t%$\\t%3, %2, %0"
1031
  [(set_attr "units" "l")
1032
   (set (attr "cross")
1033
        (symbol_ref "CROSS_OPERANDS (operands[0], operands[2])"))])
1034
 
1035
(define_insn "*ucmpsi_insn_64"
1036
  [(set (match_operand:SI 0 "register_operand" "=ab,a,b,a,b")
1037
        (match_operator:SI 1 "ltugtu_operator"
1038
           [(match_operand:SI 2 "register_operand" "ab,a,b,?b,?a")
1039
            (match_operand:SI 3 "reg_or_ucst5_operand" "Iu5,aIu5,bIu5,aIu5,bIu5")]))]
1040
  "TARGET_INSNS_64"
1041
  "%|%.\\tcmp%C1\\t%$\\t%3, %2, %0"
1042
  [(set_attr "units" "l")
1043
   (set (attr "cross")
1044
        (symbol_ref "CROSS_OPERANDS (operands[0], operands[2])"))])
1045
 
1046
(define_insn "*ucmpsi_insn"
1047
  [(set (match_operand:SI 0 "register_operand" "=ab,a,b,a,b")
1048
        (match_operator:SI 1 "ltugtu_operator"
1049
           [(match_operand:SI 2 "register_operand" "ab,a,b,?b,?a")
1050
            (match_operand:SI 3 "reg_or_ucst4_operand" "Iu4,aIu4,bIu4,aIu4,bIu4")]))]
1051
  "!TARGET_INSNS_64"
1052
  "%|%.\\tcmp%C1\\t%$\\t%3, %2, %0"
1053
  [(set_attr "units" "l")
1054
   (set (attr "cross")
1055
        (symbol_ref "CROSS_OPERANDS (operands[0], operands[2])"))])
1056
 
1057
(define_code_iterator andior_eqne [eq ne])
1058
(define_code_attr andior_name [(eq "and") (ne "ior")])
1059
(define_code_attr andior_condmod [(eq "") (ne "!")])
1060
 
1061
(define_insn "*scmpsi__insn"
1062
  [(set (match_operand:SI 0 "register_operand" "=A,B,A,B")
1063
        (if_then_else:SI
1064
         (andior_eqne:SI (match_operand:SI 4 "register_operand" "0,0,0,0")
1065
                         (const_int 0))
1066
         (match_dup 4)
1067
         (match_operator:SI 1 "eqltgt_operator"
1068
          [(match_operand:SI 2 "register_operand" "a,b,?b,?a")
1069
           (match_operand:SI 3 "reg_or_scst5_operand" "aIs5,bIs5,aIs5,bIs5")])))]
1070
  ""
1071
  "%|[%4]\\tcmp%C1\\t%$\\t%3, %2, %0"
1072
  [(set_attr "units" "l")
1073
   (set_attr "cross" "n,n,y,y")
1074
   (set_attr "predicable" "no")])
1075
 
1076
(define_insn "*ucmpsi__insn_64"
1077
  [(set (match_operand:SI 0 "register_operand" "=A,B,A,B")
1078
        (if_then_else:SI
1079
         (andior_eqne:SI (match_operand:SI 4 "register_operand" "0,0,0,0")
1080
                         (const_int 0))
1081
         (match_dup 4)
1082
         (match_operator:SI 1 "ltugtu_operator"
1083
          [(match_operand:SI 2 "register_operand" "a,b,?b,?a")
1084
           (match_operand:SI 3 "reg_or_ucst5_operand" "aIu5,bIu5,aIu5,bIu5")])))]
1085
  "TARGET_INSNS_64"
1086
  "%|[%4]\\tcmp%C1\\t%$\\t%3, %2, %0"
1087
  [(set_attr "units" "l")
1088
   (set_attr "cross" "n,n,y,y")
1089
   (set_attr "predicable" "no")])
1090
 
1091
(define_insn "*ucmpsi__insn"
1092
  [(set (match_operand:SI 0 "register_operand" "=A,B,A,B")
1093
        (if_then_else:SI
1094
         (andior_eqne:SI (match_operand:SI 4 "register_operand" "0,0,0,0")
1095
                         (const_int 0))
1096
         (match_dup 4)
1097
         (match_operator:SI 1 "ltugtu_operator"
1098
          [(match_operand:SI 2 "register_operand" "a,b,?b,?a")
1099
           (match_operand:SI 3 "reg_or_ucst4_operand" "aIu4,bIu4,aIu4,bIu4")])))]
1100
  "!TARGET_INSNS_64"
1101
  "%|[%4]\\tcmp%C1\\t%$\\t%3, %2, %0"
1102
  [(set_attr "units" "l")
1103
   (set_attr "cross" "n,n,y,y")
1104
   (set_attr "predicable" "no")])
1105
 
1106
(define_expand "cmpsi_"
1107
  [(set (match_operand:SI 0 "register_operand" "")
1108
        (if_then_else:SI
1109
         (andior_eqne:SI (match_operand:SI 4 "register_operand" "0,0,0,0")
1110
                         (const_int 0))
1111
         (match_dup 4)
1112
         (match_operator:SI 1 "c6x_comparison_operator"
1113
          [(match_operand:SI 2 "register_operand" "")
1114
           (match_operand:SI 3 "reg_or_const_int_operand" "")])))]
1115
  ""
1116
{
1117
  if (c6x_force_op_for_comparison_p (GET_CODE (operands[1]), operands[3]))
1118
    operands[3] = force_reg (SImode, operands[3]);
1119
})
1120
 
1121
(define_insn "*cmpsf_insn"
1122
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b")
1123
        (match_operator:SI 1 "eqltgt_operator"
1124
           [(match_operand:SF 2 "register_operand" "a,b,a,b")
1125
            (match_operand:SF 3 "register_operand" "a,b,?b,?a")]))]
1126
  "TARGET_FP"
1127
  "%|%.\\tcmp%c1sp\\t%$\\t%2, %3, %0"
1128
  [(set_attr "units" "s")
1129
   (set_attr "cross" "n,n,y,y")])
1130
 
1131
(define_insn "*cmpdf_insn"
1132
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b")
1133
        (match_operator:SI 1 "eqltgt_operator"
1134
           [(match_operand:DF 2 "register_operand" "a,b,a,b")
1135
            (match_operand:DF 3 "register_operand" "a,b,?b,?a")]))]
1136
  "TARGET_FP"
1137
  "%|%.\\tcmp%c1dp\\t%$\\t%2, %3, %0"
1138
  [(set_attr "type" "cmpdp")
1139
   (set_attr "units" "s")
1140
   (set_attr "cross" "n,n,y,y")])
1141
 
1142
(define_expand "cmp_"
1143
  [(set (match_operand:SI 0 "register_operand" "")
1144
        (if_then_else:SI
1145
         (andior_eqne:SI (match_operand:SI 4 "register_operand" "0,0,0,0")
1146
                         (const_int 0))
1147
         (match_dup 4)
1148
         (match_operator:SI 1 "eqltgt_operator"
1149
           [(match_operand:SFDFM 2 "register_operand" "")
1150
            (match_operand:SFDFM 3 "register_operand" "")])))]
1151
  "TARGET_FP")
1152
 
1153
(define_insn "*cmpsf__insn"
1154
  [(set (match_operand:SI 0 "register_operand" "=A,B,A,B")
1155
        (if_then_else:SI
1156
         (andior_eqne:SI (match_operand:SI 4 "register_operand" "0,0,0,0")
1157
                         (const_int 0))
1158
         (match_dup 4)
1159
         (match_operator:SI 1 "eqltgt_operator"
1160
           [(match_operand:SF 2 "register_operand" "a,b,a,b")
1161
            (match_operand:SF 3 "register_operand" "a,b,?b,?a")])))]
1162
  "TARGET_FP"
1163
  "%|[%4]\\tcmp%c1sp\\t%$\\t%2, %3, %0"
1164
  [(set_attr "units" "s")
1165
   (set_attr "cross" "n,n,y,y")
1166
   (set_attr "predicable" "no")])
1167
 
1168
;; reload_reg_class_lower will ensure that two-word reloads are allocated first,
1169
;; which could exhaust the predicate registers if we used just "a" and "b"
1170
;; constraints on operands 2 and 3.
1171
(define_insn "*cmpdf__insn"
1172
  [(set (match_operand:SI 0 "register_operand" "=A,B,A,B")
1173
        (if_then_else:SI
1174
         (andior_eqne:SI (match_operand:SI 4 "register_operand" "0,0,0,0")
1175
                         (const_int 0))
1176
         (match_dup 4)
1177
         (match_operator:SI 1 "eqltgt_operator"
1178
           [(match_operand:DF 2 "register_operand" "Da,Db,Da,Db")
1179
            (match_operand:DF 3 "register_operand" "Da,Db,?Db,?Da")])))]
1180
  "TARGET_FP"
1181
  "%|[%4]\\tcmp%c1dp\\t%$\\t%2, %3, %0"
1182
  [(set_attr "type" "cmpdp")
1183
   (set_attr "units" "s")
1184
   (set_attr "cross" "n,n,y,y")
1185
   (set_attr "predicable" "no")])
1186
 
1187
(define_split
1188
  [(set (match_operand:SI 0 "register_operand" "")
1189
        (ior:SI (match_operand 1 "c6x_any_comparison_operand" "")
1190
                (match_operand 2 "c6x_any_comparison_operand" "")))]
1191
  "!reg_overlap_mentioned_p (operands[0], operands[2])"
1192
  [(set (match_dup 0) (match_dup 1))
1193
   (set (match_dup 0)
1194
        (if_then_else:SI (ne:SI (match_dup 0) (const_int 0))
1195
                         (match_dup 0)
1196
                         (match_dup 2)))])
1197
 
1198
(define_split
1199
  [(set (match_operand:SI 0 "register_operand" "")
1200
        (and:SI (match_operand 1 "c6x_any_comparison_operand" "")
1201
                (match_operand 2 "c6x_any_comparison_operand" "")))]
1202
  "!reg_overlap_mentioned_p (operands[0], operands[2])"
1203
  [(set (match_dup 0) (match_dup 1))
1204
   (set (match_dup 0)
1205
        (if_then_else:SI (eq:SI (match_dup 0) (const_int 0))
1206
                         (match_dup 0)
1207
                         (match_dup 2)))])
1208
 
1209
 
1210
;; -------------------------------------------------------------------------
1211
;; setcc instructions
1212
;; -------------------------------------------------------------------------
1213
 
1214
(define_expand "cstoresi4"
1215
  [(set (match_operand:SI 0 "register_operand" "")
1216
        (match_operator:SI 1 "comparison_operator"
1217
         [(match_operand:SI 2 "register_operand" "")
1218
          (match_operand:SI 3 "reg_or_ucst4_operand" "")]))]
1219
  ""
1220
{
1221
  if (!c6x_comparison_operator (operands[1], SImode))
1222
    {
1223
      rtx tmpreg = gen_reg_rtx (SImode);
1224
      rtx t = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])),
1225
                              SImode, operands[2], operands[3]);
1226
      emit_insn (gen_rtx_SET (VOIDmode, tmpreg, t));
1227
      emit_insn (gen_scmpsi_insn (operands[0],
1228
                                  gen_rtx_fmt_ee (EQ, SImode, tmpreg, const0_rtx),
1229
                                  tmpreg, const0_rtx));
1230
      DONE;
1231
    }
1232
})
1233
 
1234
;; -------------------------------------------------------------------------
1235
;; Jump instructions
1236
;; -------------------------------------------------------------------------
1237
 
1238
(define_insn "indirect_jump"
1239
  [(set (pc) (match_operand:SI 0 "register_operand" "a,b"))]
1240
  ""
1241
  "%|%.\\tb\\t%$\\t%0"
1242
  [(set_attr "type" "branch")
1243
   (set_attr "units" "s")
1244
   (set_attr "cross" "y,n")
1245
   (set_attr "dest_regfile" "b")])
1246
 
1247
(define_insn "jump"
1248
  [(set (pc)
1249
        (label_ref (match_operand 0 "" "")))]
1250
  ""
1251
  "%|%.\\tb\\t%$\\t%l0"
1252
  [(set_attr "type" "branch")
1253
   (set_attr "units" "s")
1254
   (set_attr "dest_regfile" "any")])
1255
 
1256
(define_expand "tablejump"
1257
  [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
1258
              (use (label_ref (match_operand 1 "" "")))])]
1259
  "!flag_pic || !TARGET_INSNS_64"
1260
{
1261
})
1262
 
1263
(define_insn "*tablejump_internal"
1264
  [(set (pc) (match_operand:SI 0 "register_operand" "b"))
1265
   (use (label_ref (match_operand 1 "" "")))]
1266
  "!flag_pic || !TARGET_INSNS_64"
1267
  "%|\\tb\\t%$\\t%0"
1268
  [(set_attr "type" "branch")
1269
   (set_attr "predicable" "no")
1270
   (set_attr "units" "s")
1271
   (set_attr "dest_regfile" "b")])
1272
 
1273
;; Implement switch statements when generating PIC code.  Switches are
1274
;; implemented by `tablejump' when not using -fpic.
1275
 
1276
;; Emit code here to do the range checking and make the index zero based.
1277
;; operand 0 is the index
1278
;; operand 1 is the lower bound
1279
;; operand 2 is the range of indices (highest - lowest + 1)
1280
;; operand 3 is the label that precedes the table itself
1281
;; operand 4 is the fall through label
1282
 
1283
(define_expand "casesi"
1284
  [(use (match_operand:SI 0 "register_operand" ""))
1285
   (use (match_operand:SI 1 "const_int_operand" ""))
1286
   (use (match_operand:SI 2 "const_int_operand" ""))
1287
   (use (match_operand 3 "" ""))
1288
   (use (match_operand 4 "" ""))]
1289
  "flag_pic && TARGET_INSNS_64"
1290
{
1291
  rtx indx;
1292
  rtx low = operands[1];
1293
  rtx range = operands[2];
1294
  rtx table = operands[3];
1295
  rtx fail = operands[4];
1296
 
1297
  gcc_assert (GET_CODE (operands[1]) == CONST_INT);
1298
  gcc_assert (GET_CODE (operands[2]) == CONST_INT);
1299
 
1300
  if (!reg_or_ucst4_operand (range, SImode))
1301
    range = force_reg (SImode, range);
1302
 
1303
  /* If low bound is 0, we don't have to subtract it.  */
1304
  if (INTVAL (operands[1]) == 0)
1305
    indx = operands[0];
1306
  else
1307
    {
1308
      rtx offset = GEN_INT (-INTVAL (low));
1309
      indx = gen_reg_rtx (SImode);
1310
      if (!addsi_operand (offset, SImode))
1311
        offset = force_reg (SImode, offset);
1312
      emit_insn (gen_addsi3 (indx, operands[0], offset));
1313
    }
1314
  emit_cmp_and_jump_insns (indx, range, GTU, NULL_RTX, SImode, 1, fail);
1315
 
1316
  emit_jump_insn (gen_casesi_internal (indx, table));
1317
  DONE;
1318
})
1319
 
1320
;; This is the only instance in this file where a pattern emits more than
1321
;; one instruction.  The concern here is that the addkpc insn could otherwise
1322
;; be scheduled too far away from the label.  A tablejump always ends an
1323
;; extended basic block, so it shouldn't happen that the scheduler places
1324
;; something in the delay slots.
1325
(define_insn "casesi_internal"
1326
  [(set (pc)
1327
        (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "b")
1328
                                  (const_int 4))
1329
                         (label_ref (match_operand 1 "" "")))))
1330
   (clobber (match_scratch:SI 2 "=&b"))
1331
   (clobber (match_scratch:SI 3 "=b"))]
1332
  "flag_pic && TARGET_INSNS_64"
1333
  "addkpc\t.s2\t%l1,%2, 0\n\t\tldw\t.d2t2\t*+%2[%0], %3\n\t\tnop\t\t4\n\t\tadd\t.l2\t%2, %3, %3\n\t\tb\t.s2\t%3"
1334
  [(set_attr "type" "branch")
1335
   (set_attr "predicable" "no")
1336
   (set_attr "dest_regfile" "b")])
1337
 
1338
(define_expand "cbranch4"
1339
  [(set (pc)
1340
        (if_then_else (match_operator 0 "comparison_operator"
1341
                       [(match_operand:SIDIM 1 "register_operand" "")
1342
                        (match_operand:SIDIM 2 "reg_or_const_int_operand" "")])
1343
                      (label_ref (match_operand 3 "" ""))
1344
                      (pc)))]
1345
  ""
1346
{
1347
  rtx t = c6x_expand_compare (operands[0], VOIDmode);
1348
  operands[0] = t;
1349
  operands[1] = XEXP (t, 0);
1350
  operands[2] = XEXP (t, 1);
1351
})
1352
 
1353
(define_expand "cbranch4"
1354
  [(set (pc)
1355
        (if_then_else (match_operator 0 "c6x_fp_comparison_operator"
1356
                       [(match_operand:SFDFM 1 "register_operand" "")
1357
                        (match_operand:SFDFM 2 "register_operand" "")])
1358
                      (label_ref (match_operand 3 "" ""))
1359
                      (pc)))]
1360
  ""
1361
{
1362
  rtx t = c6x_expand_compare (operands[0], VOIDmode);
1363
  operands[0] = t;
1364
  operands[1] = XEXP (t, 0);
1365
  operands[2] = XEXP (t, 1);
1366
})
1367
 
1368
(define_insn "br_true"
1369
  [(set (pc)
1370
        (if_then_else (match_operator 0 "predicate_operator"
1371
                        [(match_operand:SI 1 "register_operand" "AB")
1372
                         (const_int 0)])
1373
                      (label_ref (match_operand 2 "" ""))
1374
                      (pc)))]
1375
  ""
1376
  "%|[%J0]\\tb\\t%$\\t%l2"
1377
  [(set_attr "type" "branch")
1378
   (set_attr "predicable" "no")
1379
   (set_attr "units" "s")
1380
   (set_attr "dest_regfile" "any")])
1381
 
1382
(define_insn "br_false"
1383
  [(set (pc)
1384
        (if_then_else (match_operator 0 "predicate_operator"
1385
                        [(match_operand:SI 1 "register_operand" "AB")
1386
                         (const_int 0)])
1387
                      (pc)
1388
                      (label_ref (match_operand 2 "" ""))))]
1389
  ""
1390
  "%|[%j0]\\tb\\t%$\\t%l2"
1391
  [(set_attr "type" "branch")
1392
   (set_attr "predicable" "no")
1393
   (set_attr "units" "s")
1394
   (set_attr "dest_regfile" "any")])
1395
 
1396
(define_expand "return"
1397
  [(parallel
1398
    [(return)
1399
     (use (reg:SI REG_B3))])]
1400
  "reload_completed && get_frame_size () == 0 && c6x_nsaved_regs () == 0")
1401
 
1402
;; We can't expand this before we know where the link register is stored.
1403
(define_insn_and_split "eh_return"
1404
  [(unspec_volatile [(match_operand:SI 0 "register_operand" "ab")]
1405
                    UNSPECV_EH_RETURN)
1406
   (clobber (match_scratch:SI 1 "=&ab"))]
1407
  ""
1408
  "#"
1409
  "&& reload_completed"
1410
  [(const_int 0)]
1411
  "
1412
  {
1413
    c6x_set_return_address (operands[0], operands[1]);
1414
    DONE;
1415
  }"
1416
)
1417
 
1418
;; -------------------------------------------------------------------------
1419
;; Doloop
1420
;; -------------------------------------------------------------------------
1421
 
1422
; operand 0 is the loop count pseudo register
1423
; operand 1 is the number of loop iterations or 0 if it is unknown
1424
; operand 2 is the maximum number of loop iterations
1425
; operand 3 is the number of levels of enclosed loops
1426
; operand 4 is the label to jump to at the top of the loop
1427
(define_expand "doloop_end"
1428
  [(parallel [(set (pc) (if_then_else
1429
                          (ne (match_operand:SI 0 "" "")
1430
                              (const_int 1))
1431
                          (label_ref (match_operand 4 "" ""))
1432
                          (pc)))
1433
              (set (match_dup 0)
1434
                   (plus:SI (match_dup 0)
1435
                            (const_int -1)))
1436
              (clobber (match_scratch:SI 5 ""))])]
1437
  "TARGET_INSNS_64PLUS && optimize"
1438
{
1439
  /* The loop optimizer doesn't check the predicates... */
1440
  if (GET_MODE (operands[0]) != SImode)
1441
    FAIL;
1442
})
1443
 
1444
(define_insn "mvilc"
1445
  [(set (reg:SI REG_ILC)
1446
        (unspec [(match_operand:SI 0 "register_operand" "a,b")] UNSPEC_MVILC))]
1447
  "TARGET_INSNS_64PLUS"
1448
  "%|%.\\tmvc\\t%$\\t%0, ILC"
1449
  [(set_attr "predicable" "no")
1450
   (set_attr "cross" "y,n")
1451
   (set_attr "units" "s")
1452
   (set_attr "dest_regfile" "b")
1453
   (set_attr "type" "mvilc")])
1454
 
1455
(define_insn "sploop"
1456
  [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i")
1457
                     (reg:SI REG_ILC)]
1458
                    UNSPECV_SPLOOP)]
1459
  "TARGET_INSNS_64PLUS"
1460
  "%|%.\\tsploop\t%0"
1461
  [(set_attr "predicable" "no")
1462
   (set_attr "type" "sploop")])
1463
 
1464
(define_insn "spkernel"
1465
  [(set (pc)
1466
        (if_then_else
1467
         (ne (unspec_volatile:SI
1468
              [(match_operand:SI 0 "const_int_operand" "i")
1469
               (match_operand:SI 1 "const_int_operand" "i")]
1470
              UNSPECV_SPKERNEL)
1471
             (const_int 1))
1472
         (label_ref (match_operand 2 "" ""))
1473
         (pc)))]
1474
  "TARGET_INSNS_64PLUS"
1475
  "%|%.\\tspkernel\t%0, %1"
1476
  [(set_attr "predicable" "no")
1477
   (set_attr "type" "spkernel")])
1478
 
1479
(define_insn "loop_end"
1480
  [(set (pc)
1481
        (if_then_else (ne (match_operand:SI 3 "nonimmediate_operand" "0,0,0,*r")
1482
                          (const_int 1))
1483
                      (label_ref (match_operand 1 "" ""))
1484
                      (pc)))
1485
   (set (match_operand:SI 0 "nonimmediate_operand" "=AB,*r,m,m")
1486
        (plus:SI (match_dup 3)
1487
                 (const_int -1)))
1488
   (clobber (match_scratch:SI 2 "=X,&AB,&AB,&AB"))]
1489
  "TARGET_INSNS_64PLUS && optimize"
1490
  "#"
1491
  [(set_attr "type" "spkernel")])
1492
 
1493
(define_split
1494
  [(set (pc)
1495
        (if_then_else (ne (match_operand:SI 3 "nonimmediate_operand" "")
1496
                          (const_int 1))
1497
                      (label_ref (match_operand 1 "" ""))
1498
                      (pc)))
1499
   (set (match_operand:SI 0 "memory_operand" "")
1500
        (plus:SI (match_dup 3)
1501
                 (const_int -1)))
1502
   (clobber (match_scratch 2))]
1503
  ""
1504
  [(set (match_dup 2) (plus:SI (match_dup 3) (const_int -1)))
1505
   (set (match_dup 0) (match_dup 2))
1506
   (set (pc)
1507
        (if_then_else (ne (match_dup 2) (const_int 0))
1508
                      (label_ref (match_dup 1))
1509
                      (pc)))]
1510
{
1511
  if (!REG_P (operands[3]))
1512
    {
1513
      emit_move_insn (operands[2], operands[3]);
1514
      operands[3] = operands[2];
1515
    }
1516
})
1517
 
1518
;; -------------------------------------------------------------------------
1519
;; Delayed-branch real jumps and shadows
1520
;; -------------------------------------------------------------------------
1521
 
1522
(define_insn "real_jump"
1523
  [(unspec [(match_operand 0 "c6x_jump_operand" "a,b,s") (const_int 0)]
1524
           UNSPEC_REAL_JUMP)]
1525
  ""
1526
{
1527
  if (GET_CODE (operands[0]) == LABEL_REF)
1528
    return "%|%.\\tb\\t%$\\t%l0";
1529
  return "%|%.\\tb\\t%$\\t%0";
1530
}
1531
  [(set_attr "type" "branch")
1532
   (set_attr "has_shadow" "y")
1533
   (set_attr "units" "s")
1534
   (set_attr "cross" "y,n,n")
1535
   (set_attr "dest_regfile" "b,b,any")])
1536
 
1537
(define_insn "real_call"
1538
  [(unspec [(match_operand 0 "c6x_call_operand" "a,b,S1") (const_int 1)]
1539
           UNSPEC_REAL_JUMP)
1540
   (clobber (reg:SI REG_B3))]
1541
  ""
1542
  "%|%.\\tcall\\t%$\\t%0"
1543
  [(set_attr "type" "call")
1544
   (set_attr "has_shadow" "y")
1545
   (set_attr "predicable" "no")
1546
   (set_attr "units" "s")
1547
   (set_attr "cross" "y,n,n")
1548
   (set_attr "dest_regfile" "b,b,any")])
1549
 
1550
(define_insn "real_ret"
1551
  [(unspec [(match_operand 0 "register_operand" "a,b") (const_int 2)]
1552
           UNSPEC_REAL_JUMP)]
1553
  ""
1554
  "%|%.\\tret\\t%$\\t%0"
1555
  [(set_attr "type" "branch")
1556
   (set_attr "has_shadow" "y")
1557
   (set_attr "units" "s")
1558
   (set_attr "cross" "y,n")
1559
   (set_attr "dest_regfile" "b")])
1560
 
1561
;; computed_jump_p returns true if it finds a constant; so use one in the
1562
;; unspec.
1563
(define_insn "indirect_jump_shadow"
1564
  [(set (pc) (unspec [(const_int 1)] UNSPEC_JUMP_SHADOW))]
1565
  ""
1566
  ";; indirect jump occurs"
1567
  [(set_attr "type" "shadow")])
1568
 
1569
;; Operand 0 may be a PARALLEL which isn't handled by output_operand, so
1570
;; we don't try to print it.
1571
(define_insn "indirect_call_value_shadow"
1572
  [(set (match_operand 0 "" "")
1573
        (call (unspec [(pc)] UNSPEC_JUMP_SHADOW)
1574
              (const_int 0)))]
1575
  ""
1576
  ";; indirect call occurs, with return value"
1577
  [(set_attr "type" "shadow")])
1578
 
1579
(define_insn "indirect_sibcall_shadow"
1580
  [(call (unspec [(pc)] UNSPEC_JUMP_SHADOW)
1581
         (const_int 0))]
1582
  "SIBLING_CALL_P (insn)"
1583
  ";; indirect sibcall occurs"
1584
  [(set_attr "type" "shadow")])
1585
 
1586
(define_insn "indirect_call_shadow"
1587
  [(call (unspec [(pc)] UNSPEC_JUMP_SHADOW)
1588
         (const_int 0))]
1589
  ""
1590
  ";; indirect call occurs"
1591
  [(set_attr "type" "shadow")])
1592
 
1593
(define_insn "call_value_shadow"
1594
  [(set (match_operand 0 "" "")
1595
        (call (unspec [(match_operand 1 "" "")] UNSPEC_JUMP_SHADOW)
1596
              (const_int 0)))]
1597
  ""
1598
  ";; call to %1 occurs, with return value"
1599
  [(set_attr "type" "shadow")])
1600
 
1601
(define_insn "call_shadow"
1602
  [(call (unspec [(match_operand 0 "" "")] UNSPEC_JUMP_SHADOW)
1603
         (const_int 0))]
1604
  "!SIBLING_CALL_P (insn)"
1605
  ";; call to %0 occurs"
1606
  [(set_attr "type" "shadow")])
1607
 
1608
(define_insn "sibcall_shadow"
1609
  [(call (unspec [(match_operand 0 "" "")] UNSPEC_JUMP_SHADOW)
1610
         (const_int 0))]
1611
  "SIBLING_CALL_P (insn)"
1612
  ";; sibcall to %0 occurs"
1613
  [(set_attr "type" "shadow")])
1614
 
1615
(define_insn "jump_shadow"
1616
  [(set (pc) (unspec [(match_operand 0 "" "")] UNSPEC_JUMP_SHADOW))]
1617
  ""
1618
  ";; jump to %0 occurs"
1619
  [(set_attr "type" "shadow")])
1620
 
1621
(define_insn "condjump_shadow"
1622
  [(set (pc)
1623
        (if_then_else (eq (unspec [(const_int 0)] UNSPEC_JUMP_SHADOW)
1624
                          (const_int 0))
1625
                      (match_operand 0 "" "")
1626
                      (pc)))]
1627
  ""
1628
  ";; condjump to %0 occurs"
1629
  [(set_attr "type" "shadow")])
1630
 
1631
(define_insn "return_shadow"
1632
  [(unspec [(const_int 0)] UNSPEC_JUMP_SHADOW)
1633
   (return)]
1634
  ""
1635
  ";; return occurs"
1636
  [(set_attr "type" "shadow")])
1637
 
1638
;; -------------------------------------------------------------------------
1639
;; Add instructions
1640
;; -------------------------------------------------------------------------
1641
 
1642
(define_insn "addsi3"
1643
  [(set (match_operand:SI 0 "register_operand"
1644
              "=a   ,b   , a, b, a, b,    a,    b, ab,  a,  b,  a,  b,ab")
1645
    (plus:SI (match_operand:SI 1 "register_operand"
1646
              "%a   ,b   , a, b, b, a,    b,    a,  0,  a,  b,  z,  z,0")
1647
             (match_operand:SI 2 "addsi_operand"
1648
               "aIs5,bIs5,?b,?a,?a,?b,?aIs5,?bIs5,I5x,I5x,I5x,Iux,Iux,IsB")))]
1649
  ""
1650
{
1651
  if (CONSTANT_P (operands[2]))
1652
    {
1653
      HOST_WIDE_INT val = INTVAL (operands[2]);
1654
 
1655
      if (c6x_get_unit_specifier (insn) == 'd')
1656
        {
1657
          bool issp = (TARGET_INSNS_64PLUS
1658
                       && operands[1] == stack_pointer_rtx
1659
                       && GET_CODE (PATTERN (insn)) != COND_EXEC);
1660
 
1661
          if (get_attr_cross (insn) == CROSS_N)
1662
            {
1663
              if (satisfies_constraint_Iu5 (operands[2]))
1664
                return "%|%.\\tadd\\t%$\\t%1, %2, %0";
1665
              else if (satisfies_constraint_In5 (operands[2]))
1666
                return "%|%.\\tsub\\t%$\\t%1, %n2, %0";
1667
            }
1668
 
1669
          if (issp && val > 0 && val < 32768)
1670
            {
1671
              return "%|%.\\taddab\\t%$\\t%1, %2, %0";
1672
            }
1673
          if ((val & 1) == 0 && ((val >= -62 && val <= 62)
1674
                                 || (issp && val > 0 && val < 65536)))
1675
            {
1676
              if (val < 0)
1677
                return "%|%.\\tsubah\\t%$\\t%1, %r2, %0";
1678
              else
1679
                return "%|%.\\taddah\\t%$\\t%1, %r2, %0";
1680
            }
1681
          else if ((val & 3) == 0 && ((val >= -124 && val <= 124)
1682
                                       || (issp && val > 0 && val < 131072)))
1683
            {
1684
              if (val < 0)
1685
                return "%|%.\\tsubaw\\t%$\\t%1, %R2, %0";
1686
              else
1687
                return "%|%.\\taddaw\\t%$\\t%1, %R2, %0";
1688
            }
1689
          else if ((val & 7) == 0 && val > 0 && val <= 248)
1690
            {
1691
              rtx xop[3];
1692
              xop[0] = operands[0];
1693
              xop[1] = operands[1];
1694
              xop[2] = GEN_INT (val >> 3);
1695
              output_asm_insn ("%|%.\\taddad\\t%$\\t%1, %2, %0", xop);
1696
              return "";
1697
            }
1698
        }
1699
      else
1700
        {
1701
          if (satisfies_constraint_Is5 (operands[2]))
1702
            return "%|%.\\tadd\\t%$\\t%2, %1, %0";
1703
        }
1704
      gcc_assert (rtx_equal_p (operands[0], operands[1]));
1705
      return "%|%.\\taddk\\t%$\\t%2, %0";
1706
    }
1707
  if (which_alternative == 4 || which_alternative == 5)
1708
    return "%|%.\\tadd\\t%$\\t%2, %1, %0";
1709
  else
1710
    return "%|%.\\tadd\\t%$\\t%1, %2, %0";
1711
}
1712
  [(set_attr "units62" "dls,dls,ls,ls,ls,ls,ls,ls,s,d,d,*,*,s")
1713
   (set_attr "units67" "dls,dls,ls,ls,ls,ls,ls,ls,ds,d,d,*,*,s")
1714
   (set_attr "units64" "dls,dls,dls,dls,dls,dls,ls,ls,ds,d,d,d,d,s")
1715
   (set_attr "cross" "n,n,y,y,y,y,y,y,n,n,n,y,n,n")
1716
   (set_attr "predicable" "yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,no,no,yes")])
1717
 
1718
(define_insn "subsi3"
1719
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b,a,b")
1720
        (minus:SI (match_operand:SI 1 "reg_or_scst5_operand" "a,b,aIs5,bIs5,bIs5,aIs5")
1721
                  (match_operand:SI 2 "register_operand" "a,b,a,b,?a,?b")))]
1722
  ""
1723
  "%|%.\\tsub\\t%$\\t%1, %2, %0"
1724
  [(set_attr "units62" "dls,dls,ls,ls,l,l")
1725
   (set_attr "units64" "dls,dls,ls,ls,ls,ls")
1726
   (set_attr "cross" "n,n,n,n,y,y")])
1727
 
1728
(define_insn "*addshiftsi"
1729
  [(set (match_operand:SI 0 "register_operand" "=a,b")
1730
        (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "a,b")
1731
                          (match_operand:SI 3 "adda_scale_operand" "n,n"))
1732
                 (match_operand:SI 1 "register_operand" "a,b")))]
1733
  ""
1734
  "%|%.\\tadda%d3\\t%$\\t%1, %2, %0"
1735
  [(set_attr "units" "d")])
1736
 
1737
(define_insn "*subshiftsi"
1738
  [(set (match_operand:SI 0 "register_operand" "=a,b")
1739
        (minus:SI (match_operand:SI 1 "register_operand" "a,b")
1740
                  (mult:SI (match_operand:SI 2 "register_operand" "a,b")
1741
                           (match_operand:SI 3 "suba_scale_operand" "n,n"))))]
1742
  ""
1743
  "%|%.\\tsuba%d3\\t%$\\t%1, %2, %0"
1744
  [(set_attr "units" "d")])
1745
 
1746
(define_insn "addsidi3_widen"
1747
  [(set (match_operand:DI 0 "register_operand" "=a,b,a,b")
1748
        (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%a,b,a,b"))
1749
                 (zero_extend:DI (match_operand:SI 2 "register_operand" "a,b,?b,?a"))))]
1750
  ""
1751
  "%|%.\\taddu\\t%$\\t%1, %2, %0"
1752
  [(set_attr "units" "l")
1753
   (set_attr "cross" "n,n,y,y")])
1754
 
1755
(define_expand "adddi3"
1756
  [(set (match_operand:DI 0 "register_operand" "")
1757
        (plus:DI (match_operand:DI 1 "register_operand" "")
1758
                 (match_operand:DI 2 "register_operand" "")))]
1759
  ""
1760
{
1761
  rtx tmp;
1762
  rtx lo_half[3], hi_half[3];
1763
  split_di (operands + 1, 2, lo_half + 1, hi_half + 1);
1764
  if (reg_overlap_mentioned_p (operands[0], hi_half[1])
1765
      || reg_overlap_mentioned_p (operands[0], hi_half[2]))
1766
    tmp = gen_reg_rtx (DImode);
1767
  else
1768
    tmp = operands[0];
1769
  split_di (&tmp, 1, lo_half, hi_half);
1770
  emit_insn (gen_addsidi3_widen (tmp, lo_half[1], lo_half[2]));
1771
  emit_insn (gen_addsi3 (hi_half[0], copy_rtx (hi_half[0]), hi_half[1]));
1772
  emit_insn (gen_addsi3 (copy_rtx (hi_half[0]),
1773
                         copy_rtx (hi_half[0]), hi_half[2]));
1774
  if (tmp != operands[0])
1775
    emit_move_insn (operands[0], tmp);
1776
  DONE;
1777
})
1778
 
1779
(define_insn "addsf3"
1780
  [(set (match_operand:SF 0 "register_operand" "=a,b,a,b")
1781
        (plus:SF (match_operand:SF 1 "register_operand" "%a,b,a,b")
1782
                 (match_operand:SF 2 "register_operand" "a,b,?b,?a")))]
1783
  "TARGET_FP"
1784
  "%|%.\\taddsp\\t%$\\t%1, %2, %0"
1785
  [(set_attr "type" "fp4")
1786
   (set_attr "units67" "l")
1787
   (set_attr "units67p" "ls")
1788
   (set_attr "units674" "ls")
1789
   (set_attr "cross" "n,n,y,y")])
1790
 
1791
(define_insn "adddf3"
1792
  [(set (match_operand:DF 0 "register_operand" "=a,b,a,b")
1793
        (plus:DF (match_operand:DF 1 "register_operand" "%a,b,a,b")
1794
                 (match_operand:DF 2 "register_operand" "a,b,?b,?a")))]
1795
  "TARGET_FP"
1796
  "%|%.\\tadddp\\t%$\\t%1, %2, %0"
1797
  [(set_attr "type" "adddp")
1798
   (set_attr "units67" "l")
1799
   (set_attr "units67p" "ls")
1800
   (set_attr "units674" "ls")
1801
   (set_attr "cross" "n,n,y,y")])
1802
 
1803
(define_insn "subsf3"
1804
  [(set (match_operand:SF 0 "register_operand" "=a,b, a, b, a, b")
1805
        (minus:SF (match_operand:SF 1 "register_operand" "a,b, b, a, a, b")
1806
                  (match_operand:SF 2 "register_operand" "a,b,?a,?b,?b,?a")))]
1807
  "TARGET_FP"
1808
  "%|%.\\tsubsp\\t%$\\t%1, %2, %0"
1809
  [(set_attr "type" "fp4")
1810
   (set_attr "units67" "l")
1811
   (set_attr "units67p" "ls")
1812
   (set_attr "units674" "ls")
1813
   (set_attr "cross" "n,n,y,y,y,y")])
1814
 
1815
(define_insn "subdf3"
1816
  [(set (match_operand:DF 0 "register_operand" "=a,b, a, b, a, b")
1817
        (minus:DF (match_operand:DF 1 "register_operand" "a,b, b, a, a, b")
1818
                  (match_operand:DF 2 "register_operand" "a,b,?a,?b,?b,?a")))]
1819
  "TARGET_FP"
1820
  "%|%.\\tsubdp\\t%$\\t%1, %2, %0"
1821
  [(set_attr "type" "adddp")
1822
   (set_attr "units67" "l")
1823
   (set_attr "units67p" "ls")
1824
   (set_attr "units674" "ls")
1825
   (set_attr "cross" "n,n,y,y,y,y")])
1826
 
1827
;; -------------------------------------------------------------------------
1828
;; Logical instructions
1829
;; -------------------------------------------------------------------------
1830
 
1831
(define_insn "andsi3"
1832
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b,a,b")
1833
        (and:SI (match_operand:SI 1 "register_operand" "%a,b,b,a,a,b")
1834
                (match_operand:SI 2 "andsi_operand" "aIs5,bIs5,?aIs5,?bIs5,aJc,bJc")))]
1835
  ""
1836
{
1837
  if (which_alternative < 4)
1838
    return "%|%.\\tand\\t%$\\t%2, %1, %0";
1839
  else
1840
    return "%|%.\\tclr\\t%$\\t%1, %f2, %F2, %0";
1841
}
1842
  [(set_attr "units62" "ls,ls,ls,ls,s,s")
1843
   (set_attr "units64" "dls,dls,dls,dls,s,s")
1844
   (set_attr "cross" "n,n,y,y,n,n")])
1845
 
1846
(define_insn "iorsi3"
1847
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b,a,b")
1848
        (ior:SI (match_operand:SI 1 "register_operand" "%a,b,b,a,a,b")
1849
                (match_operand:SI 2 "iorsi_operand" "aIs5,bIs5,?aIs5,?bIs5,aJs,bJs")))]
1850
  ""
1851
{
1852
  if (which_alternative < 4)
1853
    return "%|%.\\tor\\t%$\\t%2, %1, %0";
1854
  else
1855
    return "%|%.\\tset\\t%$\\t%1, %s2, %S2, %0";
1856
}
1857
  [(set_attr "units62" "ls,ls,ls,ls,s,s")
1858
   (set_attr "units64" "dls,dls,dls,dls,s,s")
1859
   (set_attr "cross" "n,n,y,y,n,n")])
1860
 
1861
(define_insn "xorsi3"
1862
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b")
1863
        (xor:SI (match_operand:SI 1 "register_operand" "%a,b,b,a")
1864
                (match_operand:SI 2 "reg_or_scst5_operand" "aIs5,bIs5,?aIs5,?bIs5")))]
1865
  ""
1866
  "%|%.\\txor\\t%$\\t%2, %1, %0"
1867
  [(set_attr "units62" "ls")
1868
   (set_attr "units64" "dls")
1869
   (set_attr "cross" "n,n,y,y")])
1870
 
1871
;; -------------------------------------------------------------------------
1872
;; Conversions
1873
;; -------------------------------------------------------------------------
1874
 
1875
(define_insn "extendsfdf2"
1876
  [(set (match_operand:DF 0 "register_operand" "=a,b,a,b")
1877
        (float_extend:DF (match_operand:SF 1 "register_operand" "a,b,?b,?a")))]
1878
  "TARGET_FP"
1879
  "%|%.\\tspdp\\t%$\\t%1,%0"
1880
  [(set_attr "type" "dp2")
1881
   (set_attr "units" "s")
1882
   (set_attr "cross" "n,n,y,y")])
1883
 
1884
(define_insn "truncdfsf2"
1885
  [(set (match_operand:SF 0 "register_operand" "=a,b")
1886
        (float_truncate:SF (match_operand:DF 1 "register_operand" "a,b")))]
1887
  "TARGET_FP"
1888
  "%|%.\\tdpsp\\t%$\\t%1,%0"
1889
  [(set_attr "type" "fp4")
1890
   (set_attr "units" "l")
1891
   (set_attr "cross" "n")])
1892
 
1893
;;;; Convert between signed integer types and floating point.
1894
(define_insn "floatsisf2"
1895
  [(set (match_operand:SF 0 "register_operand" "=a,b,a,b")
1896
        (float:SF (match_operand:SI 1 "register_operand" "a,b,?b,?a")))]
1897
  "TARGET_FP"
1898
  "%|%.\\tintsp\\t%$\\t%1,%0"
1899
  [(set_attr "type" "fp4")
1900
   (set_attr "units" "l")
1901
   (set_attr "cross" "n,n,y,y")])
1902
 
1903
(define_insn "floatunssisf2"
1904
  [(set (match_operand:SF 0 "register_operand" "=a,b,a,b")
1905
        (unsigned_float:SF (match_operand:SI 1 "register_operand" "a,b,?b,?a")))]
1906
  "TARGET_FP"
1907
  "%|%.\\tintspu\\t%$\\t%1,%0"
1908
  [(set_attr "type" "fp4")
1909
   (set_attr "units" "l")
1910
   (set_attr "cross" "n,n,y,y")])
1911
 
1912
(define_insn "floatsidf2"
1913
  [(set (match_operand:DF 0 "register_operand" "=a,b,a,b")
1914
        (float:DF (match_operand:SI 1 "register_operand" "a,b,?b,?a")))]
1915
  "TARGET_FP"
1916
  "%|%.\\tintdp\\t%$\\t%1,%0"
1917
  [(set_attr "type" "intdp")
1918
   (set_attr "units" "l")
1919
   (set_attr "cross" "n,n,y,y")])
1920
 
1921
(define_insn "floatunssidf2"
1922
  [(set (match_operand:DF 0 "register_operand" "=a,b,a,b")
1923
        (unsigned_float:DF (match_operand:SI 1 "register_operand" "a,b,?b,?a")))]
1924
  "TARGET_FP"
1925
  "%|%.\\tintdpu\\t%$\\t%1,%0"
1926
  [(set_attr "type" "intdp")
1927
   (set_attr "units" "l")
1928
   (set_attr "cross" "n,n,y,y")])
1929
 
1930
(define_insn "fix_truncsfsi2"
1931
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b")
1932
        (fix:SI (match_operand:SF 1 "register_operand" "a,b,?b,?a")))]
1933
  "TARGET_FP"
1934
  "%|%.\\tsptrunc\\t%$\\t%1,%0"
1935
  [(set_attr "type" "fp4")
1936
   (set_attr "units" "l")
1937
   (set_attr "cross" "n,n,y,y")])
1938
 
1939
(define_insn "fix_truncdfsi2"
1940
  [(set (match_operand:SI 0 "register_operand" "=a,b")
1941
        (fix:SI (match_operand:DF 1 "register_operand" "a,b")))]
1942
  "TARGET_FP"
1943
  "%|%.\\tdptrunc\\t%$\\t%1,%0"
1944
  [(set_attr "type" "fp4")
1945
   (set_attr "units" "l")
1946
   (set_attr "cross" "n")])
1947
 
1948
;; -------------------------------------------------------------------------
1949
;; Saturating arithmetic
1950
;; -------------------------------------------------------------------------
1951
 
1952
(define_insn "saddsi3"
1953
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b,a,b,a,b")
1954
        (ss_plus:SI (match_operand:SI 1 "register_operand" "a,b,?b,?a,a,b,?b,?a")
1955
                    (match_operand:SI 2 "reg_or_const_int_operand" "a,b,a,b,aIs5,bIs5,aIs5,bIs5")))]
1956
  ""
1957
  "%|%.\\tsadd\\t%$\\t%2, %1, %0"
1958
  [(set_attr "units" "ls,ls,ls,ls,l,l,l,l")
1959
   (set_attr "cross" "n,n,y,y,n,n,y,y")])
1960
 
1961
(define_insn "ssubsi3"
1962
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b")
1963
        (ss_minus:SI (match_operand:SI 1 "reg_or_scst5_operand" "aIs5,bIs5,?bIs5,?aIs5")
1964
                     (match_operand:SI 2 "register_operand" "a,b,a,b")))]
1965
  ""
1966
  "%|%.\\tssub\\t%$\\t%1, %2, %0"
1967
  [(set_attr "units" "l")
1968
   (set_attr "cross" "n,n,y,y")])
1969
 
1970
(define_insn "subcsi3"
1971
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b")
1972
        (unspec:SI
1973
         [(match_operand:SI 1 "register_operand" "a,b,a,b")
1974
          (match_operand:SI 2 "register_operand" "a,b,?b,?a")]
1975
         UNSPEC_SUBC))]
1976
  ""
1977
  "%|%.\\tsubc\\t%$\\t%1, %2, %0"
1978
  [(set_attr "units" "l")
1979
   (set_attr "cross" "n,n,y,y")])
1980
 
1981
;; -------------------------------------------------------------------------
1982
;; Call instructions
1983
;; -------------------------------------------------------------------------
1984
 
1985
(define_expand "call"
1986
 [(match_operand 0 "" "")]
1987
 ""
1988
{
1989
  c6x_expand_call (NULL_RTX, operands[0], false);
1990
  DONE;
1991
})
1992
 
1993
(define_expand "call_value"
1994
  [(match_operand 0 "" "")
1995
   (match_operand 1 "" "")]
1996
 ""
1997
{
1998
  c6x_expand_call (operands[0], operands[1], false);
1999
  DONE;
2000
})
2001
 
2002
(define_expand "sibcall"
2003
 [(match_operand 0 "" "")]
2004
 ""
2005
{
2006
  c6x_expand_call (NULL_RTX, operands[0], true);
2007
  cfun->machine->contains_sibcall = true;
2008
  DONE;
2009
})
2010
 
2011
(define_expand "sibcall_value"
2012
  [(match_operand 0 "" "")
2013
   (match_operand 1 "" "")]
2014
 ""
2015
{
2016
  c6x_expand_call (operands[0], operands[1], true);
2017
  cfun->machine->contains_sibcall = true;
2018
  DONE;
2019
})
2020
 
2021
(define_insn "call_internal"
2022
  [(call (mem (match_operand:SI 0 "c6x_call_operand" "S1,a,b"))
2023
         (const_int 0))]
2024
  "!SIBLING_CALL_P (insn)"
2025
  "%|%.\\tcall\\t%$\\t%0"
2026
  [(set_attr "type" "call")
2027
   (set_attr "predicable" "no")
2028
   (set_attr "units" "s")
2029
   (set_attr "dest_regfile" "any,b,b")
2030
   (set_attr "cross" "n,y,n")])
2031
 
2032
(define_insn "call_value_internal"
2033
  [(set (match_operand 0 "" "")
2034
        (call (mem (match_operand:SI 1 "c6x_call_operand" "S1,a,b"))
2035
              (const_int 0)))]
2036
  ""
2037
  "%|%.\\tcall\\t%$\\t%1"
2038
  [(set_attr "type" "call")
2039
   (set_attr "predicable" "no")
2040
   (set_attr "units" "s")
2041
   (set_attr "dest_regfile" "any,b,b")
2042
   (set_attr "cross" "n,y,n")])
2043
 
2044
(define_insn "sibcall_internal"
2045
  [(call (mem (match_operand:SI 0 "c6x_call_operand" "S1,C"))
2046
         (const_int 0))]
2047
  "SIBLING_CALL_P (insn)"
2048
  "%|%.\\tb\\t%$\\t%0"
2049
  [(set_attr "type" "branch")
2050
   (set_attr "predicable" "no")
2051
   (set_attr "units" "s")
2052
   (set_attr "dest_regfile" "any,b")])
2053
 
2054
(define_insn "callp"
2055
  [(call (mem (match_operand:SI 0 "c6x_call_operand" "S1"))
2056
         (const_int 0))
2057
   (unspec [(const_int 6)] UNSPEC_NOP)]
2058
  "!SIBLING_CALL_P (insn)"
2059
  "%|%.\\tcallp\\t%$\\t%0, B3"
2060
  [(set_attr "type" "callp")
2061
   (set_attr "predicable" "no")
2062
   (set_attr "units" "s")
2063
   (set_attr "dest_regfile" "b")
2064
   (set_attr "cross" "n")])
2065
 
2066
(define_insn "callp_value"
2067
  [(set (match_operand:SI 0 "register_operand" "")
2068
        (call (mem (match_operand:SI 1 "c6x_call_operand" "S1"))
2069
              (const_int 0)))
2070
   (unspec [(const_int 6)] UNSPEC_NOP)]
2071
  "!SIBLING_CALL_P (insn)"
2072
  "%|%.\\tcallp\\t%$\\t%1, B3"
2073
  [(set_attr "type" "callp")
2074
   (set_attr "predicable" "no")
2075
   (set_attr "units" "s")
2076
   (set_attr "dest_regfile" "b")
2077
   (set_attr "cross" "n")])
2078
 
2079
(define_insn "return_internal"
2080
  [(return)
2081
   (use (match_operand:SI 0 "register_operand" "b"))]
2082
  "reload_completed"
2083
  "%|%.\\tret\\t%$\\t%0"
2084
  [(set_attr "type" "branch")
2085
   (set_attr "units" "s")
2086
   (set_attr "dest_regfile" "b")])
2087
 
2088
(define_insn "addkpc"
2089
  [(set (match_operand:SI 0 "register_operand" "=b")
2090
        (unspec:SI [(match_operand 1 "" "")] UNSPEC_ADDKPC))
2091
   (unspec [(match_operand 2 "const_int_operand" "n")] UNSPEC_NOP)]
2092
  "TARGET_INSNS_64"
2093
  "%|%.\\taddkpc\\t%$\\t%l1, %0, %2"
2094
  [(set_attr "units" "s")
2095
   (set_attr "dest_regfile" "b")])
2096
 
2097
;; -------------------------------------------------------------------------
2098
;; Unary operations
2099
;; -------------------------------------------------------------------------
2100
 
2101
(define_insn "negsi2"
2102
  [(set (match_operand:SI 0 "register_operand" "=a, a, b, b")
2103
        (neg:SI (match_operand:SI 1 "register_operand" "a,?b, b,?a")))]
2104
  ""
2105
  "%|%.\\tneg\\t%$\\t%1, %0"
2106
  [(set_attr "units" "ls")
2107
   (set_attr "cross" "n,y,n,y")])
2108
 
2109
(define_insn "one_cmplsi2"
2110
  [(set (match_operand:SI 0 "register_operand" "=a, a, b, b")
2111
        (not:SI (match_operand:SI 1 "register_operand" "a,?b, b,?a")))]
2112
  ""
2113
  "%|%.\\tnot\\t%$\\t%1, %0"
2114
  [(set_attr "units" "ls")
2115
   (set_attr "cross" "n,y,n,y")])
2116
 
2117
(define_insn "clrsbsi2"
2118
  [(set (match_operand:SI 0 "register_operand" "=a, a, b, b")
2119
        (clrsb:SI (match_operand:SI 1 "register_operand" "a,?b, b,?a")))]
2120
  ""
2121
  "%|%.\\tnorm\\t%$\\t%1, %0"
2122
  [(set_attr "units" "l")
2123
   (set_attr "cross" "n,y,n,y")])
2124
 
2125
(define_insn "clzsi2"
2126
  [(set (match_operand:SI 0 "register_operand" "=a, a, b, b")
2127
        (clz:SI (match_operand:SI 1 "register_operand" "a,?b, b,?a")))]
2128
  ""
2129
  "%|%.\\tlmbd\\t%$\\t1, %1, %0"
2130
  [(set_attr "units" "l")
2131
   (set_attr "cross" "n,y,n,y")])
2132
 
2133
;; bitrevsi2 is defined in c6x-mult.md.in.
2134
 
2135
(define_expand "ctzsi2"
2136
  [(set (match_operand:SI 0 "register_operand" "")
2137
        (ctz:SI (match_operand:SI 1 "register_operand" "")))]
2138
  "TARGET_INSNS_64"
2139
{
2140
  rtx tmpreg = gen_reg_rtx (SImode);
2141
  emit_insn (gen_bitrevsi2 (tmpreg, operands[1]));
2142
  emit_insn (gen_clzsi2 (operands[0], tmpreg));
2143
  DONE;
2144
})
2145
 
2146
(define_expand "ctzdi2"
2147
  [(set (match_operand:DI 0 "register_operand" "")
2148
        (ctz:DI (match_operand:DI 1 "register_operand" "")))]
2149
  "TARGET_INSNS_64"
2150
{
2151
  rtx tmpreg = gen_reg_rtx (DImode);
2152
  rtx out;
2153
  emit_insn (gen_bitrevsi2 (gen_highpart (SImode, tmpreg),
2154
                            gen_lowpart (SImode, operands[1])));
2155
  emit_insn (gen_bitrevsi2 (gen_lowpart (SImode, tmpreg),
2156
                            gen_highpart (SImode, operands[1])));
2157
  out = expand_unop (DImode, clz_optab, tmpreg, operands[0], 1);
2158
  if (!rtx_equal_p (out, operands[0]))
2159
    emit_move_insn (operands[0], out);
2160
  DONE;
2161
})
2162
 
2163
(define_insn "ssabssi2"
2164
  [(set (match_operand:SI 0 "register_operand" "=a, a, b, b")
2165
        (ss_abs:SI (match_operand:SI 1 "register_operand" "a,?b, b,?a")))]
2166
  ""
2167
  "%|%.\\tabs\\t%$\\t%1, %0"
2168
  [(set_attr "units" "l")
2169
   (set_attr "cross" "n,y,n,y")])
2170
 
2171
;; -------------------------------------------------------------------------
2172
;; Shift instructions
2173
;; -------------------------------------------------------------------------
2174
 
2175
(define_code_iterator any_shift [ss_ashift ashift ashiftrt lshiftrt])
2176
(define_code_iterator any_rshift [ashiftrt lshiftrt])
2177
(define_code_attr shift_code [(ss_ashift "ss_ashl") (ashift "ashl")
2178
                              (ashiftrt "ashr") (lshiftrt "lshr")])
2179
(define_code_attr shift_insn [(ss_ashift "sshl") (ashift "shl")
2180
                              (ashiftrt "shr") (lshiftrt "shru")])
2181
 
2182
(define_insn "si3"
2183
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b")
2184
        (any_shift:SI (match_operand:SI 1 "register_operand" "a,b,?b,?a")
2185
                      (match_operand:SI 2 "reg_or_ucst5_operand" "aIu5,bIu5,aIu5,bIu5")))]
2186
  ""
2187
  "%|%.\\t\\t%$\\t%1, %2, %0"
2188
  [(set_attr "units" "s")
2189
   (set_attr "cross" "n,n,y,y")])
2190
 
2191
;; See c6x-mult.md.in for the rotlsi3 pattern.
2192
 
2193
(define_insn "rotrdi3_16"
2194
  [(set (match_operand:DI 0 "register_operand" "=a,b")
2195
        (rotatert:DI (match_operand:DI 1 "register_operand" "a,b")
2196
                     (const_int 16)))]
2197
  "TARGET_INSNS_64PLUS"
2198
  "%|%.\\tdpackx2\\t%$\\t%P1, %p1, %0"
2199
  [(set_attr "units" "l")
2200
   (set_attr "cross" "n")])
2201
 
2202
(define_insn "shlmbsi3"
2203
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,b")
2204
        (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "a,b,?b,?a")
2205
                           (const_int 8))
2206
                (lshiftrt:SI (match_operand:SI 2 "register_operand" "a,b,a,b")
2207
                             (const_int 24))))]
2208
  "TARGET_INSNS_64"
2209
  "%|%.\\tshlmb\\t%$\\t%2, %1, %0"
2210
  [(set_attr "units" "ls")
2211
   (set_attr "cross" "n,n,y,y")])
2212
 
2213
(define_expand "ashldi3"
2214
  [(set (match_operand:DI 0 "register_operand" "")
2215
        (ashift:DI (match_operand:DI 1 "register_operand" "")
2216
                   (match_operand:SI 2 "const_int_operand" "")))]
2217
  "TARGET_INSNS_64"
2218
{
2219
  if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 8)
2220
    {
2221
      rtx lo0, lo1, hi0, hi1, tmp;
2222
      lo0 = gen_lowpart (SImode, operands[0]);
2223
      hi0 = gen_highpart (SImode, operands[0]);
2224
      lo1 = gen_lowpart (SImode, operands[1]);
2225
      hi1 = gen_highpart (SImode, operands[1]);
2226
      if (reg_overlap_mentioned_p (hi0, lo1))
2227
        tmp = gen_reg_rtx (SImode);
2228
      else
2229
        tmp = hi0;
2230
      emit_insn (gen_shlmbsi3 (tmp, hi1, lo1));
2231
      emit_insn (gen_ashlsi3 (lo0, lo1, operands[2]));
2232
      if (tmp != hi0)
2233
        emit_move_insn (hi0, tmp);
2234
      DONE;
2235
    }
2236
  FAIL;
2237
})
2238
 
2239
(define_expand "rotrdi3"
2240
  [(set (match_operand:DI 0 "register_operand" "")
2241
        (rotatert:DI (match_operand:DI 1 "register_operand" "")
2242
                     (match_operand:SI 2 "const_int_operand" "")))]
2243
  "TARGET_INSNS_64PLUS"
2244
{
2245
  if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 16)
2246
    {
2247
      emit_insn (gen_rotrdi3_16 (operands[0], operands[1]));
2248
      DONE;
2249
    }
2250
  FAIL;
2251
})
2252
 
2253
(define_insn "bswapv2hi2"
2254
  [(set (match_operand:V2HI 0 "register_operand" "=a,b,a,b")
2255
        (bswap:V2HI (match_operand:V2HI 1 "register_operand" "a,b,?b,?a")))]
2256
  "TARGET_INSNS_64"
2257
  "%|%.\\tswap4\\t%$\\t%1, %0"
2258
  [(set_attr "units" "l")
2259
   (set_attr "cross" "n,n,y,y")])
2260
 
2261
(define_expand "bswapsi2"
2262
  [(set (match_operand:SI 0 "register_operand" "")
2263
        (bswap:SI (match_operand:SI 1 "register_operand" "")))]
2264
  "TARGET_INSNS_64"
2265
{
2266
  rtx tmpreg = gen_reg_rtx (SImode);
2267
  rtx tmpv2 = gen_lowpart (V2HImode, tmpreg);
2268
  rtx op0v2 = gen_lowpart (V2HImode, operands[0]);
2269
  emit_insn (gen_rotlsi3 (tmpreg, operands[1], GEN_INT (16)));
2270
  emit_insn (gen_bswapv2hi2 (op0v2, tmpv2));
2271
  DONE;
2272
})
2273
 
2274
;; -------------------------------------------------------------------------
2275
;; Division
2276
;; -------------------------------------------------------------------------
2277
 
2278
(define_insn "divsi3_insn"
2279
  [(set (reg:SI REG_A4) (div:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2280
   (clobber (reg:SI REG_A0))
2281
   (clobber (reg:SI REG_A1))
2282
   (clobber (reg:SI REG_A2))
2283
   (clobber (reg:SI REG_A6))
2284
   (clobber (reg:SI REG_B0))
2285
   (clobber (reg:SI REG_B1))
2286
   (clobber (reg:SI REG_B2))
2287
   (clobber (reg:SI REG_B3))
2288
   (clobber (reg:SI REG_B4))
2289
   (clobber (reg:SI REG_B5))
2290
   (clobber (reg:SI REG_B30))
2291
   (clobber (reg:SI REG_B31))]
2292
  ""
2293
  "%|%.\\tcall\\t%$\\t__c6xabi_divi"
2294
  [(set_attr "type" "call")
2295
   (set_attr "dest_regfile" "any")
2296
   (set_attr "units" "s")
2297
   (set_attr "cross" "n")])
2298
 
2299
(define_insn "divsi3_insn_indcall"
2300
  [(set (reg:SI REG_A4) (div:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2301
   (use (match_operand:SI 0 "register_operand" "b"))
2302
   (clobber (reg:SI REG_A0))
2303
   (clobber (reg:SI REG_A1))
2304
   (clobber (reg:SI REG_A2))
2305
   (clobber (reg:SI REG_A6))
2306
   (clobber (reg:SI REG_B0))
2307
   (clobber (reg:SI REG_B1))
2308
   (clobber (reg:SI REG_B2))
2309
   (clobber (reg:SI REG_B3))
2310
   (clobber (reg:SI REG_B4))
2311
   (clobber (reg:SI REG_B5))
2312
   (clobber (reg:SI REG_B30))
2313
   (clobber (reg:SI REG_B31))]
2314
  ""
2315
  "%|%.\\tcall\\t%$\\t%0"
2316
  [(set_attr "type" "call")
2317
   (set_attr "dest_regfile" "any")
2318
   (set_attr "units" "s")
2319
   (set_attr "cross" "n")])
2320
 
2321
(define_insn "udivsi3_insn"
2322
  [(set (reg:SI REG_A4) (udiv:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2323
   (clobber (reg:SI REG_A0))
2324
   (clobber (reg:SI REG_A1))
2325
   (clobber (reg:SI REG_A2))
2326
   (clobber (reg:SI REG_A6))
2327
   (clobber (reg:SI REG_B0))
2328
   (clobber (reg:SI REG_B1))
2329
   (clobber (reg:SI REG_B2))
2330
   (clobber (reg:SI REG_B3))
2331
   (clobber (reg:SI REG_B4))
2332
   (clobber (reg:SI REG_B30))
2333
   (clobber (reg:SI REG_B31))]
2334
  ""
2335
  "%|%.\\tcall\\t%$\\t__c6xabi_divu"
2336
  [(set_attr "type" "call")
2337
   (set_attr "dest_regfile" "any")
2338
   (set_attr "units" "s")
2339
   (set_attr "cross" "n")])
2340
 
2341
(define_insn "udivsi3_insn_indcall"
2342
  [(set (reg:SI REG_A4) (udiv:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2343
   (use (match_operand:SI 0 "register_operand" "b"))
2344
   (clobber (reg:SI REG_A0))
2345
   (clobber (reg:SI REG_A1))
2346
   (clobber (reg:SI REG_A2))
2347
   (clobber (reg:SI REG_A6))
2348
   (clobber (reg:SI REG_B0))
2349
   (clobber (reg:SI REG_B1))
2350
   (clobber (reg:SI REG_B2))
2351
   (clobber (reg:SI REG_B3))
2352
   (clobber (reg:SI REG_B4))
2353
   (clobber (reg:SI REG_B30))
2354
   (clobber (reg:SI REG_B31))]
2355
  ""
2356
  "%|%.\\tcall\\t%$\\t%0"
2357
  [(set_attr "type" "call")
2358
   (set_attr "dest_regfile" "any")
2359
   (set_attr "units" "s")
2360
   (set_attr "cross" "n")])
2361
 
2362
(define_insn "modsi3_insn"
2363
  [(set (reg:SI REG_A4) (mod:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2364
   (clobber (reg:SI REG_A1))
2365
   (clobber (reg:SI REG_A2))
2366
   (clobber (reg:SI REG_A5))
2367
   (clobber (reg:SI REG_A6))
2368
   (clobber (reg:SI REG_B0))
2369
   (clobber (reg:SI REG_B1))
2370
   (clobber (reg:SI REG_B2))
2371
   (clobber (reg:SI REG_B3))
2372
   (clobber (reg:SI REG_B4))
2373
   (clobber (reg:SI REG_B30))
2374
   (clobber (reg:SI REG_B31))]
2375
  ""
2376
  "%|%.\\tcall\\t%$\\t__c6xabi_remi"
2377
  [(set_attr "type" "call")
2378
   (set_attr "dest_regfile" "any")
2379
   (set_attr "units" "s")
2380
   (set_attr "cross" "n")])
2381
 
2382
(define_insn "modsi3_insn_indcall"
2383
  [(set (reg:SI REG_A4) (mod:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2384
   (use (match_operand:SI 0 "register_operand" "b"))
2385
   (clobber (reg:SI REG_A1))
2386
   (clobber (reg:SI REG_A2))
2387
   (clobber (reg:SI REG_A5))
2388
   (clobber (reg:SI REG_A6))
2389
   (clobber (reg:SI REG_B0))
2390
   (clobber (reg:SI REG_B1))
2391
   (clobber (reg:SI REG_B2))
2392
   (clobber (reg:SI REG_B3))
2393
   (clobber (reg:SI REG_B4))
2394
   (clobber (reg:SI REG_B30))
2395
   (clobber (reg:SI REG_B31))]
2396
  ""
2397
  "%|%.\\tcall\\t%$\\t%0"
2398
  [(set_attr "type" "call")
2399
   (set_attr "dest_regfile" "any")
2400
   (set_attr "units" "s")
2401
   (set_attr "cross" "n")])
2402
 
2403
(define_insn "divmodsi4_insn"
2404
  [(set (reg:SI REG_A4) (div:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2405
   (set (reg:SI REG_A5) (mod:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2406
   (clobber (reg:SI REG_A1))
2407
   (clobber (reg:SI REG_A2))
2408
   (clobber (reg:SI REG_A6))
2409
   (clobber (reg:SI REG_B0))
2410
   (clobber (reg:SI REG_B1))
2411
   (clobber (reg:SI REG_B2))
2412
   (clobber (reg:SI REG_B3))
2413
   (clobber (reg:SI REG_B4))
2414
   (clobber (reg:SI REG_B30))
2415
   (clobber (reg:SI REG_B31))]
2416
  ""
2417
  "%|%.\\tcall\\t%$\\t__c6xabi_divremi"
2418
  [(set_attr "type" "call")
2419
   (set_attr "dest_regfile" "any")
2420
   (set_attr "units" "s")
2421
   (set_attr "cross" "n")])
2422
 
2423
(define_insn "divmodsi4_insn_indcall"
2424
  [(set (reg:SI REG_A4) (div:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2425
   (set (reg:SI REG_A5) (mod:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2426
   (use (match_operand:SI 0 "register_operand" "b"))
2427
   (clobber (reg:SI REG_A1))
2428
   (clobber (reg:SI REG_A2))
2429
   (clobber (reg:SI REG_A5))
2430
   (clobber (reg:SI REG_A6))
2431
   (clobber (reg:SI REG_B0))
2432
   (clobber (reg:SI REG_B1))
2433
   (clobber (reg:SI REG_B2))
2434
   (clobber (reg:SI REG_B3))
2435
   (clobber (reg:SI REG_B4))
2436
   (clobber (reg:SI REG_B30))
2437
   (clobber (reg:SI REG_B31))]
2438
  ""
2439
  "%|%.\\tcall\\t%$\\t%0"
2440
  [(set_attr "type" "call")
2441
   (set_attr "dest_regfile" "any")
2442
   (set_attr "units" "s")
2443
   (set_attr "cross" "n")])
2444
 
2445
(define_insn "umodsi3_insn"
2446
  [(set (reg:SI REG_A4) (umod:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2447
   (clobber (reg:SI REG_A1))
2448
   (clobber (reg:SI REG_A5))
2449
   (clobber (reg:SI REG_A7))
2450
   (clobber (reg:SI REG_B0))
2451
   (clobber (reg:SI REG_B1))
2452
   (clobber (reg:SI REG_B2))
2453
   (clobber (reg:SI REG_B3))
2454
   (clobber (reg:SI REG_B4))
2455
   (clobber (reg:SI REG_B30))
2456
   (clobber (reg:SI REG_B31))]
2457
  ""
2458
  "%|%.\\tcall\\t%$\\t__c6xabi_remu"
2459
  [(set_attr "type" "call")
2460
   (set_attr "dest_regfile" "any")
2461
   (set_attr "units" "s")
2462
   (set_attr "cross" "n")])
2463
 
2464
(define_insn "umodsi3_insn_indcall"
2465
  [(set (reg:SI REG_A4) (umod:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2466
   (use (match_operand:SI 0 "register_operand" "b"))
2467
   (clobber (reg:SI REG_A1))
2468
   (clobber (reg:SI REG_A5))
2469
   (clobber (reg:SI REG_A7))
2470
   (clobber (reg:SI REG_B0))
2471
   (clobber (reg:SI REG_B1))
2472
   (clobber (reg:SI REG_B2))
2473
   (clobber (reg:SI REG_B3))
2474
   (clobber (reg:SI REG_B4))
2475
   (clobber (reg:SI REG_B30))
2476
   (clobber (reg:SI REG_B31))]
2477
  ""
2478
  "%|%.\\tcall\\t%$\\t%0"
2479
  [(set_attr "type" "call")
2480
   (set_attr "dest_regfile" "any")
2481
   (set_attr "units" "s")
2482
   (set_attr "cross" "n")])
2483
 
2484
(define_insn "udivmodsi4_insn"
2485
  [(set (reg:SI REG_A4) (udiv:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2486
   (set (reg:SI REG_A5) (umod:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2487
   (clobber (reg:SI REG_A0))
2488
   (clobber (reg:SI REG_A1))
2489
   (clobber (reg:SI REG_A2))
2490
   (clobber (reg:SI REG_A6))
2491
   (clobber (reg:SI REG_B0))
2492
   (clobber (reg:SI REG_B1))
2493
   (clobber (reg:SI REG_B2))
2494
   (clobber (reg:SI REG_B3))
2495
   (clobber (reg:SI REG_B4))
2496
   (clobber (reg:SI REG_B30))
2497
   (clobber (reg:SI REG_B31))]
2498
  ""
2499
  "%|%.\\tcall\\t%$\\t__c6xabi_divremu"
2500
  [(set_attr "type" "call")
2501
   (set_attr "dest_regfile" "any")
2502
   (set_attr "units" "s")
2503
   (set_attr "cross" "n")])
2504
 
2505
(define_insn "udivmodsi4_insn_indcall"
2506
  [(set (reg:SI REG_A4) (udiv:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2507
   (set (reg:SI REG_A5) (umod:SI (reg:SI REG_A4) (reg:SI REG_B4)))
2508
   (use (match_operand:SI 0 "register_operand" "b"))
2509
   (clobber (reg:SI REG_A0))
2510
   (clobber (reg:SI REG_A1))
2511
   (clobber (reg:SI REG_A2))
2512
   (clobber (reg:SI REG_A6))
2513
   (clobber (reg:SI REG_B0))
2514
   (clobber (reg:SI REG_B1))
2515
   (clobber (reg:SI REG_B2))
2516
   (clobber (reg:SI REG_B3))
2517
   (clobber (reg:SI REG_B4))
2518
   (clobber (reg:SI REG_B30))
2519
   (clobber (reg:SI REG_B31))]
2520
  ""
2521
  "%|%.\\tcall\\t%$\\t%0"
2522
  [(set_attr "type" "call")
2523
   (set_attr "dest_regfile" "any")
2524
   (set_attr "units" "s")
2525
   (set_attr "cross" "n")])
2526
 
2527
(define_insn_and_split "divmodsi4"
2528
  [(set (match_operand:SI 0 "register_operand" "")
2529
        (div:SI (match_operand:SI 1 "register_operand" "")
2530
                   (match_operand:SI 2 "register_operand" "")))
2531
   (set (match_operand:SI 3 "register_operand" "")
2532
        (mod:SI (match_dup 1) (match_dup 2)))
2533
   (clobber (reg:SI REG_A0))
2534
   (clobber (reg:SI REG_A1))
2535
   (clobber (reg:SI REG_A2))
2536
   (clobber (reg:SI REG_A4))
2537
   (clobber (reg:SI REG_A5))
2538
   (clobber (reg:SI REG_A6))
2539
   (clobber (reg:SI REG_B0))
2540
   (clobber (reg:SI REG_B1))
2541
   (clobber (reg:SI REG_B2))
2542
   (clobber (reg:SI REG_B3))
2543
   (clobber (reg:SI REG_B4))
2544
   (clobber (reg:SI REG_B5))
2545
   (clobber (reg:SI REG_B30))
2546
   (clobber (reg:SI REG_B31))]
2547
  ""
2548
  "#"
2549
  ""
2550
  [(const_int 0)]
2551
{
2552
  rtx reg = NULL_RTX;
2553
 
2554
  if (TARGET_LONG_CALLS)
2555
    {
2556
      if (reload_completed)
2557
        reg = gen_rtx_REG (SImode, REG_A6);
2558
      else
2559
        reg = gen_reg_rtx (SImode);
2560
    }
2561
  emit_move_insn (gen_rtx_REG (SImode, REG_A4), operands[1]);
2562
  emit_move_insn (gen_rtx_REG (SImode, REG_B4), operands[2]);
2563
  if (find_reg_note (curr_insn, REG_UNUSED, operands[3]))
2564
    {
2565
      if (TARGET_LONG_CALLS)
2566
        {
2567
          emit_move_insn (reg, optab_libfunc (sdiv_optab, SImode));
2568
          emit_insn (gen_divsi3_insn_indcall (reg));
2569
        }
2570
      else
2571
        emit_insn (gen_divsi3_insn ());
2572
      emit_move_insn (operands[0], gen_rtx_REG (SImode, REG_A4));
2573
    }
2574
  else if (find_reg_note (curr_insn, REG_UNUSED, operands[0]))
2575
    {
2576
      if (TARGET_LONG_CALLS)
2577
        {
2578
          emit_move_insn (reg, optab_libfunc (smod_optab, SImode));
2579
          emit_insn (gen_modsi3_insn_indcall (reg));
2580
        }
2581
      else
2582
        emit_insn (gen_modsi3_insn ());
2583
      emit_move_insn (operands[3], gen_rtx_REG (SImode, REG_A4));
2584
    }
2585
  else
2586
    {
2587
      if (TARGET_LONG_CALLS)
2588
        {
2589
          emit_move_insn (reg, optab_libfunc (sdivmod_optab, SImode));
2590
          emit_insn (gen_divmodsi4_insn_indcall (reg));
2591
        }
2592
      else
2593
        emit_insn (gen_divmodsi4_insn ());
2594
      emit_move_insn (operands[0], gen_rtx_REG (SImode, REG_A4));
2595
      emit_move_insn (operands[3], gen_rtx_REG (SImode, REG_A5));
2596
    }
2597
  DONE;
2598
})
2599
 
2600
(define_insn_and_split "udivmodsi4"
2601
  [(set (match_operand:SI 0 "register_operand" "")
2602
        (udiv:SI (match_operand:SI 1 "register_operand" "")
2603
                   (match_operand:SI 2 "register_operand" "")))
2604
   (set (match_operand:SI 3 "register_operand" "")
2605
        (umod:SI (match_dup 1) (match_dup 2)))
2606
   (clobber (reg:SI REG_A0))
2607
   (clobber (reg:SI REG_A1))
2608
   (clobber (reg:SI REG_A2))
2609
   (clobber (reg:SI REG_A4))
2610
   (clobber (reg:SI REG_A5))
2611
   (clobber (reg:SI REG_A6))
2612
   (clobber (reg:SI REG_A7))
2613
   (clobber (reg:SI REG_B0))
2614
   (clobber (reg:SI REG_B1))
2615
   (clobber (reg:SI REG_B2))
2616
   (clobber (reg:SI REG_B3))
2617
   (clobber (reg:SI REG_B4))
2618
   (clobber (reg:SI REG_B30))
2619
   (clobber (reg:SI REG_B31))]
2620
  ""
2621
  "#"
2622
  ""
2623
  [(const_int 0)]
2624
{
2625
  rtx reg = NULL_RTX;
2626
 
2627
  if (TARGET_LONG_CALLS)
2628
    {
2629
      if (reload_completed)
2630
        reg = gen_rtx_REG (SImode, REG_A6);
2631
      else
2632
        reg = gen_reg_rtx (SImode);
2633
    }
2634
 
2635
  emit_move_insn (gen_rtx_REG (SImode, REG_A4), operands[1]);
2636
  emit_move_insn (gen_rtx_REG (SImode, REG_B4), operands[2]);
2637
  if (find_reg_note (curr_insn, REG_UNUSED, operands[3]))
2638
    {
2639
      if (TARGET_LONG_CALLS)
2640
        {
2641
          emit_move_insn (reg, optab_libfunc (udiv_optab, SImode));
2642
          emit_insn (gen_udivsi3_insn_indcall (reg));
2643
        }
2644
      else
2645
        emit_insn (gen_udivsi3_insn ());
2646
      emit_move_insn (operands[0], gen_rtx_REG (SImode, REG_A4));
2647
    }
2648
  else if (find_reg_note (curr_insn, REG_UNUSED, operands[0]))
2649
    {
2650
      if (TARGET_LONG_CALLS)
2651
        {
2652
          emit_move_insn (reg, optab_libfunc (umod_optab, SImode));
2653
          emit_insn (gen_umodsi3_insn_indcall (reg));
2654
        }
2655
      else
2656
        emit_insn (gen_umodsi3_insn ());
2657
      emit_move_insn (operands[3], gen_rtx_REG (SImode, REG_A4));
2658
    }
2659
  else
2660
    {
2661
      if (TARGET_LONG_CALLS)
2662
        {
2663
          emit_move_insn (reg, optab_libfunc (udivmod_optab, SImode));
2664
          emit_insn (gen_udivmodsi4_insn_indcall (reg));
2665
        }
2666
      else
2667
        emit_insn (gen_udivmodsi4_insn ());
2668
      emit_move_insn (operands[0], gen_rtx_REG (SImode, REG_A4));
2669
      emit_move_insn (operands[3], gen_rtx_REG (SImode, REG_A5));
2670
    }
2671
  DONE;
2672
})
2673
 
2674
;; -------------------------------------------------------------------------
2675
;; Multiplication
2676
;; See c6x-mult.md.in for define_insn patterns.
2677
;; -------------------------------------------------------------------------
2678
 
2679
(define_expand "mulhisi3"
2680
  [(set (match_operand:SI 0 "register_operand" "")
2681
        (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" ""))
2682
                 (sign_extend:SI (match_operand:HI 2 "reg_or_scst5_operand" ""))))]
2683
  ""
2684
{
2685
  if (CONSTANT_P (operands[2]))
2686
    {
2687
      emit_insn (gen_mulhisi3_const (operands[0], operands[1], operands[2]));
2688
      DONE;
2689
    }
2690
})
2691
 
2692
(define_expand "usmulhisi3"
2693
  [(set (match_operand:SI 0 "register_operand" "")
2694
        (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" ""))
2695
                 (sign_extend:SI (match_operand:HI 2 "reg_or_scst5_operand" ""))))]
2696
 ""
2697
{
2698
  if (CONSTANT_P (operands[2]))
2699
    {
2700
      emit_insn (gen_usmulhisi3_const (operands[0], operands[1], operands[2]));
2701
      DONE;
2702
    }
2703
})
2704
 
2705
(define_expand "mulsi3"
2706
  [(set (match_operand:SI 0 "register_operand" "")
2707
        (mult:SI (match_operand:SI 1 "register_operand" "")
2708
                 (match_operand:SI 2 "register_operand" "")))]
2709
  ""
2710
{
2711
  if (!TARGET_MPY32)
2712
    {
2713
      rtx lo1 = gen_lowpart (HImode, operands[1]);
2714
      rtx lo2 = gen_lowpart (HImode, operands[2]);
2715
      /*   (N * AH + AL) * (N * BH + BL)
2716
         = N*(AH * BL + BH * AL) + AL*BL  */
2717
      rtx tmp1 = gen_reg_rtx (SImode);
2718
      rtx tmp2 = gen_reg_rtx (SImode);
2719
      rtx tmp3 = gen_reg_rtx (SImode);
2720
      emit_insn (gen_umulhisi3 (tmp1, lo1, lo2));
2721
      emit_insn (gen_umulhisi3_lh (tmp2, lo1, operands[2]));
2722
      emit_insn (gen_umulhisi3_hl (tmp3, operands[1], lo2));
2723
      emit_insn (gen_addsi3 (tmp2, tmp2, tmp3));
2724
      emit_insn (gen_ashlsi3 (tmp2, tmp2, GEN_INT (16)));
2725
      emit_insn (gen_addsi3 (operands[0], tmp1, tmp2));
2726
      DONE;
2727
    }
2728
})
2729
 
2730
;; -------------------------------------------------------------------------
2731
;; Floating point multiplication
2732
;; -------------------------------------------------------------------------
2733
 
2734
(define_insn "mulsf3"
2735
  [(set (match_operand:SF 0 "register_operand" "=a,b,a,b")
2736
        (mult:SF (match_operand:SF 1 "register_operand" "%a,b,?a,?b")
2737
                 (match_operand:SF 2 "register_operand" "a,b,b,a")))]
2738
  "TARGET_FP"
2739
  "%|%.\\tmpysp\\t%$\\t%1, %2, %0"
2740
 [(set_attr "type" "mpy4")
2741
  (set_attr "units" "m")
2742
  (set_attr "cross" "n,n,y,y")])
2743
 
2744
(define_insn "muldf3"
2745
  [(set (match_operand:DF 0 "register_operand" "=a,b")
2746
        (mult:DF (match_operand:DF 1 "register_operand" "%a,b")
2747
                 (match_operand:DF 2 "register_operand" "a,b")))]
2748
  "TARGET_FP"
2749
  "%|%.\\tmpydp\\t%$\\t%1, %2, %0"
2750
 [(set_attr "type" "mpydp")
2751
  (set_attr "units" "m")
2752
  (set_attr "cross" "n")])
2753
 
2754
;; Note that mpyspdp and mpysp2dp are available on C67x, despite what the
2755
;; manual says.
2756
(define_insn "*muldf_ext1"
2757
  [(set (match_operand:DF 0 "register_operand" "=a,b,a,b")
2758
        (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "a,b,a,b"))
2759
                 (match_operand:DF 2 "register_operand" "a,b,?b,?a")))]
2760
  "TARGET_FP_EXT"
2761
  "%|%.\\tmpyspdp\\t%$\\t%1, %2, %0"
2762
 [(set_attr "type" "mpyspdp")
2763
  (set_attr "units" "m")
2764
  (set_attr "cross" "n,n,y,y")])
2765
 
2766
(define_insn "*muldf_ext2"
2767
  [(set (match_operand:DF 0 "register_operand" "=a,b,a,b")
2768
        (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "%a,b,a,b"))
2769
                 (float_extend:DF (match_operand:SF 2 "register_operand" "a,b,?b,?a"))))]
2770
  "TARGET_FP_EXT"
2771
  "%|%.\\tmpysp2dp\\t%$\\t%1, %2, %0"
2772
 [(set_attr "type" "mpysp2dp")
2773
  (set_attr "units" "m")
2774
  (set_attr "cross" "n,n,y,y")])
2775
 
2776
;; -------------------------------------------------------------------------
2777
;; Floating point division
2778
;; -------------------------------------------------------------------------
2779
 
2780
(define_insn "rcpsf2"
2781
  [(set (match_operand:SF 0 "register_operand" "=a,b,a,b")
2782
        (unspec:SF [(match_operand:SF 1 "register_operand" "a,b,?b,?a")]
2783
                   UNSPEC_RCP))]
2784
  "TARGET_FP"
2785
  "%|%.\\trcpsp\\t%$\\t%1, %0"
2786
 [(set_attr "units" "s")
2787
  (set_attr "cross" "n,n,y,y")])
2788
 
2789
(define_insn "rcpdf2"
2790
  [(set (match_operand:DF 0 "register_operand" "=a,b")
2791
        (unspec:DF [(match_operand:DF 1 "register_operand" "a,b")]
2792
                   UNSPEC_RCP))]
2793
  "TARGET_FP"
2794
  "%|%.\\trcpdp\\t%$\\t%1, %0"
2795
 [(set_attr "type" "dp2")
2796
  (set_attr "units" "s")
2797
  (set_attr "cross" "n")])
2798
 
2799
(define_expand "divsf3"
2800
  [(set (match_dup 4)
2801
        (unspec:SF [(match_operand:SF 2 "register_operand" "")]
2802
                   UNSPEC_RCP))
2803
   (set (match_dup 5) (mult:SF (match_dup 2) (match_dup 4)))
2804
   (set (match_dup 6) (minus:SF (match_dup 3) (match_dup 5)))
2805
   (set (match_dup 4) (mult:SF (match_dup 4) (match_dup 6)))
2806
   (set (match_dup 5) (mult:SF (match_dup 2) (match_dup 4)))
2807
   (set (match_dup 6) (minus:SF (match_dup 3) (match_dup 5)))
2808
   (set (match_dup 4) (mult:SF (match_dup 4) (match_dup 6)))
2809
   (set (match_operand:SF 0 "register_operand" "")
2810
        (mult:SF (match_operand:SF 1 "register_operand")
2811
                 (match_dup 4)))]
2812
  "TARGET_FP && flag_reciprocal_math"
2813
{
2814
  operands[3] = force_reg (SFmode,
2815
                           CONST_DOUBLE_FROM_REAL_VALUE (dconst2, SFmode));
2816
  operands[4] = gen_reg_rtx (SFmode);
2817
  operands[5] = gen_reg_rtx (SFmode);
2818
  operands[6] = gen_reg_rtx (SFmode);
2819
})
2820
 
2821
(define_expand "divdf3"
2822
  [(set (match_dup 4)
2823
        (unspec:DF [(match_operand:DF 2 "register_operand" "")]
2824
                   UNSPEC_RCP))
2825
   (set (match_dup 5) (mult:DF (match_dup 2) (match_dup 4)))
2826
   (set (match_dup 6) (minus:DF (match_dup 3) (match_dup 5)))
2827
   (set (match_dup 4) (mult:DF (match_dup 4) (match_dup 6)))
2828
   (set (match_dup 5) (mult:DF (match_dup 2) (match_dup 4)))
2829
   (set (match_dup 6) (minus:DF (match_dup 3) (match_dup 5)))
2830
   (set (match_dup 4) (mult:DF (match_dup 4) (match_dup 6)))
2831
   (set (match_dup 5) (mult:DF (match_dup 2) (match_dup 4)))
2832
   (set (match_dup 6) (minus:DF (match_dup 3) (match_dup 5)))
2833
   (set (match_dup 4) (mult:DF (match_dup 4) (match_dup 6)))
2834
   (set (match_operand:DF 0 "register_operand" "")
2835
        (mult:DF (match_operand:DF 1 "register_operand")
2836
                 (match_dup 4)))]
2837
  "TARGET_FP && flag_reciprocal_math"
2838
{
2839
  operands[3] = force_reg (DFmode,
2840
                           CONST_DOUBLE_FROM_REAL_VALUE (dconst2, DFmode));
2841
  operands[4] = gen_reg_rtx (DFmode);
2842
  operands[5] = gen_reg_rtx (DFmode);
2843
  operands[6] = gen_reg_rtx (DFmode);
2844
})
2845
 
2846
;; -------------------------------------------------------------------------
2847
;; Block moves
2848
;; -------------------------------------------------------------------------
2849
 
2850
(define_expand "movmemsi"
2851
  [(use (match_operand:BLK 0 "memory_operand" ""))
2852
   (use (match_operand:BLK 1 "memory_operand" ""))
2853
   (use (match_operand:SI 2 "nonmemory_operand" ""))
2854
   (use (match_operand:SI 3 "const_int_operand" ""))
2855
   (use (match_operand:SI 4 "const_int_operand" ""))
2856
   (use (match_operand:SI 5 "const_int_operand" ""))]
2857
  ""
2858
{
2859
 if (c6x_expand_movmem (operands[0], operands[1], operands[2], operands[3],
2860
                        operands[4], operands[5]))
2861
   DONE;
2862
 else
2863
   FAIL;
2864
})
2865
 
2866
;; -------------------------------------------------------------------------
2867
;; Prologue and epilogue.
2868
;; -------------------------------------------------------------------------
2869
 
2870
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
2871
;; all of memory.  This blocks insns from being moved across this point.
2872
 
2873
(define_insn "blockage"
2874
  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
2875
  ""
2876
  ""
2877
  [(set_attr "type" "blockage")])
2878
 
2879
(define_insn "push_rts"
2880
  [(set (mem:SI (reg:SI REG_SP)) (reg:SI REG_B14))
2881
   (set (mem:DI (plus:SI (reg:SI REG_SP) (const_int -8))) (reg:DI REG_A14))
2882
   (set (mem:DI (plus:SI (reg:SI REG_SP) (const_int -16))) (reg:DI REG_B12))
2883
   (set (mem:DI (plus:SI (reg:SI REG_SP) (const_int -24))) (reg:DI REG_A12))
2884
   (set (mem:DI (plus:SI (reg:SI REG_SP) (const_int -32))) (reg:DI REG_B10))
2885
   (set (mem:DI (plus:SI (reg:SI REG_SP) (const_int -40))) (reg:DI REG_A10))
2886
   (set (mem:DI (plus:SI (reg:SI REG_SP) (const_int -48))) (reg:DI REG_B2))
2887
   (set (reg:SI REG_SP) (plus:SI (reg:SI REG_SP) (const_int -56)))
2888
   (unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
2889
   (clobber (reg:SI REG_A3))]
2890
  "TARGET_INSNS_64PLUS"
2891
  "%|%.\\tcallp\\t%$\\t__c6xabi_push_rts, a3"
2892
  [(set_attr "type" "callp")
2893
   (set_attr "dest_regfile" "a")
2894
   (set_attr "units" "s")
2895
   (set_attr "cross" "n")])
2896
 
2897
(define_insn "pop_rts"
2898
  [(set (reg:SI REG_B14) (mem:SI (plus:SI (reg:SI REG_SP) (const_int 56))))
2899
   (set (reg:DI REG_A14) (mem:DI (plus:SI (reg:SI REG_SP) (const_int 48))))
2900
   (set (reg:DI REG_B12) (mem:DI (plus:SI (reg:SI REG_SP) (const_int 40))))
2901
   (set (reg:DI REG_A12) (mem:DI (plus:SI (reg:SI REG_SP) (const_int 32))))
2902
   (set (reg:DI REG_B10) (mem:DI (plus:SI (reg:SI REG_SP) (const_int 24))))
2903
   (set (reg:DI REG_A10) (mem:DI (plus:SI (reg:SI REG_SP) (const_int 16))))
2904
   (set (reg:DI REG_B2) (mem:DI (plus:SI (reg:SI REG_SP) (const_int 8))))
2905
   (set (reg:SI REG_SP) (plus:SI (reg:SI REG_SP) (const_int 56)))
2906
   (clobber (reg:SI REG_A3))
2907
   (return)]
2908
  "TARGET_INSNS_64PLUS"
2909
  "%|%.\\tretp\\t%$\\t__c6xabi_pop_rts, a3"
2910
  [(set_attr "type" "callp")
2911
   (set_attr "dest_regfile" "a")
2912
   (set_attr "units" "s")
2913
   (set_attr "cross" "n")])
2914
 
2915
(define_expand "prologue"
2916
  [(const_int 1)]
2917
  ""
2918
  "c6x_expand_prologue (); DONE;")
2919
 
2920
(define_expand "epilogue"
2921
  [(const_int 1)]
2922
  ""
2923
  "c6x_expand_epilogue (false); DONE;")
2924
 
2925
(define_expand "sibcall_epilogue"
2926
  [(return)]
2927
  ""
2928
{
2929
  c6x_expand_epilogue (true);
2930
  DONE;
2931
})
2932
 
2933
(define_insn "setup_dsbt"
2934
  [(set (match_operand:SI 0 "pic_register_operand" "+Z")
2935
        (unspec:SI [(match_dup 0)
2936
                    (match_operand:SI 1 "symbolic_operand" "")]
2937
                   UNSPEC_SETUP_DSBT))]
2938
  "TARGET_DSBT"
2939
  "%|%.\\tldw\\t%$\\t*+%0($DSBT_index%1), %0"
2940
  [(set_attr "type" "load")
2941
   (set_attr "units" "d_addr")
2942
   (set_attr "dest_regfile" "b")
2943
   (set_attr "addr_regfile" "b")])
2944
 
2945
 
2946
;; A dummy use/set to prevent prologue and epiloge overlapping.
2947
;; This can be caused by sched-ebb in the presence of multiple
2948
;; exit sequences, and causes the unwinding table generation to explode.
2949
(define_insn "epilogue_barrier"
2950
 [(set (match_operand:SI 0 "register_operand" "")
2951
       (unspec:SI [(match_operand:SI 1 "register_operand" "")]
2952
                  UNSPEC_EPILOGUE_BARRIER))]
2953
 ""
2954
 ""
2955
 [(set_attr "type" "blockage")])
2956
 
2957
;; -------------------------------------------------------------------------
2958
;; Vector insns
2959
;; -------------------------------------------------------------------------
2960
 
2961
(define_code_iterator logical [and ior xor])
2962
(define_code_attr logical_insn [(and "and") (ior "ior") (xor "xor")])
2963
(define_code_attr logical_opcode [(and "and") (ior "or") (xor "xor")])
2964
(define_code_iterator plusminus [plus minus])
2965
(define_code_attr plusminus_insn [(plus "add") (minus "sub")])
2966
(define_code_iterator ss_plusminus [ss_plus ss_minus])
2967
(define_code_attr ss_plusminus_insn [(ss_plus "add") (ss_minus "sub")])
2968
 
2969
;; Vector logical insns
2970
 
2971
(define_insn "3"
2972
  [(set (match_operand:VEC4M 0 "register_operand" "=a,b,a,b")
2973
        (logical:VEC4M (match_operand:VEC4M 1 "register_operand" "a,b,a,b")
2974
                      (match_operand:VEC4M 2 "register_operand" "a,b,?b,?a")))]
2975
  ""
2976
  "%|%.\\t\\t%$\\t%1, %2, %0"
2977
  [(set_attr "units62" "ls")
2978
   (set_attr "units64" "dls")
2979
   (set_attr "cross" "n,n,y,y")])
2980
 
2981
;; Vector add/subtract
2982
 
2983
(define_insn "v2hi3"
2984
  [(set (match_operand:V2HI 0 "register_operand" "=a,b,a,b")
2985
        (plusminus:V2HI (match_operand:V2HI 1 "register_operand" "a,b,a,b")
2986
                        (match_operand:V2HI 2 "register_operand" "a,b,?b,?a")))]
2987
  ""
2988
  "%|%.\\t2\\t%$\\t%1, %2, %0"
2989
 [(set_attr "units62" "l")
2990
  (set_attr "units64" "dls")
2991
  (set_attr "cross" "n,n,y,y")])
2992
 
2993
(define_insn "v4qi3"
2994
  [(set (match_operand:V4QI 0 "register_operand" "=a,b,a,b")
2995
        (plusminus:V4QI (match_operand:V4QI 1 "register_operand" "a,b,a,b")
2996
                        (match_operand:V4QI 2 "register_operand" "a,b,?b,?a")))]
2997
  "TARGET_INSNS_64"
2998
  "%|%.\\t4\\t%$\\t%1, %2, %0"
2999
 [(set_attr "units" "l")
3000
  (set_attr "cross" "n,n,y,y")])
3001
 
3002
(define_insn "ss_addv2hi3"
3003
  [(set (match_operand:V2HI 0 "register_operand" "=a,b,a,b")
3004
        (ss_plus:V2HI (match_operand:V2HI 1 "register_operand" "a,b,a,b")
3005
                      (match_operand:V2HI 2 "register_operand" "a,b,?b,?a")))]
3006
  "TARGET_INSNS_64"
3007
  "%|%.\\tsadd2\\t%$\\t%1, %2, %0"
3008
 [(set_attr "units" "s")
3009
  (set_attr "cross" "n,n,y,y")])
3010
 
3011
(define_insn "ss_subv2hi3"
3012
  [(set (match_operand:V2HI 0 "register_operand" "=a,b,a,b")
3013
        (ss_minus:V2HI (match_operand:V2HI 1 "register_operand" "a,b,a,b")
3014
                       (match_operand:V2HI 2 "register_operand" "a,b,?b,?a")))]
3015
  "TARGET_INSNS_64"
3016
  "%|%.\\tssub2\\t%$\\t%1, %2, %0"
3017
 [(set_attr "units" "l")
3018
  (set_attr "cross" "n,n,y,y")])
3019
 
3020
(define_insn "us_addv4qi3"
3021
  [(set (match_operand:V4QI 0 "register_operand" "=a,b,a,b")
3022
        (ss_plus:V4QI (match_operand:V4QI 1 "register_operand" "a,b,a,b")
3023
                      (match_operand:V4QI 2 "register_operand" "a,b,?b,?a")))]
3024
  "TARGET_INSNS_64"
3025
  "%|%.\\tsaddu4\\t%$\\t%1, %2, %0"
3026
 [(set_attr "units" "s")
3027
  (set_attr "cross" "n,n,y,y")])
3028
 
3029
;; Vector/scalar min/max
3030
 
3031
(define_mode_iterator SMINMAX [HI V2HI])
3032
(define_mode_iterator UMINMAX [QI V4QI])
3033
 
3034
(define_insn "smax3"
3035
  [(set (match_operand:SMINMAX 0 "register_operand" "=a,b,a,b")
3036
        (smax:SMINMAX (match_operand:SMINMAX 1 "register_operand" "a,b,a,b")
3037
                      (match_operand:SMINMAX 2 "register_operand" "a,b,?b,?a")))]
3038
  "TARGET_INSNS_64"
3039
  "%|%.\\tmax2\\t%$\\t%1, %2, %0"
3040
  [(set_attr "units64" "l")
3041
   (set_attr "units64p" "ls")
3042
   (set_attr "cross" "n,n,y,y")])
3043
 
3044
(define_insn "smin3"
3045
  [(set (match_operand:SMINMAX 0 "register_operand" "=a,b,a,b")
3046
        (smin:SMINMAX (match_operand:SMINMAX 1 "register_operand" "a,b,a,b")
3047
                      (match_operand:SMINMAX 2 "register_operand" "a,b,?b,?a")))]
3048
  "TARGET_INSNS_64"
3049
  "%|%.\\tmin2\\t%$\\t%1, %2, %0"
3050
  [(set_attr "units64" "l")
3051
   (set_attr "units64p" "ls")
3052
   (set_attr "cross" "n,n,y,y")])
3053
 
3054
(define_insn "umax3"
3055
  [(set (match_operand:UMINMAX 0 "register_operand" "=a,b,a,b")
3056
        (umax:UMINMAX (match_operand:UMINMAX 1 "register_operand" "a,b,a,b")
3057
                      (match_operand:UMINMAX 2 "register_operand" "a,b,?b,?a")))]
3058
  "TARGET_INSNS_64"
3059
  "%|%.\\tmaxu4\\t%$\\t%1, %2, %0"
3060
  [(set_attr "units" "l")
3061
   (set_attr "cross" "n,n,y,y")])
3062
 
3063
(define_insn "umin3"
3064
  [(set (match_operand:UMINMAX 0 "register_operand" "=a,b,a,b")
3065
        (umin:UMINMAX (match_operand:UMINMAX 1 "register_operand" "a,b,a,b")
3066
                      (match_operand:UMINMAX 2 "register_operand" "a,b,?b,?a")))]
3067
  "TARGET_INSNS_64"
3068
  "%|%.\\tminu4\\t%$\\t%1, %2, %0"
3069
  [(set_attr "units" "l")
3070
   (set_attr "cross" "n,n,y,y")])
3071
 
3072
;; Vector shifts
3073
 
3074
(define_insn "v2hi3"
3075
  [(set (match_operand:V2HI 0 "register_operand" "=a,b,a,b")
3076
        (any_rshift:V2HI (match_operand:V2HI 1 "register_operand" "a,b,?b,?a")
3077
                         (match_operand:SI 2 "reg_or_ucst5_operand" "aIu5,bIu5,aIu5,bIu5")))]
3078
  "TARGET_INSNS_64"
3079
  "%|%.\\t2\\t%$\\t%1, %2, %0"
3080
  [(set_attr "units" "s")
3081
   (set_attr "cross" "n,n,y,y")])
3082
 
3083
;; See c6x-mult.md.in for avg2/avgu4
3084
 
3085
;; Widening vector multiply and dot product.
3086
;; See c6x-mult.md.in for the define_insn patterns
3087
 
3088
(define_expand "sdot_prodv2hi"
3089
  [(match_operand:SI 0 "register_operand" "")
3090
   (match_operand:V2HI 1 "register_operand" "")
3091
   (match_operand:V2HI 2 "register_operand" "")
3092
   (match_operand:SI 3 "register_operand" "")]
3093
  "TARGET_INSNS_64"
3094
{
3095
  rtx t = gen_reg_rtx (SImode);
3096
  emit_insn (gen_dotv2hi (t, operands[1], operands[2]));
3097
  emit_insn (gen_addsi3 (operands[0], operands[3], t));
3098
  DONE;
3099
})
3100
 
3101
;; Unary vector operations
3102
 
3103
(define_insn "ssabsv2hi2"
3104
  [(set (match_operand:V2HI 0 "register_operand" "=a, a, b, b")
3105
        (ss_abs:V2HI (match_operand:V2HI 1 "register_operand" "a,?b, b,?a")))]
3106
  "TARGET_INSNS_64"
3107
  "%|%.\\tabs2\\t%$\\t%1, %0"
3108
  [(set_attr "units" "l")
3109
   (set_attr "cross" "n,y,n,y")])
3110
 
3111
;; Pack insns
3112
 
3113
(define_insn "*packv2hi_insv"
3114
  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+a,b,a,b,ab")
3115
                         (const_int 16)
3116
                         (const_int 16))
3117
        (match_operand:SI 1 "nonmemory_operand" "a,b,?b,?a,n"))]
3118
  "TARGET_INSNS_64"
3119
  "@
3120
   %|%.\\tpack2\\t%$\\t%1, %0, %0
3121
   %|%.\\tpack2\\t%$\\t%1, %0, %0
3122
   %|%.\\tpack2\\t%$\\t%1, %0, %0
3123
   %|%.\\tpack2\\t%$\\t%1, %0, %0
3124
   %|%.\\tmvklh\\t%$\\t%1, %0"
3125
  [(set_attr "units" "ls")
3126
   (set_attr "cross" "n,n,y,y,n")])
3127
 
3128
(define_insn "movstricthi"
3129
  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+a,b,a,b"))
3130
        (match_operand:HI 1 "register_operand" "a,b,?b,?a"))]
3131
  "TARGET_INSNS_64"
3132
  "%|%.\\tpackhl2\\t%$\\t%0, %1, %0"
3133
  [(set_attr "units" "ls")
3134
   (set_attr "cross" "n,n,y,y")])
3135
 
3136
(include "c6x-mult.md")
3137
(include "sync.md")

powered by: WebSVN 2.1.0

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