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