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