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