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