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