OSDN Git Service

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