]>
Commit | Line | Data |
---|---|---|
36a05131 | 1 | ;; Frv Machine Description |
a5544970 | 2 | ;; Copyright (C) 1999-2019 Free Software Foundation, Inc. |
36a05131 BS |
3 | ;; Contributed by Red Hat, Inc. |
4 | ||
7ec022b2 | 5 | ;; This file is part of GCC. |
36a05131 | 6 | |
7ec022b2 | 7 | ;; GCC is free software; you can redistribute it and/or modify |
36a05131 | 8 | ;; it under the terms of the GNU General Public License as published by |
2f83c7d6 | 9 | ;; the Free Software Foundation; either version 3, or (at your option) |
36a05131 BS |
10 | ;; any later version. |
11 | ||
7ec022b2 | 12 | ;; GCC is distributed in the hope that it will be useful, |
36a05131 BS |
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | ;; GNU General Public License for more details. | |
16 | ||
17 | ;; You should have received a copy of the GNU General Public License | |
2f83c7d6 NC |
18 | ;; along with GCC; see the file COPYING3. If not see |
19 | ;; <http://www.gnu.org/licenses/>. | |
36a05131 BS |
20 | |
21 | ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. | |
22 | ||
23 | \f | |
24 | ;; :::::::::::::::::::: | |
25 | ;; :: | |
26 | ;; :: Unspec's used | |
27 | ;; :: | |
28 | ;; :::::::::::::::::::: | |
29 | ||
34208acf AO |
30 | ;; GOT constants must go 12/HI/LO for the splitter to work |
31 | ||
36a05131 BS |
32 | (define_constants |
33 | [(UNSPEC_BLOCKAGE 0) | |
34 | (UNSPEC_CC_TO_GPR 1) | |
35 | (UNSPEC_GPR_TO_CC 2) | |
36 | (UNSPEC_PIC_PROLOGUE 3) | |
37 | (UNSPEC_CR_LOGIC 4) | |
38 | (UNSPEC_STACK_ADJUST 5) | |
34208acf AO |
39 | (UNSPEC_EH_RETURN_EPILOGUE 6) |
40 | (UNSPEC_GOT 7) | |
41 | (UNSPEC_LDD 8) | |
38c28a25 | 42 | (UNSPEC_OPTIONAL_MEMBAR 9) |
34208acf | 43 | |
bef8809e AH |
44 | (UNSPEC_GETTLSOFF 200) |
45 | (UNSPEC_TLS_LOAD_GOTTLSOFF12 201) | |
46 | (UNSPEC_TLS_INDIRECT_CALL 202) | |
47 | (UNSPEC_TLS_TLSDESC_LDD 203) | |
48 | (UNSPEC_TLS_TLSDESC_LDD_AUX 204) | |
49 | (UNSPEC_TLS_TLSOFF_LD 205) | |
50 | (UNSPEC_TLS_LDDI 206) | |
51 | (UNSPEC_TLSOFF_HILO 207) | |
52 | ||
34208acf AO |
53 | (R_FRV_GOT12 11) |
54 | (R_FRV_GOTHI 12) | |
55 | (R_FRV_GOTLO 13) | |
56 | (R_FRV_FUNCDESC 14) | |
57 | (R_FRV_FUNCDESC_GOT12 15) | |
58 | (R_FRV_FUNCDESC_GOTHI 16) | |
59 | (R_FRV_FUNCDESC_GOTLO 17) | |
60 | (R_FRV_FUNCDESC_VALUE 18) | |
61 | (R_FRV_FUNCDESC_GOTOFF12 19) | |
62 | (R_FRV_FUNCDESC_GOTOFFHI 20) | |
63 | (R_FRV_FUNCDESC_GOTOFFLO 21) | |
64 | (R_FRV_GOTOFF12 22) | |
65 | (R_FRV_GOTOFFHI 23) | |
66 | (R_FRV_GOTOFFLO 24) | |
67 | (R_FRV_GPREL12 25) | |
68 | (R_FRV_GPRELHI 26) | |
69 | (R_FRV_GPRELLO 27) | |
bef8809e AH |
70 | (R_FRV_GOTTLSOFF_HI 28) |
71 | (R_FRV_GOTTLSOFF_LO 29) | |
72 | (R_FRV_TLSMOFFHI 30) | |
73 | (R_FRV_TLSMOFFLO 31) | |
74 | (R_FRV_TLSMOFF12 32) | |
75 | (R_FRV_TLSDESCHI 33) | |
76 | (R_FRV_TLSDESCLO 34) | |
77 | (R_FRV_GOTTLSDESCHI 35) | |
78 | (R_FRV_GOTTLSDESCLO 36) | |
79 | ||
80 | (GR8_REG 8) | |
81 | (GR9_REG 9) | |
82 | (GR14_REG 14) | |
83 | ;; LR_REG conflicts with definition in frv.h | |
84 | (LRREG 169) | |
34208acf AO |
85 | (FDPIC_REG 15) |
86 | ]) | |
36a05131 | 87 | |
3abcb3a7 | 88 | (define_mode_iterator IMODE [QI HI SI DI]) |
c14ff86e AH |
89 | (define_mode_attr IMODEsuffix [(QI "b") (HI "h") (SI "") (DI "d")]) |
90 | (define_mode_attr BREADsuffix [(QI "ub") (HI "uh") (SI "") (DI "d")]) | |
36a05131 | 91 | \f |
36a05131 BS |
92 | (define_attr "length" "" (const_int 4)) |
93 | ||
94 | ;; Processor type -- this attribute must exactly match the processor_type | |
95 | ;; enumeration in frv-protos.h. | |
96 | ||
c557edf4 | 97 | (define_attr "cpu" "generic,fr550,fr500,fr450,fr405,fr400,fr300,simple,tomcat" |
5c5e8419 | 98 | (const (symbol_ref "(enum attr_cpu) frv_cpu_type"))) |
36a05131 BS |
99 | |
100 | ;; Attribute is "yes" for branches and jumps that span too great a distance | |
101 | ;; to be implemented in the most natural way. Such instructions will use | |
102 | ;; a call instruction in some way. | |
103 | ||
104 | (define_attr "far_jump" "yes,no" (const_string "no")) | |
105 | ||
106 | ;; Instruction type | |
c557edf4 | 107 | ;; "unknown" must come last. |
36a05131 | 108 | (define_attr "type" |
bef8809e | 109 | "int,sethi,setlo,mul,div,gload,gstore,fload,fstore,movfg,movgf,macc,scan,cut,branch,jump,jumpl,call,spr,trap,fnop,fsconv,fsadd,fscmp,fsmul,fsmadd,fsdiv,sqrt_single,fdconv,fdadd,fdcmp,fdmul,fdmadd,fddiv,sqrt_double,mnop,mlogic,maveh,msath,maddh,mqaddh,mpackh,munpackh,mdpackh,mbhconv,mrot,mshift,mexpdhw,mexpdhd,mwcut,mmulh,mmulxh,mmach,mmrdh,mqmulh,mqmulxh,mqmach,mcpx,mqcpx,mcut,mclracc,mclracca,mdunpackh,mbhconve,mrdacc,mwtacc,maddacc,mdaddacc,mabsh,mdrot,mcpl,mdcut,mqsath,mqlimh,mqshift,mset,ccr,multi,load_or_call,unknown" |
36a05131 BS |
110 | (const_string "unknown")) |
111 | ||
c557edf4 | 112 | (define_attr "acc_group" "none,even,odd" |
5c5e8419 | 113 | (symbol_ref "(enum attr_acc_group) frv_acc_group (insn)")) |
36a05131 | 114 | \f |
c557edf4 RS |
115 | ;; Scheduling and Packing Overview |
116 | ;; ------------------------------- | |
117 | ;; | |
118 | ;; FR-V instructions are divided into five groups: integer, floating-point, | |
119 | ;; media, branch and control. Each group is associated with a separate set | |
120 | ;; of processing units, the number and behavior of which depend on the target | |
121 | ;; target processor. Integer units have names like I0 and I1, floating-point | |
122 | ;; units have names like F0 and F1, and so on. | |
123 | ;; | |
124 | ;; Each member of the FR-V family has its own restrictions on which | |
125 | ;; instructions can issue to which units. For example, some processors | |
126 | ;; allow loads to issue to I0 or I1 while others only allow them to issue | |
127 | ;; to I0. As well as these processor-specific restrictions, there is a | |
128 | ;; general rule that an instruction can only issue to unit X + 1 if an | |
129 | ;; instruction in the same packet issued to unit X. | |
130 | ;; | |
131 | ;; Sometimes the only way to honor these restrictions is by adding nops | |
132 | ;; to a packet. For example, on the fr550, media instructions that access | |
133 | ;; ACC4-7 can only issue to M1 or M3. It is therefore only possible to | |
134 | ;; execute these instructions by packing them with something that issues | |
135 | ;; to M0. When no useful M0 instruction exists, an "mnop" can be used | |
136 | ;; instead. | |
137 | ;; | |
138 | ;; Having decided which instructions should issue to which units, the packet | |
139 | ;; should be ordered according to the following template: | |
140 | ;; | |
141 | ;; I0 F0/M0 I1 F1/M1 .... B0 B1 ... | |
142 | ;; | |
143 | ;; Note that VLIW packets execute strictly in parallel. Every instruction | |
144 | ;; in the packet will stall until all input operands are ready. These | |
145 | ;; operands are then read simultaneously before any registers are modified. | |
146 | ;; This means that it's OK to have write-after-read hazards between | |
147 | ;; instructions in the same packet, even if the write is listed earlier | |
148 | ;; than the read. | |
149 | ;; | |
150 | ;; Three gcc passes are involved in generating VLIW packets: | |
151 | ;; | |
152 | ;; (1) The scheduler. This pass uses the standard scheduling code and | |
153 | ;; behaves in much the same way as it would for a superscalar RISC | |
154 | ;; architecture. | |
155 | ;; | |
156 | ;; (2) frv_reorg. This pass inserts nops into packets in order to meet | |
157 | ;; the processor's issue requirements. It also has code to optimize | |
158 | ;; the type of padding used to align labels. | |
159 | ;; | |
160 | ;; (3) frv_pack_insns. The final packing phase, which puts the | |
161 | ;; instructions into assembly language order according to the | |
162 | ;; "I0 F0/M0 ..." template above. | |
163 | ;; | |
164 | ;; In the ideal case, these three passes will agree on which instructions | |
165 | ;; should be packed together, but this won't always happen. In particular: | |
166 | ;; | |
167 | ;; (a) (2) might not pack predicated instructions in the same way as (1). | |
168 | ;; The scheduler tries to schedule predicated instructions for the | |
169 | ;; worst case, assuming the predicate is true. However, if we have | |
170 | ;; something like a predicated load, it isn't always possible to | |
171 | ;; fill the load delay with useful instructions. (2) should then | |
172 | ;; pack the user of the loaded value as aggressively as possible, | |
173 | ;; in order to optimize the case when the predicate is false. | |
174 | ;; See frv_pack_insn_p for more details. | |
175 | ;; | |
176 | ;; (b) The final shorten_branches pass runs between (2) and (3). | |
177 | ;; Since (2) inserts nops, it is possible that some branches | |
178 | ;; that were thought to be in range during (2) turned out to | |
179 | ;; out-of-range in (3). | |
180 | ;; | |
181 | ;; All three passes use DFAs to model issue restrictions. The main | |
182 | ;; question that the DFAs are supposed to answer is simply: can these | |
183 | ;; instructions be packed together? The DFAs are not responsible for | |
184 | ;; assigning instructions to execution units; that's the job of | |
185 | ;; frv_sort_insn_group, see below for details. | |
186 | ;; | |
187 | ;; To get the best results, the DFAs should try to allow packets to | |
188 | ;; be built in every possible order. This gives the scheduler more | |
189 | ;; flexibility, removing the need for things like multipass lookahead. | |
190 | ;; It also means we can take more advantage of inter-packet dependencies. | |
191 | ;; | |
192 | ;; For example, suppose we're compiling for the fr400 and we have: | |
193 | ;; | |
194 | ;; addi gr4,#1,gr5 | |
195 | ;; ldi @(gr6,gr0),gr4 | |
196 | ;; | |
197 | ;; We can pack these instructions together by assigning the load to I0 and | |
198 | ;; the addition to I1. However, because of the anti dependence between the | |
199 | ;; two instructions, the scheduler must schedule the addition first. | |
200 | ;; We should generally get better schedules if the DFA allows both | |
201 | ;; (ldi, addi) and (addi, ldi), leaving the final packing pass to | |
202 | ;; reorder the packet where appropriate. | |
203 | ;; | |
204 | ;; Almost all integer instructions can issue to any unit in the range I0 | |
205 | ;; to Ix, where the value of "x" depends on the type of instruction and | |
206 | ;; on the target processor. The rules for other instruction groups are | |
207 | ;; usually similar. | |
208 | ;; | |
209 | ;; When the restrictions are as regular as this, we can get the desired | |
210 | ;; behavior by claiming the DFA unit associated with the highest unused | |
211 | ;; execution unit. For example, if an instruction can issue to I0 or I1, | |
212 | ;; the DFA first tries to take the DFA unit associated with I1, and will | |
213 | ;; only take I0's unit if I1 isn't free. (Note that, as mentioned above, | |
214 | ;; the DFA does not assign instructions to units. An instruction that | |
215 | ;; claims DFA unit I1 will not necessarily issue to I1 in the final packet.) | |
216 | ;; | |
217 | ;; There are some cases, such as the fr550 media restriction mentioned | |
218 | ;; above, where the rule is not as simple as "any unit between 0 and X". | |
219 | ;; Even so, allocating higher units first brings us close to the ideal. | |
220 | ;; | |
221 | ;; Having divided instructions into packets, passes (2) and (3) must | |
222 | ;; assign instructions to specific execution units. They do this using | |
223 | ;; the following algorithm: | |
224 | ;; | |
225 | ;; 1. Partition the instructions into groups (integer, float/media, etc.) | |
226 | ;; | |
227 | ;; 2. For each group of instructions: | |
228 | ;; | |
229 | ;; (a) Issue each instruction in the reset DFA state and use the | |
230 | ;; DFA cpu_unit_query interface to find out which unit it picks | |
231 | ;; first. | |
232 | ;; | |
233 | ;; (b) Sort the instructions into ascending order of picked units. | |
234 | ;; Instructions that pick I1 first come after those that pick | |
235 | ;; I0 first, and so on. Let S be the sorted sequence and S[i] | |
236 | ;; be the ith element of it (counting from zero). | |
237 | ;; | |
238 | ;; (c) If this is the control or branch group, goto (i) | |
239 | ;; | |
240 | ;; (d) Find the largest L such that S[0]...S[L-1] can be issued | |
241 | ;; consecutively from the reset state and such that the DFA | |
242 | ;; claims unit X when S[X] is added. Let D be the DFA state | |
243 | ;; after instructions S[0]...S[L-1] have been issued. | |
244 | ;; | |
245 | ;; (e) If L is the length of S, goto (i) | |
246 | ;; | |
247 | ;; (f) Let U be the number of units belonging to this group and #S be | |
248 | ;; the length of S. Create a new sequence S' by concatenating | |
249 | ;; S[L]...S[#S-1] and (U - #S) nops. | |
250 | ;; | |
251 | ;; (g) For each permutation S'' of S', try issuing S'' from last to | |
252 | ;; first, starting with state D. See if the DFA claims unit | |
253 | ;; X + L when each S''[X] is added. If so, set S to the | |
254 | ;; concatenation of S[0]...S[L-1] and S'', then goto (i). | |
255 | ;; | |
c112cf2b | 256 | ;; (h) If (g) found no permutation, abort. |
c557edf4 RS |
257 | ;; |
258 | ;; (i) S is now the sorted sequence for this group, meaning that S[X] | |
259 | ;; issues to unit X. Trim any unwanted nops from the end of S. | |
260 | ;; | |
261 | ;; The sequence calculated by (b) is trivially correct for control | |
262 | ;; instructions since they can't be packed. It is also correct for branch | |
263 | ;; instructions due to their simple issue requirements. For integer and | |
264 | ;; floating-point/media instructions, the sequence calculated by (b) is | |
265 | ;; often the correct answer; the rest of the algorithm is optimized for | |
266 | ;; the case in which it is correct. | |
267 | ;; | |
268 | ;; If there were no irregularities in the issue restrictions then step | |
269 | ;; (d) would not be needed. It is mainly there to cope with the fr550 | |
270 | ;; integer restrictions, where a store can issue to I1, but only if a store | |
271 | ;; also issues to I0. (Note that if a packet has two stores, they will be | |
272 | ;; at the beginning of the sequence calculated by (b).) It also copes | |
273 | ;; with fr400 M-2 instructions, which must issue to M0, and which cannot | |
274 | ;; be issued together with an mnop in M1. | |
275 | ;; | |
276 | ;; Step (g) is the main one for integer and float/media instructions. | |
277 | ;; The first permutation it tries is S' itself (because, as noted above, | |
278 | ;; the sequence calculated by (b) is often correct). If S' doesn't work, | |
279 | ;; the implementation tries varying the beginning of the sequence first. | |
280 | ;; Thus the nops towards the end of the sequence will only move to lower | |
281 | ;; positions if absolutely necessary. | |
282 | ;; | |
283 | ;; The algorithm is theoretically exponential in the number of instructions | |
284 | ;; in a group, although it's only O(n log(n)) if the sequence calculated by | |
285 | ;; (b) is acceptable. In practice, the algorithm completes quickly even | |
286 | ;; in the rare cases where (g) needs to try other permutations. | |
287 | (define_automaton "integer, float_media, branch, control, idiv, div") | |
288 | ||
289 | ;; The main issue units. Note that not all units are available on | |
290 | ;; all processors. | |
291 | (define_query_cpu_unit "i0,i1,i2,i3" "integer") | |
292 | (define_query_cpu_unit "f0,f1,f2,f3" "float_media") | |
293 | (define_query_cpu_unit "b0,b1" "branch") | |
294 | (define_query_cpu_unit "c" "control") | |
295 | ||
296 | ;; Division units. | |
297 | (define_cpu_unit "idiv1,idiv2" "idiv") | |
298 | (define_cpu_unit "div1,div2,root" "div") | |
299 | ||
300 | ;; Control instructions cannot be packed with others. | |
301 | (define_reservation "control" "i0+i1+i2+i3+f0+f1+f2+f3+b0+b1") | |
302 | ||
303 | ;; Generic reservation for control insns | |
304 | (define_insn_reservation "control" 1 | |
305 | (eq_attr "type" "trap,spr,unknown,multi") | |
306 | "c + control") | |
36a05131 | 307 | |
bef8809e AH |
308 | ;; Reservation for relaxable calls to gettlsoff. |
309 | (define_insn_reservation "load_or_call" 3 | |
310 | (eq_attr "type" "load_or_call") | |
311 | "c + control") | |
312 | ||
36a05131 BS |
313 | ;; :::::::::::::::::::: |
314 | ;; :: | |
315 | ;; :: Generic/FR500 scheduler description | |
316 | ;; :: | |
317 | ;; :::::::::::::::::::: | |
318 | ||
36a05131 | 319 | ;; Integer insns |
c557edf4 RS |
320 | ;; Synthetic units used to describe issue restrictions. |
321 | (define_automaton "fr500_integer") | |
322 | (define_cpu_unit "fr500_load0,fr500_load1,fr500_store0" "fr500_integer") | |
323 | (exclusion_set "fr500_load0,fr500_load1" "fr500_store0") | |
324 | ||
325 | (define_bypass 0 "fr500_i1_sethi" "fr500_i1_setlo") | |
326 | (define_insn_reservation "fr500_i1_sethi" 1 | |
36a05131 BS |
327 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
328 | (eq_attr "type" "sethi")) | |
c557edf4 | 329 | "i1|i0") |
36a05131 | 330 | |
c557edf4 | 331 | (define_insn_reservation "fr500_i1_setlo" 1 |
36a05131 BS |
332 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
333 | (eq_attr "type" "setlo")) | |
c557edf4 | 334 | "i1|i0") |
36a05131 | 335 | |
c557edf4 | 336 | (define_insn_reservation "fr500_i1_int" 1 |
36a05131 BS |
337 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
338 | (eq_attr "type" "int")) | |
c557edf4 | 339 | "i1|i0") |
36a05131 | 340 | |
c557edf4 | 341 | (define_insn_reservation "fr500_i1_mul" 3 |
36a05131 BS |
342 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
343 | (eq_attr "type" "mul")) | |
c557edf4 | 344 | "i1|i0") |
36a05131 | 345 | |
c557edf4 | 346 | (define_insn_reservation "fr500_i1_div" 19 |
36a05131 BS |
347 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
348 | (eq_attr "type" "div")) | |
c557edf4 | 349 | "(i1|i0),(idiv1*18|idiv2*18)") |
36a05131 | 350 | |
c557edf4 | 351 | (define_insn_reservation "fr500_i2" 4 |
36a05131 | 352 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
c557edf4 RS |
353 | (eq_attr "type" "gload,fload")) |
354 | "(i1|i0) + (fr500_load0|fr500_load1)") | |
36a05131 | 355 | |
c557edf4 | 356 | (define_insn_reservation "fr500_i3" 0 |
36a05131 | 357 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
c557edf4 RS |
358 | (eq_attr "type" "gstore,fstore")) |
359 | "i0 + fr500_store0") | |
36a05131 | 360 | |
c557edf4 | 361 | (define_insn_reservation "fr500_i4" 3 |
36a05131 | 362 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
c557edf4 | 363 | (eq_attr "type" "movgf,movfg")) |
36a05131 BS |
364 | "i0") |
365 | ||
c557edf4 | 366 | (define_insn_reservation "fr500_i5" 0 |
36a05131 BS |
367 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
368 | (eq_attr "type" "jumpl")) | |
369 | "i0") | |
370 | ||
36a05131 BS |
371 | ;; |
372 | ;; Branch-instructions | |
373 | ;; | |
c557edf4 | 374 | (define_insn_reservation "fr500_branch" 0 |
36a05131 BS |
375 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
376 | (eq_attr "type" "jump,branch,ccr")) | |
c557edf4 | 377 | "b1|b0") |
36a05131 | 378 | |
c557edf4 | 379 | (define_insn_reservation "fr500_call" 0 |
36a05131 BS |
380 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
381 | (eq_attr "type" "call")) | |
382 | "b0") | |
383 | ||
c557edf4 RS |
384 | ;; Floating point insns. The default latencies are for non-media |
385 | ;; instructions; media instructions incur an extra cycle. | |
36a05131 | 386 | |
c557edf4 RS |
387 | (define_bypass 4 "fr500_farith" "fr500_m1,fr500_m2,fr500_m3, |
388 | fr500_m4,fr500_m5,fr500_m6") | |
389 | (define_insn_reservation "fr500_farith" 3 | |
36a05131 | 390 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
c557edf4 RS |
391 | (eq_attr "type" "fnop,fsconv,fsadd,fsmul,fsmadd,fdconv,fdadd,fdmul,fdmadd")) |
392 | "(f1|f0)") | |
36a05131 | 393 | |
c557edf4 | 394 | (define_insn_reservation "fr500_fcmp" 4 |
36a05131 | 395 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
c557edf4 RS |
396 | (eq_attr "type" "fscmp,fdcmp")) |
397 | "(f1|f0)") | |
36a05131 | 398 | |
c557edf4 RS |
399 | (define_bypass 11 "fr500_fdiv" "fr500_m1,fr500_m2,fr500_m3, |
400 | fr500_m4,fr500_m5,fr500_m6") | |
401 | (define_insn_reservation "fr500_fdiv" 10 | |
36a05131 BS |
402 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
403 | (eq_attr "type" "fsdiv,fddiv")) | |
c557edf4 | 404 | "(f1|f0),(div1*9 | div2*9)") |
36a05131 | 405 | |
c557edf4 RS |
406 | (define_bypass 16 "fr500_froot" "fr500_m1,fr500_m2,fr500_m3, |
407 | fr500_m4,fr500_m5,fr500_m6") | |
408 | (define_insn_reservation "fr500_froot" 15 | |
36a05131 BS |
409 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
410 | (eq_attr "type" "sqrt_single,sqrt_double")) | |
c557edf4 | 411 | "(f1|f0) + root*15") |
36a05131 | 412 | |
c557edf4 RS |
413 | ;; Media insns. Conflict table is as follows: |
414 | ;; | |
415 | ;; M1 M2 M3 M4 M5 M6 | |
416 | ;; M1 - - - - - - | |
417 | ;; M2 - - - - X X | |
418 | ;; M3 - - - - X X | |
419 | ;; M4 - - - - - X | |
420 | ;; M5 - X X - X X | |
421 | ;; M6 - X X X X X | |
422 | ;; | |
423 | ;; where X indicates an invalid combination. | |
424 | ;; | |
425 | ;; Target registers are as follows: | |
426 | ;; | |
427 | ;; M1 : FPRs | |
428 | ;; M2 : FPRs | |
429 | ;; M3 : ACCs | |
430 | ;; M4 : ACCs | |
431 | ;; M5 : FPRs | |
432 | ;; M6 : ACCs | |
433 | ;; | |
434 | ;; The default FPR latencies are for integer instructions. | |
435 | ;; Floating-point instructions need one cycle more and media | |
436 | ;; instructions need one cycle less. | |
437 | (define_automaton "fr500_media") | |
438 | (define_cpu_unit "fr500_m2_0,fr500_m2_1" "fr500_media") | |
439 | (define_cpu_unit "fr500_m3_0,fr500_m3_1" "fr500_media") | |
440 | (define_cpu_unit "fr500_m4_0,fr500_m4_1" "fr500_media") | |
441 | (define_cpu_unit "fr500_m5" "fr500_media") | |
442 | (define_cpu_unit "fr500_m6" "fr500_media") | |
443 | ||
444 | (exclusion_set "fr500_m5,fr500_m6" "fr500_m2_0,fr500_m2_1, | |
445 | fr500_m3_0,fr500_m3_1") | |
446 | (exclusion_set "fr500_m6" "fr500_m4_0,fr500_m4_1,fr500_m5") | |
447 | ||
448 | (define_bypass 2 "fr500_m1" "fr500_m1,fr500_m2,fr500_m3, | |
449 | fr500_m4,fr500_m5,fr500_m6") | |
450 | (define_bypass 4 "fr500_m1" "fr500_farith,fr500_fcmp,fr500_fdiv,fr500_froot") | |
451 | (define_insn_reservation "fr500_m1" 3 | |
36a05131 | 452 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
c557edf4 RS |
453 | (eq_attr "type" "mnop,mlogic,maveh,msath,maddh,mqaddh")) |
454 | "(f1|f0)") | |
36a05131 | 455 | |
c557edf4 RS |
456 | (define_bypass 2 "fr500_m2" "fr500_m1,fr500_m2,fr500_m3, |
457 | fr500_m4,fr500_m5,fr500_m6") | |
458 | (define_bypass 4 "fr500_m2" "fr500_farith,fr500_fcmp,fr500_fdiv,fr500_froot") | |
459 | (define_insn_reservation "fr500_m2" 3 | |
36a05131 BS |
460 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
461 | (eq_attr "type" "mrdacc,mpackh,munpackh,mbhconv,mrot,mshift,mexpdhw,mexpdhd,mwcut,mcut,mdunpackh,mbhconve")) | |
c557edf4 | 462 | "(f1|f0) + (fr500_m2_0|fr500_m2_1)") |
36a05131 | 463 | |
c557edf4 RS |
464 | (define_bypass 1 "fr500_m3" "fr500_m4") |
465 | (define_insn_reservation "fr500_m3" 2 | |
36a05131 BS |
466 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
467 | (eq_attr "type" "mclracc,mwtacc")) | |
c557edf4 | 468 | "(f1|f0) + (fr500_m3_0|fr500_m3_1)") |
36a05131 | 469 | |
c557edf4 RS |
470 | (define_bypass 1 "fr500_m4" "fr500_m4") |
471 | (define_insn_reservation "fr500_m4" 2 | |
36a05131 BS |
472 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
473 | (eq_attr "type" "mmulh,mmulxh,mmach,mmrdh,mqmulh,mqmulxh,mqmach,mcpx,mqcpx")) | |
c557edf4 | 474 | "(f1|f0) + (fr500_m4_0|fr500_m4_1)") |
36a05131 | 475 | |
c557edf4 RS |
476 | (define_bypass 2 "fr500_m5" "fr500_m1,fr500_m2,fr500_m3, |
477 | fr500_m4,fr500_m5,fr500_m6") | |
478 | (define_bypass 4 "fr500_m5" "fr500_farith,fr500_fcmp,fr500_fdiv,fr500_froot") | |
479 | (define_insn_reservation "fr500_m5" 3 | |
36a05131 BS |
480 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
481 | (eq_attr "type" "mdpackh")) | |
c557edf4 | 482 | "(f1|f0) + fr500_m5") |
36a05131 | 483 | |
c557edf4 RS |
484 | (define_bypass 1 "fr500_m6" "fr500_m4") |
485 | (define_insn_reservation "fr500_m6" 2 | |
36a05131 BS |
486 | (and (eq_attr "cpu" "generic,fr500,tomcat") |
487 | (eq_attr "type" "mclracca")) | |
c557edf4 | 488 | "(f1|f0) + fr500_m6") |
36a05131 BS |
489 | |
490 | ;; :::::::::::::::::::: | |
491 | ;; :: | |
492 | ;; :: FR400 scheduler description | |
493 | ;; :: | |
494 | ;; :::::::::::::::::::: | |
495 | ||
496 | ;; Category 2 media instructions use both media units, but can be packed | |
497 | ;; with non-media instructions. Use fr400_m1unit to claim the M1 unit | |
498 | ;; without claiming a slot. | |
499 | ||
36a05131 BS |
500 | ;; Name Class Units Latency |
501 | ;; ==== ===== ===== ======= | |
502 | ;; int I1 I0/I1 1 | |
503 | ;; sethi I1 I0/I1 0 -- does not interfere with setlo | |
504 | ;; setlo I1 I0/I1 1 | |
505 | ;; mul I1 I0 3 (*) | |
506 | ;; div I1 I0 20 (*) | |
507 | ;; gload I2 I0 4 (*) | |
508 | ;; fload I2 I0 4 -- only 3 if read by a media insn | |
509 | ;; gstore I3 I0 0 -- provides no result | |
510 | ;; fstore I3 I0 0 -- provides no result | |
511 | ;; movfg I4 I0 3 (*) | |
512 | ;; movgf I4 I0 3 (*) | |
513 | ;; jumpl I5 I0 0 -- provides no result | |
514 | ;; | |
515 | ;; (*) The results of these instructions can be read one cycle earlier | |
516 | ;; than indicated. The penalty given is for instructions with write-after- | |
517 | ;; write dependencies. | |
518 | ||
519 | ;; The FR400 can only do loads and stores in I0, so we there's no danger | |
520 | ;; of memory unit collision in the same packet. There's only one divide | |
521 | ;; unit too. | |
522 | ||
af30facd AH |
523 | (define_automaton "fr400_integer") |
524 | (define_cpu_unit "fr400_mul" "fr400_integer") | |
525 | ||
36a05131 | 526 | (define_insn_reservation "fr400_i1_int" 1 |
c557edf4 | 527 | (and (eq_attr "cpu" "fr400,fr405,fr450") |
36a05131 | 528 | (eq_attr "type" "int")) |
c557edf4 | 529 | "i1|i0") |
36a05131 | 530 | |
c557edf4 RS |
531 | (define_bypass 0 "fr400_i1_sethi" "fr400_i1_setlo") |
532 | (define_insn_reservation "fr400_i1_sethi" 1 | |
533 | (and (eq_attr "cpu" "fr400,fr405,fr450") | |
36a05131 | 534 | (eq_attr "type" "sethi")) |
c557edf4 | 535 | "i1|i0") |
36a05131 BS |
536 | |
537 | (define_insn_reservation "fr400_i1_setlo" 1 | |
c557edf4 | 538 | (and (eq_attr "cpu" "fr400,fr405,fr450") |
36a05131 | 539 | (eq_attr "type" "setlo")) |
c557edf4 | 540 | "i1|i0") |
36a05131 | 541 | |
c557edf4 | 542 | ;; 3 is the worst case (write-after-write hazard). |
36a05131 | 543 | (define_insn_reservation "fr400_i1_mul" 3 |
c557edf4 RS |
544 | (and (eq_attr "cpu" "fr400,fr405") |
545 | (eq_attr "type" "mul")) | |
af30facd | 546 | "i0 + fr400_mul") |
c557edf4 RS |
547 | |
548 | (define_insn_reservation "fr450_i1_mul" 2 | |
549 | (and (eq_attr "cpu" "fr450") | |
36a05131 | 550 | (eq_attr "type" "mul")) |
af30facd | 551 | "i0 + fr400_mul") |
c557edf4 RS |
552 | |
553 | (define_bypass 1 "fr400_i1_macc" "fr400_i1_macc") | |
554 | (define_insn_reservation "fr400_i1_macc" 2 | |
555 | (and (eq_attr "cpu" "fr405,fr450") | |
556 | (eq_attr "type" "macc")) | |
af30facd | 557 | "(i0|i1) + fr400_mul") |
c557edf4 RS |
558 | |
559 | (define_insn_reservation "fr400_i1_scan" 1 | |
560 | (and (eq_attr "cpu" "fr400,fr405,fr450") | |
561 | (eq_attr "type" "scan")) | |
562 | "i0") | |
563 | ||
564 | (define_insn_reservation "fr400_i1_cut" 2 | |
565 | (and (eq_attr "cpu" "fr405,fr450") | |
566 | (eq_attr "type" "cut")) | |
af30facd | 567 | "i0 + fr400_mul") |
36a05131 | 568 | |
c557edf4 | 569 | ;; 20 is for a write-after-write hazard. |
36a05131 | 570 | (define_insn_reservation "fr400_i1_div" 20 |
c557edf4 RS |
571 | (and (eq_attr "cpu" "fr400,fr405") |
572 | (eq_attr "type" "div")) | |
573 | "i0 + idiv1*19") | |
574 | ||
575 | (define_insn_reservation "fr450_i1_div" 19 | |
576 | (and (eq_attr "cpu" "fr450") | |
36a05131 | 577 | (eq_attr "type" "div")) |
c557edf4 | 578 | "i0 + idiv1*19") |
36a05131 | 579 | |
c557edf4 RS |
580 | ;; 4 is for a write-after-write hazard. |
581 | (define_insn_reservation "fr400_i2" 4 | |
582 | (and (eq_attr "cpu" "fr400,fr405") | |
583 | (eq_attr "type" "gload,fload")) | |
584 | "i0") | |
585 | ||
586 | (define_insn_reservation "fr450_i2_gload" 3 | |
587 | (and (eq_attr "cpu" "fr450") | |
36a05131 | 588 | (eq_attr "type" "gload")) |
c557edf4 | 589 | "i0") |
36a05131 | 590 | |
c557edf4 RS |
591 | ;; 4 is for a write-after-write hazard. |
592 | (define_insn_reservation "fr450_i2_fload" 4 | |
593 | (and (eq_attr "cpu" "fr450") | |
36a05131 | 594 | (eq_attr "type" "fload")) |
c557edf4 | 595 | "i0") |
36a05131 | 596 | |
c557edf4 RS |
597 | (define_insn_reservation "fr400_i3" 0 |
598 | (and (eq_attr "cpu" "fr400,fr405,fr450") | |
599 | (eq_attr "type" "gstore,fstore")) | |
600 | "i0") | |
36a05131 | 601 | |
c557edf4 RS |
602 | ;; 3 is for a write-after-write hazard. |
603 | (define_insn_reservation "fr400_i4" 3 | |
604 | (and (eq_attr "cpu" "fr400,fr405") | |
605 | (eq_attr "type" "movfg,movgf")) | |
606 | "i0") | |
36a05131 | 607 | |
c557edf4 RS |
608 | (define_insn_reservation "fr450_i4_movfg" 2 |
609 | (and (eq_attr "cpu" "fr450") | |
36a05131 | 610 | (eq_attr "type" "movfg")) |
c557edf4 | 611 | "i0") |
36a05131 | 612 | |
c557edf4 RS |
613 | ;; 3 is for a write-after-write hazard. |
614 | (define_insn_reservation "fr450_i4_movgf" 3 | |
615 | (and (eq_attr "cpu" "fr450") | |
36a05131 | 616 | (eq_attr "type" "movgf")) |
c557edf4 | 617 | "i0") |
36a05131 | 618 | |
c557edf4 RS |
619 | (define_insn_reservation "fr400_i5" 0 |
620 | (and (eq_attr "cpu" "fr400,fr405,fr450") | |
36a05131 | 621 | (eq_attr "type" "jumpl")) |
c557edf4 | 622 | "i0") |
36a05131 BS |
623 | |
624 | ;; The bypass between FPR loads and media instructions, described above. | |
625 | ||
626 | (define_bypass 3 | |
c557edf4 | 627 | "fr400_i2" |
36a05131 BS |
628 | "fr400_m1_1,fr400_m1_2,\ |
629 | fr400_m2_1,fr400_m2_2,\ | |
630 | fr400_m3_1,fr400_m3_2,\ | |
631 | fr400_m4_1,fr400_m4_2,\ | |
632 | fr400_m5") | |
633 | ||
634 | ;; The branch instructions all use the B unit and produce no result. | |
635 | ||
636 | (define_insn_reservation "fr400_b" 0 | |
c557edf4 | 637 | (and (eq_attr "cpu" "fr400,fr405,fr450") |
36a05131 | 638 | (eq_attr "type" "jump,branch,ccr,call")) |
c557edf4 | 639 | "b0") |
36a05131 BS |
640 | |
641 | ;; FP->FP moves are marked as "fsconv" instructions in the define_insns | |
642 | ;; below, but are implemented on the FR400 using "mlogic" instructions. | |
643 | ;; It's easier to class "fsconv" as a "m1:1" instruction than provide | |
644 | ;; separate define_insns for the FR400. | |
645 | ||
646 | ;; M1 instructions store their results in FPRs. Any instruction can read | |
647 | ;; the result in the following cycle, so no penalty occurs. | |
648 | ||
c557edf4 RS |
649 | (define_automaton "fr400_media") |
650 | (define_cpu_unit "fr400_m1a,fr400_m1b,fr400_m2a" "fr400_media") | |
651 | (exclusion_set "fr400_m1a,fr400_m1b" "fr400_m2a") | |
652 | ||
653 | (define_reservation "fr400_m1" "(f1|f0) + (fr400_m1a|fr400_m1b)") | |
654 | (define_reservation "fr400_m2" "f0 + fr400_m2a") | |
655 | ||
36a05131 | 656 | (define_insn_reservation "fr400_m1_1" 1 |
c557edf4 RS |
657 | (and (eq_attr "cpu" "fr400,fr405") |
658 | (eq_attr "type" "fsconv,mnop,mlogic,maveh,msath,maddh,mabsh,mset")) | |
659 | "fr400_m1") | |
36a05131 BS |
660 | |
661 | (define_insn_reservation "fr400_m1_2" 1 | |
c557edf4 RS |
662 | (and (eq_attr "cpu" "fr400,fr405") |
663 | (eq_attr "type" "mqaddh,mqsath,mqlimh,mqshift")) | |
664 | "fr400_m2") | |
36a05131 BS |
665 | |
666 | ;; M2 instructions store their results in accumulators, which are read | |
667 | ;; by M2 or M4 media commands. M2 instructions can read the results in | |
668 | ;; the following cycle, but M4 instructions must wait a cycle more. | |
669 | ||
670 | (define_bypass 1 | |
671 | "fr400_m2_1,fr400_m2_2" | |
672 | "fr400_m2_1,fr400_m2_2") | |
673 | ||
674 | (define_insn_reservation "fr400_m2_1" 2 | |
c557edf4 | 675 | (and (eq_attr "cpu" "fr400,fr405") |
36a05131 | 676 | (eq_attr "type" "mmulh,mmulxh,mmach,mmrdh,mcpx,maddacc")) |
c557edf4 | 677 | "fr400_m1") |
36a05131 BS |
678 | |
679 | (define_insn_reservation "fr400_m2_2" 2 | |
c557edf4 | 680 | (and (eq_attr "cpu" "fr400,fr405") |
36a05131 | 681 | (eq_attr "type" "mqmulh,mqmulxh,mqmach,mqcpx,mdaddacc")) |
c557edf4 | 682 | "fr400_m2") |
36a05131 BS |
683 | |
684 | ;; For our purposes, there seems to be little real difference between | |
685 | ;; M1 and M3 instructions. Keep them separate anyway in case the distinction | |
686 | ;; is needed later. | |
687 | ||
688 | (define_insn_reservation "fr400_m3_1" 1 | |
c557edf4 | 689 | (and (eq_attr "cpu" "fr400,fr405") |
36a05131 | 690 | (eq_attr "type" "mpackh,mrot,mshift,mexpdhw")) |
c557edf4 | 691 | "fr400_m1") |
36a05131 BS |
692 | |
693 | (define_insn_reservation "fr400_m3_2" 1 | |
c557edf4 | 694 | (and (eq_attr "cpu" "fr400,fr405") |
36a05131 | 695 | (eq_attr "type" "munpackh,mdpackh,mbhconv,mexpdhd,mwcut,mdrot,mcpl")) |
c557edf4 | 696 | "fr400_m2") |
36a05131 BS |
697 | |
698 | ;; M4 instructions write to accumulators or FPRs. MOVFG and STF | |
699 | ;; instructions can read an FPR result in the following cycle, but | |
700 | ;; M-unit instructions must wait a cycle more for either kind of result. | |
701 | ||
c557edf4 | 702 | (define_bypass 1 "fr400_m4_1,fr400_m4_2" "fr400_i3,fr400_i4") |
36a05131 BS |
703 | |
704 | (define_insn_reservation "fr400_m4_1" 2 | |
c557edf4 | 705 | (and (eq_attr "cpu" "fr400,fr405") |
36a05131 | 706 | (eq_attr "type" "mrdacc,mcut,mclracc")) |
c557edf4 | 707 | "fr400_m1") |
36a05131 BS |
708 | |
709 | (define_insn_reservation "fr400_m4_2" 2 | |
c557edf4 | 710 | (and (eq_attr "cpu" "fr400,fr405") |
36a05131 | 711 | (eq_attr "type" "mclracca,mdcut")) |
c557edf4 | 712 | "fr400_m2") |
36a05131 BS |
713 | |
714 | ;; M5 instructions always incur a 1-cycle penalty. | |
715 | ||
716 | (define_insn_reservation "fr400_m5" 2 | |
c557edf4 | 717 | (and (eq_attr "cpu" "fr400,fr405") |
36a05131 | 718 | (eq_attr "type" "mwtacc")) |
c557edf4 RS |
719 | "fr400_m2") |
720 | ||
721 | ;; :::::::::::::::::::: | |
722 | ;; :: | |
723 | ;; :: FR450 media scheduler description | |
724 | ;; :: | |
725 | ;; :::::::::::::::::::: | |
726 | ||
727 | ;; The FR451 media restrictions are similar to the FR400's, but not as | |
728 | ;; strict and not as regular. There are 6 categories with the following | |
729 | ;; restrictions: | |
730 | ;; | |
731 | ;; M1 | |
732 | ;; M-1 M-2 M-3 M-4 M-5 M-6 | |
733 | ;; M-1: x x x | |
734 | ;; M-2: x x x x x x | |
735 | ;; M0 M-3: x x x | |
736 | ;; M-4: x x x x | |
737 | ;; M-5: x x x | |
738 | ;; M-6: x x x x x x | |
739 | ;; | |
740 | ;; where "x" indicates a conflict. | |
741 | ;; | |
742 | ;; There is no difference between M-1 and M-3 as far as issue | |
743 | ;; restrictions are concerned, so they are combined as "m13". | |
744 | ||
745 | ;; Units for odd-numbered categories. There can be two of these | |
746 | ;; in a packet. | |
747 | (define_cpu_unit "fr450_m13a,fr450_m13b" "float_media") | |
748 | (define_cpu_unit "fr450_m5a,fr450_m5b" "float_media") | |
749 | ||
750 | ;; Units for even-numbered categories. There can only be one per packet. | |
751 | (define_cpu_unit "fr450_m2a,fr450_m4a,fr450_m6a" "float_media") | |
752 | ||
753 | ;; Enforce the restriction matrix above. | |
754 | (exclusion_set "fr450_m2a,fr450_m4a,fr450_m6a" "fr450_m13a,fr450_m13b") | |
755 | (exclusion_set "fr450_m2a,fr450_m6a" "fr450_m5a,fr450_m5b") | |
756 | (exclusion_set "fr450_m4a,fr450_m6a" "fr450_m2a") | |
757 | ||
758 | (define_reservation "fr450_m13" "(f1|f0) + (fr450_m13a|fr450_m13b)") | |
759 | (define_reservation "fr450_m2" "f0 + fr450_m2a") | |
760 | (define_reservation "fr450_m4" "f0 + fr450_m4a") | |
761 | (define_reservation "fr450_m5" "(f1|f0) + (fr450_m5a|fr450_m5b)") | |
762 | (define_reservation "fr450_m6" "(f0|f1) + fr450_m6a") | |
763 | ||
764 | ;; MD-1, MD-3 and MD-8 instructions, which are the same as far | |
765 | ;; as scheduling is concerned. The inputs and outputs are FPRs. | |
766 | ;; Instructions that have 32-bit inputs and outputs belong to M-1 while | |
767 | ;; the rest belong to M-2. | |
768 | ;; | |
769 | ;; ??? Arithmetic shifts (MD-6) have an extra cycle latency, but we don't | |
770 | ;; make the distinction between them and logical shifts. | |
771 | (define_insn_reservation "fr450_md138_1" 1 | |
772 | (and (eq_attr "cpu" "fr450") | |
773 | (eq_attr "type" "fsconv,mnop,mlogic,maveh,msath,maddh,mabsh,mset, | |
774 | mrot,mshift,mexpdhw,mpackh")) | |
775 | "fr450_m13") | |
776 | ||
777 | (define_insn_reservation "fr450_md138_2" 1 | |
778 | (and (eq_attr "cpu" "fr450") | |
779 | (eq_attr "type" "mqaddh,mqsath,mqlimh, | |
780 | mdrot,mwcut,mqshift,mexpdhd, | |
781 | munpackh,mdpackh,mbhconv,mcpl")) | |
782 | "fr450_m2") | |
783 | ||
784 | ;; MD-2 instructions. These take FPR or ACC inputs and produce an ACC output. | |
785 | ;; Instructions that write to double ACCs belong to M-3 while those that write | |
786 | ;; to quad ACCs belong to M-4. | |
787 | (define_insn_reservation "fr450_md2_3" 2 | |
788 | (and (eq_attr "cpu" "fr450") | |
789 | (eq_attr "type" "mmulh,mmach,mcpx,mmulxh,mmrdh,maddacc")) | |
790 | "fr450_m13") | |
791 | ||
792 | (define_insn_reservation "fr450_md2_4" 2 | |
793 | (and (eq_attr "cpu" "fr450") | |
794 | (eq_attr "type" "mqmulh,mqmach,mqcpx,mqmulxh,mdaddacc")) | |
795 | "fr450_m4") | |
796 | ||
797 | ;; Another MD-2 instruction can use the result on the following cycle. | |
798 | (define_bypass 1 "fr450_md2_3,fr450_md2_4" "fr450_md2_3,fr450_md2_4") | |
799 | ||
800 | ;; MD-4 instructions that write to ACCs. | |
801 | (define_insn_reservation "fr450_md4_3" 2 | |
802 | (and (eq_attr "cpu" "fr450") | |
803 | (eq_attr "type" "mclracc")) | |
804 | "fr450_m13") | |
805 | ||
806 | (define_insn_reservation "fr450_md4_4" 3 | |
807 | (and (eq_attr "cpu" "fr450") | |
808 | (eq_attr "type" "mclracca")) | |
809 | "fr450_m4") | |
810 | ||
811 | ;; MD-4 instructions that write to FPRs. | |
812 | (define_insn_reservation "fr450_md4_1" 2 | |
813 | (and (eq_attr "cpu" "fr450") | |
814 | (eq_attr "type" "mcut")) | |
815 | "fr450_m13") | |
816 | ||
817 | (define_insn_reservation "fr450_md4_5" 2 | |
818 | (and (eq_attr "cpu" "fr450") | |
819 | (eq_attr "type" "mrdacc")) | |
820 | "fr450_m5") | |
821 | ||
822 | (define_insn_reservation "fr450_md4_6" 2 | |
823 | (and (eq_attr "cpu" "fr450") | |
824 | (eq_attr "type" "mdcut")) | |
825 | "fr450_m6") | |
826 | ||
827 | ;; Integer instructions can read the FPR result of an MD-4 instruction on | |
828 | ;; the following cycle. | |
829 | (define_bypass 1 "fr450_md4_1,fr450_md4_5,fr450_md4_6" | |
830 | "fr400_i3,fr450_i4_movfg") | |
831 | ||
832 | ;; MD-5 instructions, which belong to M-3. They take FPR inputs and | |
833 | ;; write to ACCs. | |
834 | (define_insn_reservation "fr450_md5_3" 2 | |
835 | (and (eq_attr "cpu" "fr450") | |
836 | (eq_attr "type" "mwtacc")) | |
837 | "fr450_m13") | |
838 | ||
839 | ;; :::::::::::::::::::: | |
840 | ;; :: | |
841 | ;; :: FR550 scheduler description | |
842 | ;; :: | |
843 | ;; :::::::::::::::::::: | |
844 | ||
845 | ;; Prevent loads and stores from being issued in the same packet. | |
846 | ;; These units must go into the generic "integer" reservation because | |
847 | ;; of the constraints on fr550_store0 and fr550_store1. | |
848 | (define_cpu_unit "fr550_load0,fr550_load1" "integer") | |
849 | (define_cpu_unit "fr550_store0,fr550_store1" "integer") | |
850 | (exclusion_set "fr550_load0,fr550_load1" "fr550_store0,fr550_store1") | |
851 | ||
852 | ;; A store can only issue to I1 if one has also been issued to I0. | |
853 | (presence_set "fr550_store1" "fr550_store0") | |
854 | ||
855 | (define_bypass 0 "fr550_sethi" "fr550_setlo") | |
856 | (define_insn_reservation "fr550_sethi" 1 | |
857 | (and (eq_attr "cpu" "fr550") | |
858 | (eq_attr "type" "sethi")) | |
859 | "i3|i2|i1|i0") | |
860 | ||
861 | (define_insn_reservation "fr550_setlo" 1 | |
862 | (and (eq_attr "cpu" "fr550") | |
863 | (eq_attr "type" "setlo")) | |
864 | "i3|i2|i1|i0") | |
865 | ||
866 | (define_insn_reservation "fr550_int" 1 | |
867 | (and (eq_attr "cpu" "fr550") | |
868 | (eq_attr "type" "int")) | |
869 | "i3|i2|i1|i0") | |
870 | ||
871 | (define_insn_reservation "fr550_mul" 2 | |
872 | (and (eq_attr "cpu" "fr550") | |
873 | (eq_attr "type" "mul")) | |
874 | "i1|i0") | |
875 | ||
876 | (define_insn_reservation "fr550_div" 19 | |
877 | (and (eq_attr "cpu" "fr550") | |
878 | (eq_attr "type" "div")) | |
879 | "(i1|i0),(idiv1*18 | idiv2*18)") | |
880 | ||
881 | (define_insn_reservation "fr550_load" 3 | |
882 | (and (eq_attr "cpu" "fr550") | |
883 | (eq_attr "type" "gload,fload")) | |
884 | "(i1|i0)+(fr550_load0|fr550_load1)") | |
885 | ||
886 | ;; We can only issue a store to I1 if one was also issued to I0. | |
887 | ;; This means that, as far as frv_reorder_packet is concerned, | |
888 | ;; the instruction has the same priority as an I0-only instruction. | |
889 | (define_insn_reservation "fr550_store" 1 | |
890 | (and (eq_attr "cpu" "fr550") | |
891 | (eq_attr "type" "gstore,fstore")) | |
892 | "(i0+fr550_store0)|(i1+fr550_store1)") | |
893 | ||
894 | (define_insn_reservation "fr550_transfer" 2 | |
895 | (and (eq_attr "cpu" "fr550") | |
896 | (eq_attr "type" "movgf,movfg")) | |
897 | "i0") | |
898 | ||
899 | (define_insn_reservation "fr550_jumpl" 0 | |
900 | (and (eq_attr "cpu" "fr550") | |
901 | (eq_attr "type" "jumpl")) | |
902 | "i0") | |
903 | ||
904 | (define_cpu_unit "fr550_ccr0,fr550_ccr1" "float_media") | |
905 | ||
906 | (define_insn_reservation "fr550_branch" 0 | |
907 | (and (eq_attr "cpu" "fr550") | |
908 | (eq_attr "type" "jump,branch")) | |
909 | "b1|b0") | |
910 | ||
911 | (define_insn_reservation "fr550_ccr" 0 | |
912 | (and (eq_attr "cpu" "fr550") | |
913 | (eq_attr "type" "ccr")) | |
914 | "(b1|b0) + (fr550_ccr1|fr550_ccr0)") | |
915 | ||
916 | (define_insn_reservation "fr550_call" 0 | |
917 | (and (eq_attr "cpu" "fr550") | |
918 | (eq_attr "type" "call")) | |
919 | "b0") | |
920 | ||
921 | (define_automaton "fr550_float_media") | |
922 | (define_cpu_unit "fr550_add0,fr550_add1" "fr550_float_media") | |
923 | ||
924 | ;; There are three possible combinations of floating-point/media instructions: | |
925 | ;; | |
926 | ;; - one media and one float | |
927 | ;; - up to four float, no media | |
928 | ;; - up to four media, no float | |
929 | (define_cpu_unit "fr550_f0,fr550_f1,fr550_f2,fr550_f3" "fr550_float_media") | |
930 | (define_cpu_unit "fr550_m0,fr550_m1,fr550_m2,fr550_m3" "fr550_float_media") | |
931 | (exclusion_set "fr550_f1,fr550_f2,fr550_f3" "fr550_m1,fr550_m2,fr550_m3") | |
35f2d8ef NC |
932 | (exclusion_set "fr550_m0" "fr550_f1,fr550_f2,fr550_f3") |
933 | ;; FIXME: This next exclusion set should be defined as well, so that we do | |
934 | ;; not get a packet containing multiple media instructions plus a single | |
935 | ;; floating point instruction. At the moment we can get away with not | |
936 | ;; defining it because gcc does not seem to generate such packets. | |
937 | ;; | |
938 | ;; If we do enable the exclusion however the insertion of fnop insns into | |
939 | ;; a packet containing media instructions will stop working, because the | |
940 | ;; fnop insn counts as a floating point instruction. The correct solution | |
941 | ;; is to fix the reservation for the fnop insn so that it does not have the | |
942 | ;; same restrictions as ordinary floating point insns. | |
943 | ;;(exclusion_set "fr550_f0" "fr550_m1,fr550_m2,fr550_m3") | |
c557edf4 RS |
944 | |
945 | (define_reservation "fr550_float" "fr550_f0|fr550_f1|fr550_f2|fr550_f3") | |
946 | (define_reservation "fr550_media" "fr550_m0|fr550_m1|fr550_m2|fr550_m3") | |
947 | ||
948 | (define_insn_reservation "fr550_f1" 0 | |
949 | (and (eq_attr "cpu" "fr550") | |
950 | (eq_attr "type" "fnop")) | |
951 | "(f3|f2|f1|f0) + fr550_float") | |
952 | ||
953 | (define_insn_reservation "fr550_f2" 3 | |
954 | (and (eq_attr "cpu" "fr550") | |
955 | (eq_attr "type" "fsconv,fsadd,fscmp")) | |
956 | "(f3|f2|f1|f0) + (fr550_add0|fr550_add1) + fr550_float") | |
957 | ||
958 | (define_insn_reservation "fr550_f3_mul" 3 | |
959 | (and (eq_attr "cpu" "fr550") | |
960 | (eq_attr "type" "fsmul")) | |
961 | "(f1|f0) + fr550_float") | |
962 | ||
963 | (define_insn_reservation "fr550_f3_div" 10 | |
964 | (and (eq_attr "cpu" "fr550") | |
965 | (eq_attr "type" "fsdiv")) | |
966 | "(f1|f0) + fr550_float") | |
967 | ||
968 | (define_insn_reservation "fr550_f3_sqrt" 15 | |
969 | (and (eq_attr "cpu" "fr550") | |
970 | (eq_attr "type" "sqrt_single")) | |
971 | "(f1|f0) + fr550_float") | |
972 | ||
aabcd309 | 973 | ;; Synthetic units for enforcing media issue restrictions. Certain types |
c557edf4 RS |
974 | ;; of insn in M2 conflict with certain types in M0: |
975 | ;; | |
976 | ;; M2 | |
977 | ;; MNOP MALU MSFT MMAC MSET | |
978 | ;; MNOP - - x - - | |
979 | ;; MALU - x x - - | |
980 | ;; M0 MSFT - - x - x | |
981 | ;; MMAC - - x x - | |
982 | ;; MSET - - x - - | |
983 | ;; | |
984 | ;; where "x" indicates a conflict. The same restrictions apply to | |
985 | ;; M3 and M1. | |
986 | ;; | |
987 | ;; In addition -- and this is the awkward bit! -- instructions that | |
988 | ;; access ACC0-3 can only issue to M0 or M2. Those that access ACC4-7 | |
989 | ;; can only issue to M1 or M3. We refer to such instructions as "even" | |
990 | ;; and "odd" respectively. | |
991 | (define_cpu_unit "fr550_malu0,fr550_malu1" "float_media") | |
992 | (define_cpu_unit "fr550_malu2,fr550_malu3" "float_media") | |
993 | (define_cpu_unit "fr550_msft0,fr550_msft1" "float_media") | |
994 | (define_cpu_unit "fr550_mmac0,fr550_mmac1" "float_media") | |
995 | (define_cpu_unit "fr550_mmac2,fr550_mmac3" "float_media") | |
996 | (define_cpu_unit "fr550_mset0,fr550_mset1" "float_media") | |
997 | (define_cpu_unit "fr550_mset2,fr550_mset3" "float_media") | |
998 | ||
999 | (exclusion_set "fr550_malu0" "fr550_malu2") | |
1000 | (exclusion_set "fr550_malu1" "fr550_malu3") | |
1001 | ||
1002 | (exclusion_set "fr550_msft0" "fr550_mset2") | |
1003 | (exclusion_set "fr550_msft1" "fr550_mset3") | |
1004 | ||
1005 | (exclusion_set "fr550_mmac0" "fr550_mmac2") | |
1006 | (exclusion_set "fr550_mmac1" "fr550_mmac3") | |
1007 | ||
1008 | ;; If an MSFT or MMAC instruction issues to a unit other than M0, we may | |
1009 | ;; need to insert some nops. In the worst case, the packet will end up | |
1010 | ;; having 4 integer instructions and 4 media instructions, leaving no | |
1011 | ;; room for any branch instructions that the DFA might have accepted. | |
1012 | ;; | |
1013 | ;; This doesn't matter for JUMP_INSNs and CALL_INSNs because they are | |
1014 | ;; always the last instructions to be passed to the DFA, and could be | |
1015 | ;; pushed out to a separate packet once the nops have been added. | |
1016 | ;; However, it does cause problems for ccr instructions since they | |
1017 | ;; can occur anywhere in the unordered packet. | |
1018 | (exclusion_set "fr550_msft1,fr550_mmac1,fr550_mmac2,fr550_mmac3" | |
1019 | "fr550_ccr0,fr550_ccr1") | |
1020 | ||
1021 | (define_reservation "fr550_malu" | |
1022 | "(f3 + fr550_malu3) | (f2 + fr550_malu2) | |
1023 | | (f1 + fr550_malu1) | (f0 + fr550_malu0)") | |
1024 | ||
1025 | (define_reservation "fr550_msft_even" | |
1026 | "f0 + fr550_msft0") | |
1027 | ||
1028 | (define_reservation "fr550_msft_odd" | |
1029 | "f1 + fr550_msft1") | |
1030 | ||
1031 | (define_reservation "fr550_msft_either" | |
1032 | "(f1 + fr550_msft1) | (f0 + fr550_msft0)") | |
1033 | ||
1034 | (define_reservation "fr550_mmac_even" | |
1035 | "(f2 + fr550_mmac2) | (f0 + fr550_mmac0)") | |
1036 | ||
1037 | (define_reservation "fr550_mmac_odd" | |
1038 | "(f3 + fr550_mmac3) | (f1 + fr550_mmac1)") | |
1039 | ||
1040 | (define_reservation "fr550_mset" | |
1041 | "(f3 + fr550_mset3) | (f2 + fr550_mset2) | |
1042 | | (f1 + fr550_mset1) | (f0 + fr550_mset0)") | |
1043 | ||
1044 | (define_insn_reservation "fr550_mnop" 0 | |
1045 | (and (eq_attr "cpu" "fr550") | |
1046 | (eq_attr "type" "mnop")) | |
1047 | "fr550_media + (f3|f2|f1|f0)") | |
1048 | ||
1049 | (define_insn_reservation "fr550_malu" 2 | |
1050 | (and (eq_attr "cpu" "fr550") | |
1051 | (eq_attr "type" "mlogic,maveh,msath,mabsh,maddh,mqaddh,mqsath")) | |
1052 | "fr550_media + fr550_malu") | |
1053 | ||
1054 | ;; These insns only operate on FPRs and so don't need to be classified | |
1055 | ;; as even/odd. | |
1056 | (define_insn_reservation "fr550_msft_1_either" 2 | |
1057 | (and (eq_attr "cpu" "fr550") | |
1058 | (eq_attr "type" "mrot,mwcut,mshift,mexpdhw,mexpdhd,mpackh, | |
1059 | munpackh,mdpackh,mbhconv,mdrot,mcpl")) | |
1060 | "fr550_media + fr550_msft_either") | |
1061 | ||
1062 | ;; These insns read from ACC0-3. | |
1063 | (define_insn_reservation "fr550_msft_1_even" 2 | |
1064 | (and (eq_attr "cpu" "fr550") | |
1065 | (and (eq_attr "type" "mcut,mrdacc,mdcut") | |
1066 | (eq_attr "acc_group" "even"))) | |
1067 | "fr550_media + fr550_msft_even") | |
1068 | ||
1069 | ;; These insns read from ACC4-7. | |
1070 | (define_insn_reservation "fr550_msft_1_odd" 2 | |
1071 | (and (eq_attr "cpu" "fr550") | |
1072 | (and (eq_attr "type" "mcut,mrdacc,mdcut") | |
1073 | (eq_attr "acc_group" "odd"))) | |
1074 | "fr550_media + fr550_msft_odd") | |
1075 | ||
1076 | ;; MCLRACC with A=1 can issue to either M0 or M1. | |
1077 | (define_insn_reservation "fr550_msft_2_either" 2 | |
1078 | (and (eq_attr "cpu" "fr550") | |
1079 | (eq_attr "type" "mclracca")) | |
1080 | "fr550_media + fr550_msft_either") | |
1081 | ||
1082 | ;; These insns write to ACC0-3. | |
1083 | (define_insn_reservation "fr550_msft_2_even" 2 | |
1084 | (and (eq_attr "cpu" "fr550") | |
1085 | (and (eq_attr "type" "mclracc,mwtacc") | |
1086 | (eq_attr "acc_group" "even"))) | |
1087 | "fr550_media + fr550_msft_even") | |
1088 | ||
1089 | ;; These insns write to ACC4-7. | |
1090 | (define_insn_reservation "fr550_msft_2_odd" 2 | |
1091 | (and (eq_attr "cpu" "fr550") | |
1092 | (and (eq_attr "type" "mclracc,mwtacc") | |
1093 | (eq_attr "acc_group" "odd"))) | |
1094 | "fr550_media + fr550_msft_odd") | |
1095 | ||
1096 | ;; These insns read from and write to ACC0-3. | |
1097 | (define_insn_reservation "fr550_mmac_even" 2 | |
1098 | (and (eq_attr "cpu" "fr550") | |
1099 | (and (eq_attr "type" "mmulh,mmulxh,mmach,mmrdh,mqmulh,mqmulxh,mqmach, | |
1100 | maddacc,mdaddacc,mcpx,mqcpx") | |
1101 | (eq_attr "acc_group" "even"))) | |
1102 | "fr550_media + fr550_mmac_even") | |
1103 | ||
1104 | ;; These insns read from and write to ACC4-7. | |
1105 | (define_insn_reservation "fr550_mmac_odd" 2 | |
1106 | (and (eq_attr "cpu" "fr550") | |
1107 | (and (eq_attr "type" "mmulh,mmulxh,mmach,mmrdh,mqmulh,mqmulxh,mqmach, | |
1108 | maddacc,mdaddacc,mcpx,mqcpx") | |
1109 | (eq_attr "acc_group" "odd"))) | |
1110 | "fr550_media + fr550_mmac_odd") | |
1111 | ||
1112 | (define_insn_reservation "fr550_mset" 1 | |
1113 | (and (eq_attr "cpu" "fr550") | |
1114 | (eq_attr "type" "mset")) | |
1115 | "fr550_media + fr550_mset") | |
36a05131 BS |
1116 | |
1117 | ;; :::::::::::::::::::: | |
1118 | ;; :: | |
1119 | ;; :: Simple/FR300 scheduler description | |
1120 | ;; :: | |
1121 | ;; :::::::::::::::::::: | |
1122 | ||
1123 | ;; Fr300 or simple processor. To describe it as 1 insn issue | |
1124 | ;; processor, we use control unit. | |
1125 | ||
1126 | (define_insn_reservation "fr300_lat1" 1 | |
1127 | (and (eq_attr "cpu" "fr300,simple") | |
1128 | (eq_attr "type" "!gload,fload,movfg,movgf")) | |
c557edf4 | 1129 | "c + control") |
36a05131 BS |
1130 | |
1131 | (define_insn_reservation "fr300_lat2" 2 | |
1132 | (and (eq_attr "cpu" "fr300,simple") | |
1133 | (eq_attr "type" "gload,fload,movfg,movgf")) | |
c557edf4 | 1134 | "c + control") |
36a05131 BS |
1135 | |
1136 | \f | |
1137 | ;; :::::::::::::::::::: | |
1138 | ;; :: | |
1139 | ;; :: Delay Slots | |
1140 | ;; :: | |
1141 | ;; :::::::::::::::::::: | |
1142 | ||
1143 | ;; The insn attribute mechanism can be used to specify the requirements for | |
1144 | ;; delay slots, if any, on a target machine. An instruction is said to require | |
1145 | ;; a "delay slot" if some instructions that are physically after the | |
1146 | ;; instruction are executed as if they were located before it. Classic | |
1147 | ;; examples are branch and call instructions, which often execute the following | |
1148 | ;; instruction before the branch or call is performed. | |
1149 | ||
1150 | ;; On some machines, conditional branch instructions can optionally "annul" | |
1151 | ;; instructions in the delay slot. This means that the instruction will not be | |
1152 | ;; executed for certain branch outcomes. Both instructions that annul if the | |
1153 | ;; branch is true and instructions that annul if the branch is false are | |
1154 | ;; supported. | |
1155 | ||
1156 | ;; Delay slot scheduling differs from instruction scheduling in that | |
1157 | ;; determining whether an instruction needs a delay slot is dependent only | |
1158 | ;; on the type of instruction being generated, not on data flow between the | |
1159 | ;; instructions. See the next section for a discussion of data-dependent | |
1160 | ;; instruction scheduling. | |
1161 | ||
1162 | ;; The requirement of an insn needing one or more delay slots is indicated via | |
1163 | ;; the `define_delay' expression. It has the following form: | |
1164 | ;; | |
1165 | ;; (define_delay TEST | |
1166 | ;; [DELAY-1 ANNUL-TRUE-1 ANNUL-FALSE-1 | |
1167 | ;; DELAY-2 ANNUL-TRUE-2 ANNUL-FALSE-2 | |
1168 | ;; ...]) | |
1169 | ||
1170 | ;; TEST is an attribute test that indicates whether this `define_delay' applies | |
1171 | ;; to a particular insn. If so, the number of required delay slots is | |
1172 | ;; determined by the length of the vector specified as the second argument. An | |
1173 | ;; insn placed in delay slot N must satisfy attribute test DELAY-N. | |
1174 | ;; ANNUL-TRUE-N is an attribute test that specifies which insns may be annulled | |
1175 | ;; if the branch is true. Similarly, ANNUL-FALSE-N specifies which insns in | |
1176 | ;; the delay slot may be annulled if the branch is false. If annulling is not | |
1177 | ;; supported for that delay slot, `(nil)' should be coded. | |
1178 | ||
1179 | ;; For example, in the common case where branch and call insns require a single | |
1180 | ;; delay slot, which may contain any insn other than a branch or call, the | |
1181 | ;; following would be placed in the `md' file: | |
1182 | ||
1183 | ;; (define_delay (eq_attr "type" "branch,call") | |
1184 | ;; [(eq_attr "type" "!branch,call") (nil) (nil)]) | |
1185 | ||
1186 | ;; Multiple `define_delay' expressions may be specified. In this case, each | |
1187 | ;; such expression specifies different delay slot requirements and there must | |
1188 | ;; be no insn for which tests in two `define_delay' expressions are both true. | |
1189 | ||
1190 | ;; For example, if we have a machine that requires one delay slot for branches | |
1191 | ;; but two for calls, no delay slot can contain a branch or call insn, and any | |
1192 | ;; valid insn in the delay slot for the branch can be annulled if the branch is | |
1193 | ;; true, we might represent this as follows: | |
1194 | ||
1195 | ;; (define_delay (eq_attr "type" "branch") | |
1196 | ;; [(eq_attr "type" "!branch,call") | |
1197 | ;; (eq_attr "type" "!branch,call") | |
1198 | ;; (nil)]) | |
1199 | ;; | |
1200 | ;; (define_delay (eq_attr "type" "call") | |
1201 | ;; [(eq_attr "type" "!branch,call") (nil) (nil) | |
1202 | ;; (eq_attr "type" "!branch,call") (nil) (nil)]) | |
1203 | ||
1204 | ;; Note - it is the backend's responsibility to fill any unfilled delay slots | |
1205 | ;; at assembler generation time. This is usually done by adding a special print | |
839a4992 | 1206 | ;; operand to the delayed instruction, and then in the PRINT_OPERAND function |
36a05131 BS |
1207 | ;; calling dbr_sequence_length() to determine how many delay slots were filled. |
1208 | ;; For example: | |
1209 | ;; | |
1210 | ;; --------------<machine>.md----------------- | |
1211 | ;; (define_insn "call" | |
1212 | ;; [(call (match_operand 0 "memory_operand" "m") | |
1213 | ;; (match_operand 1 "" ""))] | |
1214 | ;; "" | |
1215 | ;; "call_delayed %0,%1,%2%#" | |
1216 | ;; [(set_attr "length" "4") | |
1217 | ;; (set_attr "type" "call")]) | |
1218 | ;; | |
1219 | ;; -------------<machine>.h------------------- | |
1220 | ;; #define PRINT_OPERAND_PUNCT_VALID_P(CODE) (CODE == '#') | |
1221 | ;; | |
1222 | ;; ------------<machine>.c------------------ | |
1223 | ;; void | |
1224 | ;; machine_print_operand (file, x, code) | |
1225 | ;; FILE * file; | |
1226 | ;; rtx x; | |
1227 | ;; int code; | |
1228 | ;; { | |
1229 | ;; switch (code) | |
1230 | ;; { | |
1231 | ;; case '#': | |
1232 | ;; if (dbr_sequence_length () == 0) | |
1233 | ;; fputs ("\n\tnop", file); | |
1234 | ;; return; | |
1235 | \f | |
1236 | ;; :::::::::::::::::::: | |
1237 | ;; :: | |
1238 | ;; :: Notes on Patterns | |
1239 | ;; :: | |
1240 | ;; :::::::::::::::::::: | |
1241 | ||
1242 | ;; If you need to construct a sequence of assembler instructions in order | |
1243 | ;; to implement a pattern be sure to escape any backslashes and double quotes | |
112cdef5 | 1244 | ;; that you use, e.g.: |
36a05131 BS |
1245 | ;; |
1246 | ;; (define_insn "an example" | |
1247 | ;; [(some rtl)] | |
1248 | ;; "" | |
1249 | ;; "* | |
1250 | ;; { static char buffer [100]; | |
1251 | ;; sprintf (buffer, \"insn \\t %d\", REGNO (operands[1])); | |
1252 | ;; return buffer; | |
1253 | ;; }" | |
1254 | ;; ) | |
1255 | ;; | |
1256 | ;; Also if there is more than one instruction, they can be separated by \\; | |
1257 | ;; which is a space saving synonym for \\n\\t: | |
1258 | ;; | |
1259 | ;; (define_insn "another example" | |
1260 | ;; [(some rtl)] | |
1261 | ;; "" | |
1262 | ;; "* | |
1263 | ;; { static char buffer [100]; | |
1264 | ;; sprintf (buffer, \"insn1 \\t %d\\;insn2 \\t %%1\", | |
1265 | ;; REGNO (operands[1])); | |
1266 | ;; return buffer; | |
1267 | ;; }" | |
1268 | ;; ) | |
1269 | ;; | |
1270 | ||
6d26dc3b | 1271 | (include "predicates.md") |
49ac143d | 1272 | (include "constraints.md") |
36a05131 BS |
1273 | \f |
1274 | ;; :::::::::::::::::::: | |
1275 | ;; :: | |
1276 | ;; :: Moves | |
1277 | ;; :: | |
1278 | ;; :::::::::::::::::::: | |
1279 | ||
1280 | ;; Wrap moves in define_expand to prevent memory->memory moves from being | |
1281 | ;; generated at the RTL level, which generates better code for most machines | |
1282 | ;; which can't do mem->mem moves. | |
1283 | ||
1284 | ;; If operand 0 is a `subreg' with mode M of a register whose own mode is wider | |
1285 | ;; than M, the effect of this instruction is to store the specified value in | |
1286 | ;; the part of the register that corresponds to mode M. The effect on the rest | |
1287 | ;; of the register is undefined. | |
1288 | ||
1289 | ;; This class of patterns is special in several ways. First of all, each of | |
1290 | ;; these names *must* be defined, because there is no other way to copy a datum | |
1291 | ;; from one place to another. | |
1292 | ||
1293 | ;; Second, these patterns are not used solely in the RTL generation pass. Even | |
1294 | ;; the reload pass can generate move insns to copy values from stack slots into | |
1295 | ;; temporary registers. When it does so, one of the operands is a hard | |
1296 | ;; register and the other is an operand that can need to be reloaded into a | |
1297 | ;; register. | |
1298 | ||
1299 | ;; Therefore, when given such a pair of operands, the pattern must | |
1300 | ;; generate RTL which needs no reloading and needs no temporary | |
1301 | ;; registers--no registers other than the operands. For example, if | |
1302 | ;; you support the pattern with a `define_expand', then in such a | |
1303 | ;; case the `define_expand' mustn't call `force_reg' or any other such | |
1304 | ;; function which might generate new pseudo registers. | |
1305 | ||
1306 | ;; This requirement exists even for subword modes on a RISC machine | |
1307 | ;; where fetching those modes from memory normally requires several | |
1308 | ;; insns and some temporary registers. Look in `spur.md' to see how | |
1309 | ;; the requirement can be satisfied. | |
1310 | ||
1311 | ;; During reload a memory reference with an invalid address may be passed as an | |
1312 | ;; operand. Such an address will be replaced with a valid address later in the | |
1313 | ;; reload pass. In this case, nothing may be done with the address except to | |
1314 | ;; use it as it stands. If it is copied, it will not be replaced with a valid | |
1315 | ;; address. No attempt should be made to make such an address into a valid | |
1316 | ;; address and no routine (such as `change_address') that will do so may be | |
1317 | ;; called. Note that `general_operand' will fail when applied to such an | |
1318 | ;; address. | |
1319 | ;; | |
1320 | ;; The global variable `reload_in_progress' (which must be explicitly declared | |
1321 | ;; if required) can be used to determine whether such special handling is | |
1322 | ;; required. | |
1323 | ;; | |
1324 | ;; The variety of operands that have reloads depends on the rest of | |
1325 | ;; the machine description, but typically on a RISC machine these can | |
1326 | ;; only be pseudo registers that did not get hard registers, while on | |
1327 | ;; other machines explicit memory references will get optional | |
1328 | ;; reloads. | |
1329 | ;; | |
1330 | ;; If a scratch register is required to move an object to or from memory, it | |
1331 | ;; can be allocated using `gen_reg_rtx' prior to reload. But this is | |
1332 | ;; impossible during and after reload. If there are cases needing scratch | |
1333 | ;; registers after reload, you must define `SECONDARY_INPUT_RELOAD_CLASS' and | |
1334 | ;; perhaps also `SECONDARY_OUTPUT_RELOAD_CLASS' to detect them, and provide | |
1335 | ;; patterns `reload_inM' or `reload_outM' to handle them. | |
1336 | ||
1337 | ;; The constraints on a `moveM' must permit moving any hard register to any | |
f939c3e6 RS |
1338 | ;; other hard register provided that `TARGET_HARD_REGNO_MODE_OK' permits |
1339 | ;; mode M in both registers and `REGISTER_MOVE_COST' applied to their | |
1340 | ;; classes returns a value of 2. | |
36a05131 BS |
1341 | |
1342 | ;; It is obligatory to support floating point `moveM' instructions | |
1343 | ;; into and out of any registers that can hold fixed point values, | |
1344 | ;; because unions and structures (which have modes `SImode' or | |
1345 | ;; `DImode') can be in those registers and they may have floating | |
1346 | ;; point members. | |
1347 | ||
f939c3e6 RS |
1348 | ;; There may also be a need to support fixed point `moveM' instructions |
1349 | ;; in and out of floating point registers. Unfortunately, I have | |
1350 | ;; forgotten why this was so, and I don't know whether it is still true. | |
1351 | ;; If `TARGET_HARD_REGNO_MODE_OK' rejects fixed point values in floating | |
1352 | ;; point registers, then the constraints of the fixed point `moveM' | |
1353 | ;; instructions must be designed to avoid ever trying to reload into a | |
1354 | ;; floating point register. | |
36a05131 BS |
1355 | |
1356 | (define_expand "movqi" | |
1357 | [(set (match_operand:QI 0 "general_operand" "") | |
1358 | (match_operand:QI 1 "general_operand" ""))] | |
1359 | "" | |
2a2e3f05 | 1360 | "{ frv_emit_move (QImode, operands[0], operands[1]); DONE; }") |
36a05131 BS |
1361 | |
1362 | (define_insn "*movqi_load" | |
1363 | [(set (match_operand:QI 0 "register_operand" "=d,f") | |
1364 | (match_operand:QI 1 "frv_load_operand" "m,m"))] | |
1365 | "" | |
1366 | "* return output_move_single (operands, insn);" | |
1367 | [(set_attr "length" "4") | |
1368 | (set_attr "type" "gload,fload")]) | |
1369 | ||
1370 | (define_insn "*movqi_internal" | |
6f4c062b AO |
1371 | [(set (match_operand:QI 0 "move_destination_operand" "=d,d,m,m,?f,?f,?d,?m,f,d,f") |
1372 | (match_operand:QI 1 "move_source_operand" "L,d,d,O, d, f, f, f,GO,!m,!m"))] | |
36a05131 BS |
1373 | "register_operand(operands[0], QImode) || reg_or_0_operand (operands[1], QImode)" |
1374 | "* return output_move_single (operands, insn);" | |
1375 | [(set_attr "length" "4") | |
6f4c062b | 1376 | (set_attr "type" "int,int,gstore,gstore,movgf,fsconv,movfg,fstore,movgf,gload,fload")]) |
36a05131 BS |
1377 | |
1378 | (define_expand "movhi" | |
1379 | [(set (match_operand:HI 0 "general_operand" "") | |
1380 | (match_operand:HI 1 "general_operand" ""))] | |
1381 | "" | |
2a2e3f05 | 1382 | "{ frv_emit_move (HImode, operands[0], operands[1]); DONE; }") |
36a05131 BS |
1383 | |
1384 | (define_insn "*movhi_load" | |
1385 | [(set (match_operand:HI 0 "register_operand" "=d,f") | |
1386 | (match_operand:HI 1 "frv_load_operand" "m,m"))] | |
1387 | "" | |
1388 | "* return output_move_single (operands, insn);" | |
1389 | [(set_attr "length" "4") | |
1390 | (set_attr "type" "gload,fload")]) | |
1391 | ||
1392 | (define_insn "*movhi_internal" | |
6f4c062b AO |
1393 | [(set (match_operand:HI 0 "move_destination_operand" "=d,d,d,m,m,?f,?f,?d,?m,f,d,f") |
1394 | (match_operand:HI 1 "move_source_operand" "L,n,d,d,O, d, f, f, f,GO,!m,!m"))] | |
36a05131 BS |
1395 | "register_operand(operands[0], HImode) || reg_or_0_operand (operands[1], HImode)" |
1396 | "* return output_move_single (operands, insn);" | |
6f4c062b AO |
1397 | [(set_attr "length" "4,8,4,4,4,4,4,4,4,4,4,4") |
1398 | (set_attr "type" "int,multi,int,gstore,gstore,movgf,fsconv,movfg,fstore,movgf,gload,fload")]) | |
36a05131 BS |
1399 | |
1400 | ;; Split 2 word load of constants into sethi/setlo instructions | |
1401 | (define_split | |
1402 | [(set (match_operand:HI 0 "integer_register_operand" "") | |
1403 | (match_operand:HI 1 "int_2word_operand" ""))] | |
1404 | "reload_completed" | |
1405 | [(set (match_dup 0) | |
1406 | (high:HI (match_dup 1))) | |
1407 | (set (match_dup 0) | |
1408 | (lo_sum:HI (match_dup 0) | |
1409 | (match_dup 1)))] | |
1410 | "") | |
1411 | ||
1412 | (define_insn "movhi_high" | |
1413 | [(set (match_operand:HI 0 "integer_register_operand" "=d") | |
1414 | (high:HI (match_operand:HI 1 "int_2word_operand" "i")))] | |
1415 | "" | |
1416 | "sethi #hi(%1), %0" | |
1417 | [(set_attr "type" "sethi") | |
1418 | (set_attr "length" "4")]) | |
1419 | ||
1420 | (define_insn "movhi_lo_sum" | |
1421 | [(set (match_operand:HI 0 "integer_register_operand" "+d") | |
1422 | (lo_sum:HI (match_dup 0) | |
1423 | (match_operand:HI 1 "int_2word_operand" "i")))] | |
1424 | "" | |
1425 | "setlo #lo(%1), %0" | |
1426 | [(set_attr "type" "setlo") | |
1427 | (set_attr "length" "4")]) | |
1428 | ||
1429 | (define_expand "movsi" | |
1430 | [(set (match_operand:SI 0 "move_destination_operand" "") | |
1431 | (match_operand:SI 1 "move_source_operand" ""))] | |
1432 | "" | |
2a2e3f05 | 1433 | "{ frv_emit_move (SImode, operands[0], operands[1]); DONE; }") |
36a05131 BS |
1434 | |
1435 | ;; Note - it is best to only have one movsi pattern and to handle | |
1436 | ;; all the various contingencies by the use of alternatives. This | |
839a4992 | 1437 | ;; allows reload the greatest amount of flexibility (since reload will |
0fa2e4df | 1438 | ;; only choose amongst alternatives for a selected insn, it will not |
36a05131 BS |
1439 | ;; replace the insn with another one). |
1440 | ||
1441 | ;; Unfortunately, we do have to separate out load-type moves from the rest, | |
1442 | ;; and only allow memory source operands in the former. If we do memory and | |
1443 | ;; constant loads in a single pattern, reload will be tempted to force | |
1444 | ;; constants into memory when the destination is a floating-point register. | |
1445 | ;; That may make a function use a PIC pointer when it didn't before, and we | |
1446 | ;; cannot change PIC usage (and hence stack layout) so late in the game. | |
839a4992 | 1447 | ;; The resulting sequences for loading constants into FPRs are preferable |
36a05131 BS |
1448 | ;; even when we're not generating PIC code. |
1449 | ||
6f4c062b AO |
1450 | ;; However, if we don't accept input from memory at all in the generic |
1451 | ;; movsi pattern, reloads for asm instructions that reference pseudos | |
1452 | ;; that end up assigned to memory will fail to match, because we | |
1453 | ;; recognize them right after they're emitted, and we don't | |
1454 | ;; re-recognize them again after the substitution for memory. So keep | |
1455 | ;; a memory constraint available, just make sure reload won't be | |
1456 | ;; tempted to use it. | |
2a2e3f05 AH |
1457 | ;; |
1458 | ||
1459 | ||
36a05131 BS |
1460 | (define_insn "*movsi_load" |
1461 | [(set (match_operand:SI 0 "register_operand" "=d,f") | |
1462 | (match_operand:SI 1 "frv_load_operand" "m,m"))] | |
1463 | "" | |
1464 | "* return output_move_single (operands, insn);" | |
1465 | [(set_attr "length" "4") | |
1466 | (set_attr "type" "gload,fload")]) | |
1467 | ||
34208acf | 1468 | (define_insn "*movsi_got" |
36a05131 | 1469 | [(set (match_operand:SI 0 "integer_register_operand" "=d") |
34208acf | 1470 | (match_operand:SI 1 "got12_operand" ""))] |
36a05131 | 1471 | "" |
34208acf | 1472 | "addi gr0, %1, %0" |
36a05131 BS |
1473 | [(set_attr "type" "int") |
1474 | (set_attr "length" "4")]) | |
1475 | ||
34208acf | 1476 | (define_insn "*movsi_high_got" |
36a05131 | 1477 | [(set (match_operand:SI 0 "integer_register_operand" "=d") |
34208acf | 1478 | (high:SI (match_operand:SI 1 "const_unspec_operand" "")))] |
36a05131 | 1479 | "" |
34208acf | 1480 | "sethi %1, %0" |
36a05131 BS |
1481 | [(set_attr "type" "sethi") |
1482 | (set_attr "length" "4")]) | |
1483 | ||
34208acf AO |
1484 | (define_insn "*movsi_lo_sum_got" |
1485 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
1486 | (lo_sum:SI (match_operand:SI 1 "integer_register_operand" "0") | |
1487 | (match_operand:SI 2 "const_unspec_operand" "")))] | |
36a05131 | 1488 | "" |
34208acf | 1489 | "setlo %2, %0" |
36a05131 BS |
1490 | [(set_attr "type" "setlo") |
1491 | (set_attr "length" "4")]) | |
1492 | ||
34208acf | 1493 | (define_insn "*movsi_internal" |
6f4c062b AO |
1494 | [(set (match_operand:SI 0 "move_destination_operand" "=d,d,d,m,m,z,d,d,f,f,m,?f,?z,d,f") |
1495 | (match_operand:SI 1 "move_source_operand" "L,n,d,d,O,d,z,f,d,f,f,GO,GO,!m,!m"))] | |
34208acf AO |
1496 | "register_operand (operands[0], SImode) || reg_or_0_operand (operands[1], SImode)" |
1497 | "* return output_move_single (operands, insn);" | |
6f4c062b AO |
1498 | [(set_attr "length" "4,8,4,4,4,4,4,4,4,4,4,4,4,4,4") |
1499 | (set_attr "type" "int,multi,int,gstore,gstore,spr,spr,movfg,movgf,fsconv,fstore,movgf,spr,gload,fload")]) | |
34208acf AO |
1500 | |
1501 | ;; Split 2 word load of constants into sethi/setlo instructions | |
1502 | (define_insn_and_split "*movsi_2word" | |
36a05131 | 1503 | [(set (match_operand:SI 0 "integer_register_operand" "=d") |
34208acf | 1504 | (match_operand:SI 1 "int_2word_operand" "i"))] |
36a05131 BS |
1505 | "" |
1506 | "#" | |
1507 | "reload_completed" | |
1508 | [(set (match_dup 0) | |
34208acf | 1509 | (high:SI (match_dup 1))) |
36a05131 BS |
1510 | (set (match_dup 0) |
1511 | (lo_sum:SI (match_dup 0) | |
34208acf | 1512 | (match_dup 1)))] |
36a05131 | 1513 | "" |
34208acf AO |
1514 | [(set_attr "length" "8") |
1515 | (set_attr "type" "multi")]) | |
36a05131 | 1516 | |
34208acf | 1517 | (define_insn "movsi_high" |
36a05131 | 1518 | [(set (match_operand:SI 0 "integer_register_operand" "=d") |
34208acf | 1519 | (high:SI (match_operand:SI 1 "int_2word_operand" "i")))] |
36a05131 | 1520 | "" |
34208acf | 1521 | "sethi #hi(%1), %0" |
36a05131 BS |
1522 | [(set_attr "type" "sethi") |
1523 | (set_attr "length" "4")]) | |
1524 | ||
34208acf | 1525 | (define_insn "movsi_lo_sum" |
36a05131 BS |
1526 | [(set (match_operand:SI 0 "integer_register_operand" "+d") |
1527 | (lo_sum:SI (match_dup 0) | |
34208acf | 1528 | (match_operand:SI 1 "int_2word_operand" "i")))] |
36a05131 | 1529 | "" |
34208acf | 1530 | "setlo #lo(%1), %0" |
36a05131 BS |
1531 | [(set_attr "type" "setlo") |
1532 | (set_attr "length" "4")]) | |
1533 | ||
1534 | (define_expand "movdi" | |
1535 | [(set (match_operand:DI 0 "nonimmediate_operand" "") | |
1536 | (match_operand:DI 1 "general_operand" ""))] | |
1537 | "" | |
2a2e3f05 | 1538 | "{ frv_emit_move (DImode, operands[0], operands[1]); DONE; }") |
36a05131 BS |
1539 | |
1540 | (define_insn "*movdi_double" | |
1541 | [(set (match_operand:DI 0 "move_destination_operand" "=e,?h,??d,??f,R,?R,??m,??m,e,?h,??d,??f,?e,??d,?h,??f,R,m,e,??d,e,??d,?h,??f") | |
1542 | (match_operand:DI 1 "move_source_operand" " e,h,d,f,e,h,d,f,R,R,m,m,h,f,e,d,GO,GO,GO,GO,nF,nF,GO,GO"))] | |
1543 | "TARGET_DOUBLE | |
1544 | && (register_operand (operands[0], DImode) | |
1545 | || reg_or_0_operand (operands[1], DImode))" | |
1546 | "* return output_move_double (operands, insn);" | |
1547 | [(set_attr "length" "8,4,8,8,4,4,8,8,4,4,8,8,4,8,4,8,4,8,8,8,16,16,8,8") | |
1548 | (set_attr "type" "multi,fdconv,multi,multi,gstore,fstore,gstore,fstore,gload,fload,gload,fload,movfg,movfg,movgf,movgf,gstore,gstore,multi,multi,multi,multi,movgf,movgf")]) | |
1549 | ||
1550 | (define_insn "*movdi_nodouble" | |
1551 | [(set (match_operand:DI 0 "move_destination_operand" "=e,?h,??d,??f,R,?R,??m,??m,e,?h,??d,??f,?e,??d,?h,??f,R,m,e,??d,e,??d,?h,??f") | |
1552 | (match_operand:DI 1 "move_source_operand" " e,h,d,f,e,h,d,f,R,R,m,m,h,f,e,d,GO,GO,GO,GO,nF,nF,GO,GO"))] | |
1553 | "!TARGET_DOUBLE | |
1554 | && (register_operand (operands[0], DImode) | |
1555 | || reg_or_0_operand (operands[1], DImode))" | |
1556 | "* return output_move_double (operands, insn);" | |
1557 | [(set_attr "length" "8,8,8,8,4,4,8,8,4,4,8,8,8,8,8,8,4,8,8,8,16,16,8,8") | |
1558 | (set_attr "type" "multi,multi,multi,multi,gstore,fstore,gstore,fstore,gload,fload,gload,fload,movfg,movfg,movgf,movgf,gstore,gstore,multi,multi,multi,multi,movgf,movgf")]) | |
1559 | ||
1560 | (define_split | |
1561 | [(set (match_operand:DI 0 "register_operand" "") | |
1562 | (match_operand:DI 1 "dbl_memory_two_insn_operand" ""))] | |
1563 | "reload_completed" | |
1564 | [(const_int 0)] | |
1565 | "frv_split_double_load (operands[0], operands[1]);") | |
1566 | ||
1567 | (define_split | |
1568 | [(set (match_operand:DI 0 "odd_reg_operand" "") | |
1569 | (match_operand:DI 1 "memory_operand" ""))] | |
1570 | "reload_completed" | |
1571 | [(const_int 0)] | |
1572 | "frv_split_double_load (operands[0], operands[1]);") | |
1573 | ||
1574 | (define_split | |
1575 | [(set (match_operand:DI 0 "dbl_memory_two_insn_operand" "") | |
1576 | (match_operand:DI 1 "reg_or_0_operand" ""))] | |
1577 | "reload_completed" | |
1578 | [(const_int 0)] | |
1579 | "frv_split_double_store (operands[0], operands[1]);") | |
1580 | ||
1581 | (define_split | |
1582 | [(set (match_operand:DI 0 "memory_operand" "") | |
1583 | (match_operand:DI 1 "odd_reg_operand" ""))] | |
1584 | "reload_completed" | |
1585 | [(const_int 0)] | |
1586 | "frv_split_double_store (operands[0], operands[1]);") | |
1587 | ||
1588 | (define_split | |
1589 | [(set (match_operand:DI 0 "register_operand" "") | |
1590 | (match_operand:DI 1 "register_operand" ""))] | |
1591 | "reload_completed | |
1592 | && (odd_reg_operand (operands[0], DImode) | |
1593 | || odd_reg_operand (operands[1], DImode) | |
1594 | || (integer_register_operand (operands[0], DImode) | |
1595 | && integer_register_operand (operands[1], DImode)) | |
1596 | || (!TARGET_DOUBLE | |
1597 | && fpr_operand (operands[0], DImode) | |
1598 | && fpr_operand (operands[1], DImode)))" | |
1599 | [(set (match_dup 2) (match_dup 4)) | |
1600 | (set (match_dup 3) (match_dup 5))] | |
1601 | " | |
1602 | { | |
1603 | rtx op0 = operands[0]; | |
1604 | rtx op0_low = gen_lowpart (SImode, op0); | |
1605 | rtx op0_high = gen_highpart (SImode, op0); | |
1606 | rtx op1 = operands[1]; | |
1607 | rtx op1_low = gen_lowpart (SImode, op1); | |
1608 | rtx op1_high = gen_highpart (SImode, op1); | |
1609 | ||
1610 | /* We normally copy the low-numbered register first. However, if the first | |
1611 | register operand 0 is the same as the second register of operand 1, we | |
1612 | must copy in the opposite order. */ | |
1613 | ||
1614 | if (REGNO (op0_high) == REGNO (op1_low)) | |
1615 | { | |
1616 | operands[2] = op0_low; | |
1617 | operands[3] = op0_high; | |
1618 | operands[4] = op1_low; | |
1619 | operands[5] = op1_high; | |
1620 | } | |
1621 | else | |
1622 | { | |
1623 | operands[2] = op0_high; | |
1624 | operands[3] = op0_low; | |
1625 | operands[4] = op1_high; | |
1626 | operands[5] = op1_low; | |
1627 | } | |
1628 | }") | |
1629 | ||
1630 | (define_split | |
1631 | [(set (match_operand:DI 0 "register_operand" "") | |
1632 | (match_operand:DI 1 "const_int_operand" ""))] | |
1633 | "reload_completed" | |
1634 | [(set (match_dup 2) (match_dup 4)) | |
a6cb87fb | 1635 | (set (match_dup 3) (match_dup 5))] |
36a05131 BS |
1636 | " |
1637 | { | |
1638 | rtx op0 = operands[0]; | |
1639 | rtx op1 = operands[1]; | |
1640 | ||
1641 | operands[2] = gen_highpart (SImode, op0); | |
1642 | operands[3] = gen_lowpart (SImode, op0); | |
a6cb87fb AO |
1643 | if (HOST_BITS_PER_WIDE_INT <= 32) |
1644 | { | |
1645 | operands[4] = GEN_INT ((INTVAL (op1) < 0) ? -1 : 0); | |
1646 | operands[5] = op1; | |
1647 | } | |
1648 | else | |
1649 | { | |
5c5e8419 JR |
1650 | operands[4] = gen_int_mode ((INTVAL (op1) >> 16) >> 16, SImode); |
1651 | operands[5] = gen_int_mode (INTVAL (op1), SImode); | |
a6cb87fb | 1652 | } |
36a05131 BS |
1653 | }") |
1654 | ||
1655 | (define_split | |
1656 | [(set (match_operand:DI 0 "register_operand" "") | |
1657 | (match_operand:DI 1 "const_double_operand" ""))] | |
1658 | "reload_completed" | |
1659 | [(set (match_dup 2) (match_dup 4)) | |
1660 | (set (match_dup 3) (match_dup 5))] | |
1661 | " | |
1662 | { | |
1663 | rtx op0 = operands[0]; | |
1664 | rtx op1 = operands[1]; | |
1665 | ||
1666 | operands[2] = gen_highpart (SImode, op0); | |
1667 | operands[3] = gen_lowpart (SImode, op0); | |
1668 | operands[4] = GEN_INT (CONST_DOUBLE_HIGH (op1)); | |
1669 | operands[5] = GEN_INT (CONST_DOUBLE_LOW (op1)); | |
1670 | }") | |
1671 | ||
1672 | ;; Floating Point Moves | |
1673 | ;; | |
1674 | ;; Note - Patterns for SF mode moves are compulsory, but | |
05713b80 | 1675 | ;; patterns for DF are optional, as GCC can synthesize them. |
36a05131 BS |
1676 | |
1677 | (define_expand "movsf" | |
1678 | [(set (match_operand:SF 0 "general_operand" "") | |
1679 | (match_operand:SF 1 "general_operand" ""))] | |
1680 | "" | |
2a2e3f05 | 1681 | "{ frv_emit_move (SFmode, operands[0], operands[1]); DONE; }") |
36a05131 BS |
1682 | |
1683 | (define_split | |
1684 | [(set (match_operand:SF 0 "integer_register_operand" "") | |
1685 | (match_operand:SF 1 "int_2word_operand" ""))] | |
1686 | "reload_completed" | |
1687 | [(set (match_dup 0) | |
1688 | (high:SF (match_dup 1))) | |
1689 | (set (match_dup 0) | |
1690 | (lo_sum:SF (match_dup 0) | |
1691 | (match_dup 1)))] | |
1692 | "") | |
1693 | ||
1694 | (define_insn "*movsf_load_has_fprs" | |
1695 | [(set (match_operand:SF 0 "register_operand" "=f,d") | |
1696 | (match_operand:SF 1 "frv_load_operand" "m,m"))] | |
1697 | "TARGET_HAS_FPRS" | |
1698 | "* return output_move_single (operands, insn);" | |
1699 | [(set_attr "length" "4") | |
1700 | (set_attr "type" "fload,gload")]) | |
1701 | ||
1702 | (define_insn "*movsf_internal_has_fprs" | |
1703 | [(set (match_operand:SF 0 "move_destination_operand" "=f,f,m,m,?f,?d,?d,m,?d") | |
1704 | (match_operand:SF 1 "move_source_operand" "f,OG,f,OG,d,f,d,d,F"))] | |
1705 | "TARGET_HAS_FPRS | |
1706 | && (register_operand (operands[0], SFmode) || reg_or_0_operand (operands[1], SFmode))" | |
1707 | "* return output_move_single (operands, insn);" | |
1708 | [(set_attr "length" "4,4,4,4,4,4,4,4,8") | |
1709 | (set_attr "type" "fsconv,movgf,fstore,gstore,movgf,movfg,int,gstore,multi")]) | |
1710 | ||
1711 | ;; If we don't support the double instructions, prefer gprs over fprs, since it | |
1712 | ;; will all be emulated | |
1713 | (define_insn "*movsf_internal_no_fprs" | |
1714 | [(set (match_operand:SF 0 "move_destination_operand" "=d,d,m,d,d") | |
1715 | (match_operand:SF 1 "move_source_operand" " d,OG,dOG,m,F"))] | |
1716 | "!TARGET_HAS_FPRS | |
1717 | && (register_operand (operands[0], SFmode) || reg_or_0_operand (operands[1], SFmode))" | |
1718 | "* return output_move_single (operands, insn);" | |
1719 | [(set_attr "length" "4,4,4,4,8") | |
1720 | (set_attr "type" "int,int,gstore,gload,multi")]) | |
1721 | ||
1722 | (define_insn "movsf_high" | |
1723 | [(set (match_operand:SF 0 "integer_register_operand" "=d") | |
1724 | (high:SF (match_operand:SF 1 "int_2word_operand" "i")))] | |
1725 | "" | |
1726 | "sethi #hi(%1), %0" | |
1727 | [(set_attr "type" "sethi") | |
1728 | (set_attr "length" "4")]) | |
1729 | ||
1730 | (define_insn "movsf_lo_sum" | |
1731 | [(set (match_operand:SF 0 "integer_register_operand" "+d") | |
1732 | (lo_sum:SF (match_dup 0) | |
1733 | (match_operand:SF 1 "int_2word_operand" "i")))] | |
1734 | "" | |
1735 | "setlo #lo(%1), %0" | |
1736 | [(set_attr "type" "setlo") | |
1737 | (set_attr "length" "4")]) | |
1738 | ||
1739 | (define_expand "movdf" | |
1740 | [(set (match_operand:DF 0 "nonimmediate_operand" "") | |
1741 | (match_operand:DF 1 "general_operand" ""))] | |
1742 | "" | |
2a2e3f05 | 1743 | "{ frv_emit_move (DFmode, operands[0], operands[1]); DONE; }") |
36a05131 BS |
1744 | |
1745 | (define_insn "*movdf_double" | |
34208acf AO |
1746 | [(set (match_operand:DF 0 "move_destination_operand" "=h,?e,??f,??d,R,?R,??m,??m,h,?e,??f,??d,?h,??f,?e,??d,R,m,h,??f,e,??d,e,??d") |
1747 | (match_operand:DF 1 "move_source_operand" " h,e,f,d,h,e,f,d,R,R,m,m,e,d,h,f,GO,GO,GO,GO,GO,GO,F,F"))] | |
36a05131 BS |
1748 | "TARGET_DOUBLE |
1749 | && (register_operand (operands[0], DFmode) | |
1750 | || reg_or_0_operand (operands[1], DFmode))" | |
1751 | "* return output_move_double (operands, insn);" | |
34208acf AO |
1752 | [(set_attr "length" "4,8,8,8,4,4,8,8,4,4,8,8,4,8,4,8,4,8,8,8,8,8,16,16") |
1753 | (set_attr "type" "fdconv,multi,multi,multi,fstore,gstore,fstore,gstore,fload,gload,fload,gload,movgf,movgf,movfg,movfg,gstore,gstore,movgf,movgf,multi,multi,multi,multi")]) | |
36a05131 BS |
1754 | |
1755 | ;; If we don't support the double instructions, prefer gprs over fprs, since it | |
1756 | ;; will all be emulated | |
1757 | (define_insn "*movdf_nodouble" | |
1758 | [(set (match_operand:DF 0 "move_destination_operand" "=e,?h,??d,??f,R,?R,??m,??m,e,?h,??d,??f,?e,??d,?h,??f,R,m,e,??d,e,??d,?h,??f") | |
1759 | (match_operand:DF 1 "move_source_operand" " e,h,d,f,e,h,d,f,R,R,m,m,h,f,e,d,GO,GO,GO,GO,nF,nF,GO,GO"))] | |
1760 | "!TARGET_DOUBLE | |
1761 | && (register_operand (operands[0], DFmode) | |
1762 | || reg_or_0_operand (operands[1], DFmode))" | |
1763 | "* return output_move_double (operands, insn);" | |
1764 | [(set_attr "length" "8,8,8,8,4,4,8,8,4,4,8,8,8,8,8,8,4,8,8,8,16,16,8,8") | |
1765 | (set_attr "type" "multi,multi,multi,multi,gstore,fstore,gstore,fstore,gload,fload,gload,fload,movfg,movfg,movgf,movgf,gstore,gstore,multi,multi,multi,multi,movgf,movgf")]) | |
1766 | ||
1767 | (define_split | |
1768 | [(set (match_operand:DF 0 "register_operand" "") | |
1769 | (match_operand:DF 1 "dbl_memory_two_insn_operand" ""))] | |
1770 | "reload_completed" | |
1771 | [(const_int 0)] | |
1772 | "frv_split_double_load (operands[0], operands[1]);") | |
1773 | ||
1774 | (define_split | |
1775 | [(set (match_operand:DF 0 "odd_reg_operand" "") | |
1776 | (match_operand:DF 1 "memory_operand" ""))] | |
1777 | "reload_completed" | |
1778 | [(const_int 0)] | |
1779 | "frv_split_double_load (operands[0], operands[1]);") | |
1780 | ||
1781 | (define_split | |
1782 | [(set (match_operand:DF 0 "dbl_memory_two_insn_operand" "") | |
1783 | (match_operand:DF 1 "reg_or_0_operand" ""))] | |
1784 | "reload_completed" | |
1785 | [(const_int 0)] | |
1786 | "frv_split_double_store (operands[0], operands[1]);") | |
1787 | ||
1788 | (define_split | |
1789 | [(set (match_operand:DF 0 "memory_operand" "") | |
1790 | (match_operand:DF 1 "odd_reg_operand" ""))] | |
1791 | "reload_completed" | |
1792 | [(const_int 0)] | |
1793 | "frv_split_double_store (operands[0], operands[1]);") | |
1794 | ||
1795 | (define_split | |
1796 | [(set (match_operand:DF 0 "register_operand" "") | |
1797 | (match_operand:DF 1 "register_operand" ""))] | |
1798 | "reload_completed | |
1799 | && (odd_reg_operand (operands[0], DFmode) | |
1800 | || odd_reg_operand (operands[1], DFmode) | |
1801 | || (integer_register_operand (operands[0], DFmode) | |
1802 | && integer_register_operand (operands[1], DFmode)) | |
1803 | || (!TARGET_DOUBLE | |
1804 | && fpr_operand (operands[0], DFmode) | |
1805 | && fpr_operand (operands[1], DFmode)))" | |
1806 | [(set (match_dup 2) (match_dup 4)) | |
1807 | (set (match_dup 3) (match_dup 5))] | |
1808 | " | |
1809 | { | |
1810 | rtx op0 = operands[0]; | |
1811 | rtx op0_low = gen_lowpart (SImode, op0); | |
1812 | rtx op0_high = gen_highpart (SImode, op0); | |
1813 | rtx op1 = operands[1]; | |
1814 | rtx op1_low = gen_lowpart (SImode, op1); | |
1815 | rtx op1_high = gen_highpart (SImode, op1); | |
1816 | ||
1817 | /* We normally copy the low-numbered register first. However, if the first | |
1818 | register operand 0 is the same as the second register of operand 1, we | |
1819 | must copy in the opposite order. */ | |
1820 | ||
1821 | if (REGNO (op0_high) == REGNO (op1_low)) | |
1822 | { | |
1823 | operands[2] = op0_low; | |
1824 | operands[3] = op0_high; | |
1825 | operands[4] = op1_low; | |
1826 | operands[5] = op1_high; | |
1827 | } | |
1828 | else | |
1829 | { | |
1830 | operands[2] = op0_high; | |
1831 | operands[3] = op0_low; | |
1832 | operands[4] = op1_high; | |
1833 | operands[5] = op1_low; | |
1834 | } | |
1835 | }") | |
1836 | ||
1837 | (define_split | |
1838 | [(set (match_operand:DF 0 "register_operand" "") | |
1839 | (match_operand:DF 1 "const_int_operand" ""))] | |
1840 | "reload_completed" | |
1841 | [(set (match_dup 2) (match_dup 4)) | |
a6cb87fb | 1842 | (set (match_dup 3) (match_dup 5))] |
36a05131 BS |
1843 | " |
1844 | { | |
1845 | rtx op0 = operands[0]; | |
1846 | rtx op1 = operands[1]; | |
1847 | ||
1848 | operands[2] = gen_highpart (SImode, op0); | |
1849 | operands[3] = gen_lowpart (SImode, op0); | |
a6cb87fb AO |
1850 | if (HOST_BITS_PER_WIDE_INT <= 32) |
1851 | { | |
1852 | operands[4] = GEN_INT ((INTVAL (op1) < 0) ? -1 : 0); | |
1853 | operands[5] = op1; | |
1854 | } | |
1855 | else | |
1856 | { | |
35f2d8ef NC |
1857 | operands[4] = GEN_INT (((((unsigned HOST_WIDE_INT)INTVAL (op1) >> 16) |
1858 | >> 16) ^ ((unsigned HOST_WIDE_INT)1 << 31)) | |
a6cb87fb AO |
1859 | - ((unsigned HOST_WIDE_INT)1 << 31)); |
1860 | operands[5] = GEN_INT (trunc_int_for_mode (INTVAL (op1), SImode)); | |
1861 | } | |
36a05131 BS |
1862 | }") |
1863 | ||
1864 | (define_split | |
1865 | [(set (match_operand:DF 0 "register_operand" "") | |
1866 | (match_operand:DF 1 "const_double_operand" ""))] | |
1867 | "reload_completed" | |
1868 | [(set (match_dup 2) (match_dup 4)) | |
1869 | (set (match_dup 3) (match_dup 5))] | |
1870 | " | |
1871 | { | |
1872 | rtx op0 = operands[0]; | |
1873 | rtx op1 = operands[1]; | |
36a05131 BS |
1874 | long l[2]; |
1875 | ||
34a72c33 | 1876 | REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op1), l); |
36a05131 BS |
1877 | |
1878 | operands[2] = gen_highpart (SImode, op0); | |
1879 | operands[3] = gen_lowpart (SImode, op0); | |
1880 | operands[4] = GEN_INT (l[0]); | |
1881 | operands[5] = GEN_INT (l[1]); | |
1882 | }") | |
1883 | ||
1884 | ;; String/block move insn. | |
1885 | ;; Argument 0 is the destination | |
1886 | ;; Argument 1 is the source | |
1887 | ;; Argument 2 is the length | |
1888 | ;; Argument 3 is the alignment | |
1889 | ||
76715c32 | 1890 | (define_expand "cpymemsi" |
36a05131 BS |
1891 | [(parallel [(set (match_operand:BLK 0 "" "") |
1892 | (match_operand:BLK 1 "" "")) | |
1893 | (use (match_operand:SI 2 "" "")) | |
1894 | (use (match_operand:SI 3 "" ""))])] | |
1895 | "" | |
1896 | " | |
1897 | { | |
1898 | if (frv_expand_block_move (operands)) | |
1899 | DONE; | |
1900 | else | |
1901 | FAIL; | |
1902 | }") | |
1903 | ||
57e84f18 | 1904 | ;; String/block set insn. |
36a05131 BS |
1905 | ;; Argument 0 is the destination |
1906 | ;; Argument 1 is the length | |
57e84f18 AS |
1907 | ;; Argument 2 is the byte value -- ignore any value but zero |
1908 | ;; Argument 3 is the alignment | |
36a05131 | 1909 | |
57e84f18 | 1910 | (define_expand "setmemsi" |
36a05131 | 1911 | [(parallel [(set (match_operand:BLK 0 "" "") |
57e84f18 | 1912 | (match_operand 2 "" "")) |
36a05131 | 1913 | (use (match_operand:SI 1 "" "")) |
57e84f18 | 1914 | (use (match_operand:SI 3 "" ""))])] |
36a05131 BS |
1915 | "" |
1916 | " | |
1917 | { | |
57e84f18 AS |
1918 | /* If value to set is not zero, use the library routine. */ |
1919 | if (operands[2] != const0_rtx) | |
1920 | FAIL; | |
1921 | ||
36a05131 BS |
1922 | if (frv_expand_block_clear (operands)) |
1923 | DONE; | |
1924 | else | |
1925 | FAIL; | |
1926 | }") | |
c14ff86e | 1927 | \f |
c14ff86e | 1928 | |
38c28a25 AH |
1929 | ;; The "membar" part of a __builtin_read* or __builtin_write* function. |
1930 | ;; Operand 0 is a volatile reference to the memory that the function reads | |
1931 | ;; or writes. Operand 1 is the address being accessed, or zero if the | |
1932 | ;; address isn't a known constant. Operand 2 describes the __builtin | |
1933 | ;; function (either FRV_IO_READ or FRV_IO_WRITE). | |
c14ff86e AH |
1934 | (define_insn "optional_membar_<mode>" |
1935 | [(set (match_operand:IMODE 0 "memory_operand" "=m") | |
38c28a25 AH |
1936 | (unspec:IMODE [(match_operand 1 "const_int_operand" "") |
1937 | (match_operand 2 "const_int_operand" "")] | |
1938 | UNSPEC_OPTIONAL_MEMBAR))] | |
c14ff86e AH |
1939 | "" |
1940 | "membar" | |
1941 | [(set_attr "length" "4")]) | |
36a05131 BS |
1942 | \f |
1943 | ;; :::::::::::::::::::: | |
1944 | ;; :: | |
1945 | ;; :: Reload CC registers | |
1946 | ;; :: | |
1947 | ;; :::::::::::::::::::: | |
1948 | ||
1949 | ;; Use as a define_expand so that cse/gcse/combine can't accidentally | |
1950 | ;; create movcc insns. | |
1951 | ||
1952 | (define_expand "movcc" | |
1953 | [(parallel [(set (match_operand:CC 0 "move_destination_operand" "") | |
1954 | (match_operand:CC 1 "move_source_operand" "")) | |
1955 | (clobber (match_dup 2))])] | |
1956 | "" | |
1957 | " | |
1958 | { | |
1959 | if (! reload_in_progress && ! reload_completed) | |
1960 | FAIL; | |
1961 | ||
1962 | operands[2] = gen_rtx_REG (CC_CCRmode, ICR_TEMP); | |
1963 | }") | |
1964 | ||
1965 | (define_insn "*internal_movcc" | |
1966 | [(set (match_operand:CC 0 "move_destination_operand" "=t,d,d,m,d") | |
1967 | (match_operand:CC 1 "move_source_operand" "d,d,m,d,t")) | |
1968 | (clobber (match_scratch:CC_CCR 2 "=X,X,X,X,&v"))] | |
1969 | "reload_in_progress || reload_completed" | |
1970 | "@ | |
1971 | cmpi %1, #0, %0 | |
1972 | mov %1, %0 | |
1973 | ld%I1%U1 %M1, %0 | |
1974 | st%I0%U0 %1, %M0 | |
1975 | #" | |
1976 | [(set_attr "length" "4,4,4,4,20") | |
1977 | (set_attr "type" "int,int,gload,gstore,multi")]) | |
1978 | ||
1979 | ;; To move an ICC value to a GPR for a signed comparison, we create a value | |
1980 | ;; that when compared to 0, sets the N and Z flags appropriately (we don't care | |
1981 | ;; about the V and C flags, since these comparisons are signed). | |
1982 | ||
1983 | (define_split | |
1984 | [(set (match_operand:CC 0 "integer_register_operand" "") | |
1985 | (match_operand:CC 1 "icc_operand" "")) | |
1986 | (clobber (match_operand:CC_CCR 2 "icr_operand" ""))] | |
1987 | "reload_in_progress || reload_completed" | |
1988 | [(match_dup 3)] | |
1989 | " | |
1990 | { | |
1991 | rtx dest = simplify_gen_subreg (SImode, operands[0], CCmode, 0); | |
1992 | rtx icc = operands[1]; | |
1993 | rtx icr = operands[2]; | |
1994 | ||
1995 | start_sequence (); | |
1996 | ||
f7df4a84 | 1997 | emit_insn (gen_rtx_SET (icr, gen_rtx_LT (CC_CCRmode, icc, const0_rtx))); |
36a05131 BS |
1998 | |
1999 | emit_insn (gen_movsi (dest, const1_rtx)); | |
2000 | ||
2001 | emit_insn (gen_rtx_COND_EXEC (VOIDmode, | |
2002 | gen_rtx_NE (CC_CCRmode, icr, const0_rtx), | |
f7df4a84 | 2003 | gen_rtx_SET (dest, |
36a05131 BS |
2004 | gen_rtx_NEG (SImode, dest)))); |
2005 | ||
f7df4a84 | 2006 | emit_insn (gen_rtx_SET (icr, gen_rtx_EQ (CC_CCRmode, icc, const0_rtx))); |
36a05131 BS |
2007 | |
2008 | emit_insn (gen_rtx_COND_EXEC (VOIDmode, | |
2009 | gen_rtx_NE (CC_CCRmode, icr, const0_rtx), | |
f7df4a84 | 2010 | gen_rtx_SET (dest, const0_rtx))); |
36a05131 BS |
2011 | |
2012 | operands[3] = get_insns (); | |
2013 | end_sequence (); | |
2014 | }") | |
2015 | ||
36a05131 BS |
2016 | ;; Reload CC_UNSmode for unsigned integer comparisons |
2017 | ;; Use define_expand so that cse/gcse/combine can't create movcc_uns insns | |
2018 | ||
2019 | (define_expand "movcc_uns" | |
2020 | [(parallel [(set (match_operand:CC_UNS 0 "move_destination_operand" "") | |
2021 | (match_operand:CC_UNS 1 "move_source_operand" "")) | |
2022 | (clobber (match_dup 2))])] | |
2023 | "" | |
2024 | " | |
2025 | { | |
2026 | if (! reload_in_progress && ! reload_completed) | |
2027 | FAIL; | |
2028 | operands[2] = gen_rtx_REG (CC_CCRmode, ICR_TEMP); | |
2029 | }") | |
2030 | ||
2031 | (define_insn "*internal_movcc_uns" | |
2032 | [(set (match_operand:CC_UNS 0 "move_destination_operand" "=t,d,d,m,d") | |
2033 | (match_operand:CC_UNS 1 "move_source_operand" "d,d,m,d,t")) | |
2034 | (clobber (match_scratch:CC_CCR 2 "=X,X,X,X,&v"))] | |
2035 | "reload_in_progress || reload_completed" | |
2036 | "@ | |
2037 | cmpi %1, #1, %0 | |
2038 | mov %1, %0 | |
2039 | ld%I1%U1 %M1, %0 | |
2040 | st%I0%U0 %1, %M0 | |
2041 | #" | |
2042 | [(set_attr "length" "4,4,4,4,20") | |
2043 | (set_attr "type" "int,int,gload,gstore,multi")]) | |
2044 | ||
2045 | ;; To move an ICC value to a GPR for an unsigned comparison, we create a value | |
2046 | ;; that when compared to 1, sets the Z, V, and C flags appropriately (we don't | |
2047 | ;; care about the N flag, since these comparisons are unsigned). | |
2048 | ||
2049 | (define_split | |
2050 | [(set (match_operand:CC_UNS 0 "integer_register_operand" "") | |
2051 | (match_operand:CC_UNS 1 "icc_operand" "")) | |
2052 | (clobber (match_operand:CC_CCR 2 "icr_operand" ""))] | |
2053 | "reload_in_progress || reload_completed" | |
2054 | [(match_dup 3)] | |
2055 | " | |
2056 | { | |
2057 | rtx dest = simplify_gen_subreg (SImode, operands[0], CC_UNSmode, 0); | |
2058 | rtx icc = operands[1]; | |
2059 | rtx icr = operands[2]; | |
2060 | ||
2061 | start_sequence (); | |
2062 | ||
f7df4a84 | 2063 | emit_insn (gen_rtx_SET (icr, gen_rtx_GTU (CC_CCRmode, icc, const0_rtx))); |
36a05131 BS |
2064 | |
2065 | emit_insn (gen_movsi (dest, const1_rtx)); | |
2066 | ||
2067 | emit_insn (gen_rtx_COND_EXEC (VOIDmode, | |
2068 | gen_rtx_NE (CC_CCRmode, icr, const0_rtx), | |
2069 | gen_addsi3 (dest, dest, dest))); | |
2070 | ||
f7df4a84 | 2071 | emit_insn (gen_rtx_SET (icr, gen_rtx_LTU (CC_CCRmode, icc, const0_rtx))); |
36a05131 BS |
2072 | |
2073 | emit_insn (gen_rtx_COND_EXEC (VOIDmode, | |
2074 | gen_rtx_NE (CC_CCRmode, icr, const0_rtx), | |
f7df4a84 | 2075 | gen_rtx_SET (dest, const0_rtx))); |
36a05131 BS |
2076 | |
2077 | operands[3] = get_insns (); | |
2078 | end_sequence (); | |
2079 | }") | |
2080 | ||
036ff63f RS |
2081 | ;; Reload CC_NZmode. This is mostly the same as the CCmode and CC_UNSmode |
2082 | ;; handling, but it uses different sequences for moving between GPRs and ICCs. | |
2083 | ||
2084 | (define_expand "movcc_nz" | |
2085 | [(parallel [(set (match_operand:CC_NZ 0 "move_destination_operand" "") | |
2086 | (match_operand:CC_NZ 1 "move_source_operand" "")) | |
2087 | (clobber (match_dup 2))])] | |
2088 | "" | |
2089 | " | |
2090 | { | |
2091 | if (!reload_in_progress && !reload_completed) | |
2092 | FAIL; | |
2093 | operands[2] = gen_rtx_REG (CC_CCRmode, ICR_TEMP); | |
2094 | }") | |
2095 | ||
2096 | (define_insn "*internal_movcc_nz" | |
2097 | [(set (match_operand:CC_NZ 0 "move_destination_operand" "=t,d,d,m,d") | |
2098 | (match_operand:CC_NZ 1 "move_source_operand" "d,d,m,d,t")) | |
2099 | (clobber (match_scratch:CC_CCR 2 "=X,X,X,X,&v"))] | |
2100 | "reload_in_progress || reload_completed" | |
2101 | "@ | |
2102 | cmpi %1, #0, %0 | |
2103 | mov %1, %0 | |
2104 | ld%I1%U1 %M1, %0 | |
2105 | st%I0%U0 %1, %M0 | |
2106 | #" | |
2107 | [(set_attr "length" "4,4,4,4,20") | |
2108 | (set_attr "type" "int,int,gload,gstore,multi")]) | |
2109 | ||
2110 | ;; Set the destination to a value that, when compared with zero, will | |
2111 | ;; restore the value of the Z and N flags. The values of the other | |
2112 | ;; flags don't matter. The sequence is: | |
2113 | ;; | |
2114 | ;; setlos op0,#-1 | |
2115 | ;; ckp op1,op2 | |
2116 | ;; csub gr0,op0,op0,op2 | |
2117 | ;; ckeq op1,op2 | |
2118 | ;; cmov gr0,op0,op2 | |
2119 | (define_split | |
2120 | [(set (match_operand:CC_NZ 0 "integer_register_operand" "") | |
2121 | (match_operand:CC_NZ 1 "icc_operand" "")) | |
2122 | (clobber (match_operand:CC_CCR 2 "icr_operand" ""))] | |
2123 | "reload_in_progress || reload_completed" | |
2124 | [(set (match_dup 3) | |
2125 | (const_int -1)) | |
2126 | (set (match_dup 2) | |
2127 | (ge:CC_CCR (match_dup 1) | |
2128 | (const_int 0))) | |
2129 | (cond_exec (ne:CC_CCR (match_dup 2) | |
2130 | (const_int 0)) | |
2131 | (set (match_dup 3) | |
2132 | (neg:SI (match_dup 3)))) | |
2133 | (set (match_dup 2) | |
2134 | (eq:CC_CCR (match_dup 1) | |
2135 | (const_int 0))) | |
2136 | (cond_exec (ne:CC_CCR (match_dup 2) | |
2137 | (const_int 0)) | |
2138 | (set (match_dup 3) (const_int 0)))] | |
2139 | "operands[3] = simplify_gen_subreg (SImode, operands[0], CC_NZmode, 0);") | |
2140 | ||
36a05131 BS |
2141 | ;; Reload CC_FPmode for floating point comparisons |
2142 | ;; We use a define_expand here so that cse/gcse/combine can't accidentally | |
2143 | ;; create movcc insns. If this was a named define_insn, we would not be able | |
2144 | ;; to make it conditional on reload. | |
2145 | ||
2146 | (define_expand "movcc_fp" | |
7b150713 | 2147 | [(set (match_operand:CC_FP 0 "movcc_fp_destination_operand" "") |
36a05131 BS |
2148 | (match_operand:CC_FP 1 "move_source_operand" ""))] |
2149 | "TARGET_HAS_FPRS" | |
2150 | " | |
2151 | { | |
2152 | if (! reload_in_progress && ! reload_completed) | |
2153 | FAIL; | |
2154 | }") | |
2155 | ||
2156 | (define_insn "*movcc_fp_internal" | |
7b150713 | 2157 | [(set (match_operand:CC_FP 0 "movcc_fp_destination_operand" "=d,d,d,m") |
36a05131 BS |
2158 | (match_operand:CC_FP 1 "move_source_operand" "u,d,m,d"))] |
2159 | "TARGET_HAS_FPRS && (reload_in_progress || reload_completed)" | |
2160 | "@ | |
2161 | # | |
2162 | mov %1, %0 | |
2163 | ld%I1%U1 %M1, %0 | |
2164 | st%I0%U0 %1, %M0" | |
2165 | [(set_attr "length" "12,4,4,4") | |
2166 | (set_attr "type" "multi,int,gload,gstore")]) | |
2167 | ||
2168 | ||
2169 | (define_expand "reload_incc_fp" | |
2170 | [(match_operand:CC_FP 0 "fcc_operand" "=u") | |
7b150713 | 2171 | (match_operand:CC_FP 1 "gpr_or_memory_operand_with_scratch" "m") |
36a05131 BS |
2172 | (match_operand:TI 2 "integer_register_operand" "=&d")] |
2173 | "TARGET_HAS_FPRS" | |
2174 | " | |
2175 | { | |
2176 | rtx cc_op2 = simplify_gen_subreg (CC_FPmode, operands[2], TImode, 0); | |
2177 | rtx int_op2 = simplify_gen_subreg (SImode, operands[2], TImode, 0); | |
2178 | rtx temp1 = simplify_gen_subreg (SImode, operands[2], TImode, 4); | |
2179 | rtx temp2 = simplify_gen_subreg (SImode, operands[2], TImode, 8); | |
2180 | int shift = CC_SHIFT_RIGHT (REGNO (operands[0])); | |
2181 | HOST_WIDE_INT mask; | |
2182 | ||
7b150713 AO |
2183 | if (!gpr_or_memory_operand (operands[1], CC_FPmode)) |
2184 | { | |
2185 | rtx addr; | |
2186 | rtx temp3 = simplify_gen_subreg (SImode, operands[2], TImode, 12); | |
2187 | ||
44e91694 | 2188 | gcc_assert (GET_CODE (operands[1]) == MEM); |
7b150713 AO |
2189 | |
2190 | addr = XEXP (operands[1], 0); | |
2191 | ||
44e91694 | 2192 | gcc_assert (GET_CODE (addr) == PLUS); |
7b150713 AO |
2193 | |
2194 | emit_move_insn (temp3, XEXP (addr, 1)); | |
2195 | ||
2196 | operands[1] = replace_equiv_address (operands[1], | |
2197 | gen_rtx_PLUS (GET_MODE (addr), | |
2198 | XEXP (addr, 0), | |
2199 | temp3)); | |
2200 | } | |
2201 | ||
36a05131 BS |
2202 | emit_insn (gen_movcc_fp (cc_op2, operands[1])); |
2203 | if (shift) | |
2204 | emit_insn (gen_ashlsi3 (int_op2, int_op2, GEN_INT (shift))); | |
2205 | ||
2206 | mask = ~ ((HOST_WIDE_INT)CC_MASK << shift); | |
2207 | emit_insn (gen_movsi (temp1, GEN_INT (mask))); | |
2208 | emit_insn (gen_update_fcc (operands[0], int_op2, temp1, temp2)); | |
2209 | DONE; | |
2210 | }") | |
2211 | ||
2212 | (define_expand "reload_outcc_fp" | |
2213 | [(set (match_operand:CC_FP 2 "integer_register_operand" "=&d") | |
2214 | (match_operand:CC_FP 1 "fcc_operand" "u")) | |
2215 | (set (match_operand:CC_FP 0 "memory_operand" "=m") | |
2216 | (match_dup 2))] | |
2217 | "TARGET_HAS_FPRS" | |
2218 | "") | |
2219 | ||
2220 | ;; Convert a FCC value to gpr | |
2221 | (define_insn "read_fcc" | |
2222 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
2223 | (unspec:SI [(match_operand:CC_FP 1 "fcc_operand" "u")] | |
2224 | UNSPEC_CC_TO_GPR))] | |
2225 | "TARGET_HAS_FPRS" | |
2226 | "movsg ccr, %0" | |
2227 | [(set_attr "type" "spr") | |
2228 | (set_attr "length" "4")]) | |
2229 | ||
2230 | (define_split | |
2231 | [(set (match_operand:CC_FP 0 "integer_register_operand" "") | |
2232 | (match_operand:CC_FP 1 "fcc_operand" ""))] | |
2233 | "reload_completed && TARGET_HAS_FPRS" | |
2234 | [(match_dup 2)] | |
2235 | " | |
2236 | { | |
2237 | rtx int_op0 = simplify_gen_subreg (SImode, operands[0], CC_FPmode, 0); | |
2238 | int shift = CC_SHIFT_RIGHT (REGNO (operands[1])); | |
2239 | ||
2240 | start_sequence (); | |
2241 | ||
2242 | emit_insn (gen_read_fcc (int_op0, operands[1])); | |
2243 | if (shift) | |
2244 | emit_insn (gen_lshrsi3 (int_op0, int_op0, GEN_INT (shift))); | |
2245 | ||
2246 | emit_insn (gen_andsi3 (int_op0, int_op0, GEN_INT (CC_MASK))); | |
2247 | ||
2248 | operands[2] = get_insns (); | |
2249 | end_sequence (); | |
2250 | }") | |
2251 | ||
2252 | ;; Move a gpr value to FCC. | |
2253 | ;; Operand0 = FCC | |
2254 | ;; Operand1 = reloaded value shifted appropriately | |
2255 | ;; Operand2 = mask to eliminate current register | |
2256 | ;; Operand3 = temporary to load/store ccr | |
2257 | (define_insn "update_fcc" | |
2258 | [(set (match_operand:CC_FP 0 "fcc_operand" "=u") | |
2259 | (unspec:CC_FP [(match_operand:SI 1 "integer_register_operand" "d") | |
2260 | (match_operand:SI 2 "integer_register_operand" "d")] | |
2261 | UNSPEC_GPR_TO_CC)) | |
2262 | (clobber (match_operand:SI 3 "integer_register_operand" "=&d"))] | |
2263 | "TARGET_HAS_FPRS" | |
2264 | "movsg ccr, %3\;and %2, %3, %3\;or %1, %3, %3\;movgs %3, ccr" | |
2265 | [(set_attr "type" "multi") | |
2266 | (set_attr "length" "16")]) | |
2267 | ||
2268 | ;; Reload CC_CCRmode for conditional execution registers | |
2269 | (define_insn "movcc_ccr" | |
2270 | [(set (match_operand:CC_CCR 0 "move_destination_operand" "=d,d,d,m,v,?w,C,d") | |
2271 | (match_operand:CC_CCR 1 "move_source_operand" "C,d,m,d,n,n,C,L"))] | |
2272 | "" | |
2273 | "@ | |
2274 | # | |
2275 | mov %1, %0 | |
2276 | ld%I1%U1 %M1, %0 | |
2277 | st%I0%U0 %1, %M0 | |
2278 | # | |
2279 | # | |
2280 | orcr %1, %1, %0 | |
2281 | setlos #%1, %0" | |
2282 | [(set_attr "length" "8,4,4,4,8,12,4,4") | |
2283 | (set_attr "type" "multi,int,gload,gstore,multi,multi,ccr,int")]) | |
2284 | ||
2285 | (define_expand "reload_incc_ccr" | |
2286 | [(match_operand:CC_CCR 0 "cr_operand" "=C") | |
2287 | (match_operand:CC_CCR 1 "memory_operand" "m") | |
2288 | (match_operand:CC_CCR 2 "integer_register_operand" "=&d")] | |
2289 | "" | |
2290 | " | |
2291 | { | |
2292 | rtx icc = gen_rtx_REG (CCmode, ICC_TEMP); | |
2293 | rtx int_op2 = simplify_gen_subreg (SImode, operands[2], CC_CCRmode, 0); | |
2294 | rtx icr = (ICR_P (REGNO (operands[0])) | |
2295 | ? operands[0] : gen_rtx_REG (CC_CCRmode, ICR_TEMP)); | |
2296 | ||
2297 | emit_insn (gen_movcc_ccr (operands[2], operands[1])); | |
2298 | emit_insn (gen_cmpsi_cc (icc, int_op2, const0_rtx)); | |
2299 | emit_insn (gen_movcc_ccr (icr, gen_rtx_NE (CC_CCRmode, icc, const0_rtx))); | |
2300 | ||
2301 | if (! ICR_P (REGNO (operands[0]))) | |
2302 | emit_insn (gen_movcc_ccr (operands[0], icr)); | |
2303 | ||
2304 | DONE; | |
2305 | }") | |
2306 | ||
2307 | (define_expand "reload_outcc_ccr" | |
2308 | [(set (match_operand:CC_CCR 2 "integer_register_operand" "=&d") | |
2309 | (match_operand:CC_CCR 1 "cr_operand" "C")) | |
2310 | (set (match_operand:CC_CCR 0 "memory_operand" "=m") | |
2311 | (match_dup 2))] | |
2312 | "" | |
2313 | "") | |
2314 | ||
2315 | (define_split | |
2316 | [(set (match_operand:CC_CCR 0 "integer_register_operand" "") | |
2317 | (match_operand:CC_CCR 1 "cr_operand" ""))] | |
2318 | "reload_completed" | |
2319 | [(match_dup 2)] | |
2320 | " | |
2321 | { | |
2322 | rtx int_op0 = simplify_gen_subreg (SImode, operands[0], CC_CCRmode, 0); | |
2323 | ||
2324 | start_sequence (); | |
2325 | emit_move_insn (operands[0], const1_rtx); | |
2326 | emit_insn (gen_rtx_COND_EXEC (VOIDmode, | |
2327 | gen_rtx_EQ (CC_CCRmode, | |
2328 | operands[1], | |
2329 | const0_rtx), | |
f7df4a84 | 2330 | gen_rtx_SET (int_op0, const0_rtx))); |
36a05131 BS |
2331 | |
2332 | operands[2] = get_insns (); | |
2333 | end_sequence (); | |
2334 | }") | |
2335 | ||
2336 | (define_split | |
2337 | [(set (match_operand:CC_CCR 0 "cr_operand" "") | |
2338 | (match_operand:CC_CCR 1 "const_int_operand" ""))] | |
2339 | "reload_completed" | |
2340 | [(match_dup 2)] | |
2341 | " | |
2342 | { | |
2343 | rtx icc = gen_rtx_REG (CCmode, ICC_TEMP); | |
2344 | rtx r0 = gen_rtx_REG (SImode, GPR_FIRST); | |
2345 | rtx icr = (ICR_P (REGNO (operands[0])) | |
2346 | ? operands[0] : gen_rtx_REG (CC_CCRmode, ICR_TEMP)); | |
2347 | ||
2348 | start_sequence (); | |
2349 | ||
2350 | emit_insn (gen_cmpsi_cc (icc, r0, const0_rtx)); | |
2351 | ||
2352 | emit_insn (gen_movcc_ccr (icr, | |
2353 | gen_rtx_fmt_ee (((INTVAL (operands[1]) == 0) | |
2354 | ? EQ : NE), CC_CCRmode, | |
2355 | r0, const0_rtx))); | |
2356 | ||
2357 | if (! ICR_P (REGNO (operands[0]))) | |
2358 | emit_insn (gen_movcc_ccr (operands[0], icr)); | |
2359 | ||
2360 | operands[2] = get_insns (); | |
2361 | end_sequence (); | |
2362 | }") | |
2363 | ||
2364 | \f | |
2365 | ;; :::::::::::::::::::: | |
2366 | ;; :: | |
2367 | ;; :: Conversions | |
2368 | ;; :: | |
2369 | ;; :::::::::::::::::::: | |
2370 | ||
2371 | ;; Signed conversions from a smaller integer to a larger integer | |
2372 | ;; | |
2373 | ;; These operations are optional. If they are not | |
05713b80 | 2374 | ;; present GCC will synthesize them for itself |
36a05131 BS |
2375 | ;; Even though frv does not provide these instructions, we define them |
2376 | ;; to allow load + sign extend to be collapsed together | |
2377 | (define_insn "extendqihi2" | |
2378 | [(set (match_operand:HI 0 "integer_register_operand" "=d,d") | |
2379 | (sign_extend:HI (match_operand:QI 1 "gpr_or_memory_operand" "d,m")))] | |
2380 | "" | |
2381 | "@ | |
2382 | # | |
2383 | ldsb%I1%U1 %M1,%0" | |
2384 | [(set_attr "length" "8,4") | |
2385 | (set_attr "type" "multi,gload")]) | |
2386 | ||
2387 | (define_split | |
2388 | [(set (match_operand:HI 0 "integer_register_operand" "") | |
2389 | (sign_extend:HI (match_operand:QI 1 "integer_register_operand" "")))] | |
2390 | "reload_completed" | |
2391 | [(match_dup 2) | |
2392 | (match_dup 3)] | |
2393 | " | |
2394 | { | |
2395 | rtx op0 = gen_lowpart (SImode, operands[0]); | |
2396 | rtx op1 = gen_lowpart (SImode, operands[1]); | |
2397 | rtx shift = GEN_INT (24); | |
2398 | ||
2399 | operands[2] = gen_ashlsi3 (op0, op1, shift); | |
2400 | operands[3] = gen_ashrsi3 (op0, op0, shift); | |
2401 | }") | |
2402 | ||
2403 | (define_insn "extendqisi2" | |
2404 | [(set (match_operand:SI 0 "integer_register_operand" "=d,d") | |
2405 | (sign_extend:SI (match_operand:QI 1 "gpr_or_memory_operand" "d,m")))] | |
2406 | "" | |
2407 | "@ | |
2408 | # | |
2409 | ldsb%I1%U1 %M1,%0" | |
2410 | [(set_attr "length" "8,4") | |
2411 | (set_attr "type" "multi,gload")]) | |
2412 | ||
2413 | (define_split | |
2414 | [(set (match_operand:SI 0 "integer_register_operand" "") | |
2415 | (sign_extend:SI (match_operand:QI 1 "integer_register_operand" "")))] | |
2416 | "reload_completed" | |
2417 | [(match_dup 2) | |
2418 | (match_dup 3)] | |
2419 | " | |
2420 | { | |
2421 | rtx op0 = gen_lowpart (SImode, operands[0]); | |
2422 | rtx op1 = gen_lowpart (SImode, operands[1]); | |
2423 | rtx shift = GEN_INT (24); | |
2424 | ||
2425 | operands[2] = gen_ashlsi3 (op0, op1, shift); | |
2426 | operands[3] = gen_ashrsi3 (op0, op0, shift); | |
2427 | }") | |
2428 | ||
2429 | ;;(define_insn "extendqidi2" | |
2430 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2431 | ;; (sign_extend:DI (match_operand:QI 1 "general_operand" "g")))] | |
2432 | ;; "" | |
2433 | ;; "extendqihi2 %0,%1" | |
2434 | ;; [(set_attr "length" "4")]) | |
2435 | ||
2436 | (define_insn "extendhisi2" | |
2437 | [(set (match_operand:SI 0 "integer_register_operand" "=d,d") | |
2438 | (sign_extend:SI (match_operand:HI 1 "gpr_or_memory_operand" "d,m")))] | |
2439 | "" | |
2440 | "@ | |
2441 | # | |
2442 | ldsh%I1%U1 %M1,%0" | |
2443 | [(set_attr "length" "8,4") | |
2444 | (set_attr "type" "multi,gload")]) | |
2445 | ||
2446 | (define_split | |
2447 | [(set (match_operand:SI 0 "integer_register_operand" "") | |
2448 | (sign_extend:SI (match_operand:HI 1 "integer_register_operand" "")))] | |
2449 | "reload_completed" | |
2450 | [(match_dup 2) | |
2451 | (match_dup 3)] | |
2452 | " | |
2453 | { | |
2454 | rtx op0 = gen_lowpart (SImode, operands[0]); | |
2455 | rtx op1 = gen_lowpart (SImode, operands[1]); | |
2456 | rtx shift = GEN_INT (16); | |
2457 | ||
2458 | operands[2] = gen_ashlsi3 (op0, op1, shift); | |
2459 | operands[3] = gen_ashrsi3 (op0, op0, shift); | |
2460 | }") | |
2461 | ||
2462 | ;;(define_insn "extendhidi2" | |
2463 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2464 | ;; (sign_extend:DI (match_operand:HI 1 "general_operand" "g")))] | |
2465 | ;; "" | |
2466 | ;; "extendhihi2 %0,%1" | |
2467 | ;; [(set_attr "length" "4")]) | |
2468 | ;; | |
2469 | ;;(define_insn "extendsidi2" | |
2470 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2471 | ;; (sign_extend:DI (match_operand:SI 1 "general_operand" "g")))] | |
2472 | ;; "" | |
2473 | ;; "extendsidi2 %0,%1" | |
2474 | ;; [(set_attr "length" "4")]) | |
2475 | ||
2476 | ;; Unsigned conversions from a smaller integer to a larger integer | |
2477 | (define_insn "zero_extendqihi2" | |
2478 | [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d") | |
2479 | (zero_extend:HI | |
2480 | (match_operand:QI 1 "gpr_or_memory_operand" "d,L,m")))] | |
2481 | "" | |
2482 | "@ | |
2483 | andi %1,#0xff,%0 | |
2484 | setlos %1,%0 | |
2485 | ldub%I1%U1 %M1,%0" | |
2486 | [(set_attr "length" "4") | |
2487 | (set_attr "type" "int,int,gload")]) | |
2488 | ||
2489 | (define_insn "zero_extendqisi2" | |
2490 | [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d") | |
2491 | (zero_extend:SI | |
2492 | (match_operand:QI 1 "gpr_or_memory_operand" "d,L,m")))] | |
2493 | "" | |
2494 | "@ | |
2495 | andi %1,#0xff,%0 | |
2496 | setlos %1,%0 | |
2497 | ldub%I1%U1 %M1,%0" | |
2498 | [(set_attr "length" "4") | |
2499 | (set_attr "type" "int,int,gload")]) | |
2500 | ||
2501 | ;;(define_insn "zero_extendqidi2" | |
2502 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2503 | ;; (zero_extend:DI (match_operand:QI 1 "general_operand" "g")))] | |
2504 | ;; "" | |
2505 | ;; "zero_extendqihi2 %0,%1" | |
2506 | ;; [(set_attr "length" "4")]) | |
2507 | ||
2508 | ;; Do not set the type for the sethi to "sethi", since the scheduler will think | |
2509 | ;; the sethi takes 0 cycles as part of allowing sethi/setlo to be in the same | |
2510 | ;; VLIW instruction. | |
2511 | (define_insn "zero_extendhisi2" | |
2512 | [(set (match_operand:SI 0 "integer_register_operand" "=d,d") | |
2513 | (zero_extend:SI (match_operand:HI 1 "gpr_or_memory_operand" "0,m")))] | |
2514 | "" | |
2515 | "@ | |
2516 | sethi #hi(#0),%0 | |
2517 | lduh%I1%U1 %M1,%0" | |
2518 | [(set_attr "length" "4") | |
2519 | (set_attr "type" "int,gload")]) | |
2520 | ||
2521 | ;;(define_insn "zero_extendhidi2" | |
2522 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2523 | ;; (zero_extend:DI (match_operand:HI 1 "general_operand" "g")))] | |
2524 | ;; "" | |
2525 | ;; "zero_extendhihi2 %0,%1" | |
2526 | ;; [(set_attr "length" "4")]) | |
2527 | ;; | |
2528 | ;;(define_insn "zero_extendsidi2" | |
2529 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2530 | ;; (zero_extend:DI (match_operand:SI 1 "general_operand" "g")))] | |
2531 | ;; "" | |
2532 | ;; "zero_extendsidi2 %0,%1" | |
2533 | ;; [(set_attr "length" "4")]) | |
2534 | ;; | |
2535 | ;;;; Convert between floating point types of different sizes. | |
2536 | ;; | |
2537 | ;;(define_insn "extendsfdf2" | |
2538 | ;; [(set (match_operand:DF 0 "register_operand" "=r") | |
2539 | ;; (float_extend:DF (match_operand:SF 1 "register_operand" "r")))] | |
2540 | ;; "" | |
2541 | ;; "extendsfdf2 %0,%1" | |
2542 | ;; [(set_attr "length" "4")]) | |
2543 | ;; | |
2544 | ;;(define_insn "truncdfsf2" | |
2545 | ;; [(set (match_operand:SF 0 "register_operand" "=r") | |
2546 | ;; (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))] | |
2547 | ;; "" | |
2548 | ;; "truncdfsf2 %0,%1" | |
2549 | ;; [(set_attr "length" "4")]) | |
2550 | ||
2551 | ;;;; Convert between signed integer types and floating point. | |
2552 | (define_insn "floatsisf2" | |
2553 | [(set (match_operand:SF 0 "fpr_operand" "=f") | |
2554 | (float:SF (match_operand:SI 1 "fpr_operand" "f")))] | |
2555 | "TARGET_HARD_FLOAT" | |
2556 | "fitos %1,%0" | |
2557 | [(set_attr "length" "4") | |
2558 | (set_attr "type" "fsconv")]) | |
2559 | ||
2560 | (define_insn "floatsidf2" | |
2561 | [(set (match_operand:DF 0 "fpr_operand" "=h") | |
2562 | (float:DF (match_operand:SI 1 "fpr_operand" "f")))] | |
2563 | "TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
2564 | "fitod %1,%0" | |
2565 | [(set_attr "length" "4") | |
2566 | (set_attr "type" "fdconv")]) | |
2567 | ||
2568 | ;;(define_insn "floatdisf2" | |
2569 | ;; [(set (match_operand:SF 0 "register_operand" "=r") | |
2570 | ;; (float:SF (match_operand:DI 1 "register_operand" "r")))] | |
2571 | ;; "" | |
2572 | ;; "floatdisf2 %0,%1" | |
2573 | ;; [(set_attr "length" "4")]) | |
2574 | ;; | |
2575 | ;;(define_insn "floatdidf2" | |
2576 | ;; [(set (match_operand:DF 0 "register_operand" "=r") | |
2577 | ;; (float:DF (match_operand:DI 1 "register_operand" "r")))] | |
2578 | ;; "" | |
2579 | ;; "floatdidf2 %0,%1" | |
2580 | ;; [(set_attr "length" "4")]) | |
2581 | ||
2582 | (define_insn "fix_truncsfsi2" | |
2583 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
2584 | (fix:SI (match_operand:SF 1 "fpr_operand" "f")))] | |
2585 | "TARGET_HARD_FLOAT" | |
2586 | "fstoi %1,%0" | |
2587 | [(set_attr "length" "4") | |
2588 | (set_attr "type" "fsconv")]) | |
2589 | ||
2590 | (define_insn "fix_truncdfsi2" | |
2591 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
2592 | (fix:SI (match_operand:DF 1 "fpr_operand" "h")))] | |
2593 | "TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
2594 | "fdtoi %1,%0" | |
2595 | [(set_attr "length" "4") | |
2596 | (set_attr "type" "fdconv")]) | |
2597 | ||
2598 | ;;(define_insn "fix_truncsfdi2" | |
2599 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2600 | ;; (fix:DI (match_operand:SF 1 "register_operand" "r")))] | |
2601 | ;; "" | |
2602 | ;; "fix_truncsfdi2 %0,%1" | |
2603 | ;; [(set_attr "length" "4")]) | |
2604 | ;; | |
2605 | ;;(define_insn "fix_truncdfdi2" | |
2606 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2607 | ;; (fix:DI (match_operand:DF 1 "register_operand" "r")))] | |
2608 | ;; "" | |
2609 | ;; "fix_truncdfdi2 %0,%1" | |
2610 | ;; [(set_attr "length" "4")]) | |
2611 | ;; | |
2612 | ;;;; Convert between unsigned integer types and floating point. | |
2613 | ;; | |
2614 | ;;(define_insn "floatunssisf2" | |
2615 | ;; [(set (match_operand:SF 0 "register_operand" "=r") | |
2616 | ;; (unsigned_float:SF (match_operand:SI 1 "register_operand" "r")))] | |
2617 | ;; "" | |
2618 | ;; "floatunssisf2 %0,%1" | |
2619 | ;; [(set_attr "length" "4")]) | |
2620 | ;; | |
2621 | ;;(define_insn "floatunssidf2" | |
2622 | ;; [(set (match_operand:DF 0 "register_operand" "=r") | |
2623 | ;; (unsigned_float:DF (match_operand:SI 1 "register_operand" "r")))] | |
2624 | ;; "" | |
2625 | ;; "floatunssidf2 %0,%1" | |
2626 | ;; [(set_attr "length" "4")]) | |
2627 | ;; | |
2628 | ;;(define_insn "floatunsdisf2" | |
2629 | ;; [(set (match_operand:SF 0 "register_operand" "=r") | |
2630 | ;; (unsigned_float:SF (match_operand:DI 1 "register_operand" "r")))] | |
2631 | ;; "" | |
2632 | ;; "floatunsdisf2 %0,%1" | |
2633 | ;; [(set_attr "length" "4")]) | |
2634 | ;; | |
2635 | ;;(define_insn "floatunsdidf2" | |
2636 | ;; [(set (match_operand:DF 0 "register_operand" "=r") | |
2637 | ;; (unsigned_float:DF (match_operand:DI 1 "register_operand" "r")))] | |
2638 | ;; "" | |
2639 | ;; "floatunsdidf2 %0,%1" | |
2640 | ;; [(set_attr "length" "4")]) | |
2641 | ;; | |
2642 | ;;(define_insn "fixuns_truncsfsi2" | |
2643 | ;; [(set (match_operand:SI 0 "register_operand" "=r") | |
2644 | ;; (unsigned_fix:SI (match_operand:SF 1 "register_operand" "r")))] | |
2645 | ;; "" | |
2646 | ;; "fixuns_truncsfsi2 %0,%1" | |
2647 | ;; [(set_attr "length" "4")]) | |
2648 | ;; | |
2649 | ;;(define_insn "fixuns_truncdfsi2" | |
2650 | ;; [(set (match_operand:SI 0 "register_operand" "=r") | |
2651 | ;; (unsigned_fix:SI (match_operand:DF 1 "register_operand" "r")))] | |
2652 | ;; "" | |
2653 | ;; "fixuns_truncdfsi2 %0,%1" | |
2654 | ;; [(set_attr "length" "4")]) | |
2655 | ;; | |
2656 | ;;(define_insn "fixuns_truncsfdi2" | |
2657 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2658 | ;; (unsigned_fix:DI (match_operand:SF 1 "register_operand" "r")))] | |
2659 | ;; "" | |
2660 | ;; "fixuns_truncsfdi2 %0,%1" | |
2661 | ;; [(set_attr "length" "4")]) | |
2662 | ;; | |
2663 | ;;(define_insn "fixuns_truncdfdi2" | |
2664 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2665 | ;; (unsigned_fix:DI (match_operand:DF 1 "register_operand" "r")))] | |
2666 | ;; "" | |
2667 | ;; "fixuns_truncdfdi2 %0,%1" | |
2668 | ;; [(set_attr "length" "4")]) | |
2669 | ||
2670 | \f | |
2671 | ;; :::::::::::::::::::: | |
2672 | ;; :: | |
2300b9dd | 2673 | ;; :: 32-bit Integer arithmetic |
36a05131 BS |
2674 | ;; :: |
2675 | ;; :::::::::::::::::::: | |
2676 | ||
2677 | ;; Addition | |
2678 | (define_insn "addsi3" | |
2679 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
2680 | (plus:SI (match_operand:SI 1 "integer_register_operand" "%d") | |
34208acf | 2681 | (match_operand:SI 2 "gpr_or_int12_operand" "dNOPQ")))] |
36a05131 BS |
2682 | "" |
2683 | "add%I2 %1,%2,%0" | |
2684 | [(set_attr "length" "4") | |
2685 | (set_attr "type" "int")]) | |
2686 | ||
2687 | ;; Subtraction. No need to worry about constants, since the compiler | |
2688 | ;; canonicalizes them into addsi3's. We prevent SUBREG's here to work around a | |
2689 | ;; combine bug, that combines the 32x32->upper 32 bit multiply that uses a | |
2690 | ;; SUBREG with a minus that shows up in modulus by constants. | |
2691 | (define_insn "subsi3" | |
2692 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
2693 | (minus:SI (match_operand:SI 1 "gpr_no_subreg_operand" "d") | |
2694 | (match_operand:SI 2 "gpr_no_subreg_operand" "d")))] | |
2695 | "" | |
2696 | "sub %1,%2,%0" | |
2697 | [(set_attr "length" "4") | |
2698 | (set_attr "type" "int")]) | |
2699 | ||
2300b9dd | 2700 | ;; Signed multiplication producing 64-bit results from 32-bit inputs |
36a05131 BS |
2701 | ;; Note, frv doesn't have a 32x32->32 bit multiply, but the compiler |
2702 | ;; will do the 32x32->64 bit multiply and use the bottom word. | |
2703 | (define_expand "mulsidi3" | |
2704 | [(set (match_operand:DI 0 "integer_register_operand" "") | |
2705 | (mult:DI (sign_extend:DI (match_operand:SI 1 "integer_register_operand" "")) | |
2706 | (sign_extend:DI (match_operand:SI 2 "gpr_or_int12_operand" ""))))] | |
2707 | "" | |
2708 | " | |
2709 | { | |
2710 | if (GET_CODE (operands[2]) == CONST_INT) | |
2711 | { | |
2712 | emit_insn (gen_mulsidi3_const (operands[0], operands[1], operands[2])); | |
2713 | DONE; | |
2714 | } | |
2715 | }") | |
2716 | ||
2717 | (define_insn "*mulsidi3_reg" | |
2718 | [(set (match_operand:DI 0 "even_gpr_operand" "=e") | |
2719 | (mult:DI (sign_extend:DI (match_operand:SI 1 "integer_register_operand" "%d")) | |
2720 | (sign_extend:DI (match_operand:SI 2 "integer_register_operand" "d"))))] | |
2721 | "" | |
2722 | "smul %1,%2,%0" | |
2723 | [(set_attr "length" "4") | |
2724 | (set_attr "type" "mul")]) | |
2725 | ||
2726 | (define_insn "mulsidi3_const" | |
2727 | [(set (match_operand:DI 0 "even_gpr_operand" "=e") | |
2728 | (mult:DI (sign_extend:DI (match_operand:SI 1 "integer_register_operand" "d")) | |
2729 | (match_operand:SI 2 "int12_operand" "NOP")))] | |
2730 | "" | |
2731 | "smuli %1,%2,%0" | |
2732 | [(set_attr "length" "4") | |
2733 | (set_attr "type" "mul")]) | |
2734 | ||
2300b9dd | 2735 | ;; Unsigned multiplication producing 64-bit results from 32-bit inputs |
36a05131 BS |
2736 | (define_expand "umulsidi3" |
2737 | [(set (match_operand:DI 0 "even_gpr_operand" "") | |
2738 | (mult:DI (zero_extend:DI (match_operand:SI 1 "integer_register_operand" "")) | |
2739 | (zero_extend:DI (match_operand:SI 2 "gpr_or_int12_operand" ""))))] | |
2740 | "" | |
2741 | " | |
2742 | { | |
2743 | if (GET_CODE (operands[2]) == CONST_INT) | |
2744 | { | |
2745 | emit_insn (gen_umulsidi3_const (operands[0], operands[1], operands[2])); | |
2746 | DONE; | |
2747 | } | |
2748 | }") | |
2749 | ||
2750 | (define_insn "*mulsidi3_reg" | |
2751 | [(set (match_operand:DI 0 "even_gpr_operand" "=e") | |
2752 | (mult:DI (zero_extend:DI (match_operand:SI 1 "integer_register_operand" "%d")) | |
2753 | (zero_extend:DI (match_operand:SI 2 "integer_register_operand" "d"))))] | |
2754 | "" | |
2755 | "umul %1,%2,%0" | |
2756 | [(set_attr "length" "4") | |
2757 | (set_attr "type" "mul")]) | |
2758 | ||
2759 | (define_insn "umulsidi3_const" | |
2760 | [(set (match_operand:DI 0 "even_gpr_operand" "=e") | |
2761 | (mult:DI (zero_extend:DI (match_operand:SI 1 "integer_register_operand" "d")) | |
2762 | (match_operand:SI 2 "int12_operand" "NOP")))] | |
2763 | "" | |
2764 | "umuli %1,%2,%0" | |
2765 | [(set_attr "length" "4") | |
2766 | (set_attr "type" "mul")]) | |
2767 | ||
2768 | ;; Signed Division | |
2769 | (define_insn "divsi3" | |
2770 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
2771 | (div:SI (match_operand:SI 1 "register_operand" "d,d") | |
2772 | (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))] | |
2773 | "" | |
2774 | "sdiv%I2 %1,%2,%0" | |
2775 | [(set_attr "length" "4") | |
2776 | (set_attr "type" "div")]) | |
2777 | ||
2778 | ;; Unsigned Division | |
2779 | (define_insn "udivsi3" | |
2780 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
2781 | (udiv:SI (match_operand:SI 1 "register_operand" "d,d") | |
2782 | (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))] | |
2783 | "" | |
2784 | "udiv%I2 %1,%2,%0" | |
2785 | [(set_attr "length" "4") | |
2786 | (set_attr "type" "div")]) | |
2787 | ||
2788 | ;; Negation | |
2789 | (define_insn "negsi2" | |
2790 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
2791 | (neg:SI (match_operand:SI 1 "integer_register_operand" "d")))] | |
2792 | "" | |
2793 | "sub %.,%1,%0" | |
2794 | [(set_attr "length" "4") | |
2795 | (set_attr "type" "int")]) | |
2796 | ||
2797 | ;; Find first one bit | |
2798 | ;; (define_insn "ffssi2" | |
2799 | ;; [(set (match_operand:SI 0 "register_operand" "=r") | |
2800 | ;; (ffs:SI (match_operand:SI 1 "register_operand" "r")))] | |
2801 | ;; "" | |
2802 | ;; "ffssi2 %0,%1" | |
2803 | ;; [(set_attr "length" "4")]) | |
2804 | ||
2805 | \f | |
2806 | ;; :::::::::::::::::::: | |
2807 | ;; :: | |
2300b9dd | 2808 | ;; :: 64-bit Integer arithmetic |
36a05131 BS |
2809 | ;; :: |
2810 | ;; :::::::::::::::::::: | |
2811 | ||
2812 | ;; Addition | |
6b34e55e RS |
2813 | (define_insn_and_split "adddi3" |
2814 | [(set (match_operand:DI 0 "integer_register_operand" "=&e,e") | |
2815 | (plus:DI (match_operand:DI 1 "integer_register_operand" "%e,0") | |
2816 | (match_operand:DI 2 "gpr_or_int10_operand" "eJ,eJ"))) | |
2817 | (clobber (match_scratch:CC 3 "=t,t"))] | |
36a05131 | 2818 | "" |
36a05131 BS |
2819 | "#" |
2820 | "reload_completed" | |
2821 | [(match_dup 4) | |
2822 | (match_dup 5)] | |
2823 | " | |
2824 | { | |
6b34e55e RS |
2825 | rtx parts[3][2]; |
2826 | int op, part; | |
2827 | ||
2828 | for (op = 0; op < 3; op++) | |
2829 | for (part = 0; part < 2; part++) | |
2830 | parts[op][part] = simplify_gen_subreg (SImode, operands[op], | |
2831 | DImode, part * UNITS_PER_WORD); | |
2832 | ||
2833 | operands[4] = gen_adddi3_lower (parts[0][1], parts[1][1], parts[2][1], | |
2834 | operands[3]); | |
2835 | operands[5] = gen_adddi3_upper (parts[0][0], parts[1][0], parts[2][0], | |
2836 | copy_rtx (operands[3])); | |
36a05131 BS |
2837 | }" |
2838 | [(set_attr "length" "8") | |
2839 | (set_attr "type" "multi")]) | |
2840 | ||
2841 | ;; Subtraction No need to worry about constants, since the compiler | |
2842 | ;; canonicalizes them into adddi3's. | |
1ff905e9 | 2843 | (define_insn_and_split "subdi3" |
36a05131 BS |
2844 | [(set (match_operand:DI 0 "integer_register_operand" "=&e,e,e") |
2845 | (minus:DI (match_operand:DI 1 "integer_register_operand" "e,0,e") | |
2846 | (match_operand:DI 2 "integer_register_operand" "e,e,0"))) | |
1ff905e9 | 2847 | (clobber (match_scratch:CC 3 "=t,t,t"))] |
36a05131 BS |
2848 | "" |
2849 | "#" | |
2850 | "reload_completed" | |
2851 | [(match_dup 4) | |
2852 | (match_dup 5)] | |
2853 | " | |
2854 | { | |
2855 | rtx op0_high = gen_highpart (SImode, operands[0]); | |
2856 | rtx op1_high = gen_highpart (SImode, operands[1]); | |
2857 | rtx op2_high = gen_highpart (SImode, operands[2]); | |
2858 | rtx op0_low = gen_lowpart (SImode, operands[0]); | |
2859 | rtx op1_low = gen_lowpart (SImode, operands[1]); | |
2860 | rtx op2_low = gen_lowpart (SImode, operands[2]); | |
2861 | rtx op3 = operands[3]; | |
2862 | ||
2863 | operands[4] = gen_subdi3_lower (op0_low, op1_low, op2_low, op3); | |
2864 | operands[5] = gen_subdi3_upper (op0_high, op1_high, op2_high, op3); | |
2865 | }" | |
2866 | [(set_attr "length" "8") | |
2867 | (set_attr "type" "multi")]) | |
2868 | ||
1ae58c30 | 2869 | ;; Patterns for addsi3/subdi3 after splitting |
36a05131 BS |
2870 | (define_insn "adddi3_lower" |
2871 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
2872 | (plus:SI (match_operand:SI 1 "integer_register_operand" "d") | |
6b34e55e | 2873 | (match_operand:SI 2 "gpr_or_int10_operand" "dJ"))) |
36a05131 BS |
2874 | (set (match_operand:CC 3 "icc_operand" "=t") |
2875 | (compare:CC (plus:SI (match_dup 1) | |
2876 | (match_dup 2)) | |
2877 | (const_int 0)))] | |
6b34e55e | 2878 | "" |
36a05131 BS |
2879 | "add%I2cc %1,%2,%0,%3" |
2880 | [(set_attr "length" "4") | |
2881 | (set_attr "type" "int")]) | |
2882 | ||
2883 | (define_insn "adddi3_upper" | |
6b34e55e RS |
2884 | [(set (match_operand:SI 0 "integer_register_operand" "=d") |
2885 | (plus:SI (match_operand:SI 1 "integer_register_operand" "d") | |
2886 | (plus:SI (match_operand:SI 2 "gpr_or_int10_operand" "dJ") | |
2887 | (match_operand:CC 3 "icc_operand" "t"))))] | |
36a05131 | 2888 | "" |
6b34e55e | 2889 | "addx%I2 %1,%2,%0,%3" |
36a05131 BS |
2890 | [(set_attr "length" "4") |
2891 | (set_attr "type" "int")]) | |
2892 | ||
2893 | (define_insn "subdi3_lower" | |
2894 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
2895 | (minus:SI (match_operand:SI 1 "integer_register_operand" "d") | |
6b34e55e | 2896 | (match_operand:SI 2 "integer_register_operand" "d"))) |
36a05131 BS |
2897 | (set (match_operand:CC 3 "icc_operand" "=t") |
2898 | (compare:CC (plus:SI (match_dup 1) | |
2899 | (match_dup 2)) | |
2900 | (const_int 0)))] | |
6b34e55e RS |
2901 | "" |
2902 | "subcc %1,%2,%0,%3" | |
36a05131 BS |
2903 | [(set_attr "length" "4") |
2904 | (set_attr "type" "int")]) | |
2905 | ||
2906 | (define_insn "subdi3_upper" | |
6b34e55e RS |
2907 | [(set (match_operand:SI 0 "integer_register_operand" "=d") |
2908 | (minus:SI (match_operand:SI 1 "integer_register_operand" "d") | |
2909 | (minus:SI (match_operand:SI 2 "integer_register_operand" "d") | |
2910 | (match_operand:CC 3 "icc_operand" "t"))))] | |
36a05131 | 2911 | "" |
6b34e55e | 2912 | "subx %1,%2,%0,%3" |
36a05131 BS |
2913 | [(set_attr "length" "4") |
2914 | (set_attr "type" "int")]) | |
2915 | ||
1ff905e9 AO |
2916 | (define_insn_and_split "negdi2" |
2917 | [(set (match_operand:DI 0 "integer_register_operand" "=&e,e") | |
2918 | (neg:DI (match_operand:DI 1 "integer_register_operand" "e,0"))) | |
2919 | (clobber (match_scratch:CC 2 "=t,t"))] | |
2920 | "" | |
2921 | "#" | |
2922 | "reload_completed" | |
2923 | [(match_dup 3) | |
2924 | (match_dup 4)] | |
2925 | " | |
2926 | { | |
2927 | rtx op0_high = gen_highpart (SImode, operands[0]); | |
2928 | rtx op1_high = gen_rtx_REG (SImode, GPR_FIRST); | |
2929 | rtx op2_high = gen_highpart (SImode, operands[1]); | |
2930 | rtx op0_low = gen_lowpart (SImode, operands[0]); | |
2931 | rtx op1_low = op1_high; | |
2932 | rtx op2_low = gen_lowpart (SImode, operands[1]); | |
2933 | rtx op3 = operands[2]; | |
2934 | ||
2935 | operands[3] = gen_subdi3_lower (op0_low, op1_low, op2_low, op3); | |
2936 | operands[4] = gen_subdi3_upper (op0_high, op1_high, op2_high, op3); | |
2937 | }" | |
2938 | [(set_attr "length" "8") | |
2939 | (set_attr "type" "multi")]) | |
2940 | ||
36a05131 BS |
2941 | ;; Multiplication (same size) |
2942 | ;; (define_insn "muldi3" | |
2943 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2944 | ;; (mult:DI (match_operand:DI 1 "register_operand" "%r") | |
2945 | ;; (match_operand:DI 2 "nonmemory_operand" "ri")))] | |
2946 | ;; "" | |
2947 | ;; "muldi3 %0,%1,%2" | |
2948 | ;; [(set_attr "length" "4")]) | |
2949 | ||
2950 | ;; Signed Division | |
2951 | ;; (define_insn "divdi3" | |
2952 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2953 | ;; (div:DI (match_operand:DI 1 "register_operand" "r") | |
2954 | ;; (match_operand:DI 2 "nonmemory_operand" "ri")))] | |
2955 | ;; "" | |
2956 | ;; "divdi3 %0,%1,%2" | |
2957 | ;; [(set_attr "length" "4")]) | |
2958 | ||
2959 | ;; Undsgned Division | |
2960 | ;; (define_insn "udivdi3" | |
2961 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2962 | ;; (udiv:DI (match_operand:DI 1 "register_operand" "r") | |
2963 | ;; (match_operand:DI 2 "nonmemory_operand" "ri")))] | |
2964 | ;; "" | |
2965 | ;; "udivdi3 %0,%1,%2" | |
2966 | ;; [(set_attr "length" "4")]) | |
2967 | ||
2968 | ;; Negation | |
2969 | ;; (define_insn "negdi2" | |
2970 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2971 | ;; (neg:DI (match_operand:DI 1 "register_operand" "r")))] | |
2972 | ;; "" | |
2973 | ;; "negdi2 %0,%1" | |
2974 | ;; [(set_attr "length" "4")]) | |
2975 | ||
2976 | ;; Find first one bit | |
2977 | ;; (define_insn "ffsdi2" | |
2978 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
2979 | ;; (ffs:DI (match_operand:DI 1 "register_operand" "r")))] | |
2980 | ;; "" | |
2981 | ;; "ffsdi2 %0,%1" | |
2982 | ;; [(set_attr "length" "4")]) | |
2983 | ||
2984 | \f | |
2985 | ;; :::::::::::::::::::: | |
2986 | ;; :: | |
2300b9dd | 2987 | ;; :: 32-bit floating point arithmetic |
36a05131 BS |
2988 | ;; :: |
2989 | ;; :::::::::::::::::::: | |
2990 | ||
2991 | ;; Addition | |
2992 | (define_insn "addsf3" | |
2993 | [(set (match_operand:SF 0 "fpr_operand" "=f") | |
2994 | (plus:SF (match_operand:SF 1 "fpr_operand" "%f") | |
2995 | (match_operand:SF 2 "fpr_operand" "f")))] | |
2996 | "TARGET_HARD_FLOAT" | |
2997 | "fadds %1,%2,%0" | |
2998 | [(set_attr "length" "4") | |
2999 | (set_attr "type" "fsadd")]) | |
3000 | ||
3001 | ;; Subtraction | |
3002 | (define_insn "subsf3" | |
3003 | [(set (match_operand:SF 0 "fpr_operand" "=f") | |
3004 | (minus:SF (match_operand:SF 1 "fpr_operand" "f") | |
3005 | (match_operand:SF 2 "fpr_operand" "f")))] | |
3006 | "TARGET_HARD_FLOAT" | |
3007 | "fsubs %1,%2,%0" | |
3008 | [(set_attr "length" "4") | |
3009 | (set_attr "type" "fsadd")]) | |
3010 | ||
3011 | ;; Multiplication | |
3012 | (define_insn "mulsf3" | |
3013 | [(set (match_operand:SF 0 "fpr_operand" "=f") | |
3014 | (mult:SF (match_operand:SF 1 "fpr_operand" "%f") | |
3015 | (match_operand:SF 2 "fpr_operand" "f")))] | |
3016 | "TARGET_HARD_FLOAT" | |
3017 | "fmuls %1,%2,%0" | |
3018 | [(set_attr "length" "4") | |
3019 | (set_attr "type" "fsmul")]) | |
3020 | ||
3021 | ;; Multiplication with addition/subtraction | |
be2fbfb6 | 3022 | (define_insn "fmasf4" |
36a05131 | 3023 | [(set (match_operand:SF 0 "fpr_operand" "=f") |
be2fbfb6 RH |
3024 | (fma:SF (match_operand:SF 1 "fpr_operand" "f") |
3025 | (match_operand:SF 2 "fpr_operand" "f") | |
3026 | (match_operand:SF 3 "fpr_operand" "0")))] | |
36a05131 BS |
3027 | "TARGET_HARD_FLOAT && TARGET_MULADD" |
3028 | "fmadds %1,%2,%0" | |
3029 | [(set_attr "length" "4") | |
c557edf4 | 3030 | (set_attr "type" "fsmadd")]) |
36a05131 | 3031 | |
be2fbfb6 | 3032 | (define_insn "fmssf4" |
36a05131 | 3033 | [(set (match_operand:SF 0 "fpr_operand" "=f") |
be2fbfb6 RH |
3034 | (fma:SF (match_operand:SF 1 "fpr_operand" "f") |
3035 | (match_operand:SF 2 "fpr_operand" "f") | |
3036 | (neg:SF (match_operand:SF 3 "fpr_operand" "0"))))] | |
36a05131 BS |
3037 | "TARGET_HARD_FLOAT && TARGET_MULADD" |
3038 | "fmsubs %1,%2,%0" | |
3039 | [(set_attr "length" "4") | |
c557edf4 | 3040 | (set_attr "type" "fsmadd")]) |
36a05131 BS |
3041 | |
3042 | ;; Division | |
3043 | (define_insn "divsf3" | |
3044 | [(set (match_operand:SF 0 "fpr_operand" "=f") | |
3045 | (div:SF (match_operand:SF 1 "fpr_operand" "f") | |
3046 | (match_operand:SF 2 "fpr_operand" "f")))] | |
3047 | "TARGET_HARD_FLOAT" | |
3048 | "fdivs %1,%2,%0" | |
3049 | [(set_attr "length" "4") | |
3050 | (set_attr "type" "fsdiv")]) | |
3051 | ||
3052 | ;; Negation | |
3053 | (define_insn "negsf2" | |
3054 | [(set (match_operand:SF 0 "fpr_operand" "=f") | |
3055 | (neg:SF (match_operand:SF 1 "fpr_operand" "f")))] | |
3056 | "TARGET_HARD_FLOAT" | |
3057 | "fnegs %1,%0" | |
3058 | [(set_attr "length" "4") | |
3059 | (set_attr "type" "fsconv")]) | |
3060 | ||
3061 | ;; Absolute value | |
3062 | (define_insn "abssf2" | |
3063 | [(set (match_operand:SF 0 "fpr_operand" "=f") | |
3064 | (abs:SF (match_operand:SF 1 "fpr_operand" "f")))] | |
3065 | "TARGET_HARD_FLOAT" | |
3066 | "fabss %1,%0" | |
3067 | [(set_attr "length" "4") | |
3068 | (set_attr "type" "fsconv")]) | |
3069 | ||
3070 | ;; Square root | |
3071 | (define_insn "sqrtsf2" | |
3072 | [(set (match_operand:SF 0 "fpr_operand" "=f") | |
3073 | (sqrt:SF (match_operand:SF 1 "fpr_operand" "f")))] | |
3074 | "TARGET_HARD_FLOAT" | |
3075 | "fsqrts %1,%0" | |
3076 | [(set_attr "length" "4") | |
3077 | (set_attr "type" "sqrt_single")]) | |
3078 | ||
3079 | \f | |
3080 | ;; :::::::::::::::::::: | |
3081 | ;; :: | |
2300b9dd | 3082 | ;; :: 64-bit floating point arithmetic |
36a05131 BS |
3083 | ;; :: |
3084 | ;; :::::::::::::::::::: | |
3085 | ||
3086 | ;; Addition | |
3087 | (define_insn "adddf3" | |
3088 | [(set (match_operand:DF 0 "even_fpr_operand" "=h") | |
3089 | (plus:DF (match_operand:DF 1 "fpr_operand" "%h") | |
3090 | (match_operand:DF 2 "fpr_operand" "h")))] | |
3091 | "TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
3092 | "faddd %1,%2,%0" | |
3093 | [(set_attr "length" "4") | |
3094 | (set_attr "type" "fdadd")]) | |
3095 | ||
3096 | ;; Subtraction | |
3097 | (define_insn "subdf3" | |
3098 | [(set (match_operand:DF 0 "even_fpr_operand" "=h") | |
3099 | (minus:DF (match_operand:DF 1 "fpr_operand" "h") | |
3100 | (match_operand:DF 2 "fpr_operand" "h")))] | |
3101 | "TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
3102 | "fsubd %1,%2,%0" | |
3103 | [(set_attr "length" "4") | |
3104 | (set_attr "type" "fdadd")]) | |
3105 | ||
3106 | ;; Multiplication | |
3107 | (define_insn "muldf3" | |
3108 | [(set (match_operand:DF 0 "even_fpr_operand" "=h") | |
3109 | (mult:DF (match_operand:DF 1 "fpr_operand" "%h") | |
3110 | (match_operand:DF 2 "fpr_operand" "h")))] | |
3111 | "TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
3112 | "fmuld %1,%2,%0" | |
3113 | [(set_attr "length" "4") | |
3114 | (set_attr "type" "fdmul")]) | |
3115 | ||
3116 | ;; Multiplication with addition/subtraction | |
3117 | (define_insn "*muladddf4" | |
3118 | [(set (match_operand:DF 0 "fpr_operand" "=f") | |
3119 | (plus:DF (mult:DF (match_operand:DF 1 "fpr_operand" "%f") | |
3120 | (match_operand:DF 2 "fpr_operand" "f")) | |
3121 | (match_operand:DF 3 "fpr_operand" "0")))] | |
3122 | "TARGET_HARD_FLOAT && TARGET_DOUBLE && TARGET_MULADD" | |
3123 | "fmaddd %1,%2,%0" | |
3124 | [(set_attr "length" "4") | |
c557edf4 | 3125 | (set_attr "type" "fdmadd")]) |
36a05131 BS |
3126 | |
3127 | (define_insn "*mulsubdf4" | |
3128 | [(set (match_operand:DF 0 "fpr_operand" "=f") | |
3129 | (minus:DF (mult:DF (match_operand:DF 1 "fpr_operand" "%f") | |
3130 | (match_operand:DF 2 "fpr_operand" "f")) | |
3131 | (match_operand:DF 3 "fpr_operand" "0")))] | |
3132 | "TARGET_HARD_FLOAT && TARGET_DOUBLE && TARGET_MULADD" | |
3133 | "fmsubd %1,%2,%0" | |
3134 | [(set_attr "length" "4") | |
c557edf4 | 3135 | (set_attr "type" "fdmadd")]) |
36a05131 BS |
3136 | |
3137 | ;; Division | |
3138 | (define_insn "divdf3" | |
3139 | [(set (match_operand:DF 0 "even_fpr_operand" "=h") | |
3140 | (div:DF (match_operand:DF 1 "fpr_operand" "h") | |
3141 | (match_operand:DF 2 "fpr_operand" "h")))] | |
3142 | "TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
3143 | "fdivd %1,%2,%0" | |
3144 | [(set_attr "length" "4") | |
3145 | (set_attr "type" "fddiv")]) | |
3146 | ||
3147 | ;; Negation | |
3148 | (define_insn "negdf2" | |
3149 | [(set (match_operand:DF 0 "even_fpr_operand" "=h") | |
3150 | (neg:DF (match_operand:DF 1 "fpr_operand" "h")))] | |
3151 | "TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
3152 | "fnegd %1,%0" | |
3153 | [(set_attr "length" "4") | |
3154 | (set_attr "type" "fdconv")]) | |
3155 | ||
3156 | ;; Absolute value | |
3157 | (define_insn "absdf2" | |
3158 | [(set (match_operand:DF 0 "even_fpr_operand" "=h") | |
3159 | (abs:DF (match_operand:DF 1 "fpr_operand" "h")))] | |
3160 | "TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
3161 | "fabsd %1,%0" | |
3162 | [(set_attr "length" "4") | |
3163 | (set_attr "type" "fdconv")]) | |
3164 | ||
3165 | ;; Square root | |
3166 | (define_insn "sqrtdf2" | |
3167 | [(set (match_operand:DF 0 "even_fpr_operand" "=h") | |
3168 | (sqrt:DF (match_operand:DF 1 "fpr_operand" "h")))] | |
3169 | "TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
3170 | "fsqrtd %1,%0" | |
3171 | [(set_attr "length" "4") | |
3172 | (set_attr "type" "sqrt_double")]) | |
3173 | ||
3174 | \f | |
3175 | ;; :::::::::::::::::::: | |
3176 | ;; :: | |
2300b9dd | 3177 | ;; :: 32-bit Integer Shifts and Rotates |
36a05131 BS |
3178 | ;; :: |
3179 | ;; :::::::::::::::::::: | |
3180 | ||
3181 | ;; Arithmetic Shift Left | |
3182 | (define_insn "ashlsi3" | |
3183 | [(set (match_operand:SI 0 "integer_register_operand" "=d,d") | |
3184 | (ashift:SI (match_operand:SI 1 "integer_register_operand" "d,d") | |
3185 | (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))] | |
3186 | "" | |
3187 | "sll%I2 %1,%2,%0" | |
3188 | [(set_attr "length" "4") | |
3189 | (set_attr "type" "int")]) | |
3190 | ||
3191 | ;; Arithmetic Shift Right | |
3192 | (define_insn "ashrsi3" | |
3193 | [(set (match_operand:SI 0 "integer_register_operand" "=d,d") | |
3194 | (ashiftrt:SI (match_operand:SI 1 "integer_register_operand" "d,d") | |
3195 | (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))] | |
3196 | "" | |
3197 | "sra%I2 %1, %2, %0" | |
3198 | [(set_attr "length" "4") | |
3199 | (set_attr "type" "int")]) | |
3200 | ||
3201 | ;; Logical Shift Right | |
3202 | (define_insn "lshrsi3" | |
3203 | [(set (match_operand:SI 0 "integer_register_operand" "=d,d") | |
3204 | (lshiftrt:SI (match_operand:SI 1 "integer_register_operand" "d,d") | |
3205 | (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))] | |
3206 | "" | |
3207 | "srl%I2 %1, %2, %0" | |
3208 | [(set_attr "length" "4") | |
3209 | (set_attr "type" "int")]) | |
3210 | ||
3211 | ;; Rotate Left | |
3212 | ;; (define_insn "rotlsi3" | |
3213 | ;; [(set (match_operand:SI 0 "register_operand" "=r") | |
3214 | ;; (rotate:SI (match_operand:SI 1 "register_operand" "r") | |
3215 | ;; (match_operand:SI 2 "nonmemory_operand" "ri")))] | |
3216 | ;; "" | |
3217 | ;; "rotlsi3 %0,%1,%2" | |
3218 | ;; [(set_attr "length" "4")]) | |
3219 | ||
3220 | ;; Rotate Right | |
3221 | ;; (define_insn "rotrsi3" | |
3222 | ;; [(set (match_operand:SI 0 "register_operand" "=r") | |
3223 | ;; (rotatert:SI (match_operand:SI 1 "register_operand" "r") | |
3224 | ;; (match_operand:SI 2 "nonmemory_operand" "ri")))] | |
3225 | ;; "" | |
3226 | ;; "rotrsi3 %0,%1,%2" | |
3227 | ;; [(set_attr "length" "4")]) | |
3228 | ||
3229 | \f | |
3230 | ;; :::::::::::::::::::: | |
3231 | ;; :: | |
2300b9dd | 3232 | ;; :: 64-bit Integer Shifts and Rotates |
36a05131 BS |
3233 | ;; :: |
3234 | ;; :::::::::::::::::::: | |
3235 | ||
3236 | ;; Arithmetic Shift Left | |
3237 | ;; (define_insn "ashldi3" | |
3238 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
3239 | ;; (ashift:DI (match_operand:DI 1 "register_operand" "r") | |
3240 | ;; (match_operand:SI 2 "nonmemory_operand" "ri")))] | |
3241 | ;; "" | |
3242 | ;; "ashldi3 %0,%1,%2" | |
3243 | ;; [(set_attr "length" "4")]) | |
3244 | ||
3245 | ;; Arithmetic Shift Right | |
3246 | ;; (define_insn "ashrdi3" | |
3247 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
3248 | ;; (ashiftrt:DI (match_operand:DI 1 "register_operand" "r") | |
3249 | ;; (match_operand:SI 2 "nonmemory_operand" "ri")))] | |
3250 | ;; "" | |
3251 | ;; "ashrdi3 %0,%1,%2" | |
3252 | ;; [(set_attr "length" "4")]) | |
3253 | ||
3254 | ;; Logical Shift Right | |
3255 | ;; (define_insn "lshrdi3" | |
3256 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
3257 | ;; (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") | |
3258 | ;; (match_operand:SI 2 "nonmemory_operand" "ri")))] | |
3259 | ;; "" | |
3260 | ;; "lshrdi3 %0,%1,%2" | |
3261 | ;; [(set_attr "length" "4")]) | |
3262 | ||
3263 | ;; Rotate Left | |
3264 | ;; (define_insn "rotldi3" | |
3265 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
3266 | ;; (rotate:DI (match_operand:DI 1 "register_operand" "r") | |
3267 | ;; (match_operand:SI 2 "nonmemory_operand" "ri")))] | |
3268 | ;; "" | |
3269 | ;; "rotldi3 %0,%1,%2" | |
3270 | ;; [(set_attr "length" "4")]) | |
3271 | ||
3272 | ;; Rotate Right | |
3273 | ;; (define_insn "rotrdi3" | |
3274 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
3275 | ;; (rotatert:DI (match_operand:DI 1 "register_operand" "r") | |
3276 | ;; (match_operand:SI 2 "nonmemory_operand" "ri")))] | |
3277 | ;; "" | |
3278 | ;; "rotrdi3 %0,%1,%2" | |
3279 | ;; [(set_attr "length" "4")]) | |
3280 | ||
3281 | \f | |
3282 | ;; :::::::::::::::::::: | |
3283 | ;; :: | |
2300b9dd | 3284 | ;; :: 32-Bit Integer Logical operations |
36a05131 BS |
3285 | ;; :: |
3286 | ;; :::::::::::::::::::: | |
3287 | ||
2300b9dd | 3288 | ;; Logical AND, 32-bit integers |
36a05131 BS |
3289 | (define_insn "andsi3_media" |
3290 | [(set (match_operand:SI 0 "gpr_or_fpr_operand" "=d,f") | |
3291 | (and:SI (match_operand:SI 1 "gpr_or_fpr_operand" "%d,f") | |
3292 | (match_operand:SI 2 "gpr_fpr_or_int12_operand" "dNOP,f")))] | |
3293 | "TARGET_MEDIA" | |
3294 | "@ | |
3295 | and%I2 %1, %2, %0 | |
3296 | mand %1, %2, %0" | |
3297 | [(set_attr "length" "4") | |
3298 | (set_attr "type" "int,mlogic")]) | |
3299 | ||
3300 | (define_insn "andsi3_nomedia" | |
3301 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
3302 | (and:SI (match_operand:SI 1 "integer_register_operand" "%d") | |
3303 | (match_operand:SI 2 "gpr_or_int12_operand" "dNOP")))] | |
3304 | "!TARGET_MEDIA" | |
3305 | "and%I2 %1, %2, %0" | |
3306 | [(set_attr "length" "4") | |
3307 | (set_attr "type" "int")]) | |
3308 | ||
3309 | (define_expand "andsi3" | |
3310 | [(set (match_operand:SI 0 "gpr_or_fpr_operand" "") | |
3311 | (and:SI (match_operand:SI 1 "gpr_or_fpr_operand" "") | |
3312 | (match_operand:SI 2 "gpr_fpr_or_int12_operand" "")))] | |
3313 | "" | |
3314 | "") | |
3315 | ||
2300b9dd | 3316 | ;; Inclusive OR, 32-bit integers |
36a05131 BS |
3317 | (define_insn "iorsi3_media" |
3318 | [(set (match_operand:SI 0 "gpr_or_fpr_operand" "=d,f") | |
3319 | (ior:SI (match_operand:SI 1 "gpr_or_fpr_operand" "%d,f") | |
3320 | (match_operand:SI 2 "gpr_fpr_or_int12_operand" "dNOP,f")))] | |
3321 | "TARGET_MEDIA" | |
3322 | "@ | |
3323 | or%I2 %1, %2, %0 | |
3324 | mor %1, %2, %0" | |
3325 | [(set_attr "length" "4") | |
3326 | (set_attr "type" "int,mlogic")]) | |
3327 | ||
3328 | (define_insn "iorsi3_nomedia" | |
3329 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
3330 | (ior:SI (match_operand:SI 1 "integer_register_operand" "%d") | |
3331 | (match_operand:SI 2 "gpr_or_int12_operand" "dNOP")))] | |
3332 | "!TARGET_MEDIA" | |
3333 | "or%I2 %1, %2, %0" | |
3334 | [(set_attr "length" "4") | |
3335 | (set_attr "type" "int")]) | |
3336 | ||
3337 | (define_expand "iorsi3" | |
3338 | [(set (match_operand:SI 0 "gpr_or_fpr_operand" "") | |
3339 | (ior:SI (match_operand:SI 1 "gpr_or_fpr_operand" "") | |
3340 | (match_operand:SI 2 "gpr_fpr_or_int12_operand" "")))] | |
3341 | "" | |
3342 | "") | |
3343 | ||
2300b9dd | 3344 | ;; Exclusive OR, 32-bit integers |
36a05131 BS |
3345 | (define_insn "xorsi3_media" |
3346 | [(set (match_operand:SI 0 "gpr_or_fpr_operand" "=d,f") | |
3347 | (xor:SI (match_operand:SI 1 "gpr_or_fpr_operand" "%d,f") | |
3348 | (match_operand:SI 2 "gpr_fpr_or_int12_operand" "dNOP,f")))] | |
3349 | "TARGET_MEDIA" | |
3350 | "@ | |
3351 | xor%I2 %1, %2, %0 | |
3352 | mxor %1, %2, %0" | |
3353 | [(set_attr "length" "4") | |
3354 | (set_attr "type" "int,mlogic")]) | |
3355 | ||
3356 | (define_insn "xorsi3_nomedia" | |
3357 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
3358 | (xor:SI (match_operand:SI 1 "integer_register_operand" "%d") | |
3359 | (match_operand:SI 2 "gpr_or_int12_operand" "dNOP")))] | |
3360 | "!TARGET_MEDIA" | |
3361 | "xor%I2 %1, %2, %0" | |
3362 | [(set_attr "length" "4") | |
3363 | (set_attr "type" "int")]) | |
3364 | ||
3365 | (define_expand "xorsi3" | |
3366 | [(set (match_operand:SI 0 "gpr_or_fpr_operand" "") | |
3367 | (xor:SI (match_operand:SI 1 "gpr_or_fpr_operand" "") | |
3368 | (match_operand:SI 2 "gpr_fpr_or_int12_operand" "")))] | |
3369 | "" | |
3370 | "") | |
3371 | ||
2300b9dd | 3372 | ;; One's complement, 32-bit integers |
36a05131 BS |
3373 | (define_insn "one_cmplsi2_media" |
3374 | [(set (match_operand:SI 0 "gpr_or_fpr_operand" "=d,f") | |
3375 | (not:SI (match_operand:SI 1 "gpr_or_fpr_operand" "d,f")))] | |
3376 | "TARGET_MEDIA" | |
3377 | "@ | |
3378 | not %1, %0 | |
3379 | mnot %1, %0" | |
3380 | [(set_attr "length" "4") | |
3381 | (set_attr "type" "int,mlogic")]) | |
3382 | ||
3383 | (define_insn "one_cmplsi2_nomedia" | |
3384 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
3385 | (not:SI (match_operand:SI 1 "integer_register_operand" "d")))] | |
3386 | "!TARGET_MEDIA" | |
3387 | "not %1,%0" | |
3388 | [(set_attr "length" "4") | |
3389 | (set_attr "type" "int")]) | |
3390 | ||
3391 | (define_expand "one_cmplsi2" | |
3392 | [(set (match_operand:SI 0 "gpr_or_fpr_operand" "") | |
3393 | (not:SI (match_operand:SI 1 "gpr_or_fpr_operand" "")))] | |
3394 | "" | |
3395 | "") | |
3396 | ||
3397 | \f | |
3398 | ;; :::::::::::::::::::: | |
3399 | ;; :: | |
2300b9dd | 3400 | ;; :: 64-Bit Integer Logical operations |
36a05131 BS |
3401 | ;; :: |
3402 | ;; :::::::::::::::::::: | |
3403 | ||
2300b9dd | 3404 | ;; Logical AND, 64-bit integers |
36a05131 BS |
3405 | ;; (define_insn "anddi3" |
3406 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
3407 | ;; (and:DI (match_operand:DI 1 "register_operand" "%r") | |
3408 | ;; (match_operand:DI 2 "nonmemory_operand" "ri")))] | |
3409 | ;; "" | |
3410 | ;; "anddi3 %0,%1,%2" | |
3411 | ;; [(set_attr "length" "4")]) | |
3412 | ||
2300b9dd | 3413 | ;; Inclusive OR, 64-bit integers |
36a05131 BS |
3414 | ;; (define_insn "iordi3" |
3415 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
3416 | ;; (ior:DI (match_operand:DI 1 "register_operand" "%r") | |
3417 | ;; (match_operand:DI 2 "nonmemory_operand" "ri")))] | |
3418 | ;; "" | |
3419 | ;; "iordi3 %0,%1,%2" | |
3420 | ;; [(set_attr "length" "4")]) | |
3421 | ||
2300b9dd | 3422 | ;; Exclusive OR, 64-bit integers |
36a05131 BS |
3423 | ;; (define_insn "xordi3" |
3424 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
3425 | ;; (xor:DI (match_operand:DI 1 "register_operand" "%r") | |
3426 | ;; (match_operand:DI 2 "nonmemory_operand" "ri")))] | |
3427 | ;; "" | |
3428 | ;; "xordi3 %0,%1,%2" | |
3429 | ;; [(set_attr "length" "4")]) | |
3430 | ||
2300b9dd | 3431 | ;; One's complement, 64-bit integers |
36a05131 BS |
3432 | ;; (define_insn "one_cmpldi2" |
3433 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
3434 | ;; (not:DI (match_operand:DI 1 "register_operand" "r")))] | |
3435 | ;; "" | |
3436 | ;; "notdi3 %0,%1" | |
3437 | ;; [(set_attr "length" "4")]) | |
3438 | ||
3439 | \f | |
3440 | ;; :::::::::::::::::::: | |
3441 | ;; :: | |
3442 | ;; :: Combination of integer operation with comparison | |
3443 | ;; :: | |
3444 | ;; :::::::::::::::::::: | |
3445 | ||
3446 | (define_insn "*combo_intop_compare1" | |
036ff63f RS |
3447 | [(set (match_operand:CC_NZ 0 "icc_operand" "=t") |
3448 | (compare:CC_NZ | |
3449 | (match_operator:SI 1 "intop_compare_operator" | |
3450 | [(match_operand:SI 2 "integer_register_operand" "d") | |
3451 | (match_operand:SI 3 "gpr_or_int10_operand" "dJ")]) | |
3452 | (const_int 0)))] | |
36a05131 BS |
3453 | "" |
3454 | "%O1%I3cc %2, %3, %., %0" | |
3455 | [(set_attr "type" "int") | |
3456 | (set_attr "length" "4")]) | |
3457 | ||
3458 | (define_insn "*combo_intop_compare2" | |
036ff63f RS |
3459 | [(set (match_operand:CC_NZ 0 "icc_operand" "=t") |
3460 | (compare:CC_NZ | |
3461 | (match_operator:SI 1 "intop_compare_operator" | |
3462 | [(match_operand:SI 2 "integer_register_operand" "d") | |
3463 | (match_operand:SI 3 "gpr_or_int10_operand" "dJ")]) | |
3464 | (const_int 0))) | |
36a05131 BS |
3465 | (set (match_operand:SI 4 "integer_register_operand" "=d") |
3466 | (match_operator:SI 5 "intop_compare_operator" | |
3467 | [(match_dup 2) | |
3468 | (match_dup 3)]))] | |
3469 | "GET_CODE (operands[1]) == GET_CODE (operands[5])" | |
3470 | "%O1%I3cc %2, %3, %4, %0" | |
3471 | [(set_attr "type" "int") | |
3472 | (set_attr "length" "4")]) | |
36a05131 BS |
3473 | \f |
3474 | ;; :::::::::::::::::::: | |
3475 | ;; :: | |
3476 | ;; :: Comparisons | |
3477 | ;; :: | |
3478 | ;; :::::::::::::::::::: | |
3479 | ||
f90b7a5a | 3480 | ;; The comparisons are generated by the branch and/or scc operations |
36a05131 BS |
3481 | |
3482 | (define_insn "cmpsi_cc" | |
3483 | [(set (match_operand:CC 0 "icc_operand" "=t,t") | |
3484 | (compare:CC (match_operand:SI 1 "integer_register_operand" "d,d") | |
3485 | (match_operand:SI 2 "gpr_or_int10_operand" "d,J")))] | |
3486 | "" | |
3487 | "cmp%I2 %1,%2,%0" | |
3488 | [(set_attr "length" "4") | |
3489 | (set_attr "type" "int")]) | |
3490 | ||
3491 | (define_insn "*cmpsi_cc_uns" | |
3492 | [(set (match_operand:CC_UNS 0 "icc_operand" "=t,t") | |
3493 | (compare:CC_UNS (match_operand:SI 1 "integer_register_operand" "d,d") | |
3494 | (match_operand:SI 2 "gpr_or_int10_operand" "d,J")))] | |
3495 | "" | |
3496 | "cmp%I2 %1,%2,%0" | |
3497 | [(set_attr "length" "4") | |
3498 | (set_attr "type" "int")]) | |
3499 | ||
036ff63f RS |
3500 | ;; The only requirement for a CC_NZmode GPR or memory value is that |
3501 | ;; comparing it against zero must set the Z and N flags appropriately. | |
3502 | ;; The source operand is therefore a valid CC_NZmode value. | |
3503 | (define_insn "*cmpsi_cc_nz" | |
3504 | [(set (match_operand:CC_NZ 0 "nonimmediate_operand" "=t,d,m") | |
3505 | (compare:CC_NZ (match_operand:SI 1 "integer_register_operand" "d,d,d") | |
3506 | (const_int 0)))] | |
3507 | "" | |
3508 | "@ | |
3509 | cmpi %1, #0, %0 | |
3510 | mov %1, %0 | |
3511 | st%I0%U0 %1, %M0" | |
3512 | [(set_attr "length" "4,4,4") | |
3513 | (set_attr "type" "int,int,gstore")]) | |
3514 | ||
36a05131 BS |
3515 | (define_insn "*cmpsf_cc_fp" |
3516 | [(set (match_operand:CC_FP 0 "fcc_operand" "=u") | |
3517 | (compare:CC_FP (match_operand:SF 1 "fpr_operand" "f") | |
3518 | (match_operand:SF 2 "fpr_operand" "f")))] | |
3519 | "TARGET_HARD_FLOAT" | |
3520 | "fcmps %1,%2,%0" | |
3521 | [(set_attr "length" "4") | |
c557edf4 | 3522 | (set_attr "type" "fscmp")]) |
36a05131 BS |
3523 | |
3524 | (define_insn "*cmpdf_cc_fp" | |
3525 | [(set (match_operand:CC_FP 0 "fcc_operand" "=u") | |
3526 | (compare:CC_FP (match_operand:DF 1 "even_fpr_operand" "h") | |
3527 | (match_operand:DF 2 "even_fpr_operand" "h")))] | |
3528 | "TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
3529 | "fcmpd %1,%2,%0" | |
3530 | [(set_attr "length" "4") | |
c557edf4 | 3531 | (set_attr "type" "fdcmp")]) |
36a05131 BS |
3532 | |
3533 | \f | |
3534 | ;; :::::::::::::::::::: | |
3535 | ;; :: | |
3536 | ;; :: Branches | |
3537 | ;; :: | |
3538 | ;; :::::::::::::::::::: | |
3539 | ||
3540 | ;; Define_expands called by the machine independent part of the compiler | |
f90b7a5a | 3541 | ;; to allocate a new comparison register. |
36a05131 | 3542 | |
f90b7a5a PB |
3543 | (define_expand "cbranchdf4" |
3544 | [(use (match_operator 0 "ordered_comparison_operator" | |
3545 | [(match_operand:DF 1 "fpr_operand" "") | |
3546 | (match_operand:DF 2 "fpr_operand" "")])) | |
3547 | (use (match_operand 3 ""))] | |
3548 | "TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
3549 | { if (frv_emit_cond_branch (operands)) DONE; gcc_unreachable (); }) | |
36a05131 | 3550 | |
f90b7a5a PB |
3551 | (define_expand "cbranchsf4" |
3552 | [(use (match_operator 0 "ordered_comparison_operator" | |
3553 | [(match_operand:SF 1 "fpr_operand" "") | |
3554 | (match_operand:SF 2 "fpr_operand" "")])) | |
3555 | (use (match_operand 3 ""))] | |
3556 | "TARGET_HARD_FLOAT" | |
3557 | { if (frv_emit_cond_branch (operands)) DONE; gcc_unreachable (); }) | |
36a05131 | 3558 | |
f90b7a5a PB |
3559 | (define_expand "cbranchsi4" |
3560 | [(use (match_operator 0 "ordered_comparison_operator" | |
3561 | [(match_operand:SI 1 "integer_register_operand" "") | |
3562 | (match_operand:SI 2 "gpr_or_int10_operand" "")])) | |
3563 | (use (match_operand 3 ""))] | |
36a05131 | 3564 | "" |
f90b7a5a | 3565 | { if (frv_emit_cond_branch (operands)) DONE; gcc_unreachable (); }) |
36a05131 BS |
3566 | |
3567 | ;; Actual branches. We must allow for the (label_ref) and the (pc) to be | |
3568 | ;; swapped. If they are swapped, it reverses the sense of the branch. | |
3569 | ;; | |
3570 | ;; Note - unlike the define expands above, these patterns can be amalgamated | |
3571 | ;; into one pattern for branch-if-true and one for branch-if-false. This does | |
3572 | ;; require an operand operator to select the correct branch mnemonic. | |
3573 | ;; | |
3574 | ;; If a fixed condition code register is being used, (as opposed to, say, | |
3575 | ;; using cc0), then the expands could look like this: | |
3576 | ;; | |
3577 | ;; (define_insn "*branch_true" | |
3578 | ;; [(set (pc) | |
3579 | ;; (if_then_else (match_operator:CC 0 "comparison_operator" | |
3580 | ;; [(reg:CC <number_of_CC_register>) | |
3581 | ;; (const_int 0)]) | |
3582 | ;; (label_ref (match_operand 1 "" "")) | |
3583 | ;; (pc)))] | |
3584 | ;; "" | |
3585 | ;; "b%B0 %1" | |
3586 | ;; [(set_attr "length" "4")] | |
3587 | ;; ) | |
3588 | ;; | |
3589 | ;; In the above example the %B is a directive to frv_print_operand() | |
3590 | ;; to decode and print the correct branch mnemonic. | |
3591 | ||
036ff63f | 3592 | (define_insn "*branch_int_true" |
36a05131 | 3593 | [(set (pc) |
036ff63f RS |
3594 | (if_then_else (match_operator 0 "integer_relational_operator" |
3595 | [(match_operand 1 "icc_operand" "t") | |
3596 | (const_int 0)]) | |
36a05131 BS |
3597 | (label_ref (match_operand 2 "" "")) |
3598 | (pc)))] | |
3599 | "" | |
3600 | "* | |
3601 | { | |
3602 | if (get_attr_length (insn) == 4) | |
3603 | return \"b%c0 %1,%#,%l2\"; | |
3604 | else | |
3605 | return \"b%C0 %1,%#,1f\;call %l2\\n1:\"; | |
3606 | }" | |
3607 | [(set (attr "length") | |
3608 | (if_then_else | |
3609 | (and (ge (minus (match_dup 2) (pc)) (const_int -32768)) | |
3610 | (le (minus (match_dup 2) (pc)) (const_int 32764))) | |
3611 | (const_int 4) | |
3612 | (const_int 8))) | |
3613 | (set (attr "far_jump") | |
3614 | (if_then_else | |
3615 | (eq_attr "length" "4") | |
3616 | (const_string "no") | |
3617 | (const_string "yes"))) | |
3618 | (set (attr "type") | |
3619 | (if_then_else | |
3620 | (eq_attr "length" "4") | |
3621 | (const_string "branch") | |
3622 | (const_string "multi")))]) | |
3623 | ||
036ff63f | 3624 | (define_insn "*branch_int_false" |
36a05131 | 3625 | [(set (pc) |
036ff63f RS |
3626 | (if_then_else (match_operator 0 "integer_relational_operator" |
3627 | [(match_operand 1 "icc_operand" "t") | |
3628 | (const_int 0)]) | |
36a05131 BS |
3629 | (pc) |
3630 | (label_ref (match_operand 2 "" ""))))] | |
3631 | "" | |
3632 | "* | |
3633 | { | |
3634 | if (get_attr_length (insn) == 4) | |
3635 | return \"b%C0 %1,%#,%l2\"; | |
3636 | else | |
3637 | return \"b%c0 %1,%#,1f\;call %l2\\n1:\"; | |
3638 | }" | |
3639 | [(set (attr "length") | |
3640 | (if_then_else | |
3641 | (and (ge (minus (match_dup 2) (pc)) (const_int -32768)) | |
3642 | (le (minus (match_dup 2) (pc)) (const_int 32764))) | |
3643 | (const_int 4) | |
3644 | (const_int 8))) | |
3645 | (set (attr "far_jump") | |
3646 | (if_then_else | |
3647 | (eq_attr "length" "4") | |
3648 | (const_string "no") | |
3649 | (const_string "yes"))) | |
3650 | (set (attr "type") | |
3651 | (if_then_else | |
3652 | (eq_attr "length" "4") | |
3653 | (const_string "branch") | |
3654 | (const_string "multi")))]) | |
3655 | ||
3656 | (define_insn "*branch_fp_true" | |
3657 | [(set (pc) | |
3658 | (if_then_else (match_operator:CC_FP 0 "float_relational_operator" | |
3659 | [(match_operand 1 "fcc_operand" "u") | |
3660 | (const_int 0)]) | |
3661 | (label_ref (match_operand 2 "" "")) | |
3662 | (pc)))] | |
3663 | "" | |
3664 | "* | |
3665 | { | |
3666 | if (get_attr_length (insn) == 4) | |
3667 | return \"fb%f0 %1,%#,%l2\"; | |
3668 | else | |
3669 | return \"fb%F0 %1,%#,1f\;call %l2\\n1:\"; | |
3670 | }" | |
3671 | [(set (attr "length") | |
3672 | (if_then_else | |
3673 | (and (ge (minus (match_dup 2) (pc)) (const_int -32768)) | |
3674 | (le (minus (match_dup 2) (pc)) (const_int 32764))) | |
3675 | (const_int 4) | |
3676 | (const_int 8))) | |
3677 | (set (attr "far_jump") | |
3678 | (if_then_else | |
3679 | (eq_attr "length" "4") | |
3680 | (const_string "no") | |
3681 | (const_string "yes"))) | |
3682 | (set (attr "type") | |
3683 | (if_then_else | |
3684 | (eq_attr "length" "4") | |
3685 | (const_string "branch") | |
3686 | (const_string "multi")))]) | |
3687 | ||
3688 | (define_insn "*branch_fp_false" | |
3689 | [(set (pc) | |
3690 | (if_then_else (match_operator:CC_FP 0 "float_relational_operator" | |
3691 | [(match_operand 1 "fcc_operand" "u") | |
3692 | (const_int 0)]) | |
3693 | (pc) | |
3694 | (label_ref (match_operand 2 "" ""))))] | |
3695 | "" | |
3696 | "* | |
3697 | { | |
3698 | if (get_attr_length (insn) == 4) | |
3699 | return \"fb%F0 %1,%#,%l2\"; | |
3700 | else | |
3701 | return \"fb%f0 %1,%#,1f\;call %l2\\n1:\"; | |
3702 | }" | |
3703 | [(set (attr "length") | |
3704 | (if_then_else | |
3705 | (and (ge (minus (match_dup 2) (pc)) (const_int -32768)) | |
3706 | (le (minus (match_dup 2) (pc)) (const_int 32764))) | |
3707 | (const_int 4) | |
3708 | (const_int 8))) | |
3709 | (set (attr "far_jump") | |
3710 | (if_then_else | |
3711 | (eq_attr "length" "4") | |
3712 | (const_string "no") | |
3713 | (const_string "yes"))) | |
3714 | (set (attr "type") | |
3715 | (if_then_else | |
3716 | (eq_attr "length" "4") | |
3717 | (const_string "branch") | |
3718 | (const_string "multi")))]) | |
3719 | ||
3720 | \f | |
3721 | ;; :::::::::::::::::::: | |
3722 | ;; :: | |
3723 | ;; :: Set flag operations | |
3724 | ;; :: | |
3725 | ;; :::::::::::::::::::: | |
3726 | ||
3727 | ;; Define_expands called by the machine independent part of the compiler | |
3728 | ;; to allocate a new comparison register | |
3729 | ||
f90b7a5a PB |
3730 | (define_expand "cstoredf4" |
3731 | [(use (match_operator:SI 1 "ordered_comparison_operator" | |
3732 | [(match_operand:DF 2 "fpr_operand") | |
3733 | (match_operand:DF 3 "fpr_operand")])) | |
3734 | (clobber (match_operand:SI 0 "register_operand"))] | |
3735 | "TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
3736 | { if (frv_emit_scc (operands)) DONE; else FAIL; }) | |
36a05131 | 3737 | |
f90b7a5a PB |
3738 | (define_expand "cstoresf4" |
3739 | [(use (match_operator:SI 1 "ordered_comparison_operator" | |
3740 | [(match_operand:SF 2 "fpr_operand") | |
3741 | (match_operand:SF 3 "fpr_operand")])) | |
3742 | (clobber (match_operand:SI 0 "register_operand"))] | |
3743 | "TARGET_HARD_FLOAT" | |
3744 | { if (frv_emit_scc (operands)) DONE; else FAIL; }) | |
36a05131 | 3745 | |
f90b7a5a PB |
3746 | (define_expand "cstoresi4" |
3747 | [(use (match_operator:SI 1 "ordered_comparison_operator" | |
3748 | [(match_operand:SI 2 "integer_register_operand") | |
3749 | (match_operand:SI 3 "gpr_or_int10_operand")])) | |
3750 | (clobber (match_operand:SI 0 "register_operand"))] | |
3751 | "" | |
3752 | { if (frv_emit_scc (operands)) DONE; else FAIL; }) | |
36a05131 | 3753 | |
036ff63f | 3754 | (define_insn "*scc_int" |
36a05131 | 3755 | [(set (match_operand:SI 0 "integer_register_operand" "=d") |
036ff63f RS |
3756 | (match_operator:SI 1 "integer_relational_operator" |
3757 | [(match_operand 2 "icc_operand" "t") | |
36a05131 BS |
3758 | (const_int 0)])) |
3759 | (clobber (match_operand:CC_CCR 3 "icr_operand" "=v"))] | |
3760 | "" | |
3761 | "#" | |
3762 | [(set_attr "length" "12") | |
3763 | (set_attr "type" "multi")]) | |
3764 | ||
3765 | (define_insn "*scc_float" | |
3766 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
3767 | (match_operator:SI 1 "float_relational_operator" | |
3768 | [(match_operand:CC_FP 2 "fcc_operand" "u") | |
3769 | (const_int 0)])) | |
3770 | (clobber (match_operand:CC_CCR 3 "fcr_operand" "=w"))] | |
3771 | "" | |
3772 | "#" | |
3773 | [(set_attr "length" "12") | |
3774 | (set_attr "type" "multi")]) | |
3775 | ||
3776 | ;; XXX -- add reload_completed to the splits, because register allocation | |
3777 | ;; currently isn't ready to see cond_exec packets. | |
3778 | (define_split | |
3779 | [(set (match_operand:SI 0 "integer_register_operand" "") | |
3780 | (match_operator:SI 1 "relational_operator" | |
3781 | [(match_operand 2 "cc_operand" "") | |
3782 | (const_int 0)])) | |
3783 | (clobber (match_operand 3 "cr_operand" ""))] | |
3784 | "reload_completed" | |
3785 | [(match_dup 4)] | |
3786 | "operands[4] = frv_split_scc (operands[0], operands[1], operands[2], | |
3787 | operands[3], (HOST_WIDE_INT) 1);") | |
3788 | ||
036ff63f | 3789 | (define_insn "*scc_neg1_int" |
36a05131 | 3790 | [(set (match_operand:SI 0 "integer_register_operand" "=d") |
036ff63f RS |
3791 | (neg:SI (match_operator:SI 1 "integer_relational_operator" |
3792 | [(match_operand 2 "icc_operand" "t") | |
36a05131 BS |
3793 | (const_int 0)]))) |
3794 | (clobber (match_operand:CC_CCR 3 "icr_operand" "=v"))] | |
3795 | "" | |
3796 | "#" | |
3797 | [(set_attr "length" "12") | |
3798 | (set_attr "type" "multi")]) | |
3799 | ||
3800 | (define_insn "*scc_neg1_float" | |
3801 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
3802 | (neg:SI (match_operator:SI 1 "float_relational_operator" | |
3803 | [(match_operand:CC_FP 2 "fcc_operand" "u") | |
3804 | (const_int 0)]))) | |
3805 | (clobber (match_operand:CC_CCR 3 "fcr_operand" "=w"))] | |
3806 | "" | |
3807 | "#" | |
3808 | [(set_attr "length" "12") | |
3809 | (set_attr "type" "multi")]) | |
3810 | ||
3811 | (define_split | |
3812 | [(set (match_operand:SI 0 "integer_register_operand" "") | |
3813 | (neg:SI (match_operator:SI 1 "relational_operator" | |
3814 | [(match_operand 2 "cc_operand" "") | |
3815 | (const_int 0)]))) | |
3816 | (clobber (match_operand 3 "cr_operand" ""))] | |
3817 | "reload_completed" | |
3818 | [(match_dup 4)] | |
3819 | "operands[4] = frv_split_scc (operands[0], operands[1], operands[2], | |
3820 | operands[3], (HOST_WIDE_INT) -1);") | |
3821 | ||
3822 | \f | |
3823 | ;; :::::::::::::::::::: | |
3824 | ;; :: | |
3825 | ;; :: Conditionally executed instructions | |
3826 | ;; :: | |
3827 | ;; :::::::::::::::::::: | |
3828 | ||
3829 | ;; Convert ICC/FCC comparison into CCR bits so we can do conditional execution | |
3830 | (define_insn "*ck_signed" | |
3831 | [(set (match_operand:CC_CCR 0 "icr_operand" "=v") | |
036ff63f RS |
3832 | (match_operator:CC_CCR 1 "integer_relational_operator" |
3833 | [(match_operand 2 "icc_operand" "t") | |
36a05131 BS |
3834 | (const_int 0)]))] |
3835 | "" | |
3836 | "ck%c1 %2, %0" | |
3837 | [(set_attr "length" "4") | |
3838 | (set_attr "type" "ccr")]) | |
3839 | ||
3840 | (define_insn "*fck_float" | |
3841 | [(set (match_operand:CC_CCR 0 "fcr_operand" "=w") | |
3842 | (match_operator:CC_CCR 1 "float_relational_operator" | |
3843 | [(match_operand:CC_FP 2 "fcc_operand" "u") | |
3844 | (const_int 0)]))] | |
3845 | "TARGET_HAS_FPRS" | |
3846 | "fck%c1 %2, %0" | |
3847 | [(set_attr "length" "4") | |
3848 | (set_attr "type" "ccr")]) | |
3849 | ||
3850 | ;; Conditionally convert ICC/FCC comparison into CCR bits to provide && and || | |
3851 | ;; tests in conditional execution | |
3852 | (define_insn "cond_exec_ck" | |
3853 | [(set (match_operand:CC_CCR 0 "cr_operand" "=v,w") | |
3854 | (if_then_else:CC_CCR (match_operator 1 "ccr_eqne_operator" | |
3855 | [(match_operand 2 "cr_operand" "C,C") | |
3856 | (const_int 0)]) | |
3857 | (match_operator 3 "relational_operator" | |
3858 | [(match_operand 4 "cc_operand" "t,u") | |
3859 | (const_int 0)]) | |
3860 | (const_int 0)))] | |
3861 | "" | |
3862 | "@ | |
3863 | cck%c3 %4, %0, %2, %e1 | |
3864 | cfck%f3 %4, %0, %2, %e1" | |
3865 | [(set_attr "length" "4") | |
3866 | (set_attr "type" "ccr")]) | |
3867 | ||
3868 | ;; Conditionally set a register to either 0 or another register | |
3869 | (define_insn "*cond_exec_movqi" | |
3870 | [(cond_exec | |
3871 | (match_operator 0 "ccr_eqne_operator" | |
3872 | [(match_operand 1 "cr_operand" "C,C,C,C,C,C") | |
3873 | (const_int 0)]) | |
3874 | (set (match_operand:QI 2 "condexec_dest_operand" "=d,d,U,?f,?f,?d") | |
3875 | (match_operand:QI 3 "condexec_source_operand" "dO,U,dO,f,d,f")))] | |
3876 | "register_operand(operands[2], QImode) || reg_or_0_operand (operands[3], QImode)" | |
3877 | "* return output_condmove_single (operands, insn);" | |
3878 | [(set_attr "length" "4") | |
3879 | (set_attr "type" "int,gload,gstore,fsconv,movgf,movfg")]) | |
3880 | ||
3881 | (define_insn "*cond_exec_movhi" | |
3882 | [(cond_exec | |
3883 | (match_operator 0 "ccr_eqne_operator" | |
3884 | [(match_operand 1 "cr_operand" "C,C,C,C,C,C") | |
3885 | (const_int 0)]) | |
3886 | (set (match_operand:HI 2 "condexec_dest_operand" "=d,d,U,?f,?f,?d") | |
3887 | (match_operand:HI 3 "condexec_source_operand" "dO,U,dO,f,d,f")))] | |
3888 | "register_operand(operands[2], HImode) || reg_or_0_operand (operands[3], HImode)" | |
3889 | "* return output_condmove_single (operands, insn);" | |
3890 | [(set_attr "length" "4") | |
3891 | (set_attr "type" "int,gload,gstore,fsconv,movgf,movfg")]) | |
3892 | ||
3893 | (define_insn "*cond_exec_movsi" | |
3894 | [(cond_exec | |
3895 | (match_operator 0 "ccr_eqne_operator" | |
3896 | [(match_operand 1 "cr_operand" "C,C,C,C,C,C,C,C") | |
3897 | (const_int 0)]) | |
3898 | (set (match_operand:SI 2 "condexec_dest_operand" "=d,d,U,?f,?f,?d,?f,?m") | |
3899 | (match_operand:SI 3 "condexec_source_operand" "dO,U,dO,f,d,f,m,f")))] | |
3900 | "register_operand(operands[2], SImode) || reg_or_0_operand (operands[3], SImode)" | |
3901 | "* return output_condmove_single (operands, insn);" | |
3902 | [(set_attr "length" "4") | |
3903 | (set_attr "type" "int,gload,gstore,fsconv,movgf,movfg,fload,fstore")]) | |
3904 | ||
3905 | ||
3906 | (define_insn "*cond_exec_movsf_has_fprs" | |
3907 | [(cond_exec | |
3908 | (match_operator 0 "ccr_eqne_operator" | |
3909 | [(match_operand 1 "cr_operand" "C,C,C,C,C,C,C,C,C,C") | |
3910 | (const_int 0)]) | |
3911 | (set (match_operand:SF 2 "condexec_dest_operand" "=f,?d,?d,?f,f,f,?d,U,?U,U") | |
3912 | (match_operand:SF 3 "condexec_source_operand" "f,d,f,d,G,U,U,f,d,G")))] | |
3913 | "TARGET_HAS_FPRS" | |
3914 | "* return output_condmove_single (operands, insn);" | |
3915 | [(set_attr "length" "4") | |
3916 | (set_attr "type" "fsconv,int,movgf,movfg,movgf,fload,gload,fstore,gstore,gstore")]) | |
3917 | ||
3918 | (define_insn "*cond_exec_movsf_no_fprs" | |
3919 | [(cond_exec | |
3920 | (match_operator 0 "ccr_eqne_operator" | |
3921 | [(match_operand 1 "cr_operand" "C,C,C") | |
3922 | (const_int 0)]) | |
3923 | (set (match_operand:SF 2 "condexec_dest_operand" "=d,d,U") | |
3924 | (match_operand:SF 3 "condexec_source_operand" "d,U,dG")))] | |
3925 | "! TARGET_HAS_FPRS" | |
3926 | "* return output_condmove_single (operands, insn);" | |
3927 | [(set_attr "length" "4") | |
3928 | (set_attr "type" "int,gload,gstore")]) | |
3929 | ||
3930 | (define_insn "*cond_exec_si_binary1" | |
3931 | [(cond_exec | |
3932 | (match_operator 0 "ccr_eqne_operator" | |
3933 | [(match_operand 1 "cr_operand" "C") | |
3934 | (const_int 0)]) | |
3935 | (set (match_operand:SI 2 "integer_register_operand" "=d") | |
3936 | (match_operator:SI 3 "condexec_si_binary_operator" | |
3937 | [(match_operand:SI 4 "integer_register_operand" "d") | |
3938 | (match_operand:SI 5 "integer_register_operand" "d")])))] | |
3939 | "" | |
3940 | "* | |
3941 | { | |
3942 | switch (GET_CODE (operands[3])) | |
3943 | { | |
3944 | case PLUS: return \"cadd %4, %z5, %2, %1, %e0\"; | |
3945 | case MINUS: return \"csub %4, %z5, %2, %1, %e0\"; | |
3946 | case AND: return \"cand %4, %z5, %2, %1, %e0\"; | |
3947 | case IOR: return \"cor %4, %z5, %2, %1, %e0\"; | |
3948 | case XOR: return \"cxor %4, %z5, %2, %1, %e0\"; | |
3949 | case ASHIFT: return \"csll %4, %z5, %2, %1, %e0\"; | |
3950 | case ASHIFTRT: return \"csra %4, %z5, %2, %1, %e0\"; | |
3951 | case LSHIFTRT: return \"csrl %4, %z5, %2, %1, %e0\"; | |
44e91694 | 3952 | default: gcc_unreachable (); |
36a05131 BS |
3953 | } |
3954 | }" | |
3955 | [(set_attr "length" "4") | |
3956 | (set_attr "type" "int")]) | |
3957 | ||
3958 | (define_insn "*cond_exec_si_binary2" | |
3959 | [(cond_exec | |
3960 | (match_operator 0 "ccr_eqne_operator" | |
3961 | [(match_operand 1 "cr_operand" "C") | |
3962 | (const_int 0)]) | |
3963 | (set (match_operand:SI 2 "fpr_operand" "=f") | |
3964 | (match_operator:SI 3 "condexec_si_media_operator" | |
3965 | [(match_operand:SI 4 "fpr_operand" "f") | |
3966 | (match_operand:SI 5 "fpr_operand" "f")])))] | |
3967 | "TARGET_MEDIA" | |
3968 | "* | |
3969 | { | |
3970 | switch (GET_CODE (operands[3])) | |
3971 | { | |
3972 | case AND: return \"cmand %4, %5, %2, %1, %e0\"; | |
3973 | case IOR: return \"cmor %4, %5, %2, %1, %e0\"; | |
3974 | case XOR: return \"cmxor %4, %5, %2, %1, %e0\"; | |
44e91694 | 3975 | default: gcc_unreachable (); |
36a05131 BS |
3976 | } |
3977 | }" | |
3978 | [(set_attr "length" "4") | |
3979 | (set_attr "type" "mlogic")]) | |
3980 | ||
3981 | ;; Note, flow does not (currently) know how to handle an operation that uses | |
3982 | ;; only part of the hard registers allocated for a multiregister value, such as | |
3983 | ;; DImode in this case if the user is only interested in the lower 32-bits. So | |
3984 | ;; we emit a USE of the entire register after the csmul instruction so it won't | |
3985 | ;; get confused. See frv_ifcvt_modify_insn for more details. | |
3986 | ||
3987 | (define_insn "*cond_exec_si_smul" | |
3988 | [(cond_exec | |
3989 | (match_operator 0 "ccr_eqne_operator" | |
3990 | [(match_operand 1 "cr_operand" "C") | |
3991 | (const_int 0)]) | |
3992 | (set (match_operand:DI 2 "even_gpr_operand" "=e") | |
3993 | (mult:DI (sign_extend:DI (match_operand:SI 3 "integer_register_operand" "%d")) | |
3994 | (sign_extend:DI (match_operand:SI 4 "integer_register_operand" "d")))))] | |
3995 | "" | |
3996 | "csmul %3, %4, %2, %1, %e0" | |
3997 | [(set_attr "length" "4") | |
3998 | (set_attr "type" "mul")]) | |
3999 | ||
4000 | (define_insn "*cond_exec_si_divide" | |
4001 | [(cond_exec | |
4002 | (match_operator 0 "ccr_eqne_operator" | |
4003 | [(match_operand 1 "cr_operand" "C") | |
4004 | (const_int 0)]) | |
4005 | (set (match_operand:SI 2 "integer_register_operand" "=d") | |
4006 | (match_operator:SI 3 "condexec_si_divide_operator" | |
4007 | [(match_operand:SI 4 "integer_register_operand" "d") | |
4008 | (match_operand:SI 5 "integer_register_operand" "d")])))] | |
4009 | "" | |
4010 | "* | |
4011 | { | |
4012 | switch (GET_CODE (operands[3])) | |
4013 | { | |
4014 | case DIV: return \"csdiv %4, %z5, %2, %1, %e0\"; | |
4015 | case UDIV: return \"cudiv %4, %z5, %2, %1, %e0\"; | |
44e91694 | 4016 | default: gcc_unreachable (); |
36a05131 BS |
4017 | } |
4018 | }" | |
4019 | [(set_attr "length" "4") | |
4020 | (set_attr "type" "div")]) | |
4021 | ||
4022 | (define_insn "*cond_exec_si_unary1" | |
4023 | [(cond_exec | |
4024 | (match_operator 0 "ccr_eqne_operator" | |
4025 | [(match_operand 1 "cr_operand" "C") | |
4026 | (const_int 0)]) | |
4027 | (set (match_operand:SI 2 "integer_register_operand" "=d") | |
4028 | (match_operator:SI 3 "condexec_si_unary_operator" | |
4029 | [(match_operand:SI 4 "integer_register_operand" "d")])))] | |
4030 | "" | |
4031 | "* | |
4032 | { | |
4033 | switch (GET_CODE (operands[3])) | |
4034 | { | |
4035 | case NOT: return \"cnot %4, %2, %1, %e0\"; | |
4036 | case NEG: return \"csub %., %4, %2, %1, %e0\"; | |
44e91694 | 4037 | default: gcc_unreachable (); |
36a05131 BS |
4038 | } |
4039 | }" | |
4040 | [(set_attr "length" "4") | |
4041 | (set_attr "type" "int")]) | |
4042 | ||
4043 | (define_insn "*cond_exec_si_unary2" | |
4044 | [(cond_exec | |
4045 | (match_operator 0 "ccr_eqne_operator" | |
4046 | [(match_operand 1 "cr_operand" "C") | |
4047 | (const_int 0)]) | |
4048 | (set (match_operand:SI 2 "fpr_operand" "=f") | |
4049 | (not:SI (match_operand:SI 3 "fpr_operand" "f"))))] | |
4050 | "TARGET_MEDIA" | |
4051 | "cmnot %3, %2, %1, %e0" | |
4052 | [(set_attr "length" "4") | |
4053 | (set_attr "type" "mlogic")]) | |
4054 | ||
4055 | (define_insn "*cond_exec_cmpsi_cc" | |
4056 | [(cond_exec | |
4057 | (match_operator 0 "ccr_eqne_operator" | |
4058 | [(match_operand 1 "cr_operand" "C") | |
4059 | (const_int 0)]) | |
4060 | (set (match_operand:CC 2 "icc_operand" "=t") | |
4061 | (compare:CC (match_operand:SI 3 "integer_register_operand" "d") | |
4062 | (match_operand:SI 4 "reg_or_0_operand" "dO"))))] | |
4063 | "reload_completed | |
4064 | && REGNO (operands[1]) == REGNO (operands[2]) - ICC_FIRST + ICR_FIRST" | |
4065 | "ccmp %3, %z4, %1, %e0" | |
4066 | [(set_attr "length" "4") | |
4067 | (set_attr "type" "int")]) | |
4068 | ||
4069 | (define_insn "*cond_exec_cmpsi_cc_uns" | |
4070 | [(cond_exec | |
4071 | (match_operator 0 "ccr_eqne_operator" | |
4072 | [(match_operand 1 "cr_operand" "C") | |
4073 | (const_int 0)]) | |
4074 | (set (match_operand:CC_UNS 2 "icc_operand" "=t") | |
4075 | (compare:CC_UNS (match_operand:SI 3 "integer_register_operand" "d") | |
4076 | (match_operand:SI 4 "reg_or_0_operand" "dO"))))] | |
4077 | "reload_completed | |
4078 | && REGNO (operands[1]) == REGNO (operands[2]) - ICC_FIRST + ICR_FIRST" | |
4079 | "ccmp %3, %z4, %1, %e0" | |
4080 | [(set_attr "length" "4") | |
4081 | (set_attr "type" "int")]) | |
4082 | ||
036ff63f RS |
4083 | (define_insn "*cond_exec_cmpsi_cc_nz" |
4084 | [(cond_exec | |
4085 | (match_operator 0 "ccr_eqne_operator" | |
4086 | [(match_operand 1 "cr_operand" "C") | |
4087 | (const_int 0)]) | |
4088 | (set (match_operand:CC_NZ 2 "icc_operand" "=t") | |
4089 | (compare:CC_NZ (match_operand:SI 3 "integer_register_operand" "d") | |
4090 | (const_int 0))))] | |
4091 | "reload_completed | |
4092 | && REGNO (operands[1]) == REGNO (operands[2]) - ICC_FIRST + ICR_FIRST" | |
4093 | "ccmp %3, %., %1, %e0" | |
4094 | [(set_attr "length" "4") | |
4095 | (set_attr "type" "int")]) | |
4096 | ||
36a05131 BS |
4097 | (define_insn "*cond_exec_sf_conv" |
4098 | [(cond_exec | |
4099 | (match_operator 0 "ccr_eqne_operator" | |
4100 | [(match_operand 1 "cr_operand" "C") | |
4101 | (const_int 0)]) | |
4102 | (set (match_operand:SF 2 "fpr_operand" "=f") | |
4103 | (match_operator:SF 3 "condexec_sf_conv_operator" | |
4104 | [(match_operand:SF 4 "fpr_operand" "f")])))] | |
4105 | "TARGET_HARD_FLOAT" | |
4106 | "* | |
4107 | { | |
4108 | switch (GET_CODE (operands[3])) | |
4109 | { | |
4110 | case ABS: return \"cfabss %4, %2, %1, %e0\"; | |
4111 | case NEG: return \"cfnegs %4, %2, %1, %e0\"; | |
44e91694 | 4112 | default: gcc_unreachable (); |
36a05131 BS |
4113 | } |
4114 | }" | |
4115 | [(set_attr "length" "4") | |
4116 | (set_attr "type" "fsconv")]) | |
4117 | ||
4118 | (define_insn "*cond_exec_sf_add" | |
4119 | [(cond_exec | |
4120 | (match_operator 0 "ccr_eqne_operator" | |
4121 | [(match_operand 1 "cr_operand" "C") | |
4122 | (const_int 0)]) | |
4123 | (set (match_operand:SF 2 "fpr_operand" "=f") | |
4124 | (match_operator:SF 3 "condexec_sf_add_operator" | |
4125 | [(match_operand:SF 4 "fpr_operand" "f") | |
4126 | (match_operand:SF 5 "fpr_operand" "f")])))] | |
4127 | "TARGET_HARD_FLOAT" | |
4128 | "* | |
4129 | { | |
4130 | switch (GET_CODE (operands[3])) | |
4131 | { | |
4132 | case PLUS: return \"cfadds %4, %5, %2, %1, %e0\"; | |
4133 | case MINUS: return \"cfsubs %4, %5, %2, %1, %e0\"; | |
44e91694 | 4134 | default: gcc_unreachable (); |
36a05131 BS |
4135 | } |
4136 | }" | |
4137 | [(set_attr "length" "4") | |
4138 | (set_attr "type" "fsadd")]) | |
4139 | ||
4140 | (define_insn "*cond_exec_sf_mul" | |
4141 | [(cond_exec | |
4142 | (match_operator 0 "ccr_eqne_operator" | |
4143 | [(match_operand 1 "cr_operand" "C") | |
4144 | (const_int 0)]) | |
4145 | (set (match_operand:SF 2 "fpr_operand" "=f") | |
4146 | (mult:SF (match_operand:SF 3 "fpr_operand" "f") | |
4147 | (match_operand:SF 4 "fpr_operand" "f"))))] | |
4148 | "TARGET_HARD_FLOAT" | |
4149 | "cfmuls %3, %4, %2, %1, %e0" | |
4150 | [(set_attr "length" "4") | |
4151 | (set_attr "type" "fsmul")]) | |
4152 | ||
4153 | (define_insn "*cond_exec_sf_div" | |
4154 | [(cond_exec | |
4155 | (match_operator 0 "ccr_eqne_operator" | |
4156 | [(match_operand 1 "cr_operand" "C") | |
4157 | (const_int 0)]) | |
4158 | (set (match_operand:SF 2 "fpr_operand" "=f") | |
4159 | (div:SF (match_operand:SF 3 "fpr_operand" "f") | |
4160 | (match_operand:SF 4 "fpr_operand" "f"))))] | |
4161 | "TARGET_HARD_FLOAT" | |
4162 | "cfdivs %3, %4, %2, %1, %e0" | |
4163 | [(set_attr "length" "4") | |
4164 | (set_attr "type" "fsdiv")]) | |
4165 | ||
4166 | (define_insn "*cond_exec_sf_sqrt" | |
4167 | [(cond_exec | |
4168 | (match_operator 0 "ccr_eqne_operator" | |
4169 | [(match_operand 1 "cr_operand" "C") | |
4170 | (const_int 0)]) | |
4171 | (set (match_operand:SF 2 "fpr_operand" "=f") | |
4172 | (sqrt:SF (match_operand:SF 3 "fpr_operand" "f"))))] | |
4173 | "TARGET_HARD_FLOAT" | |
4174 | "cfsqrts %3, %2, %1, %e0" | |
4175 | [(set_attr "length" "4") | |
4176 | (set_attr "type" "fsdiv")]) | |
4177 | ||
4178 | (define_insn "*cond_exec_cmpsi_cc_fp" | |
4179 | [(cond_exec | |
4180 | (match_operator 0 "ccr_eqne_operator" | |
4181 | [(match_operand 1 "cr_operand" "C") | |
4182 | (const_int 0)]) | |
4183 | (set (match_operand:CC_FP 2 "fcc_operand" "=u") | |
4184 | (compare:CC_FP (match_operand:SF 3 "fpr_operand" "f") | |
4185 | (match_operand:SF 4 "fpr_operand" "f"))))] | |
4186 | "reload_completed && TARGET_HARD_FLOAT | |
4187 | && REGNO (operands[1]) == REGNO (operands[2]) - FCC_FIRST + FCR_FIRST" | |
4188 | "cfcmps %3, %4, %2, %1, %e0" | |
4189 | [(set_attr "length" "4") | |
4190 | (set_attr "type" "fsconv")]) | |
4191 | ||
4192 | \f | |
4193 | ;; :::::::::::::::::::: | |
4194 | ;; :: | |
4195 | ;; :: Logical operations on CR registers | |
4196 | ;; :: | |
4197 | ;; :::::::::::::::::::: | |
4198 | ||
4199 | ;; We use UNSPEC to encode andcr/iorcr/etc. rather than the normal RTL | |
4200 | ;; operations, since the RTL operations only have an idea of TRUE and FALSE, | |
4201 | ;; while the CRs have TRUE, FALSE, and UNDEFINED. | |
4202 | ||
4203 | (define_expand "andcr" | |
4204 | [(set (match_operand:CC_CCR 0 "cr_operand" "") | |
4205 | (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") | |
4206 | (match_operand:CC_CCR 2 "cr_operand" "") | |
4207 | (const_int 0)] UNSPEC_CR_LOGIC))] | |
4208 | "" | |
4209 | "") | |
4210 | ||
4211 | (define_expand "orcr" | |
4212 | [(set (match_operand:CC_CCR 0 "cr_operand" "") | |
4213 | (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") | |
4214 | (match_operand:CC_CCR 2 "cr_operand" "") | |
4215 | (const_int 1)] UNSPEC_CR_LOGIC))] | |
4216 | "" | |
4217 | "") | |
4218 | ||
4219 | (define_expand "xorcr" | |
4220 | [(set (match_operand:CC_CCR 0 "cr_operand" "") | |
4221 | (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") | |
4222 | (match_operand:CC_CCR 2 "cr_operand" "") | |
4223 | (const_int 2)] UNSPEC_CR_LOGIC))] | |
4224 | "" | |
4225 | "") | |
4226 | ||
4227 | (define_expand "nandcr" | |
4228 | [(set (match_operand:CC_CCR 0 "cr_operand" "") | |
4229 | (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") | |
4230 | (match_operand:CC_CCR 2 "cr_operand" "") | |
4231 | (const_int 3)] UNSPEC_CR_LOGIC))] | |
4232 | "" | |
4233 | "") | |
4234 | ||
4235 | (define_expand "norcr" | |
4236 | [(set (match_operand:CC_CCR 0 "cr_operand" "") | |
4237 | (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") | |
4238 | (match_operand:CC_CCR 2 "cr_operand" "") | |
4239 | (const_int 4)] UNSPEC_CR_LOGIC))] | |
4240 | "" | |
4241 | "") | |
4242 | ||
4243 | (define_expand "andncr" | |
4244 | [(set (match_operand:CC_CCR 0 "cr_operand" "") | |
4245 | (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") | |
4246 | (match_operand:CC_CCR 2 "cr_operand" "") | |
4247 | (const_int 5)] UNSPEC_CR_LOGIC))] | |
4248 | "" | |
4249 | "") | |
4250 | ||
4251 | (define_expand "orncr" | |
4252 | [(set (match_operand:CC_CCR 0 "cr_operand" "") | |
4253 | (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") | |
4254 | (match_operand:CC_CCR 2 "cr_operand" "") | |
4255 | (const_int 6)] UNSPEC_CR_LOGIC))] | |
4256 | "" | |
4257 | "") | |
4258 | ||
4259 | (define_expand "nandncr" | |
4260 | [(set (match_operand:CC_CCR 0 "cr_operand" "") | |
4261 | (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") | |
4262 | (match_operand:CC_CCR 2 "cr_operand" "") | |
4263 | (const_int 7)] UNSPEC_CR_LOGIC))] | |
4264 | "" | |
4265 | "") | |
4266 | ||
4267 | (define_expand "norncr" | |
4268 | [(set (match_operand:CC_CCR 0 "cr_operand" "") | |
4269 | (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") | |
4270 | (match_operand:CC_CCR 2 "cr_operand" "") | |
4271 | (const_int 8)] UNSPEC_CR_LOGIC))] | |
4272 | "" | |
4273 | "") | |
4274 | ||
4275 | (define_expand "notcr" | |
4276 | [(set (match_operand:CC_CCR 0 "cr_operand" "") | |
4277 | (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") | |
4278 | (match_dup 1) | |
4279 | (const_int 9)] UNSPEC_CR_LOGIC))] | |
4280 | "" | |
4281 | "") | |
4282 | ||
4283 | (define_insn "*logical_cr" | |
4284 | [(set (match_operand:CC_CCR 0 "cr_operand" "=C") | |
4285 | (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "C") | |
4286 | (match_operand:CC_CCR 2 "cr_operand" "C") | |
4287 | (match_operand:SI 3 "const_int_operand" "n")] | |
4288 | UNSPEC_CR_LOGIC))] | |
4289 | "" | |
4290 | "* | |
4291 | { | |
4292 | switch (INTVAL (operands[3])) | |
4293 | { | |
4294 | default: break; | |
4295 | case 0: return \"andcr %1, %2, %0\"; | |
4296 | case 1: return \"orcr %1, %2, %0\"; | |
4297 | case 2: return \"xorcr %1, %2, %0\"; | |
4298 | case 3: return \"nandcr %1, %2, %0\"; | |
4299 | case 4: return \"norcr %1, %2, %0\"; | |
4300 | case 5: return \"andncr %1, %2, %0\"; | |
4301 | case 6: return \"orncr %1, %2, %0\"; | |
4302 | case 7: return \"nandncr %1, %2, %0\"; | |
4303 | case 8: return \"norncr %1, %2, %0\"; | |
4304 | case 9: return \"notcr %1, %0\"; | |
4305 | } | |
4306 | ||
4307 | fatal_insn (\"logical_cr\", insn); | |
4308 | }" | |
4309 | [(set_attr "length" "4") | |
4310 | (set_attr "type" "ccr")]) | |
4311 | ||
4312 | \f | |
4313 | ;; :::::::::::::::::::: | |
4314 | ;; :: | |
4315 | ;; :: Conditional move instructions | |
4316 | ;; :: | |
4317 | ;; :::::::::::::::::::: | |
4318 | ||
4319 | ||
4320 | ;; - conditional moves based on floating-point comparisons require | |
4321 | ;; TARGET_HARD_FLOAT, because an FPU is required to do the comparison. | |
4322 | ||
4323 | ;; - conditional moves between FPRs based on integer comparisons | |
4324 | ;; require TARGET_HAS_FPRS. | |
4325 | ||
4326 | (define_expand "movqicc" | |
4327 | [(set (match_operand:QI 0 "integer_register_operand" "") | |
4328 | (if_then_else:QI (match_operand 1 "" "") | |
4329 | (match_operand:QI 2 "gpr_or_int_operand" "") | |
4330 | (match_operand:QI 3 "gpr_or_int_operand" "")))] | |
4331 | "TARGET_COND_MOVE" | |
4332 | " | |
4333 | { | |
4334 | if (!frv_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) | |
4335 | FAIL; | |
4336 | ||
4337 | DONE; | |
4338 | }") | |
4339 | ||
036ff63f | 4340 | (define_insn "*movqicc_internal1_int" |
36a05131 | 4341 | [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d") |
036ff63f RS |
4342 | (if_then_else:QI (match_operator 1 "integer_relational_operator" |
4343 | [(match_operand 2 "icc_operand" "t,t,t") | |
36a05131 BS |
4344 | (const_int 0)]) |
4345 | (match_operand:QI 3 "reg_or_0_operand" "0,dO,dO") | |
4346 | (match_operand:QI 4 "reg_or_0_operand" "dO,0,dO"))) | |
4347 | (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] | |
4348 | "" | |
4349 | "#" | |
4350 | [(set_attr "length" "8,8,12") | |
4351 | (set_attr "type" "multi")]) | |
4352 | ||
4353 | (define_insn "*movqicc_internal1_float" | |
4354 | [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d") | |
4355 | (if_then_else:QI (match_operator:CC_FP 1 "float_relational_operator" | |
4356 | [(match_operand:CC_FP 2 "fcc_operand" "u,u,u") | |
4357 | (const_int 0)]) | |
4358 | (match_operand:QI 3 "reg_or_0_operand" "0,dO,dO") | |
4359 | (match_operand:QI 4 "reg_or_0_operand" "dO,0,dO"))) | |
4360 | (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))] | |
4361 | "TARGET_HARD_FLOAT" | |
4362 | "#" | |
4363 | [(set_attr "length" "8,8,12") | |
4364 | (set_attr "type" "multi")]) | |
4365 | ||
036ff63f | 4366 | (define_insn "*movqicc_internal2_int" |
36a05131 | 4367 | [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d,d,d") |
036ff63f RS |
4368 | (if_then_else:QI (match_operator 1 "integer_relational_operator" |
4369 | [(match_operand 2 "icc_operand" "t,t,t,t,t") | |
36a05131 BS |
4370 | (const_int 0)]) |
4371 | (match_operand:QI 3 "const_int_operand" "O,O,L,n,n") | |
4372 | (match_operand:QI 4 "const_int_operand" "L,n,O,O,n"))) | |
4373 | (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))] | |
4374 | "(INTVAL (operands[3]) == 0 | |
4375 | || INTVAL (operands[4]) == 0 | |
2f5b1308 JR |
4376 | || (IN_RANGE (INTVAL (operands[3]), -2048, 2047) |
4377 | && IN_RANGE (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" | |
36a05131 BS |
4378 | "#" |
4379 | [(set_attr "length" "8,12,8,12,12") | |
4380 | (set_attr "type" "multi")]) | |
4381 | ||
4382 | (define_insn "*movqicc_internal2_float" | |
4383 | [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d,d,d") | |
4384 | (if_then_else:QI (match_operator:CC_FP 1 "float_relational_operator" | |
4385 | [(match_operand:CC_FP 2 "fcc_operand" "u,u,u,u,u") | |
4386 | (const_int 0)]) | |
4387 | (match_operand:QI 3 "const_int_operand" "O,O,L,n,n") | |
4388 | (match_operand:QI 4 "const_int_operand" "L,n,O,O,n"))) | |
4389 | (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w,w,w"))] | |
4390 | "TARGET_HARD_FLOAT | |
4391 | && (INTVAL (operands[3]) == 0 | |
4392 | || INTVAL (operands[4]) == 0 | |
2f5b1308 JR |
4393 | || (IN_RANGE (INTVAL (operands[3]), -2048, 2047) |
4394 | && IN_RANGE (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" | |
36a05131 BS |
4395 | "#" |
4396 | [(set_attr "length" "8,12,8,12,12") | |
4397 | (set_attr "type" "multi")]) | |
4398 | ||
4399 | (define_split | |
4400 | [(set (match_operand:QI 0 "integer_register_operand" "") | |
4401 | (if_then_else:QI (match_operator 1 "relational_operator" | |
4402 | [(match_operand 2 "cc_operand" "") | |
4403 | (const_int 0)]) | |
4404 | (match_operand:QI 3 "gpr_or_int_operand" "") | |
4405 | (match_operand:QI 4 "gpr_or_int_operand" ""))) | |
4406 | (clobber (match_operand:CC_CCR 5 "cr_operand" ""))] | |
4407 | "reload_completed" | |
4408 | [(match_dup 6)] | |
4409 | "operands[6] = frv_split_cond_move (operands);") | |
4410 | ||
4411 | (define_expand "movhicc" | |
4412 | [(set (match_operand:HI 0 "integer_register_operand" "") | |
4413 | (if_then_else:HI (match_operand 1 "" "") | |
4414 | (match_operand:HI 2 "gpr_or_int_operand" "") | |
4415 | (match_operand:HI 3 "gpr_or_int_operand" "")))] | |
4416 | "TARGET_COND_MOVE" | |
4417 | " | |
4418 | { | |
4419 | if (!frv_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) | |
4420 | FAIL; | |
4421 | ||
4422 | DONE; | |
4423 | }") | |
4424 | ||
036ff63f | 4425 | (define_insn "*movhicc_internal1_int" |
36a05131 | 4426 | [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d") |
036ff63f RS |
4427 | (if_then_else:HI (match_operator 1 "integer_relational_operator" |
4428 | [(match_operand 2 "icc_operand" "t,t,t") | |
36a05131 BS |
4429 | (const_int 0)]) |
4430 | (match_operand:HI 3 "reg_or_0_operand" "0,dO,dO") | |
4431 | (match_operand:HI 4 "reg_or_0_operand" "dO,0,dO"))) | |
4432 | (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] | |
4433 | "" | |
4434 | "#" | |
4435 | [(set_attr "length" "8,8,12") | |
4436 | (set_attr "type" "multi")]) | |
4437 | ||
4438 | (define_insn "*movhicc_internal1_float" | |
4439 | [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d") | |
4440 | (if_then_else:HI (match_operator:CC_FP 1 "float_relational_operator" | |
4441 | [(match_operand:CC_FP 2 "fcc_operand" "u,u,u") | |
4442 | (const_int 0)]) | |
4443 | (match_operand:HI 3 "reg_or_0_operand" "0,dO,dO") | |
4444 | (match_operand:HI 4 "reg_or_0_operand" "dO,0,dO"))) | |
4445 | (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))] | |
4446 | "TARGET_HARD_FLOAT" | |
4447 | "#" | |
4448 | [(set_attr "length" "8,8,12") | |
4449 | (set_attr "type" "multi")]) | |
4450 | ||
036ff63f | 4451 | (define_insn "*movhicc_internal2_int" |
36a05131 | 4452 | [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d,d,d") |
036ff63f RS |
4453 | (if_then_else:HI (match_operator 1 "integer_relational_operator" |
4454 | [(match_operand 2 "icc_operand" "t,t,t,t,t") | |
36a05131 BS |
4455 | (const_int 0)]) |
4456 | (match_operand:HI 3 "const_int_operand" "O,O,L,n,n") | |
4457 | (match_operand:HI 4 "const_int_operand" "L,n,O,O,n"))) | |
4458 | (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))] | |
4459 | "(INTVAL (operands[3]) == 0 | |
4460 | || INTVAL (operands[4]) == 0 | |
2f5b1308 JR |
4461 | || (IN_RANGE (INTVAL (operands[3]), -2048, 2047) |
4462 | && IN_RANGE (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" | |
36a05131 BS |
4463 | "#" |
4464 | [(set_attr "length" "8,12,8,12,12") | |
4465 | (set_attr "type" "multi")]) | |
4466 | ||
4467 | (define_insn "*movhicc_internal2_float" | |
4468 | [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d,d,d") | |
4469 | (if_then_else:HI (match_operator:CC_FP 1 "float_relational_operator" | |
4470 | [(match_operand:CC_FP 2 "fcc_operand" "u,u,u,u,u") | |
4471 | (const_int 0)]) | |
4472 | (match_operand:HI 3 "const_int_operand" "O,O,L,n,n") | |
4473 | (match_operand:HI 4 "const_int_operand" "L,n,O,O,n"))) | |
4474 | (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w,w,w"))] | |
4475 | "TARGET_HARD_FLOAT | |
4476 | && (INTVAL (operands[3]) == 0 | |
4477 | || INTVAL (operands[4]) == 0 | |
2f5b1308 JR |
4478 | || (IN_RANGE (INTVAL (operands[3]), -2048, 2047) |
4479 | && IN_RANGE (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" | |
36a05131 BS |
4480 | "#" |
4481 | [(set_attr "length" "8,12,8,12,12") | |
4482 | (set_attr "type" "multi")]) | |
4483 | ||
4484 | (define_split | |
4485 | [(set (match_operand:HI 0 "integer_register_operand" "") | |
4486 | (if_then_else:HI (match_operator 1 "relational_operator" | |
4487 | [(match_operand 2 "cc_operand" "") | |
4488 | (const_int 0)]) | |
4489 | (match_operand:HI 3 "gpr_or_int_operand" "") | |
4490 | (match_operand:HI 4 "gpr_or_int_operand" ""))) | |
4491 | (clobber (match_operand:CC_CCR 5 "cr_operand" ""))] | |
4492 | "reload_completed" | |
4493 | [(match_dup 6)] | |
4494 | "operands[6] = frv_split_cond_move (operands);") | |
4495 | ||
4496 | (define_expand "movsicc" | |
4497 | [(set (match_operand:SI 0 "integer_register_operand" "") | |
4498 | (if_then_else:SI (match_operand 1 "" "") | |
4499 | (match_operand:SI 2 "gpr_or_int_operand" "") | |
4500 | (match_operand:SI 3 "gpr_or_int_operand" "")))] | |
4501 | "TARGET_COND_MOVE" | |
4502 | " | |
4503 | { | |
4504 | if (!frv_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) | |
4505 | FAIL; | |
4506 | ||
4507 | DONE; | |
4508 | }") | |
4509 | ||
036ff63f | 4510 | (define_insn "*movsicc_internal1_int" |
36a05131 | 4511 | [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d") |
036ff63f RS |
4512 | (if_then_else:SI (match_operator 1 "integer_relational_operator" |
4513 | [(match_operand 2 "icc_operand" "t,t,t") | |
36a05131 BS |
4514 | (const_int 0)]) |
4515 | (match_operand:SI 3 "reg_or_0_operand" "0,dO,dO") | |
4516 | (match_operand:SI 4 "reg_or_0_operand" "dO,0,dO"))) | |
4517 | (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] | |
4518 | "" | |
4519 | "#" | |
4520 | [(set_attr "length" "8,8,12") | |
4521 | (set_attr "type" "multi")]) | |
4522 | ||
4523 | (define_insn "*movsicc_internal1_float" | |
4524 | [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d") | |
4525 | (if_then_else:SI (match_operator:CC_FP 1 "float_relational_operator" | |
4526 | [(match_operand:CC_FP 2 "fcc_operand" "u,u,u") | |
4527 | (const_int 0)]) | |
4528 | (match_operand:SI 3 "reg_or_0_operand" "0,dO,dO") | |
4529 | (match_operand:SI 4 "reg_or_0_operand" "dO,0,dO"))) | |
4530 | (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))] | |
4531 | "TARGET_HARD_FLOAT" | |
4532 | "#" | |
4533 | [(set_attr "length" "8,8,12") | |
4534 | (set_attr "type" "multi")]) | |
4535 | ||
036ff63f | 4536 | (define_insn "*movsicc_internal2_int" |
36a05131 | 4537 | [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d,d,d") |
036ff63f RS |
4538 | (if_then_else:SI (match_operator 1 "integer_relational_operator" |
4539 | [(match_operand 2 "icc_operand" "t,t,t,t,t") | |
36a05131 BS |
4540 | (const_int 0)]) |
4541 | (match_operand:SI 3 "const_int_operand" "O,O,L,n,n") | |
4542 | (match_operand:SI 4 "const_int_operand" "L,n,O,O,n"))) | |
4543 | (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))] | |
4544 | "(INTVAL (operands[3]) == 0 | |
4545 | || INTVAL (operands[4]) == 0 | |
2f5b1308 JR |
4546 | || (IN_RANGE (INTVAL (operands[3]), -2048, 2047) |
4547 | && IN_RANGE (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" | |
36a05131 BS |
4548 | "#" |
4549 | [(set_attr "length" "8,12,8,12,12") | |
4550 | (set_attr "type" "multi")]) | |
4551 | ||
4552 | (define_insn "*movsicc_internal2_float" | |
4553 | [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d,d,d") | |
4554 | (if_then_else:SI (match_operator:CC_FP 1 "float_relational_operator" | |
4555 | [(match_operand:CC_FP 2 "fcc_operand" "u,u,u,u,u") | |
4556 | (const_int 0)]) | |
4557 | (match_operand:SI 3 "const_int_operand" "O,O,L,n,n") | |
4558 | (match_operand:SI 4 "const_int_operand" "L,n,O,O,n"))) | |
4559 | (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w,w,w"))] | |
4560 | "TARGET_HARD_FLOAT | |
4561 | && (INTVAL (operands[3]) == 0 | |
4562 | || INTVAL (operands[4]) == 0 | |
2f5b1308 JR |
4563 | || (IN_RANGE (INTVAL (operands[3]), -2048, 2047) |
4564 | && IN_RANGE (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" | |
36a05131 BS |
4565 | "#" |
4566 | [(set_attr "length" "8,12,8,12,12") | |
4567 | (set_attr "type" "multi")]) | |
4568 | ||
4569 | (define_split | |
4570 | [(set (match_operand:SI 0 "integer_register_operand" "") | |
4571 | (if_then_else:SI (match_operator 1 "relational_operator" | |
4572 | [(match_operand 2 "cc_operand" "") | |
4573 | (const_int 0)]) | |
4574 | (match_operand:SI 3 "gpr_or_int_operand" "") | |
4575 | (match_operand:SI 4 "gpr_or_int_operand" ""))) | |
4576 | (clobber (match_operand:CC_CCR 5 "cr_operand" ""))] | |
4577 | "reload_completed" | |
4578 | [(match_dup 6)] | |
4579 | "operands[6] = frv_split_cond_move (operands);") | |
4580 | ||
4581 | (define_expand "movsfcc" | |
4582 | [(set (match_operand:SF 0 "register_operand" "") | |
4583 | (if_then_else:SF (match_operand 1 "" "") | |
4584 | (match_operand:SF 2 "register_operand" "") | |
4585 | (match_operand:SF 3 "register_operand" "")))] | |
4586 | "TARGET_COND_MOVE" | |
4587 | " | |
4588 | { | |
4589 | if (!frv_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) | |
4590 | FAIL; | |
4591 | ||
4592 | DONE; | |
4593 | }") | |
4594 | ||
036ff63f | 4595 | (define_insn "*movsfcc_has_fprs_int" |
36a05131 | 4596 | [(set (match_operand:SF 0 "register_operand" "=f,f,f,?f,?f,?d") |
036ff63f RS |
4597 | (if_then_else:SF (match_operator 1 "integer_relational_operator" |
4598 | [(match_operand 2 "icc_operand" "t,t,t,t,t,t") | |
36a05131 BS |
4599 | (const_int 0)]) |
4600 | (match_operand:SF 3 "register_operand" "0,f,f,f,d,fd") | |
4601 | (match_operand:SF 4 "register_operand" "f,0,f,d,fd,fd"))) | |
4602 | (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v,v"))] | |
4603 | "TARGET_HAS_FPRS" | |
4604 | "#" | |
4605 | [(set_attr "length" "8,8,12,12,12,12") | |
4606 | (set_attr "type" "multi")]) | |
4607 | ||
4608 | (define_insn "*movsfcc_hardfloat_float" | |
4609 | [(set (match_operand:SF 0 "register_operand" "=f,f,f,?f,?f,?d") | |
4610 | (if_then_else:SF (match_operator:CC_FP 1 "float_relational_operator" | |
4611 | [(match_operand:CC_FP 2 "fcc_operand" "u,u,u,u,u,u") | |
4612 | (const_int 0)]) | |
4613 | (match_operand:SF 3 "register_operand" "0,f,f,f,d,fd") | |
4614 | (match_operand:SF 4 "register_operand" "f,0,f,d,fd,fd"))) | |
4615 | (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w,w,w,w"))] | |
4616 | "TARGET_HARD_FLOAT" | |
4617 | "#" | |
4618 | [(set_attr "length" "8,8,12,12,12,12") | |
4619 | (set_attr "type" "multi")]) | |
4620 | ||
036ff63f | 4621 | (define_insn "*movsfcc_no_fprs_int" |
36a05131 | 4622 | [(set (match_operand:SF 0 "integer_register_operand" "=d,d,d") |
036ff63f RS |
4623 | (if_then_else:SF (match_operator 1 "integer_relational_operator" |
4624 | [(match_operand 2 "icc_operand" "t,t,t") | |
36a05131 BS |
4625 | (const_int 0)]) |
4626 | (match_operand:SF 3 "integer_register_operand" "0,d,d") | |
4627 | (match_operand:SF 4 "integer_register_operand" "d,0,d"))) | |
4628 | (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] | |
4629 | "! TARGET_HAS_FPRS" | |
4630 | "#" | |
4631 | [(set_attr "length" "8,8,12") | |
4632 | (set_attr "type" "multi")]) | |
4633 | ||
4634 | (define_split | |
4635 | [(set (match_operand:SF 0 "register_operand" "") | |
4636 | (if_then_else:SF (match_operator 1 "relational_operator" | |
4637 | [(match_operand 2 "cc_operand" "") | |
4638 | (const_int 0)]) | |
4639 | (match_operand:SF 3 "register_operand" "") | |
4640 | (match_operand:SF 4 "register_operand" ""))) | |
4641 | (clobber (match_operand:CC_CCR 5 "cr_operand" ""))] | |
4642 | "reload_completed" | |
4643 | [(match_dup 6)] | |
4644 | "operands[6] = frv_split_cond_move (operands);") | |
4645 | ||
4646 | \f | |
4647 | ;; :::::::::::::::::::: | |
4648 | ;; :: | |
4649 | ;; :: Minimum, maximum, and integer absolute value | |
4650 | ;; :: | |
4651 | ;; :::::::::::::::::::: | |
4652 | ||
4653 | ;; These 'instructions' are provided to give the compiler a slightly better | |
4654 | ;; nudge at register allocation, then it would if it constructed the | |
4655 | ;; instructions from basic building blocks (since it indicates it prefers one | |
4656 | ;; of the operands to be the same as the destination. It also helps the | |
4657 | ;; earlier passes of the compiler, by not breaking things into small basic | |
4658 | ;; blocks. | |
4659 | ||
4660 | (define_expand "abssi2" | |
4661 | [(parallel [(set (match_operand:SI 0 "integer_register_operand" "") | |
4662 | (abs:SI (match_operand:SI 1 "integer_register_operand" ""))) | |
4663 | (clobber (match_dup 2)) | |
4664 | (clobber (match_dup 3))])] | |
4665 | "TARGET_COND_MOVE" | |
4666 | " | |
4667 | { | |
4668 | operands[2] = gen_reg_rtx (CCmode); | |
4669 | operands[3] = gen_reg_rtx (CC_CCRmode); | |
4670 | }") | |
4671 | ||
4672 | (define_insn_and_split "*abssi2_internal" | |
4673 | [(set (match_operand:SI 0 "integer_register_operand" "=d,d") | |
4674 | (abs:SI (match_operand:SI 1 "integer_register_operand" "0,d"))) | |
4675 | (clobber (match_operand:CC 2 "icc_operand" "=t,t")) | |
4676 | (clobber (match_operand:CC_CCR 3 "icr_operand" "=v,v"))] | |
4677 | "TARGET_COND_MOVE" | |
4678 | "#" | |
4679 | "reload_completed" | |
4680 | [(match_dup 4)] | |
4681 | "operands[4] = frv_split_abs (operands);" | |
4682 | [(set_attr "length" "12,16") | |
4683 | (set_attr "type" "multi")]) | |
4684 | ||
4685 | (define_expand "sminsi3" | |
4686 | [(parallel [(set (match_operand:SI 0 "integer_register_operand" "") | |
4687 | (smin:SI (match_operand:SI 1 "integer_register_operand" "") | |
4688 | (match_operand:SI 2 "gpr_or_int10_operand" ""))) | |
4689 | (clobber (match_dup 3)) | |
4690 | (clobber (match_dup 4))])] | |
4691 | "TARGET_COND_MOVE" | |
4692 | " | |
4693 | { | |
4694 | operands[3] = gen_reg_rtx (CCmode); | |
4695 | operands[4] = gen_reg_rtx (CC_CCRmode); | |
4696 | }") | |
4697 | ||
4698 | (define_expand "smaxsi3" | |
4699 | [(parallel [(set (match_operand:SI 0 "integer_register_operand" "") | |
4700 | (smax:SI (match_operand:SI 1 "integer_register_operand" "") | |
4701 | (match_operand:SI 2 "gpr_or_int10_operand" ""))) | |
4702 | (clobber (match_dup 3)) | |
4703 | (clobber (match_dup 4))])] | |
4704 | "TARGET_COND_MOVE" | |
4705 | " | |
4706 | { | |
4707 | operands[3] = gen_reg_rtx (CCmode); | |
4708 | operands[4] = gen_reg_rtx (CC_CCRmode); | |
4709 | }") | |
4710 | ||
4711 | (define_insn_and_split "*minmax_si_signed" | |
4712 | [(set (match_operand:SI 0 "integer_register_operand" "=d,d,&d") | |
4713 | (match_operator:SI 1 "minmax_operator" | |
4714 | [(match_operand:SI 2 "integer_register_operand" "%0,dO,d") | |
4715 | (match_operand:SI 3 "gpr_or_int10_operand" "dO,0,dJ")])) | |
4716 | (clobber (match_operand:CC 4 "icc_operand" "=t,t,t")) | |
4717 | (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] | |
4718 | "TARGET_COND_MOVE" | |
4719 | "#" | |
4720 | "reload_completed" | |
4721 | [(match_dup 6)] | |
4722 | "operands[6] = frv_split_minmax (operands);" | |
4723 | [(set_attr "length" "12,12,16") | |
4724 | (set_attr "type" "multi")]) | |
4725 | ||
4726 | (define_expand "uminsi3" | |
4727 | [(parallel [(set (match_operand:SI 0 "integer_register_operand" "") | |
4728 | (umin:SI (match_operand:SI 1 "integer_register_operand" "") | |
4729 | (match_operand:SI 2 "gpr_or_int10_operand" ""))) | |
4730 | (clobber (match_dup 3)) | |
4731 | (clobber (match_dup 4))])] | |
4732 | "TARGET_COND_MOVE" | |
4733 | " | |
4734 | { | |
4735 | operands[3] = gen_reg_rtx (CC_UNSmode); | |
4736 | operands[4] = gen_reg_rtx (CC_CCRmode); | |
4737 | }") | |
4738 | ||
4739 | (define_expand "umaxsi3" | |
4740 | [(parallel [(set (match_operand:SI 0 "integer_register_operand" "") | |
4741 | (umax:SI (match_operand:SI 1 "integer_register_operand" "") | |
4742 | (match_operand:SI 2 "gpr_or_int10_operand" ""))) | |
4743 | (clobber (match_dup 3)) | |
4744 | (clobber (match_dup 4))])] | |
4745 | "TARGET_COND_MOVE" | |
4746 | " | |
4747 | { | |
4748 | operands[3] = gen_reg_rtx (CC_UNSmode); | |
4749 | operands[4] = gen_reg_rtx (CC_CCRmode); | |
4750 | }") | |
4751 | ||
4752 | (define_insn_and_split "*minmax_si_unsigned" | |
4753 | [(set (match_operand:SI 0 "integer_register_operand" "=d,d,&d") | |
4754 | (match_operator:SI 1 "minmax_operator" | |
4755 | [(match_operand:SI 2 "integer_register_operand" "%0,dO,d") | |
4756 | (match_operand:SI 3 "gpr_or_int10_operand" "dO,0,dJ")])) | |
4757 | (clobber (match_operand:CC_UNS 4 "icc_operand" "=t,t,t")) | |
4758 | (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] | |
4759 | "TARGET_COND_MOVE" | |
4760 | "#" | |
4761 | "reload_completed" | |
4762 | [(match_dup 6)] | |
4763 | "operands[6] = frv_split_minmax (operands);" | |
4764 | [(set_attr "length" "12,12,16") | |
4765 | (set_attr "type" "multi")]) | |
4766 | ||
4767 | (define_expand "sminsf3" | |
4768 | [(parallel [(set (match_operand:SF 0 "fpr_operand" "") | |
4769 | (smin:SF (match_operand:SF 1 "fpr_operand" "") | |
4770 | (match_operand:SF 2 "fpr_operand" ""))) | |
4771 | (clobber (match_dup 3)) | |
4772 | (clobber (match_dup 4))])] | |
4773 | "TARGET_COND_MOVE && TARGET_HARD_FLOAT" | |
4774 | " | |
4775 | { | |
4776 | operands[3] = gen_reg_rtx (CC_FPmode); | |
4777 | operands[4] = gen_reg_rtx (CC_CCRmode); | |
4778 | }") | |
4779 | ||
4780 | (define_expand "smaxsf3" | |
4781 | [(parallel [(set (match_operand:SF 0 "fpr_operand" "") | |
4782 | (smax:SF (match_operand:SF 1 "fpr_operand" "") | |
4783 | (match_operand:SF 2 "fpr_operand" ""))) | |
4784 | (clobber (match_dup 3)) | |
4785 | (clobber (match_dup 4))])] | |
4786 | "TARGET_COND_MOVE && TARGET_HARD_FLOAT" | |
4787 | " | |
4788 | { | |
4789 | operands[3] = gen_reg_rtx (CC_FPmode); | |
4790 | operands[4] = gen_reg_rtx (CC_CCRmode); | |
4791 | }") | |
4792 | ||
4793 | (define_insn_and_split "*minmax_sf" | |
4794 | [(set (match_operand:SF 0 "fpr_operand" "=f,f,f") | |
4795 | (match_operator:SF 1 "minmax_operator" | |
4796 | [(match_operand:SF 2 "fpr_operand" "%0,f,f") | |
4797 | (match_operand:SF 3 "fpr_operand" "f,0,f")])) | |
4798 | (clobber (match_operand:CC_FP 4 "fcc_operand" "=u,u,u")) | |
4799 | (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))] | |
4800 | "TARGET_COND_MOVE && TARGET_HARD_FLOAT" | |
4801 | "#" | |
4802 | "reload_completed" | |
4803 | [(match_dup 6)] | |
4804 | "operands[6] = frv_split_minmax (operands);" | |
4805 | [(set_attr "length" "12,12,16") | |
4806 | (set_attr "type" "multi")]) | |
4807 | ||
4808 | (define_expand "smindf3" | |
4809 | [(parallel [(set (match_operand:DF 0 "fpr_operand" "") | |
4810 | (smin:DF (match_operand:DF 1 "fpr_operand" "") | |
4811 | (match_operand:DF 2 "fpr_operand" ""))) | |
4812 | (clobber (match_dup 3)) | |
4813 | (clobber (match_dup 4))])] | |
4814 | "TARGET_COND_MOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
4815 | " | |
4816 | { | |
4817 | operands[3] = gen_reg_rtx (CC_FPmode); | |
4818 | operands[4] = gen_reg_rtx (CC_CCRmode); | |
4819 | }") | |
4820 | ||
4821 | (define_expand "smaxdf3" | |
4822 | [(parallel [(set (match_operand:DF 0 "fpr_operand" "") | |
4823 | (smax:DF (match_operand:DF 1 "fpr_operand" "") | |
4824 | (match_operand:DF 2 "fpr_operand" ""))) | |
4825 | (clobber (match_dup 3)) | |
4826 | (clobber (match_dup 4))])] | |
4827 | "TARGET_COND_MOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
4828 | " | |
4829 | { | |
4830 | operands[3] = gen_reg_rtx (CC_FPmode); | |
4831 | operands[4] = gen_reg_rtx (CC_CCRmode); | |
4832 | }") | |
4833 | ||
4834 | (define_insn_and_split "*minmax_df" | |
4835 | [(set (match_operand:DF 0 "fpr_operand" "=f,f,f") | |
4836 | (match_operator:DF 1 "minmax_operator" | |
4837 | [(match_operand:DF 2 "fpr_operand" "%0,f,f") | |
4838 | (match_operand:DF 3 "fpr_operand" "f,0,f")])) | |
4839 | (clobber (match_operand:CC_FP 4 "fcc_operand" "=u,u,u")) | |
4840 | (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))] | |
4841 | "TARGET_COND_MOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE" | |
4842 | "#" | |
4843 | "reload_completed" | |
4844 | [(match_dup 6)] | |
4845 | "operands[6] = frv_split_minmax (operands);" | |
4846 | [(set_attr "length" "12,12,16") | |
4847 | (set_attr "type" "multi")]) | |
4848 | ||
4849 | \f | |
4850 | ;; :::::::::::::::::::: | |
4851 | ;; :: | |
4852 | ;; :: Call and branch instructions | |
4853 | ;; :: | |
4854 | ;; :::::::::::::::::::: | |
4855 | ||
4856 | ;; Subroutine call instruction returning no value. Operand 0 is the function | |
4857 | ;; to call; operand 1 is the number of bytes of arguments pushed (in mode | |
4858 | ;; `SImode', except it is normally a `const_int'); operand 2 is the number of | |
4859 | ;; registers used as operands. | |
4860 | ||
4861 | ;; On most machines, operand 2 is not actually stored into the RTL pattern. It | |
4862 | ;; is supplied for the sake of some RISC machines which need to put this | |
4863 | ;; information into the assembler code; they can put it in the RTL instead of | |
4864 | ;; operand 1. | |
4865 | ||
4866 | (define_expand "call" | |
4867 | [(use (match_operand:QI 0 "" "")) | |
4868 | (use (match_operand 1 "" "")) | |
4869 | (use (match_operand 2 "" "")) | |
4870 | (use (match_operand 3 "" ""))] | |
4871 | "" | |
4872 | " | |
4873 | { | |
4874 | rtx lr = gen_rtx_REG (Pmode, LR_REGNO); | |
4875 | rtx addr; | |
4876 | ||
44e91694 | 4877 | gcc_assert (GET_CODE (operands[0]) == MEM); |
36a05131 BS |
4878 | |
4879 | addr = XEXP (operands[0], 0); | |
4880 | if (! call_operand (addr, Pmode)) | |
4881 | addr = force_reg (Pmode, addr); | |
4882 | ||
4883 | if (! operands[2]) | |
4884 | operands[2] = const0_rtx; | |
4885 | ||
34208acf | 4886 | if (TARGET_FDPIC) |
764678d1 | 4887 | frv_expand_fdpic_call (operands, false, false); |
34208acf AO |
4888 | else |
4889 | emit_call_insn (gen_call_internal (addr, operands[1], operands[2], lr)); | |
4890 | ||
36a05131 BS |
4891 | DONE; |
4892 | }") | |
4893 | ||
4894 | (define_insn "call_internal" | |
4895 | [(call (mem:QI (match_operand:SI 0 "call_operand" "S,dNOP")) | |
4896 | (match_operand 1 "" "")) | |
4897 | (use (match_operand 2 "" "")) | |
4898 | (clobber (match_operand:SI 3 "lr_operand" "=l,l"))] | |
34208acf AO |
4899 | "! TARGET_FDPIC" |
4900 | "@ | |
4901 | call %0 | |
4902 | call%i0l %M0" | |
4903 | [(set_attr "length" "4") | |
4904 | (set_attr "type" "call,jumpl")]) | |
4905 | ||
4906 | ;; The odd use of GR0 within the UNSPEC below prevents cseing or | |
4907 | ;; hoisting function descriptor loads out of loops. This is almost | |
4908 | ;; never desirable, since if we preserve the function descriptor in a | |
4909 | ;; pair of registers, it takes two insns to move it to gr14/gr15, and | |
4910 | ;; if it's in the stack, we just waste space with the store, since | |
4911 | ;; we'll have to load back from memory anyway. And, in the worst | |
4912 | ;; case, we may end up reusing a function descriptor still pointing at | |
4913 | ;; a PLT entry, instead of to the resolved function, which means going | |
4914 | ;; through the resolver for every call that uses the outdated value. | |
4915 | ;; Bad! | |
4916 | ||
4917 | ;; The explicit MEM inside the SPEC prevents the compiler from moving | |
4918 | ;; the load before a branch after a NULL test, or before a store that | |
4919 | ;; initializes a function descriptor. | |
4920 | ||
4921 | (define_insn "movdi_ldd" | |
4922 | [(set (match_operand:DI 0 "fdpic_fptr_operand" "=e") | |
4923 | (unspec:DI [(mem:DI (match_operand:SI 1 "ldd_address_operand" "p")) | |
4924 | (reg:SI 0)] UNSPEC_LDD))] | |
36a05131 | 4925 | "" |
34208acf AO |
4926 | "ldd%I1 %M1, %0" |
4927 | [(set_attr "length" "4") | |
4928 | (set_attr "type" "gload")]) | |
4929 | ||
4930 | (define_insn "call_fdpicdi" | |
4931 | [(call (mem:QI (match_operand:DI 0 "fdpic_fptr_operand" "W")) | |
4932 | (match_operand 1 "" "")) | |
4933 | (clobber (match_operand:SI 2 "lr_operand" "=l"))] | |
4934 | "TARGET_FDPIC" | |
764678d1 | 4935 | "call%i0l %M0" |
34208acf AO |
4936 | [(set_attr "length" "4") |
4937 | (set_attr "type" "jumpl")]) | |
4938 | ||
4939 | (define_insn "call_fdpicsi" | |
4940 | [(call (mem:QI (match_operand:SI 0 "call_operand" "S,dNOP")) | |
4941 | (match_operand 1 "" "")) | |
4942 | (use (match_operand 2 "" "")) | |
4943 | (use (match_operand:SI 3 "fdpic_operand" "Z,Z")) | |
4944 | (clobber (match_operand:SI 4 "lr_operand" "=l,l"))] | |
4945 | "TARGET_FDPIC" | |
36a05131 BS |
4946 | "@ |
4947 | call %0 | |
4948 | call%i0l %M0" | |
4949 | [(set_attr "length" "4") | |
4950 | (set_attr "type" "call,jumpl")]) | |
4951 | ||
764678d1 AO |
4952 | (define_expand "sibcall" |
4953 | [(use (match_operand:QI 0 "" "")) | |
4954 | (use (match_operand 1 "" "")) | |
4955 | (use (match_operand 2 "" "")) | |
4956 | (use (match_operand 3 "" ""))] | |
4957 | "" | |
4958 | " | |
4959 | { | |
4960 | rtx addr; | |
4961 | ||
44e91694 | 4962 | gcc_assert (GET_CODE (operands[0]) == MEM); |
764678d1 AO |
4963 | |
4964 | addr = XEXP (operands[0], 0); | |
4965 | if (! sibcall_operand (addr, Pmode)) | |
4966 | addr = force_reg (Pmode, addr); | |
4967 | ||
4968 | if (! operands[2]) | |
4969 | operands[2] = const0_rtx; | |
4970 | ||
4971 | if (TARGET_FDPIC) | |
4972 | frv_expand_fdpic_call (operands, false, true); | |
4973 | else | |
4974 | emit_call_insn (gen_sibcall_internal (addr, operands[1], operands[2])); | |
4975 | ||
4976 | DONE; | |
4977 | }") | |
4978 | ||
4979 | ;; It might seem that these sibcall patterns are missing references to | |
4980 | ;; LR, but they're not necessary because sibcall_epilogue will make | |
4981 | ;; sure LR is restored, and having LR here will set | |
4982 | ;; regs_ever_used[REG_LR], forcing it to be saved on the stack, and | |
4983 | ;; then restored in sibcalls and regular return code paths, even if | |
4984 | ;; the function becomes a leaf function after tail-call elimination. | |
4985 | ||
4986 | ;; We must not use a call-saved register here. `W' limits ourselves | |
4987 | ;; to gr14 or gr15, but since we're almost running out of constraint | |
4988 | ;; letters, and most other call-clobbered registers are often used for | |
4989 | ;; argument-passing, this will do. | |
4990 | (define_insn "sibcall_internal" | |
4991 | [(call (mem:QI (match_operand:SI 0 "sibcall_operand" "WNOP")) | |
4992 | (match_operand 1 "" "")) | |
4993 | (use (match_operand 2 "" "")) | |
4994 | (return)] | |
4995 | "! TARGET_FDPIC" | |
4996 | "jmp%i0l %M0" | |
4997 | [(set_attr "length" "4") | |
4998 | (set_attr "type" "jumpl")]) | |
4999 | ||
5000 | (define_insn "sibcall_fdpicdi" | |
5001 | [(call (mem:QI (match_operand:DI 0 "fdpic_fptr_operand" "W")) | |
5002 | (match_operand 1 "" "")) | |
5003 | (return)] | |
5004 | "TARGET_FDPIC" | |
5005 | "jmp%i0l %M0" | |
5006 | [(set_attr "length" "4") | |
5007 | (set_attr "type" "jumpl")]) | |
5008 | ||
5009 | ||
36a05131 BS |
5010 | ;; Subroutine call instruction returning a value. Operand 0 is the hard |
5011 | ;; register in which the value is returned. There are three more operands, the | |
5012 | ;; same as the three operands of the `call' instruction (but with numbers | |
5013 | ;; increased by one). | |
5014 | ||
5015 | ;; Subroutines that return `BLKmode' objects use the `call' insn. | |
5016 | ||
5017 | (define_expand "call_value" | |
5018 | [(use (match_operand 0 "" "")) | |
5019 | (use (match_operand:QI 1 "" "")) | |
5020 | (use (match_operand 2 "" "")) | |
5021 | (use (match_operand 3 "" "")) | |
5022 | (use (match_operand 4 "" ""))] | |
5023 | "" | |
5024 | " | |
5025 | { | |
5026 | rtx lr = gen_rtx_REG (Pmode, LR_REGNO); | |
5027 | rtx addr; | |
5028 | ||
44e91694 | 5029 | gcc_assert (GET_CODE (operands[1]) == MEM); |
36a05131 BS |
5030 | |
5031 | addr = XEXP (operands[1], 0); | |
5032 | if (! call_operand (addr, Pmode)) | |
5033 | addr = force_reg (Pmode, addr); | |
5034 | ||
5035 | if (! operands[3]) | |
5036 | operands[3] = const0_rtx; | |
5037 | ||
34208acf | 5038 | if (TARGET_FDPIC) |
764678d1 | 5039 | frv_expand_fdpic_call (operands, true, false); |
34208acf AO |
5040 | else |
5041 | emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2], | |
5042 | operands[3], lr)); | |
5043 | ||
36a05131 BS |
5044 | DONE; |
5045 | }") | |
5046 | ||
5047 | (define_insn "call_value_internal" | |
5048 | [(set (match_operand 0 "register_operand" "=d,d") | |
5049 | (call (mem:QI (match_operand:SI 1 "call_operand" "S,dNOP")) | |
5050 | (match_operand 2 "" ""))) | |
5051 | (use (match_operand 3 "" "")) | |
5052 | (clobber (match_operand:SI 4 "lr_operand" "=l,l"))] | |
34208acf AO |
5053 | "! TARGET_FDPIC" |
5054 | "@ | |
5055 | call %1 | |
5056 | call%i1l %M1" | |
5057 | [(set_attr "length" "4") | |
5058 | (set_attr "type" "call,jumpl")]) | |
5059 | ||
5060 | (define_insn "call_value_fdpicdi" | |
5061 | [(set (match_operand 0 "register_operand" "=d") | |
5062 | (call (mem:QI (match_operand:DI 1 "fdpic_fptr_operand" "W")) | |
5063 | (match_operand 2 "" ""))) | |
5064 | (clobber (match_operand:SI 3 "lr_operand" "=l"))] | |
5065 | "TARGET_FDPIC" | |
764678d1 | 5066 | "call%i1l %M1" |
34208acf AO |
5067 | [(set_attr "length" "4") |
5068 | (set_attr "type" "jumpl")]) | |
5069 | ||
5070 | (define_insn "call_value_fdpicsi" | |
5071 | [(set (match_operand 0 "register_operand" "=d,d") | |
5072 | (call (mem:QI (match_operand:SI 1 "call_operand" "S,dNOP")) | |
5073 | (match_operand 2 "" ""))) | |
5074 | (use (match_operand 3 "" "")) | |
5075 | (use (match_operand:SI 4 "fdpic_operand" "Z,Z")) | |
5076 | (clobber (match_operand:SI 5 "lr_operand" "=l,l"))] | |
5077 | "TARGET_FDPIC" | |
36a05131 BS |
5078 | "@ |
5079 | call %1 | |
5080 | call%i1l %M1" | |
5081 | [(set_attr "length" "4") | |
5082 | (set_attr "type" "call,jumpl")]) | |
5083 | ||
764678d1 AO |
5084 | (define_expand "sibcall_value" |
5085 | [(use (match_operand 0 "" "")) | |
5086 | (use (match_operand:QI 1 "" "")) | |
5087 | (use (match_operand 2 "" "")) | |
5088 | (use (match_operand 3 "" "")) | |
5089 | (use (match_operand 4 "" ""))] | |
5090 | "" | |
5091 | " | |
5092 | { | |
5093 | rtx addr; | |
5094 | ||
44e91694 | 5095 | gcc_assert (GET_CODE (operands[1]) == MEM); |
764678d1 AO |
5096 | |
5097 | addr = XEXP (operands[1], 0); | |
5098 | if (! sibcall_operand (addr, Pmode)) | |
5099 | addr = force_reg (Pmode, addr); | |
5100 | ||
5101 | if (! operands[3]) | |
5102 | operands[3] = const0_rtx; | |
5103 | ||
5104 | if (TARGET_FDPIC) | |
5105 | frv_expand_fdpic_call (operands, true, true); | |
5106 | else | |
5107 | emit_call_insn (gen_sibcall_value_internal (operands[0], addr, operands[2], | |
5108 | operands[3])); | |
5109 | DONE; | |
5110 | }") | |
5111 | ||
5112 | (define_insn "sibcall_value_internal" | |
5113 | [(set (match_operand 0 "register_operand" "=d") | |
5114 | (call (mem:QI (match_operand:SI 1 "sibcall_operand" "WNOP")) | |
5115 | (match_operand 2 "" ""))) | |
5116 | (use (match_operand 3 "" "")) | |
5117 | (return)] | |
5118 | "! TARGET_FDPIC" | |
5119 | "jmp%i1l %M1" | |
5120 | [(set_attr "length" "4") | |
5121 | (set_attr "type" "jumpl")]) | |
5122 | ||
5123 | (define_insn "sibcall_value_fdpicdi" | |
5124 | [(set (match_operand 0 "register_operand" "=d") | |
5125 | (call (mem:QI (match_operand:DI 1 "fdpic_fptr_operand" "W")) | |
5126 | (match_operand 2 "" ""))) | |
5127 | (return)] | |
5128 | "TARGET_FDPIC" | |
5129 | "jmp%i1l %M1" | |
5130 | [(set_attr "length" "4") | |
5131 | (set_attr "type" "jumpl")]) | |
5132 | ||
36a05131 BS |
5133 | ;; return instruction generated instead of jmp to epilog |
5134 | (define_expand "return" | |
5135 | [(parallel [(return) | |
5136 | (use (match_dup 0)) | |
5137 | (use (const_int 1))])] | |
5138 | "direct_return_p ()" | |
5139 | " | |
5140 | { | |
5141 | operands[0] = gen_rtx_REG (Pmode, LR_REGNO); | |
5142 | }") | |
5143 | ||
5144 | ;; return instruction generated by the epilogue | |
5145 | (define_expand "epilogue_return" | |
5146 | [(parallel [(return) | |
5147 | (use (match_operand:SI 0 "register_operand" "")) | |
5148 | (use (const_int 0))])] | |
5149 | "" | |
5150 | "") | |
5151 | ||
5152 | (define_insn "*return_internal" | |
5153 | [(return) | |
5154 | (use (match_operand:SI 0 "register_operand" "l,d")) | |
5155 | (use (match_operand:SI 1 "immediate_operand" "n,n"))] | |
5156 | "" | |
5157 | "@ | |
5158 | ret | |
5159 | jmpl @(%0,%.)" | |
5160 | [(set_attr "length" "4") | |
5161 | (set_attr "type" "jump,jumpl")]) | |
5162 | ||
5f2b9599 AO |
5163 | (define_insn "*return_true" |
5164 | [(set (pc) | |
036ff63f RS |
5165 | (if_then_else (match_operator 0 "integer_relational_operator" |
5166 | [(match_operand 1 "icc_operand" "t") | |
5167 | (const_int 0)]) | |
5f2b9599 AO |
5168 | (return) |
5169 | (pc)))] | |
5170 | "direct_return_p ()" | |
5171 | "b%c0lr %1,%#" | |
5172 | [(set_attr "length" "4") | |
5173 | (set_attr "type" "jump")]) | |
5174 | ||
5175 | (define_insn "*return_false" | |
5176 | [(set (pc) | |
036ff63f RS |
5177 | (if_then_else (match_operator 0 "integer_relational_operator" |
5178 | [(match_operand 1 "icc_operand" "t") | |
5179 | (const_int 0)]) | |
764678d1 AO |
5180 | (pc) |
5181 | (return)))] | |
5182 | "direct_return_p ()" | |
5183 | "b%C0lr %1,%#" | |
5184 | [(set_attr "length" "4") | |
5185 | (set_attr "type" "jump")]) | |
5186 | ||
36a05131 BS |
5187 | ;; A version of addsi3 for deallocating stack space at the end of the |
5188 | ;; epilogue. The addition is done in parallel with an (unspec_volatile), | |
5189 | ;; which represents the clobbering of the deallocated space. | |
5190 | (define_insn "stack_adjust" | |
5191 | [(set (match_operand:SI 0 "register_operand" "=d") | |
5192 | (plus:SI (match_operand:SI 1 "register_operand" "d") | |
5193 | (match_operand:SI 2 "general_operand" "dNOP"))) | |
5194 | (unspec_volatile [(const_int 0)] UNSPEC_STACK_ADJUST)] | |
5195 | "" | |
5196 | "add%I2 %1,%2,%0" | |
5197 | [(set_attr "length" "4") | |
5198 | (set_attr "type" "int")]) | |
5199 | ||
5200 | ;; Normal unconditional jump | |
5201 | ||
5202 | ;; Use the "call" instruction for long branches, but prefer to use "bra" for | |
5203 | ;; short ones since it does not force us to save the link register. | |
5204 | ||
5205 | ;; This define_insn uses the branch-shortening code to decide which | |
5206 | ;; instruction it emits. Since the main branch-shortening interface is | |
5207 | ;; through get_attr_length(), the two alternatives must be given different | |
5208 | ;; lengths. Here we pretend that the far jump is 8 rather than 4 bytes | |
5209 | ;; long, though both alternatives are really the same size. | |
5210 | (define_insn "jump" | |
5211 | [(set (pc) (label_ref (match_operand 0 "" "")))] | |
5212 | "" | |
5213 | "* | |
5214 | { | |
5215 | if (get_attr_length (insn) == 4) | |
5216 | return \"bra %l0\"; | |
5217 | else | |
5218 | return \"call %l0\"; | |
5219 | }" | |
5220 | [(set (attr "length") | |
5221 | (if_then_else | |
5222 | (and (ge (minus (match_dup 0) (pc)) (const_int -32768)) | |
5223 | (le (minus (match_dup 0) (pc)) (const_int 32764))) | |
5224 | (const_int 4) | |
5225 | (const_int 8))) | |
5226 | (set (attr "far_jump") | |
5227 | (if_then_else | |
5228 | (eq_attr "length" "4") | |
5229 | (const_string "no") | |
5230 | (const_string "yes"))) | |
5231 | (set (attr "type") | |
5232 | (if_then_else | |
5233 | (eq_attr "length" "4") | |
5234 | (const_string "jump") | |
5235 | (const_string "call")))]) | |
5236 | ||
5237 | ;; Indirect jump through a register | |
5238 | (define_insn "indirect_jump" | |
5239 | [(set (pc) (match_operand:SI 0 "register_operand" "d,l"))] | |
5240 | "" | |
5241 | "@ | |
5242 | jmpl @(%0,%.) | |
5243 | bralr" | |
5244 | [(set_attr "length" "4") | |
5245 | (set_attr "type" "jumpl,branch")]) | |
5246 | ||
5247 | ;; Instruction to jump to a variable address. This is a low-level capability | |
5248 | ;; which can be used to implement a dispatch table when there is no `casesi' | |
5249 | ;; pattern. Either the 'casesi' pattern or the 'tablejump' pattern, or both, | |
5250 | ;; MUST be present in this file. | |
5251 | ||
5252 | ;; This pattern requires two operands: the address or offset, and a label which | |
5253 | ;; should immediately precede the jump table. If the macro | |
5254 | ;; `CASE_VECTOR_PC_RELATIVE' is defined then the first operand is an offset | |
5255 | ;; which counts from the address of the table; otherwise, it is an absolute | |
5256 | ;; address to jump to. In either case, the first operand has mode `Pmode'. | |
5257 | ||
5258 | ;; The `tablejump' insn is always the last insn before the jump table it uses. | |
5259 | ;; Its assembler code normally has no need to use the second operand, but you | |
5260 | ;; should incorporate it in the RTL pattern so that the jump optimizer will not | |
5261 | ;; delete the table as unreachable code. | |
5262 | ||
5263 | (define_expand "tablejump" | |
5264 | [(parallel [(set (pc) (match_operand:SI 0 "address_operand" "p")) | |
5265 | (use (label_ref (match_operand 1 "" "")))])] | |
5266 | "!flag_pic" | |
5267 | "") | |
5268 | ||
5269 | (define_insn "tablejump_insn" | |
5270 | [(set (pc) (match_operand:SI 0 "address_operand" "p")) | |
5271 | (use (label_ref (match_operand 1 "" "")))] | |
5272 | "" | |
5273 | "jmp%I0l %M0" | |
5274 | [(set_attr "length" "4") | |
5275 | (set_attr "type" "jumpl")]) | |
5276 | ||
5277 | ;; Implement switch statements when generating PIC code. Switches are | |
5278 | ;; implemented by `tablejump' when not using -fpic. | |
5279 | ||
5280 | ;; Emit code here to do the range checking and make the index zero based. | |
5281 | ;; operand 0 is the index | |
5282 | ;; operand 1 is the lower bound | |
5283 | ;; operand 2 is the range of indices (highest - lowest + 1) | |
5284 | ;; operand 3 is the label that precedes the table itself | |
5285 | ;; operand 4 is the fall through label | |
5286 | ||
5287 | (define_expand "casesi" | |
5288 | [(use (match_operand:SI 0 "integer_register_operand" "")) | |
5289 | (use (match_operand:SI 1 "const_int_operand" "")) | |
5290 | (use (match_operand:SI 2 "const_int_operand" "")) | |
5291 | (use (match_operand 3 "" "")) | |
5292 | (use (match_operand 4 "" ""))] | |
5293 | "flag_pic" | |
5294 | " | |
5295 | { | |
5296 | rtx indx; | |
5297 | rtx scale; | |
5298 | rtx low = operands[1]; | |
5299 | rtx range = operands[2]; | |
5300 | rtx table = operands[3]; | |
5301 | rtx treg; | |
5302 | rtx fail = operands[4]; | |
5303 | rtx mem; | |
5304 | rtx reg2; | |
5305 | rtx reg3; | |
5306 | ||
44e91694 | 5307 | gcc_assert (GET_CODE (operands[1]) == CONST_INT); |
36a05131 | 5308 | |
44e91694 | 5309 | gcc_assert (GET_CODE (operands[2]) == CONST_INT); |
36a05131 | 5310 | |
87b483a1 | 5311 | /* If we can't generate an immediate instruction, promote to register. */ |
2f5b1308 | 5312 | if (! IN_RANGE (INTVAL (range), -2048, 2047)) |
36a05131 BS |
5313 | range = force_reg (SImode, range); |
5314 | ||
5315 | /* If low bound is 0, we don't have to subtract it. */ | |
5316 | if (INTVAL (operands[1]) == 0) | |
5317 | indx = operands[0]; | |
5318 | else | |
5319 | { | |
5320 | indx = gen_reg_rtx (SImode); | |
2f5b1308 | 5321 | if (IN_RANGE (INTVAL (low), -2047, 2048)) |
36a05131 BS |
5322 | emit_insn (gen_addsi3 (indx, operands[0], GEN_INT (- INTVAL (low)))); |
5323 | else | |
5324 | emit_insn (gen_subsi3 (indx, operands[0], force_reg (SImode, low))); | |
5325 | } | |
5326 | ||
5327 | /* Do an unsigned comparison (in the proper mode) between the index | |
5328 | expression and the value which represents the length of the range. | |
5329 | Since we just finished subtracting the lower bound of the range | |
5330 | from the index expression, this comparison allows us to simultaneously | |
5331 | check that the original index expression value is both greater than | |
5332 | or equal to the minimum value of the range and less than or equal to | |
5333 | the maximum value of the range. */ | |
5334 | ||
5335 | emit_cmp_and_jump_insns (indx, range, GTU, NULL_RTX, SImode, 1, fail); | |
5336 | ||
87b483a1 | 5337 | /* Move the table address to a register. */ |
36a05131 BS |
5338 | treg = gen_reg_rtx (Pmode); |
5339 | emit_insn (gen_movsi (treg, gen_rtx_LABEL_REF (VOIDmode, table))); | |
5340 | ||
87b483a1 | 5341 | /* Scale index-low by wordsize. */ |
36a05131 | 5342 | scale = gen_reg_rtx (SImode); |
a556fd39 | 5343 | emit_insn (gen_ashlsi3 (scale, indx, const2_rtx)); |
36a05131 BS |
5344 | |
5345 | /* Load the address, add the start of the table back in, | |
5346 | and jump to it. */ | |
5347 | mem = gen_rtx_MEM (SImode, gen_rtx_PLUS (Pmode, scale, treg)); | |
5348 | reg2 = gen_reg_rtx (SImode); | |
5349 | reg3 = gen_reg_rtx (SImode); | |
5350 | emit_insn (gen_movsi (reg2, mem)); | |
5351 | emit_insn (gen_addsi3 (reg3, reg2, treg)); | |
5352 | emit_jump_insn (gen_tablejump_insn (reg3, table)); | |
5353 | DONE; | |
5354 | }") | |
5355 | ||
5356 | \f | |
5357 | ;; :::::::::::::::::::: | |
5358 | ;; :: | |
5359 | ;; :: Prologue and Epilogue instructions | |
5360 | ;; :: | |
5361 | ;; :::::::::::::::::::: | |
5362 | ||
5363 | ;; Called after register allocation to add any instructions needed for the | |
5364 | ;; prologue. Using a prologue insn is favored compared to putting all of the | |
5365 | ;; instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler | |
5366 | ;; to intermix instructions with the saves of the caller saved registers. In | |
5367 | ;; some cases, it might be necessary to emit a barrier instruction as the last | |
5368 | ;; insn to prevent such scheduling. | |
5369 | (define_expand "prologue" | |
5370 | [(const_int 1)] | |
5371 | "" | |
5372 | " | |
5373 | { | |
5374 | frv_expand_prologue (); | |
5375 | DONE; | |
5376 | }") | |
5377 | ||
5378 | ;; Called after register allocation to add any instructions needed for the | |
43aa4e05 | 5379 | ;; epilogue. Using an epilogue insn is favored compared to putting all of the |
36a05131 | 5380 | ;; instructions in the FUNCTION_EPILOGUE macro, since it allows the scheduler |
aabcd309 | 5381 | ;; to intermix instructions with the restores of the caller saved registers. |
36a05131 BS |
5382 | ;; In some cases, it might be necessary to emit a barrier instruction as the |
5383 | ;; first insn to prevent such scheduling. | |
5384 | (define_expand "epilogue" | |
5385 | [(const_int 2)] | |
5386 | "" | |
5387 | " | |
5388 | { | |
764678d1 | 5389 | frv_expand_epilogue (true); |
36a05131 BS |
5390 | DONE; |
5391 | }") | |
5392 | ||
5393 | ;; This pattern, if defined, emits RTL for exit from a function without the final | |
5394 | ;; branch back to the calling function. This pattern will be emitted before any | |
5395 | ;; sibling call (aka tail call) sites. | |
5396 | ;; | |
5397 | ;; The sibcall_epilogue pattern must not clobber any arguments used for | |
5398 | ;; parameter passing or any stack slots for arguments passed to the current | |
5399 | ;; function. | |
5400 | (define_expand "sibcall_epilogue" | |
5401 | [(const_int 3)] | |
5402 | "" | |
5403 | " | |
5404 | { | |
764678d1 | 5405 | frv_expand_epilogue (false); |
36a05131 BS |
5406 | DONE; |
5407 | }") | |
5408 | ||
5409 | ;; Set up the pic register to hold the address of the pic table | |
5410 | (define_insn "pic_prologue" | |
5411 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
5412 | (unspec_volatile:SI [(const_int 0)] UNSPEC_PIC_PROLOGUE)) | |
5413 | (clobber (match_operand:SI 1 "lr_operand" "=l")) | |
5414 | (clobber (match_operand:SI 2 "integer_register_operand" "=d"))] | |
5415 | "" | |
5416 | "* | |
5417 | { | |
5418 | static int frv_pic_labelno = 0; | |
5419 | ||
5420 | operands[3] = GEN_INT (frv_pic_labelno++); | |
5421 | return \"call %P3\\n%P3:\;movsg %1, %0\;sethi #gprelhi(%P3), %2\;setlo #gprello(%P3), %2\;sub %0,%2,%0\"; | |
5422 | }" | |
5423 | [(set_attr "length" "16") | |
5424 | (set_attr "type" "multi")]) | |
5425 | \f | |
5426 | ;; :::::::::::::::::::: | |
5427 | ;; :: | |
5428 | ;; :: Miscellaneous instructions | |
5429 | ;; :: | |
5430 | ;; :::::::::::::::::::: | |
5431 | ||
5432 | ;; No operation, needed in case the user uses -g but not -O. | |
5433 | (define_insn "nop" | |
5434 | [(const_int 0)] | |
5435 | "" | |
5436 | "nop" | |
5437 | [(set_attr "length" "4") | |
5438 | (set_attr "type" "int")]) | |
5439 | ||
c557edf4 RS |
5440 | (define_insn "fnop" |
5441 | [(const_int 1)] | |
5442 | "" | |
5443 | "fnop" | |
5444 | [(set_attr "length" "4") | |
5445 | (set_attr "type" "fnop")]) | |
5446 | ||
5447 | (define_insn "mnop" | |
5448 | [(const_int 2)] | |
5449 | "" | |
5450 | "mnop" | |
5451 | [(set_attr "length" "4") | |
5452 | (set_attr "type" "mnop")]) | |
5453 | ||
36a05131 BS |
5454 | ;; Pseudo instruction that prevents the scheduler from moving code above this |
5455 | ;; point. Note, type unknown is used to make sure the VLIW instructions are | |
5456 | ;; not continued past this point. | |
5457 | (define_insn "blockage" | |
5458 | [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)] | |
5459 | "" | |
5460 | "# blockage" | |
5461 | [(set_attr "length" "0") | |
5462 | (set_attr "type" "unknown")]) | |
5463 | \f | |
5464 | ;; :::::::::::::::::::: | |
5465 | ;; :: | |
5466 | ;; :: Media instructions | |
5467 | ;; :: | |
5468 | ;; :::::::::::::::::::: | |
5469 | ||
5470 | ;; Unimplemented instructions: | |
5471 | ;; - MCMPSH, MCMPUH | |
5472 | ||
5473 | (define_constants | |
5474 | [(UNSPEC_MLOGIC 100) | |
5475 | (UNSPEC_MNOT 101) | |
5476 | (UNSPEC_MAVEH 102) | |
5477 | (UNSPEC_MSATH 103) | |
5478 | (UNSPEC_MADDH 104) | |
5479 | (UNSPEC_MQADDH 105) | |
5480 | (UNSPEC_MPACKH 106) | |
5481 | (UNSPEC_MUNPACKH 107) | |
5482 | (UNSPEC_MDPACKH 108) | |
5483 | (UNSPEC_MBTOH 109) | |
5484 | (UNSPEC_MHTOB 110) | |
5485 | (UNSPEC_MROT 111) | |
5486 | (UNSPEC_MSHIFT 112) | |
5487 | (UNSPEC_MEXPDHW 113) | |
5488 | (UNSPEC_MEXPDHD 114) | |
5489 | (UNSPEC_MWCUT 115) | |
5490 | (UNSPEC_MMULH 116) | |
5491 | (UNSPEC_MMULXH 117) | |
5492 | (UNSPEC_MMACH 118) | |
5493 | (UNSPEC_MMRDH 119) | |
5494 | (UNSPEC_MQMULH 120) | |
5495 | (UNSPEC_MQMULXH 121) | |
5496 | (UNSPEC_MQMACH 122) | |
5497 | (UNSPEC_MCPX 123) | |
5498 | (UNSPEC_MQCPX 124) | |
5499 | (UNSPEC_MCUT 125) | |
5500 | (UNSPEC_MRDACC 126) | |
5501 | (UNSPEC_MRDACCG 127) | |
5502 | (UNSPEC_MWTACC 128) | |
5503 | (UNSPEC_MWTACCG 129) | |
5504 | (UNSPEC_MTRAP 130) | |
5505 | (UNSPEC_MCLRACC 131) | |
5506 | (UNSPEC_MCLRACCA 132) | |
5507 | (UNSPEC_MCOP1 133) | |
5508 | (UNSPEC_MCOP2 134) | |
5509 | (UNSPEC_MDUNPACKH 135) | |
5510 | (UNSPEC_MDUNPACKH_INTERNAL 136) | |
5511 | (UNSPEC_MBTOHE 137) | |
5512 | (UNSPEC_MBTOHE_INTERNAL 138) | |
5513 | (UNSPEC_MBTOHE 137) | |
5514 | (UNSPEC_MBTOHE_INTERNAL 138) | |
5515 | (UNSPEC_MQMACH2 139) | |
5516 | (UNSPEC_MADDACC 140) | |
5517 | (UNSPEC_MDADDACC 141) | |
5518 | (UNSPEC_MABSHS 142) | |
5519 | (UNSPEC_MDROTLI 143) | |
5520 | (UNSPEC_MCPLHI 144) | |
5521 | (UNSPEC_MCPLI 145) | |
5522 | (UNSPEC_MDCUTSSI 146) | |
5523 | (UNSPEC_MQSATHS 147) | |
5524 | (UNSPEC_MHSETLOS 148) | |
5525 | (UNSPEC_MHSETLOH 149) | |
5526 | (UNSPEC_MHSETHIS 150) | |
5527 | (UNSPEC_MHSETHIH 151) | |
5528 | (UNSPEC_MHDSETS 152) | |
5529 | (UNSPEC_MHDSETH 153) | |
c557edf4 RS |
5530 | (UNSPEC_MQLCLRHS 154) |
5531 | (UNSPEC_MQLMTHS 155) | |
5532 | (UNSPEC_MQSLLHI 156) | |
5533 | (UNSPEC_MQSRAHI 157) | |
094e84fa RS |
5534 | (UNSPEC_MASACCS 158) |
5535 | (UNSPEC_MDASACCS 159) | |
36a05131 BS |
5536 | ]) |
5537 | ||
5538 | ;; Logic operations: type "mlogic" | |
5539 | ||
5540 | (define_expand "mand" | |
5541 | [(set (match_operand:SI 0 "fpr_operand" "") | |
5542 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "") | |
5543 | (match_operand:SI 2 "fpr_operand" "") | |
5544 | (match_dup 3)] | |
5545 | UNSPEC_MLOGIC))] | |
5546 | "TARGET_MEDIA" | |
5547 | "operands[3] = GEN_INT (FRV_BUILTIN_MAND);") | |
5548 | ||
5549 | (define_expand "mor" | |
5550 | [(set (match_operand:SI 0 "fpr_operand" "") | |
5551 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "") | |
5552 | (match_operand:SI 2 "fpr_operand" "") | |
5553 | (match_dup 3)] | |
5554 | UNSPEC_MLOGIC))] | |
5555 | "TARGET_MEDIA" | |
5556 | "operands[3] = GEN_INT (FRV_BUILTIN_MOR);") | |
5557 | ||
5558 | (define_expand "mxor" | |
5559 | [(set (match_operand:SI 0 "fpr_operand" "") | |
5560 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "") | |
5561 | (match_operand:SI 2 "fpr_operand" "") | |
5562 | (match_dup 3)] | |
5563 | UNSPEC_MLOGIC))] | |
5564 | "TARGET_MEDIA" | |
5565 | "operands[3] = GEN_INT (FRV_BUILTIN_MXOR);") | |
5566 | ||
5567 | (define_insn "*mlogic" | |
5568 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
5569 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
5570 | (match_operand:SI 2 "fpr_operand" "f") | |
5571 | (match_operand:SI 3 "const_int_operand" "n")] | |
5572 | UNSPEC_MLOGIC))] | |
5573 | "TARGET_MEDIA" | |
5574 | "* | |
5575 | { | |
5576 | switch (INTVAL (operands[3])) | |
5577 | { | |
5578 | default: break; | |
5579 | case FRV_BUILTIN_MAND: return \"mand %1, %2, %0\"; | |
5580 | case FRV_BUILTIN_MOR: return \"mor %1, %2, %0\"; | |
5581 | case FRV_BUILTIN_MXOR: return \"mxor %1, %2, %0\"; | |
5582 | } | |
5583 | ||
5584 | fatal_insn (\"Bad media insn, mlogic\", insn); | |
5585 | }" | |
5586 | [(set_attr "length" "4") | |
5587 | (set_attr "type" "mlogic")]) | |
5588 | ||
5589 | (define_insn "*cond_exec_mlogic" | |
5590 | [(cond_exec | |
5591 | (match_operator 0 "ccr_eqne_operator" | |
5592 | [(match_operand 1 "cr_operand" "C") | |
5593 | (const_int 0)]) | |
5594 | (set (match_operand:SI 2 "fpr_operand" "=f") | |
5595 | (unspec:SI [(match_operand:SI 3 "fpr_operand" "f") | |
5596 | (match_operand:SI 4 "fpr_operand" "f") | |
5597 | (match_operand:SI 5 "const_int_operand" "n")] | |
5598 | UNSPEC_MLOGIC)))] | |
5599 | "TARGET_MEDIA" | |
5600 | "* | |
5601 | { | |
5602 | switch (INTVAL (operands[5])) | |
5603 | { | |
5604 | default: break; | |
5605 | case FRV_BUILTIN_MAND: return \"cmand %3, %4, %2, %1, %e0\"; | |
5606 | case FRV_BUILTIN_MOR: return \"cmor %3, %4, %2, %1, %e0\"; | |
5607 | case FRV_BUILTIN_MXOR: return \"cmxor %3, %4, %2, %1, %e0\"; | |
5608 | } | |
5609 | ||
5610 | fatal_insn (\"Bad media insn, cond_exec_mlogic\", insn); | |
5611 | }" | |
5612 | [(set_attr "length" "4") | |
5613 | (set_attr "type" "mlogic")]) | |
5614 | ||
5615 | ;; Logical not: type "mlogic" | |
5616 | ||
5617 | (define_insn "mnot" | |
5618 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
5619 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")] UNSPEC_MNOT))] | |
5620 | "TARGET_MEDIA" | |
5621 | "mnot %1, %0" | |
5622 | [(set_attr "length" "4") | |
5623 | (set_attr "type" "mlogic")]) | |
5624 | ||
5625 | (define_insn "*cond_exec_mnot" | |
5626 | [(cond_exec | |
5627 | (match_operator 0 "ccr_eqne_operator" | |
5628 | [(match_operand 1 "cr_operand" "C") | |
5629 | (const_int 0)]) | |
5630 | (set (match_operand:SI 2 "fpr_operand" "=f") | |
5631 | (unspec:SI [(match_operand:SI 3 "fpr_operand" "f")] UNSPEC_MNOT)))] | |
5632 | "TARGET_MEDIA" | |
5633 | "cmnot %3, %2, %1, %e0" | |
5634 | [(set_attr "length" "4") | |
5635 | (set_attr "type" "mlogic")]) | |
5636 | ||
5637 | ;; Dual average (halfword): type "maveh" | |
5638 | ||
5639 | (define_insn "maveh" | |
5640 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
5641 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
5642 | (match_operand:SI 2 "fpr_operand" "f")] | |
5643 | UNSPEC_MAVEH))] | |
5644 | "TARGET_MEDIA" | |
5645 | "maveh %1, %2, %0" | |
5646 | [(set_attr "length" "4") | |
5647 | (set_attr "type" "maveh")]) | |
5648 | ||
5649 | ;; Dual saturation (halfword): type "msath" | |
5650 | ||
5651 | (define_expand "msaths" | |
5652 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
5653 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
5654 | (match_operand:SI 2 "fpr_operand" "f") | |
5655 | (match_dup 3)] | |
5656 | UNSPEC_MSATH))] | |
5657 | "TARGET_MEDIA" | |
5658 | "operands[3] = GEN_INT (FRV_BUILTIN_MSATHS);") | |
5659 | ||
5660 | (define_expand "msathu" | |
5661 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
5662 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
5663 | (match_operand:SI 2 "fpr_operand" "f") | |
5664 | (match_dup 3)] | |
5665 | UNSPEC_MSATH))] | |
5666 | "TARGET_MEDIA" | |
5667 | "operands[3] = GEN_INT (FRV_BUILTIN_MSATHU);") | |
5668 | ||
5669 | (define_insn "*msath" | |
5670 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
5671 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
5672 | (match_operand:SI 2 "fpr_operand" "f") | |
5673 | (match_operand:SI 3 "const_int_operand" "n")] | |
5674 | UNSPEC_MSATH))] | |
5675 | "TARGET_MEDIA" | |
5676 | "* | |
5677 | { | |
5678 | switch (INTVAL (operands[3])) | |
5679 | { | |
5680 | default: break; | |
5681 | case FRV_BUILTIN_MSATHS: return \"msaths %1, %2, %0\"; | |
5682 | case FRV_BUILTIN_MSATHU: return \"msathu %1, %2, %0\"; | |
5683 | } | |
5684 | ||
5685 | fatal_insn (\"Bad media insn, msath\", insn); | |
5686 | }" | |
5687 | [(set_attr "length" "4") | |
5688 | (set_attr "type" "msath")]) | |
5689 | ||
5690 | ;; Dual addition/subtraction with saturation (halfword): type "maddh" | |
5691 | ||
5692 | (define_expand "maddhss" | |
5693 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
5694 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
5695 | (match_operand:SI 2 "fpr_operand" "f") | |
5696 | (match_dup 3)] | |
5697 | UNSPEC_MADDH))] | |
5698 | "TARGET_MEDIA" | |
5699 | "operands[3] = GEN_INT (FRV_BUILTIN_MADDHSS);") | |
5700 | ||
5701 | (define_expand "maddhus" | |
5702 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
5703 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
5704 | (match_operand:SI 2 "fpr_operand" "f") | |
5705 | (match_dup 3)] | |
5706 | UNSPEC_MADDH))] | |
5707 | "TARGET_MEDIA" | |
5708 | "operands[3] = GEN_INT (FRV_BUILTIN_MADDHUS);") | |
5709 | ||
5710 | (define_expand "msubhss" | |
5711 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
5712 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
5713 | (match_operand:SI 2 "fpr_operand" "f") | |
5714 | (match_dup 3)] | |
5715 | UNSPEC_MADDH))] | |
5716 | "TARGET_MEDIA" | |
5717 | "operands[3] = GEN_INT (FRV_BUILTIN_MSUBHSS);") | |
5718 | ||
5719 | (define_expand "msubhus" | |
5720 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
5721 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
5722 | (match_operand:SI 2 "fpr_operand" "f") | |
5723 | (match_dup 3)] | |
5724 | UNSPEC_MADDH))] | |
5725 | "TARGET_MEDIA" | |
5726 | "operands[3] = GEN_INT (FRV_BUILTIN_MSUBHUS);") | |
5727 | ||
5728 | (define_insn "*maddh" | |
5729 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
5730 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
5731 | (match_operand:SI 2 "fpr_operand" "f") | |
5732 | (match_operand:SI 3 "const_int_operand" "n")] | |
5733 | UNSPEC_MADDH))] | |
5734 | "TARGET_MEDIA" | |
5735 | "* | |
5736 | { | |
5737 | switch (INTVAL (operands[3])) | |
5738 | { | |
5739 | default: break; | |
5740 | case FRV_BUILTIN_MADDHSS: return \"maddhss %1, %2, %0\"; | |
5741 | case FRV_BUILTIN_MADDHUS: return \"maddhus %1, %2, %0\"; | |
5742 | case FRV_BUILTIN_MSUBHSS: return \"msubhss %1, %2, %0\"; | |
5743 | case FRV_BUILTIN_MSUBHUS: return \"msubhus %1, %2, %0\"; | |
5744 | } | |
5745 | ||
5746 | fatal_insn (\"Bad media insn, maddh\", insn); | |
5747 | }" | |
5748 | [(set_attr "length" "4") | |
5749 | (set_attr "type" "maddh")]) | |
5750 | ||
5751 | (define_insn "*cond_exec_maddh" | |
5752 | [(cond_exec | |
5753 | (match_operator 0 "ccr_eqne_operator" | |
5754 | [(match_operand 1 "cr_operand" "C") | |
5755 | (const_int 0)]) | |
5756 | (set (match_operand:SI 2 "fpr_operand" "=f") | |
5757 | (unspec:SI [(match_operand:SI 3 "fpr_operand" "f") | |
5758 | (match_operand:SI 4 "fpr_operand" "f") | |
5759 | (match_operand:SI 5 "const_int_operand" "n")] | |
5760 | UNSPEC_MADDH)))] | |
5761 | "TARGET_MEDIA" | |
5762 | "* | |
5763 | { | |
5764 | switch (INTVAL (operands[5])) | |
5765 | { | |
5766 | default: break; | |
5767 | case FRV_BUILTIN_MADDHSS: return \"cmaddhss %3, %4, %2, %1, %e0\"; | |
5768 | case FRV_BUILTIN_MADDHUS: return \"cmaddhus %3, %4, %2, %1, %e0\"; | |
5769 | case FRV_BUILTIN_MSUBHSS: return \"cmsubhss %3, %4, %2, %1, %e0\"; | |
5770 | case FRV_BUILTIN_MSUBHUS: return \"cmsubhus %3, %4, %2, %1, %e0\"; | |
5771 | } | |
5772 | ||
5773 | fatal_insn (\"Bad media insn, cond_exec_maddh\", insn); | |
5774 | }" | |
5775 | [(set_attr "length" "4") | |
5776 | (set_attr "type" "maddh")]) | |
5777 | ||
5778 | ;; Quad addition/subtraction with saturation (halfword): type "mqaddh" | |
5779 | ||
5780 | (define_expand "mqaddhss" | |
5781 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
5782 | (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") | |
5783 | (match_operand:DI 2 "even_fpr_operand" "h") | |
5784 | (match_dup 3)] | |
5785 | UNSPEC_MQADDH))] | |
5786 | "TARGET_MEDIA" | |
5787 | "operands[3] = GEN_INT (FRV_BUILTIN_MQADDHSS);") | |
5788 | ||
5789 | (define_expand "mqaddhus" | |
5790 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
5791 | (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") | |
5792 | (match_operand:DI 2 "even_fpr_operand" "h") | |
5793 | (match_dup 3)] | |
5794 | UNSPEC_MQADDH))] | |
5795 | "TARGET_MEDIA" | |
5796 | "operands[3] = GEN_INT (FRV_BUILTIN_MQADDHUS);") | |
5797 | ||
5798 | (define_expand "mqsubhss" | |
5799 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
5800 | (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") | |
5801 | (match_operand:DI 2 "even_fpr_operand" "h") | |
5802 | (match_dup 3)] | |
5803 | UNSPEC_MQADDH))] | |
5804 | "TARGET_MEDIA" | |
5805 | "operands[3] = GEN_INT (FRV_BUILTIN_MQSUBHSS);") | |
5806 | ||
5807 | (define_expand "mqsubhus" | |
5808 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
5809 | (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") | |
5810 | (match_operand:DI 2 "even_fpr_operand" "h") | |
5811 | (match_dup 3)] | |
5812 | UNSPEC_MQADDH))] | |
5813 | "TARGET_MEDIA" | |
5814 | "operands[3] = GEN_INT (FRV_BUILTIN_MQSUBHUS);") | |
5815 | ||
5816 | (define_insn "*mqaddh" | |
5817 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
5818 | (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") | |
5819 | (match_operand:DI 2 "even_fpr_operand" "h") | |
5820 | (match_operand:SI 3 "const_int_operand" "n")] | |
5821 | UNSPEC_MQADDH))] | |
5822 | "TARGET_MEDIA" | |
5823 | "* | |
5824 | { | |
5825 | switch (INTVAL (operands[3])) | |
5826 | { | |
5827 | default: break; | |
5828 | case FRV_BUILTIN_MQADDHSS: return \"mqaddhss %1, %2, %0\"; | |
5829 | case FRV_BUILTIN_MQADDHUS: return \"mqaddhus %1, %2, %0\"; | |
5830 | case FRV_BUILTIN_MQSUBHSS: return \"mqsubhss %1, %2, %0\"; | |
5831 | case FRV_BUILTIN_MQSUBHUS: return \"mqsubhus %1, %2, %0\"; | |
5832 | } | |
5833 | ||
5834 | fatal_insn (\"Bad media insn, mqaddh\", insn); | |
5835 | }" | |
5836 | [(set_attr "length" "4") | |
5837 | (set_attr "type" "mqaddh")]) | |
5838 | ||
5839 | (define_insn "*cond_exec_mqaddh" | |
5840 | [(cond_exec | |
5841 | (match_operator 0 "ccr_eqne_operator" | |
5842 | [(match_operand 1 "cr_operand" "C") | |
5843 | (const_int 0)]) | |
5844 | (set (match_operand:DI 2 "even_fpr_operand" "=h") | |
5845 | (unspec:DI [(match_operand:DI 3 "even_fpr_operand" "h") | |
5846 | (match_operand:DI 4 "even_fpr_operand" "h") | |
5847 | (match_operand:SI 5 "const_int_operand" "n")] | |
5848 | UNSPEC_MQADDH)))] | |
5849 | "TARGET_MEDIA" | |
5850 | "* | |
5851 | { | |
5852 | switch (INTVAL (operands[5])) | |
5853 | { | |
5854 | default: break; | |
5855 | case FRV_BUILTIN_MQADDHSS: return \"cmqaddhss %3, %4, %2, %1, %e0\"; | |
5856 | case FRV_BUILTIN_MQADDHUS: return \"cmqaddhus %3, %4, %2, %1, %e0\"; | |
5857 | case FRV_BUILTIN_MQSUBHSS: return \"cmqsubhss %3, %4, %2, %1, %e0\"; | |
5858 | case FRV_BUILTIN_MQSUBHUS: return \"cmqsubhus %3, %4, %2, %1, %e0\"; | |
5859 | } | |
5860 | ||
5861 | fatal_insn (\"Bad media insn, cond_exec_mqaddh\", insn); | |
5862 | }" | |
5863 | [(set_attr "length" "4") | |
5864 | (set_attr "type" "mqaddh")]) | |
5865 | ||
5866 | ;; Pack halfword: type "mpackh" | |
5867 | ||
5868 | (define_insn "mpackh" | |
5869 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
5870 | (unspec:SI [(match_operand:HI 1 "fpr_operand" "f") | |
5871 | (match_operand:HI 2 "fpr_operand" "f")] | |
5872 | UNSPEC_MPACKH))] | |
5873 | "TARGET_MEDIA" | |
5874 | "mpackh %1, %2, %0" | |
5875 | [(set_attr "length" "4") | |
5876 | (set_attr "type" "mpackh")]) | |
5877 | ||
5878 | ;; Unpack halfword: type "mpackh" | |
5879 | ||
5880 | (define_insn "munpackh" | |
5881 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
5882 | (unspec:DI [(match_operand:SI 1 "fpr_operand" "f")] | |
5883 | UNSPEC_MUNPACKH))] | |
5884 | "TARGET_MEDIA" | |
5885 | "munpackh %1, %0" | |
5886 | [(set_attr "length" "4") | |
5887 | (set_attr "type" "munpackh")]) | |
5888 | ||
5889 | ;; Dual pack halfword: type "mdpackh" | |
5890 | ||
5891 | (define_insn "mdpackh" | |
5892 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
5893 | (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") | |
5894 | (match_operand:DI 2 "even_fpr_operand" "h")] | |
5895 | UNSPEC_MDPACKH))] | |
5896 | "TARGET_MEDIA" | |
5897 | "mdpackh %1, %2, %0" | |
5898 | [(set_attr "length" "4") | |
5899 | (set_attr "type" "mdpackh")]) | |
5900 | ||
5901 | ;; Byte-halfword conversion: type "mbhconv" | |
5902 | ||
5903 | (define_insn "mbtoh" | |
5904 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
5905 | (unspec:DI [(match_operand:SI 1 "fpr_operand" "f")] | |
5906 | UNSPEC_MBTOH))] | |
5907 | "TARGET_MEDIA" | |
5908 | "mbtoh %1, %0" | |
5909 | [(set_attr "length" "4") | |
5910 | (set_attr "type" "mbhconv")]) | |
5911 | ||
5912 | (define_insn "*cond_exec_mbtoh" | |
5913 | [(cond_exec | |
5914 | (match_operator 0 "ccr_eqne_operator" | |
5915 | [(match_operand 1 "cr_operand" "C") | |
5916 | (const_int 0)]) | |
5917 | (set (match_operand:DI 2 "even_fpr_operand" "=h") | |
5918 | (unspec:DI [(match_operand:SI 3 "fpr_operand" "f")] | |
5919 | UNSPEC_MBTOH)))] | |
5920 | "TARGET_MEDIA" | |
5921 | "cmbtoh %3, %2, %1, %e0" | |
5922 | [(set_attr "length" "4") | |
5923 | (set_attr "type" "mbhconv")]) | |
5924 | ||
5925 | (define_insn "mhtob" | |
5926 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
5927 | (unspec:SI [(match_operand:DI 1 "even_fpr_operand" "h")] | |
5928 | UNSPEC_MHTOB))] | |
5929 | "TARGET_MEDIA" | |
5930 | "mhtob %1, %0" | |
5931 | [(set_attr "length" "4") | |
5932 | (set_attr "type" "mbhconv")]) | |
5933 | ||
5934 | (define_insn "*cond_exec_mhtob" | |
5935 | [(cond_exec | |
5936 | (match_operator 0 "ccr_eqne_operator" | |
5937 | [(match_operand 1 "cr_operand" "C") | |
5938 | (const_int 0)]) | |
5939 | (set (match_operand:SI 2 "fpr_operand" "=f") | |
5940 | (unspec:SI [(match_operand:DI 3 "even_fpr_operand" "h")] | |
5941 | UNSPEC_MHTOB)))] | |
5942 | "TARGET_MEDIA" | |
5943 | "cmhtob %3, %2, %1, %e0" | |
5944 | [(set_attr "length" "4") | |
5945 | (set_attr "type" "mbhconv")]) | |
5946 | ||
5947 | ;; Rotate: type "mrot" | |
5948 | ||
5949 | (define_expand "mrotli" | |
5950 | [(set (match_operand:SI 0 "fpr_operand" "") | |
5951 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "") | |
5952 | (match_operand:SI 2 "uint5_operand" "") | |
5953 | (match_dup 3)] | |
5954 | UNSPEC_MROT))] | |
5955 | "TARGET_MEDIA" | |
5956 | "operands[3] = GEN_INT (FRV_BUILTIN_MROTLI);") | |
5957 | ||
5958 | (define_expand "mrotri" | |
5959 | [(set (match_operand:SI 0 "fpr_operand" "") | |
5960 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "") | |
5961 | (match_operand:SI 2 "uint5_operand" "") | |
5962 | (match_dup 3)] | |
5963 | UNSPEC_MROT))] | |
5964 | "TARGET_MEDIA" | |
5965 | "operands[3] = GEN_INT (FRV_BUILTIN_MROTRI);") | |
5966 | ||
5967 | (define_insn "*mrot" | |
5968 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
5969 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
5970 | (match_operand:SI 2 "uint5_operand" "I") | |
5971 | (match_operand:SI 3 "const_int_operand" "n")] | |
5972 | UNSPEC_MROT))] | |
5973 | "TARGET_MEDIA" | |
5974 | "* | |
5975 | { | |
5976 | switch (INTVAL (operands[3])) | |
5977 | { | |
5978 | default: break; | |
5979 | case FRV_BUILTIN_MROTLI: return \"mrotli %1, %2, %0\"; | |
5980 | case FRV_BUILTIN_MROTRI: return \"mrotri %1, %2, %0\"; | |
5981 | } | |
5982 | ||
5983 | fatal_insn (\"Bad media insn, mrot\", insn); | |
5984 | }" | |
5985 | [(set_attr "length" "4") | |
5986 | (set_attr "type" "mrot")]) | |
5987 | ||
5988 | ;; Dual shift halfword: type "msh" | |
5989 | ||
5990 | (define_expand "msllhi" | |
5991 | [(set (match_operand:SI 0 "fpr_operand" "") | |
5992 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "") | |
5993 | (match_operand:SI 2 "uint4_operand" "") | |
5994 | (match_dup 3)] | |
5995 | UNSPEC_MSHIFT))] | |
5996 | "TARGET_MEDIA" | |
5997 | "operands[3] = GEN_INT (FRV_BUILTIN_MSLLHI);") | |
5998 | ||
5999 | (define_expand "msrlhi" | |
6000 | [(set (match_operand:SI 0 "fpr_operand" "") | |
6001 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "") | |
6002 | (match_operand:SI 2 "uint4_operand" "") | |
6003 | (match_dup 3)] | |
6004 | UNSPEC_MSHIFT))] | |
6005 | "TARGET_MEDIA" | |
6006 | "operands[3] = GEN_INT (FRV_BUILTIN_MSRLHI);") | |
6007 | ||
6008 | (define_expand "msrahi" | |
6009 | [(set (match_operand:SI 0 "fpr_operand" "") | |
6010 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "") | |
6011 | (match_operand:SI 2 "uint4_operand" "") | |
6012 | (match_dup 3)] | |
6013 | UNSPEC_MSHIFT))] | |
6014 | "TARGET_MEDIA" | |
6015 | "operands[3] = GEN_INT (FRV_BUILTIN_MSRAHI);") | |
6016 | ||
6017 | (define_insn "*mshift" | |
6018 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
6019 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
6020 | (match_operand:SI 2 "uint4_operand" "I") | |
6021 | (match_operand:SI 3 "const_int_operand" "n")] | |
6022 | UNSPEC_MSHIFT))] | |
6023 | "TARGET_MEDIA" | |
6024 | "* | |
6025 | { | |
6026 | switch (INTVAL (operands[3])) | |
6027 | { | |
6028 | default: break; | |
6029 | case FRV_BUILTIN_MSLLHI: return \"msllhi %1, %2, %0\"; | |
6030 | case FRV_BUILTIN_MSRLHI: return \"msrlhi %1, %2, %0\"; | |
6031 | case FRV_BUILTIN_MSRAHI: return \"msrahi %1, %2, %0\"; | |
6032 | } | |
6033 | ||
6034 | fatal_insn (\"Bad media insn, mshift\", insn); | |
6035 | }" | |
6036 | [(set_attr "length" "4") | |
6037 | (set_attr "type" "mshift")]) | |
6038 | ||
6039 | ;; Expand halfword to word: type "mexpdhw" | |
6040 | ||
6041 | (define_insn "mexpdhw" | |
c557edf4 | 6042 | [(set (match_operand:SI 0 "fpr_operand" "=f") |
36a05131 BS |
6043 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") |
6044 | (match_operand:SI 2 "uint1_operand" "I")] | |
6045 | UNSPEC_MEXPDHW))] | |
6046 | "TARGET_MEDIA" | |
6047 | "mexpdhw %1, %2, %0" | |
6048 | [(set_attr "length" "4") | |
6049 | (set_attr "type" "mexpdhw")]) | |
6050 | ||
6051 | (define_insn "*cond_exec_mexpdhw" | |
6052 | [(cond_exec | |
6053 | (match_operator 0 "ccr_eqne_operator" | |
6054 | [(match_operand 1 "cr_operand" "C") | |
6055 | (const_int 0)]) | |
c557edf4 | 6056 | (set (match_operand:SI 2 "fpr_operand" "=f") |
36a05131 BS |
6057 | (unspec:SI [(match_operand:SI 3 "fpr_operand" "f") |
6058 | (match_operand:SI 4 "uint1_operand" "I")] | |
6059 | UNSPEC_MEXPDHW)))] | |
6060 | "TARGET_MEDIA" | |
6061 | "cmexpdhw %3, %4, %2, %1, %e0" | |
6062 | [(set_attr "length" "4") | |
6063 | (set_attr "type" "mexpdhw")]) | |
6064 | ||
6065 | ;; Expand halfword to double: type "mexpdhd" | |
6066 | ||
6067 | (define_insn "mexpdhd" | |
6068 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
6069 | (unspec:DI [(match_operand:SI 1 "fpr_operand" "f") | |
6070 | (match_operand:SI 2 "uint1_operand" "I")] | |
6071 | UNSPEC_MEXPDHD))] | |
6072 | "TARGET_MEDIA" | |
6073 | "mexpdhd %1, %2, %0" | |
6074 | [(set_attr "length" "4") | |
6075 | (set_attr "type" "mexpdhd")]) | |
6076 | ||
6077 | (define_insn "*cond_exec_mexpdhd" | |
6078 | [(cond_exec | |
6079 | (match_operator 0 "ccr_eqne_operator" | |
6080 | [(match_operand 1 "cr_operand" "C") | |
6081 | (const_int 0)]) | |
6082 | (set (match_operand:DI 2 "even_fpr_operand" "=h") | |
6083 | (unspec:DI [(match_operand:SI 3 "fpr_operand" "f") | |
6084 | (match_operand:SI 4 "uint1_operand" "I")] | |
6085 | UNSPEC_MEXPDHD)))] | |
6086 | "TARGET_MEDIA" | |
6087 | "cmexpdhd %3, %4, %2, %1, %e0" | |
6088 | [(set_attr "length" "4") | |
6089 | (set_attr "type" "mexpdhd")]) | |
6090 | ||
6091 | ;; FR cut: type "mwcut" | |
6092 | ||
6093 | (define_insn "mwcut" | |
6094 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
6095 | (unspec:SI [(match_operand:DI 1 "fpr_operand" "f") | |
6096 | (match_operand:SI 2 "fpr_or_int6_operand" "fI")] | |
6097 | UNSPEC_MWCUT))] | |
6098 | "TARGET_MEDIA" | |
6099 | "mwcut%i2 %1, %2, %0" | |
6100 | [(set_attr "length" "4") | |
6101 | (set_attr "type" "mwcut")]) | |
6102 | ||
6103 | ;; Dual multiplication (halfword): type "mmulh" | |
6104 | ||
6105 | (define_expand "mmulhs" | |
6106 | [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") | |
6107 | (unspec:DI [(match_operand:SI 1 "fpr_operand" "f") | |
6108 | (match_operand:SI 2 "fpr_operand" "f") | |
6109 | (match_dup 4)] | |
6110 | UNSPEC_MMULH)) | |
6111 | (set (match_operand:HI 3 "accg_operand" "=B") | |
6112 | (unspec:HI [(const_int 0)] UNSPEC_MMULH))])] | |
6113 | "TARGET_MEDIA" | |
6114 | "operands[4] = GEN_INT (FRV_BUILTIN_MMULHS);") | |
6115 | ||
6116 | (define_expand "mmulhu" | |
6117 | [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") | |
6118 | (unspec:DI [(match_operand:SI 1 "fpr_operand" "f") | |
6119 | (match_operand:SI 2 "fpr_operand" "f") | |
6120 | (match_dup 4)] | |
6121 | UNSPEC_MMULH)) | |
6122 | (set (match_operand:HI 3 "accg_operand" "=B") | |
6123 | (unspec:HI [(const_int 0)] UNSPEC_MMULH))])] | |
6124 | "TARGET_MEDIA" | |
6125 | "operands[4] = GEN_INT (FRV_BUILTIN_MMULHU);") | |
6126 | ||
6127 | (define_insn "*mmulh" | |
6128 | [(set (match_operand:DI 0 "even_acc_operand" "=b") | |
6129 | (unspec:DI [(match_operand:SI 1 "fpr_operand" "f") | |
6130 | (match_operand:SI 2 "fpr_operand" "f") | |
6131 | (match_operand:SI 3 "const_int_operand" "n")] | |
6132 | UNSPEC_MMULH)) | |
6133 | (set (match_operand:HI 4 "accg_operand" "=B") | |
6134 | (unspec:HI [(const_int 0)] UNSPEC_MMULH))] | |
6135 | "TARGET_MEDIA" | |
6136 | "* | |
6137 | { | |
6138 | switch (INTVAL (operands[3])) | |
6139 | { | |
6140 | default: break; | |
6141 | case FRV_BUILTIN_MMULHS: return \"mmulhs %1, %2, %0\"; | |
6142 | case FRV_BUILTIN_MMULHU: return \"mmulhu %1, %2, %0\"; | |
6143 | } | |
6144 | ||
6145 | fatal_insn (\"Bad media insn, mmulh\", insn); | |
6146 | }" | |
6147 | [(set_attr "length" "4") | |
6148 | (set_attr "type" "mmulh")]) | |
6149 | ||
6150 | (define_insn "*cond_exec_mmulh" | |
6151 | [(cond_exec | |
6152 | (match_operator 0 "ccr_eqne_operator" | |
6153 | [(match_operand 1 "cr_operand" "C") | |
6154 | (const_int 0)]) | |
6155 | (parallel [(set (match_operand:DI 2 "even_acc_operand" "=b") | |
6156 | (unspec:DI [(match_operand:SI 3 "fpr_operand" "f") | |
6157 | (match_operand:SI 4 "fpr_operand" "f") | |
6158 | (match_operand:SI 5 "const_int_operand" "n")] | |
6159 | UNSPEC_MMULH)) | |
6160 | (set (match_operand:HI 6 "accg_operand" "=B") | |
6161 | (unspec:HI [(const_int 0)] UNSPEC_MMULH))]))] | |
6162 | "TARGET_MEDIA" | |
6163 | "* | |
6164 | { | |
6165 | switch (INTVAL (operands[5])) | |
6166 | { | |
6167 | default: break; | |
6168 | case FRV_BUILTIN_MMULHS: return \"cmmulhs %3, %4, %2, %1, %e0\"; | |
6169 | case FRV_BUILTIN_MMULHU: return \"cmmulhu %3, %4, %2, %1, %e0\"; | |
6170 | } | |
6171 | ||
6172 | fatal_insn (\"Bad media insn, cond_exec_mmulh\", insn); | |
6173 | }" | |
6174 | [(set_attr "length" "4") | |
6175 | (set_attr "type" "mmulh")]) | |
6176 | ||
6177 | ;; Dual cross multiplication (halfword): type "mmulxh" | |
6178 | ||
6179 | (define_expand "mmulxhs" | |
6180 | [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") | |
6181 | (unspec:DI [(match_operand:SI 1 "fpr_operand" "f") | |
6182 | (match_operand:SI 2 "fpr_operand" "f") | |
6183 | (match_dup 4)] | |
6184 | UNSPEC_MMULXH)) | |
6185 | (set (match_operand:HI 3 "accg_operand" "=B") | |
6186 | (unspec:HI [(const_int 0)] UNSPEC_MMULXH))])] | |
6187 | "TARGET_MEDIA" | |
6188 | "operands[4] = GEN_INT (FRV_BUILTIN_MMULXHS);") | |
6189 | ||
6190 | (define_expand "mmulxhu" | |
6191 | [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") | |
6192 | (unspec:DI [(match_operand:SI 1 "fpr_operand" "f") | |
6193 | (match_operand:SI 2 "fpr_operand" "f") | |
6194 | (match_dup 4)] | |
6195 | UNSPEC_MMULXH)) | |
6196 | (set (match_operand:HI 3 "accg_operand" "=B") | |
6197 | (unspec:HI [(const_int 0)] UNSPEC_MMULXH))])] | |
6198 | "TARGET_MEDIA" | |
6199 | "operands[4] = GEN_INT (FRV_BUILTIN_MMULXHU);") | |
6200 | ||
6201 | (define_insn "*mmulxh" | |
6202 | [(set (match_operand:DI 0 "even_acc_operand" "=b") | |
6203 | (unspec:DI [(match_operand:SI 1 "fpr_operand" "f") | |
6204 | (match_operand:SI 2 "fpr_operand" "f") | |
6205 | (match_operand:SI 3 "const_int_operand" "n")] | |
6206 | UNSPEC_MMULXH)) | |
6207 | (set (match_operand:HI 4 "accg_operand" "=B") | |
6208 | (unspec:HI [(const_int 0)] UNSPEC_MMULXH))] | |
6209 | "TARGET_MEDIA" | |
6210 | "* | |
6211 | { | |
6212 | switch (INTVAL (operands[3])) | |
6213 | { | |
6214 | default: break; | |
6215 | case FRV_BUILTIN_MMULXHS: return \"mmulxhs %1, %2, %0\"; | |
6216 | case FRV_BUILTIN_MMULXHU: return \"mmulxhu %1, %2, %0\"; | |
6217 | } | |
6218 | ||
6219 | fatal_insn (\"Bad media insn, mmulxh\", insn); | |
6220 | }" | |
6221 | [(set_attr "length" "4") | |
6222 | (set_attr "type" "mmulxh")]) | |
6223 | ||
6224 | ;; Dual product-sum (halfword): type "mmach" | |
6225 | ||
6226 | (define_expand "mmachs" | |
6227 | [(parallel [(set (match_operand:DI 0 "even_acc_operand" "+b") | |
6228 | (unspec:DI [(match_dup 0) | |
6229 | (match_operand:SI 1 "fpr_operand" "f") | |
6230 | (match_operand:SI 2 "fpr_operand" "f") | |
6231 | (match_operand:HI 3 "accg_operand" "+B") | |
6232 | (match_dup 4)] | |
6233 | UNSPEC_MMACH)) | |
6234 | (set (match_dup 3) | |
6235 | (unspec:HI [(const_int 0)] UNSPEC_MMACH))])] | |
6236 | "TARGET_MEDIA" | |
6237 | "operands[4] = GEN_INT (FRV_BUILTIN_MMACHS);") | |
6238 | ||
6239 | (define_expand "mmachu" | |
6240 | [(parallel [(set (match_operand:DI 0 "even_acc_operand" "+b") | |
6241 | (unspec:DI [(match_dup 0) | |
6242 | (match_operand:SI 1 "fpr_operand" "f") | |
6243 | (match_operand:SI 2 "fpr_operand" "f") | |
6244 | (match_operand:HI 3 "accg_operand" "+B") | |
6245 | (match_dup 4)] | |
6246 | UNSPEC_MMACH)) | |
6247 | (set (match_dup 3) | |
6248 | (unspec:HI [(const_int 0)] UNSPEC_MMACH))])] | |
6249 | "TARGET_MEDIA" | |
6250 | "operands[4] = GEN_INT (FRV_BUILTIN_MMACHU);") | |
6251 | ||
6252 | (define_insn "*mmach" | |
6253 | [(set (match_operand:DI 0 "even_acc_operand" "+b") | |
6254 | (unspec:DI [(match_dup 0) | |
6255 | (match_operand:SI 1 "fpr_operand" "f") | |
6256 | (match_operand:SI 2 "fpr_operand" "f") | |
6257 | (match_operand:HI 3 "accg_operand" "+B") | |
6258 | (match_operand:SI 4 "const_int_operand" "n")] | |
6259 | UNSPEC_MMACH)) | |
6260 | (set (match_dup 3) (unspec:HI [(const_int 0)] UNSPEC_MMACH))] | |
6261 | "TARGET_MEDIA" | |
6262 | "* | |
6263 | { | |
6264 | switch (INTVAL (operands[4])) | |
6265 | { | |
6266 | default: break; | |
6267 | case FRV_BUILTIN_MMACHS: return \"mmachs %1, %2, %0\"; | |
6268 | case FRV_BUILTIN_MMACHU: return \"mmachu %1, %2, %0\"; | |
6269 | } | |
6270 | ||
6271 | fatal_insn (\"Bad media insn, mmach\", insn); | |
6272 | }" | |
6273 | [(set_attr "length" "4") | |
6274 | (set_attr "type" "mmach")]) | |
6275 | ||
6276 | (define_insn "*cond_exec_mmach" | |
6277 | [(cond_exec | |
6278 | (match_operator 0 "ccr_eqne_operator" | |
6279 | [(match_operand 1 "cr_operand" "C") | |
6280 | (const_int 0)]) | |
6281 | (parallel [(set (match_operand:DI 2 "even_acc_operand" "+b") | |
6282 | (unspec:DI [(match_dup 2) | |
6283 | (match_operand:SI 3 "fpr_operand" "f") | |
6284 | (match_operand:SI 4 "fpr_operand" "f") | |
6285 | (match_operand:HI 5 "accg_operand" "+B") | |
6286 | (match_operand:SI 6 "const_int_operand" "n")] | |
6287 | UNSPEC_MMACH)) | |
6288 | (set (match_dup 5) | |
6289 | (unspec:HI [(const_int 0)] UNSPEC_MMACH))]))] | |
6290 | "TARGET_MEDIA" | |
6291 | "* | |
6292 | { | |
6293 | switch (INTVAL (operands[6])) | |
6294 | { | |
6295 | default: break; | |
6296 | case FRV_BUILTIN_MMACHS: return \"cmmachs %3, %4, %2, %1, %e0\"; | |
6297 | case FRV_BUILTIN_MMACHU: return \"cmmachu %3, %4, %2, %1, %e0\"; | |
6298 | } | |
6299 | ||
6300 | fatal_insn (\"Bad media insn, cond_exec_mmach\", insn); | |
6301 | }" | |
6302 | [(set_attr "length" "4") | |
6303 | (set_attr "type" "mmach")]) | |
6304 | ||
6305 | ;; Dual product-difference: type "mmrdh" | |
6306 | ||
6307 | (define_expand "mmrdhs" | |
6308 | [(parallel [(set (match_operand:DI 0 "even_acc_operand" "+b") | |
6309 | (unspec:DI [(match_dup 0) | |
6310 | (match_operand:SI 1 "fpr_operand" "f") | |
6311 | (match_operand:SI 2 "fpr_operand" "f") | |
6312 | (match_operand:HI 3 "accg_operand" "+B") | |
6313 | (match_dup 4)] | |
6314 | UNSPEC_MMRDH)) | |
6315 | (set (match_dup 3) | |
6316 | (unspec:HI [(const_int 0)] UNSPEC_MMRDH))])] | |
6317 | "TARGET_MEDIA" | |
6318 | "operands[4] = GEN_INT (FRV_BUILTIN_MMRDHS);") | |
6319 | ||
6320 | (define_expand "mmrdhu" | |
6321 | [(parallel [(set (match_operand:DI 0 "even_acc_operand" "+b") | |
6322 | (unspec:DI [(match_dup 0) | |
6323 | (match_operand:SI 1 "fpr_operand" "f") | |
6324 | (match_operand:SI 2 "fpr_operand" "f") | |
6325 | (match_operand:HI 3 "accg_operand" "+B") | |
6326 | (match_dup 4)] | |
6327 | UNSPEC_MMRDH)) | |
6328 | (set (match_dup 3) | |
6329 | (unspec:HI [(const_int 0)] UNSPEC_MMRDH))])] | |
6330 | "TARGET_MEDIA" | |
6331 | "operands[4] = GEN_INT (FRV_BUILTIN_MMRDHU);") | |
6332 | ||
6333 | (define_insn "*mmrdh" | |
6334 | [(set (match_operand:DI 0 "even_acc_operand" "+b") | |
6335 | (unspec:DI [(match_dup 0) | |
6336 | (match_operand:SI 1 "fpr_operand" "f") | |
6337 | (match_operand:SI 2 "fpr_operand" "f") | |
6338 | (match_operand:HI 3 "accg_operand" "+B") | |
6339 | (match_operand:SI 4 "const_int_operand" "n")] | |
6340 | UNSPEC_MMRDH)) | |
6341 | (set (match_dup 3) | |
6342 | (unspec:HI [(const_int 0)] UNSPEC_MMRDH))] | |
6343 | "TARGET_MEDIA" | |
6344 | "* | |
6345 | { | |
6346 | switch (INTVAL (operands[4])) | |
6347 | { | |
6348 | default: break; | |
6349 | case FRV_BUILTIN_MMRDHS: return \"mmrdhs %1, %2, %0\"; | |
6350 | case FRV_BUILTIN_MMRDHU: return \"mmrdhu %1, %2, %0\"; | |
6351 | } | |
6352 | ||
6353 | fatal_insn (\"Bad media insn, mrdh\", insn); | |
6354 | }" | |
6355 | [(set_attr "length" "4") | |
6356 | (set_attr "type" "mmrdh")]) | |
6357 | ||
6358 | ;; Quad multiply (halfword): type "mqmulh" | |
6359 | ||
6360 | (define_expand "mqmulhs" | |
6361 | [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "=A") | |
6362 | (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h") | |
6363 | (match_operand:DI 2 "even_fpr_operand" "h") | |
6364 | (match_dup 4)] | |
6365 | UNSPEC_MQMULH)) | |
6366 | (set (match_operand:V4QI 3 "accg_operand" "=B") | |
6367 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMULH))])] | |
6368 | "TARGET_MEDIA" | |
6369 | "operands[4] = GEN_INT (FRV_BUILTIN_MQMULHS);") | |
6370 | ||
6371 | (define_expand "mqmulhu" | |
6372 | [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "=A") | |
6373 | (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h") | |
6374 | (match_operand:DI 2 "even_fpr_operand" "h") | |
6375 | (match_dup 4)] | |
6376 | UNSPEC_MQMULH)) | |
6377 | (set (match_operand:V4QI 3 "accg_operand" "=B") | |
6378 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMULH))])] | |
6379 | "TARGET_MEDIA" | |
6380 | "operands[4] = GEN_INT (FRV_BUILTIN_MQMULHU);") | |
6381 | ||
6382 | (define_insn "*mqmulh" | |
6383 | [(set (match_operand:V4SI 0 "quad_acc_operand" "=A") | |
6384 | (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h") | |
6385 | (match_operand:DI 2 "even_fpr_operand" "h") | |
6386 | (match_operand:SI 3 "const_int_operand" "n")] | |
6387 | UNSPEC_MQMULH)) | |
6388 | (set (match_operand:V4QI 4 "accg_operand" "=B") | |
6389 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMULH))] | |
6390 | "TARGET_MEDIA" | |
6391 | "* | |
6392 | { | |
6393 | switch (INTVAL (operands[3])) | |
6394 | { | |
6395 | default: break; | |
6396 | case FRV_BUILTIN_MQMULHS: return \"mqmulhs %1, %2, %0\"; | |
6397 | case FRV_BUILTIN_MQMULHU: return \"mqmulhu %1, %2, %0\"; | |
6398 | } | |
6399 | ||
6400 | fatal_insn (\"Bad media insn, mqmulh\", insn); | |
6401 | }" | |
6402 | [(set_attr "length" "4") | |
6403 | (set_attr "type" "mqmulh")]) | |
6404 | ||
6405 | (define_insn "*cond_exec_mqmulh" | |
6406 | [(cond_exec | |
6407 | (match_operator 0 "ccr_eqne_operator" | |
6408 | [(match_operand 1 "cr_operand" "C") | |
6409 | (const_int 0)]) | |
6410 | (parallel [(set (match_operand:V4SI 2 "quad_acc_operand" "=A") | |
6411 | (unspec:V4SI [(match_operand:DI 3 "even_fpr_operand" "h") | |
6412 | (match_operand:DI 4 "even_fpr_operand" "h") | |
6413 | (match_operand:SI 5 "const_int_operand" "n")] | |
6414 | UNSPEC_MQMULH)) | |
6415 | (set (match_operand:V4QI 6 "accg_operand" "=B") | |
6416 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMULH))]))] | |
6417 | "TARGET_MEDIA" | |
6418 | "* | |
6419 | { | |
6420 | switch (INTVAL (operands[5])) | |
6421 | { | |
6422 | default: break; | |
6423 | case FRV_BUILTIN_MQMULHS: return \"cmqmulhs %3, %4, %2, %1, %e0\"; | |
6424 | case FRV_BUILTIN_MQMULHU: return \"cmqmulhu %3, %4, %2, %1, %e0\"; | |
6425 | } | |
6426 | ||
6427 | fatal_insn (\"Bad media insn, cond_exec_mqmulh\", insn); | |
6428 | }" | |
6429 | [(set_attr "length" "4") | |
6430 | (set_attr "type" "mqmulh")]) | |
6431 | ||
6432 | ;; Quad cross multiply (halfword): type "mqmulxh" | |
6433 | ||
6434 | (define_expand "mqmulxhs" | |
6435 | [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "=A") | |
6436 | (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h") | |
6437 | (match_operand:DI 2 "even_fpr_operand" "h") | |
6438 | (match_dup 4)] | |
6439 | UNSPEC_MQMULXH)) | |
6440 | (set (match_operand:V4QI 3 "accg_operand" "=B") | |
6441 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMULXH))])] | |
6442 | "TARGET_MEDIA" | |
6443 | "operands[4] = GEN_INT (FRV_BUILTIN_MQMULXHS);") | |
6444 | ||
6445 | (define_expand "mqmulxhu" | |
6446 | [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "=A") | |
6447 | (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h") | |
6448 | (match_operand:DI 2 "even_fpr_operand" "h") | |
6449 | (match_dup 4)] | |
6450 | UNSPEC_MQMULXH)) | |
6451 | (set (match_operand:V4QI 3 "accg_operand" "=B") | |
6452 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMULXH))])] | |
6453 | "TARGET_MEDIA" | |
6454 | "operands[4] = GEN_INT (FRV_BUILTIN_MQMULXHU);") | |
6455 | ||
6456 | (define_insn "*mqmulxh" | |
6457 | [(set (match_operand:V4SI 0 "quad_acc_operand" "=A") | |
6458 | (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h") | |
6459 | (match_operand:DI 2 "even_fpr_operand" "h") | |
6460 | (match_operand:SI 3 "const_int_operand" "n")] | |
6461 | UNSPEC_MQMULXH)) | |
6462 | (set (match_operand:V4QI 4 "accg_operand" "=B") | |
6463 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMULXH))] | |
6464 | "TARGET_MEDIA" | |
6465 | "* | |
6466 | { | |
6467 | switch (INTVAL (operands[3])) | |
6468 | { | |
6469 | default: break; | |
6470 | case FRV_BUILTIN_MQMULXHS: return \"mqmulxhs %1, %2, %0\"; | |
6471 | case FRV_BUILTIN_MQMULXHU: return \"mqmulxhu %1, %2, %0\"; | |
6472 | } | |
6473 | ||
6474 | fatal_insn (\"Bad media insn, mqmulxh\", insn); | |
6475 | }" | |
6476 | [(set_attr "length" "4") | |
6477 | (set_attr "type" "mqmulxh")]) | |
6478 | ||
6479 | ;; Quad product-sum (halfword): type "mqmach" | |
6480 | ||
6481 | (define_expand "mqmachs" | |
6482 | [(parallel [(set (match_operand:V4SI 0 "even_acc_operand" "+A") | |
6483 | (unspec:V4SI [(match_dup 0) | |
6484 | (match_operand:DI 1 "even_fpr_operand" "h") | |
6485 | (match_operand:DI 2 "even_fpr_operand" "h") | |
6486 | (match_operand:V4QI 3 "accg_operand" "+B") | |
6487 | (match_dup 4)] | |
6488 | UNSPEC_MQMACH)) | |
6489 | (set (match_dup 3) | |
6490 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH))])] | |
6491 | "TARGET_MEDIA" | |
6492 | "operands[4] = GEN_INT (FRV_BUILTIN_MQMACHS);") | |
6493 | ||
6494 | (define_expand "mqmachu" | |
6495 | [(parallel [(set (match_operand:V4SI 0 "even_acc_operand" "+A") | |
6496 | (unspec:V4SI [(match_dup 0) | |
6497 | (match_operand:DI 1 "even_fpr_operand" "h") | |
6498 | (match_operand:DI 2 "even_fpr_operand" "h") | |
6499 | (match_operand:V4QI 3 "accg_operand" "+B") | |
6500 | (match_dup 4)] | |
6501 | UNSPEC_MQMACH)) | |
6502 | (set (match_dup 3) | |
6503 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH))])] | |
6504 | "TARGET_MEDIA" | |
6505 | "operands[4] = GEN_INT (FRV_BUILTIN_MQMACHU);") | |
6506 | ||
6507 | (define_insn "*mqmach" | |
6508 | [(set (match_operand:V4SI 0 "even_acc_operand" "+A") | |
6509 | (unspec:V4SI [(match_dup 0) | |
6510 | (match_operand:DI 1 "even_fpr_operand" "h") | |
6511 | (match_operand:DI 2 "even_fpr_operand" "h") | |
6512 | (match_operand:V4QI 3 "accg_operand" "+B") | |
6513 | (match_operand:SI 4 "const_int_operand" "n")] | |
6514 | UNSPEC_MQMACH)) | |
6515 | (set (match_dup 3) | |
6516 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH))] | |
6517 | "TARGET_MEDIA" | |
6518 | "* | |
6519 | { | |
6520 | switch (INTVAL (operands[4])) | |
6521 | { | |
6522 | default: break; | |
6523 | case FRV_BUILTIN_MQMACHS: return \"mqmachs %1, %2, %0\"; | |
6524 | case FRV_BUILTIN_MQMACHU: return \"mqmachu %1, %2, %0\"; | |
6525 | } | |
6526 | ||
6527 | fatal_insn (\"Bad media insn, mqmach\", insn); | |
6528 | }" | |
6529 | [(set_attr "length" "4") | |
6530 | (set_attr "type" "mqmach")]) | |
6531 | ||
6532 | (define_insn "*cond_exec_mqmach" | |
6533 | [(cond_exec | |
6534 | (match_operator 0 "ccr_eqne_operator" | |
6535 | [(match_operand 1 "cr_operand" "C") | |
6536 | (const_int 0)]) | |
6537 | (parallel [(set (match_operand:V4SI 2 "even_acc_operand" "+A") | |
6538 | (unspec:V4SI [(match_dup 2) | |
6539 | (match_operand:DI 3 "even_fpr_operand" "h") | |
6540 | (match_operand:DI 4 "even_fpr_operand" "h") | |
6541 | (match_operand:V4QI 5 "accg_operand" "+B") | |
6542 | (match_operand:SI 6 "const_int_operand" "n")] | |
6543 | UNSPEC_MQMACH)) | |
6544 | (set (match_dup 5) | |
6545 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH))]))] | |
6546 | "TARGET_MEDIA" | |
6547 | "* | |
6548 | { | |
6549 | switch (INTVAL (operands[6])) | |
6550 | { | |
6551 | default: break; | |
6552 | case FRV_BUILTIN_MQMACHS: return \"cmqmachs %3, %4, %2, %1, %e0\"; | |
6553 | case FRV_BUILTIN_MQMACHU: return \"cmqmachu %3, %4, %2, %1, %e0\"; | |
6554 | } | |
6555 | ||
6556 | fatal_insn (\"Bad media insn, cond_exec_mqmach\", insn); | |
6557 | }" | |
6558 | [(set_attr "length" "4") | |
6559 | (set_attr "type" "mqmach")]) | |
6560 | ||
6561 | ;; Dual complex number product-sum (halfword) | |
6562 | ||
6563 | (define_expand "mcpxrs" | |
6564 | [(parallel [(set (match_operand:SI 0 "acc_operand" "=a") | |
6565 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
6566 | (match_operand:SI 2 "fpr_operand" "f") | |
6567 | (match_dup 4)] | |
6568 | UNSPEC_MCPX)) | |
6569 | (set (match_operand:QI 3 "accg_operand" "=B") | |
6570 | (unspec:QI [(const_int 0)] UNSPEC_MCPX))])] | |
6571 | "TARGET_MEDIA" | |
6572 | "operands[4] = GEN_INT (FRV_BUILTIN_MCPXRS);") | |
6573 | ||
6574 | (define_expand "mcpxru" | |
6575 | [(parallel [(set (match_operand:SI 0 "acc_operand" "=a") | |
6576 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
6577 | (match_operand:SI 2 "fpr_operand" "f") | |
6578 | (match_dup 4)] | |
6579 | UNSPEC_MCPX)) | |
6580 | (set (match_operand:QI 3 "accg_operand" "=B") | |
6581 | (unspec:QI [(const_int 0)] UNSPEC_MCPX))])] | |
6582 | "TARGET_MEDIA" | |
6583 | "operands[4] = GEN_INT (FRV_BUILTIN_MCPXRU);") | |
6584 | ||
6585 | (define_expand "mcpxis" | |
6586 | [(parallel [(set (match_operand:SI 0 "acc_operand" "=a") | |
6587 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
6588 | (match_operand:SI 2 "fpr_operand" "f") | |
6589 | (match_dup 4)] | |
6590 | UNSPEC_MCPX)) | |
6591 | (set (match_operand:QI 3 "accg_operand" "=B") | |
6592 | (unspec:QI [(const_int 0)] UNSPEC_MCPX))])] | |
6593 | "TARGET_MEDIA" | |
6594 | "operands[4] = GEN_INT (FRV_BUILTIN_MCPXIS);") | |
6595 | ||
6596 | (define_expand "mcpxiu" | |
6597 | [(parallel [(set (match_operand:SI 0 "acc_operand" "=a") | |
6598 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
6599 | (match_operand:SI 2 "fpr_operand" "f") | |
6600 | (match_dup 4)] | |
6601 | UNSPEC_MCPX)) | |
6602 | (set (match_operand:QI 3 "accg_operand" "=B") | |
6603 | (unspec:QI [(const_int 0)] UNSPEC_MCPX))])] | |
6604 | "TARGET_MEDIA" | |
6605 | "operands[4] = GEN_INT (FRV_BUILTIN_MCPXIU);") | |
6606 | ||
6607 | (define_insn "*mcpx" | |
6608 | [(parallel [(set (match_operand:SI 0 "acc_operand" "=a") | |
6609 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
6610 | (match_operand:SI 2 "fpr_operand" "f") | |
6611 | (match_operand:SI 3 "const_int_operand" "n")] | |
6612 | UNSPEC_MCPX)) | |
6613 | (set (match_operand:QI 4 "accg_operand" "=B") | |
6614 | (unspec:QI [(const_int 0)] UNSPEC_MCPX))])] | |
6615 | "TARGET_MEDIA" | |
6616 | "* | |
6617 | { | |
6618 | switch (INTVAL (operands[3])) | |
6619 | { | |
6620 | default: break; | |
6621 | case FRV_BUILTIN_MCPXRS: return \"mcpxrs %1, %2, %0\"; | |
6622 | case FRV_BUILTIN_MCPXRU: return \"mcpxru %1, %2, %0\"; | |
6623 | case FRV_BUILTIN_MCPXIS: return \"mcpxis %1, %2, %0\"; | |
6624 | case FRV_BUILTIN_MCPXIU: return \"mcpxiu %1, %2, %0\"; | |
6625 | } | |
6626 | ||
6627 | fatal_insn (\"Bad media insn, mcpx\", insn); | |
6628 | }" | |
6629 | [(set_attr "length" "4") | |
6630 | (set_attr "type" "mcpx")]) | |
6631 | ||
6632 | (define_insn "*cond_exec_mcpx" | |
6633 | [(cond_exec | |
6634 | (match_operator 0 "ccr_eqne_operator" | |
6635 | [(match_operand 1 "cr_operand" "C") | |
6636 | (const_int 0)]) | |
6637 | (parallel [(set (match_operand:SI 2 "acc_operand" "=a") | |
6638 | (unspec:SI [(match_operand:SI 3 "fpr_operand" "f") | |
6639 | (match_operand:SI 4 "fpr_operand" "f") | |
6640 | (match_operand:SI 5 "const_int_operand" "n")] | |
6641 | UNSPEC_MCPX)) | |
6642 | (set (match_operand:QI 6 "accg_operand" "=B") | |
6643 | (unspec:QI [(const_int 0)] UNSPEC_MCPX))]))] | |
6644 | "TARGET_MEDIA" | |
6645 | "* | |
6646 | { | |
6647 | switch (INTVAL (operands[5])) | |
6648 | { | |
6649 | default: break; | |
6650 | case FRV_BUILTIN_MCPXRS: return \"cmcpxrs %3, %4, %2, %1, %e0\"; | |
6651 | case FRV_BUILTIN_MCPXRU: return \"cmcpxru %3, %4, %2, %1, %e0\"; | |
6652 | case FRV_BUILTIN_MCPXIS: return \"cmcpxis %3, %4, %2, %1, %e0\"; | |
6653 | case FRV_BUILTIN_MCPXIU: return \"cmcpxiu %3, %4, %2, %1, %e0\"; | |
6654 | } | |
6655 | ||
6656 | fatal_insn (\"Bad media insn, cond_exec_mcpx\", insn); | |
6657 | }" | |
6658 | [(set_attr "length" "4") | |
6659 | (set_attr "type" "mcpx")]) | |
6660 | ||
6661 | ;; Quad complex number product-sum (halfword): type "mqcpx" | |
6662 | ||
6663 | (define_expand "mqcpxrs" | |
6664 | [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") | |
6665 | (unspec:DI [(match_operand:DI 1 "fpr_operand" "f") | |
6666 | (match_operand:DI 2 "fpr_operand" "f") | |
6667 | (match_dup 4)] | |
6668 | UNSPEC_MQCPX)) | |
6669 | (set (match_operand:HI 3 "accg_operand" "=B") | |
6670 | (unspec:HI [(const_int 0)] UNSPEC_MQCPX))])] | |
6671 | "TARGET_MEDIA" | |
6672 | "operands[4] = GEN_INT (FRV_BUILTIN_MQCPXRS);") | |
6673 | ||
6674 | (define_expand "mqcpxru" | |
6675 | [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") | |
6676 | (unspec:DI [(match_operand:DI 1 "fpr_operand" "f") | |
6677 | (match_operand:DI 2 "fpr_operand" "f") | |
6678 | (match_dup 4)] | |
6679 | UNSPEC_MQCPX)) | |
6680 | (set (match_operand:HI 3 "accg_operand" "=B") | |
6681 | (unspec:HI [(const_int 0)] UNSPEC_MQCPX))])] | |
6682 | "TARGET_MEDIA" | |
6683 | "operands[4] = GEN_INT (FRV_BUILTIN_MQCPXRU);") | |
6684 | ||
6685 | (define_expand "mqcpxis" | |
6686 | [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") | |
6687 | (unspec:DI [(match_operand:DI 1 "fpr_operand" "f") | |
6688 | (match_operand:DI 2 "fpr_operand" "f") | |
6689 | (match_dup 4)] | |
6690 | UNSPEC_MQCPX)) | |
6691 | (set (match_operand:HI 3 "accg_operand" "=B") | |
6692 | (unspec:HI [(const_int 0)] UNSPEC_MQCPX))])] | |
6693 | "TARGET_MEDIA" | |
6694 | "operands[4] = GEN_INT (FRV_BUILTIN_MQCPXIS);") | |
6695 | ||
6696 | (define_expand "mqcpxiu" | |
6697 | [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") | |
6698 | (unspec:DI [(match_operand:DI 1 "fpr_operand" "f") | |
6699 | (match_operand:DI 2 "fpr_operand" "f") | |
6700 | (match_dup 4)] | |
6701 | UNSPEC_MQCPX)) | |
6702 | (set (match_operand:HI 3 "accg_operand" "=B") | |
6703 | (unspec:HI [(const_int 0)] UNSPEC_MQCPX))])] | |
6704 | "TARGET_MEDIA" | |
6705 | "operands[4] = GEN_INT (FRV_BUILTIN_MQCPXIU);") | |
6706 | ||
6707 | (define_insn "*mqcpx" | |
6708 | [(set (match_operand:DI 0 "even_acc_operand" "=b") | |
6709 | (unspec:DI [(match_operand:DI 1 "fpr_operand" "f") | |
6710 | (match_operand:DI 2 "fpr_operand" "f") | |
6711 | (match_operand:SI 3 "const_int_operand" "n")] | |
6712 | UNSPEC_MQCPX)) | |
6713 | (set (match_operand:HI 4 "accg_operand" "=B") | |
6714 | (unspec:HI [(const_int 0)] UNSPEC_MQCPX))] | |
6715 | "TARGET_MEDIA" | |
6716 | "* | |
6717 | { | |
6718 | switch (INTVAL (operands[3])) | |
6719 | { | |
6720 | default: break; | |
6721 | case FRV_BUILTIN_MQCPXRS: return \"mqcpxrs %1, %2, %0\"; | |
6722 | case FRV_BUILTIN_MQCPXRU: return \"mqcpxru %1, %2, %0\"; | |
6723 | case FRV_BUILTIN_MQCPXIS: return \"mqcpxis %1, %2, %0\"; | |
6724 | case FRV_BUILTIN_MQCPXIU: return \"mqcpxiu %1, %2, %0\"; | |
6725 | } | |
6726 | ||
6727 | fatal_insn (\"Bad media insn, mqcpx\", insn); | |
6728 | }" | |
6729 | [(set_attr "length" "4") | |
6730 | (set_attr "type" "mqcpx")]) | |
6731 | ||
6732 | ;; Cut: type "mcut" | |
6733 | ||
6734 | (define_expand "mcut" | |
6735 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
6736 | (unspec:SI [(match_operand:SI 1 "acc_operand" "a") | |
6737 | (match_operand:SI 2 "fpr_or_int6_operand" "fI") | |
6738 | (match_operand:QI 3 "accg_operand" "B") | |
6739 | (match_dup 4)] | |
6740 | UNSPEC_MCUT))] | |
6741 | "TARGET_MEDIA" | |
6742 | "operands[4] = GEN_INT (FRV_BUILTIN_MCUT);") | |
6743 | ||
6744 | (define_expand "mcutss" | |
6745 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
6746 | (unspec:SI [(match_operand:SI 1 "acc_operand" "a") | |
6747 | (match_operand:SI 2 "fpr_or_int6_operand" "fI") | |
6748 | (match_operand:QI 3 "accg_operand" "B") | |
6749 | (match_dup 4)] | |
6750 | UNSPEC_MCUT))] | |
6751 | "TARGET_MEDIA" | |
6752 | "operands[4] = GEN_INT (FRV_BUILTIN_MCUTSS);") | |
6753 | ||
6754 | (define_insn "*mcut" | |
6755 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
6756 | (unspec:SI [(match_operand:SI 1 "acc_operand" "a") | |
6757 | (match_operand:SI 2 "fpr_or_int6_operand" "fI") | |
6758 | (match_operand:QI 3 "accg_operand" "B") | |
6759 | (match_operand:SI 4 "const_int_operand" "n")] | |
6760 | UNSPEC_MCUT))] | |
6761 | "TARGET_MEDIA" | |
6762 | "* | |
6763 | { | |
6764 | switch (INTVAL (operands[4])) | |
6765 | { | |
6766 | default: break; | |
6767 | case FRV_BUILTIN_MCUT: return \"mcut%i2 %1, %2, %0\"; | |
6768 | case FRV_BUILTIN_MCUTSS: return \"mcutss%i2 %1, %2, %0\"; | |
6769 | } | |
6770 | ||
6771 | fatal_insn (\"Bad media insn, mcut\", insn); | |
6772 | }" | |
6773 | [(set_attr "length" "4") | |
6774 | (set_attr "type" "mcut")]) | |
6775 | ||
6776 | ;; Accumulator read: type "mrdacc" | |
6777 | ||
6778 | (define_insn "mrdacc" | |
6779 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
6780 | (unspec:SI [(match_operand:SI 1 "acc_operand" "a")] UNSPEC_MRDACC))] | |
6781 | "TARGET_MEDIA" | |
6782 | "mrdacc %1, %0" | |
6783 | [(set_attr "length" "4") | |
6784 | (set_attr "type" "mrdacc")]) | |
6785 | ||
6786 | (define_insn "mrdaccg" | |
6787 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
6788 | (unspec:SI [(match_operand:QI 1 "accg_operand" "B")] UNSPEC_MRDACCG))] | |
6789 | "TARGET_MEDIA" | |
6790 | "mrdaccg %1, %0" | |
6791 | [(set_attr "length" "4") | |
6792 | (set_attr "type" "mrdacc")]) | |
6793 | ||
6794 | ;; Accumulator write: type "mwtacc" | |
6795 | ||
6796 | (define_insn "mwtacc" | |
6797 | [(set (match_operand:SI 0 "acc_operand" "=a") | |
6798 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")] UNSPEC_MWTACC))] | |
6799 | "TARGET_MEDIA" | |
6800 | "mwtacc %1, %0" | |
6801 | [(set_attr "length" "4") | |
6802 | (set_attr "type" "mwtacc")]) | |
6803 | ||
6804 | (define_insn "mwtaccg" | |
6805 | [(set (match_operand:QI 0 "accg_operand" "=B") | |
6806 | (unspec:QI [(match_operand:SI 1 "fpr_operand" "f")] UNSPEC_MWTACCG))] | |
6807 | "TARGET_MEDIA" | |
6808 | "mwtaccg %1, %0" | |
6809 | [(set_attr "length" "4") | |
6810 | (set_attr "type" "mwtacc")]) | |
6811 | ||
6812 | ;; Trap: This one executes on the control unit, not the media units. | |
6813 | ||
6814 | (define_insn "mtrap" | |
6815 | [(unspec_volatile [(const_int 0)] UNSPEC_MTRAP)] | |
6816 | "TARGET_MEDIA" | |
6817 | "mtrap" | |
6818 | [(set_attr "length" "4") | |
6819 | (set_attr "type" "trap")]) | |
6820 | ||
6821 | ;; Clear single accumulator: type "mclracc" | |
6822 | ||
6823 | (define_insn "mclracc_internal" | |
6824 | [(set (match_operand:SI 0 "acc_operand" "=a") | |
6825 | (unspec:SI [(const_int 0)] UNSPEC_MCLRACC)) | |
6826 | (set (match_operand:QI 1 "accg_operand" "=B") | |
6827 | (unspec:QI [(const_int 0)] UNSPEC_MCLRACC))] | |
6828 | "TARGET_MEDIA" | |
6829 | "mclracc %0,#0" | |
6830 | [(set_attr "length" "4") | |
6831 | (set_attr "type" "mclracc")]) | |
6832 | ||
6833 | (define_expand "mclracc" | |
6834 | [(parallel [(set (match_operand:SI 0 "acc_operand" "=a") | |
6835 | (unspec:SI [(const_int 0)] UNSPEC_MCLRACC)) | |
6836 | (set (match_dup 1) | |
6837 | (unspec:QI [(const_int 0)] UNSPEC_MCLRACC))])] | |
6838 | "TARGET_MEDIA" | |
6839 | " | |
6840 | { | |
6841 | if (GET_CODE (operands[0]) != REG || !ACC_P (REGNO (operands[0]))) | |
6842 | FAIL; | |
6843 | ||
6844 | operands[1] = frv_matching_accg_for_acc (operands[0]); | |
6845 | }") | |
6846 | ||
6847 | ;; Clear all accumulators: type "mclracca" | |
6848 | ||
6849 | (define_insn "mclracca8_internal" | |
6850 | [(set (match_operand:V4SI 0 "quad_acc_operand" "=b") | |
6851 | (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA)) | |
6852 | (set (match_operand:V4SI 1 "quad_acc_operand" "=b") | |
6853 | (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA)) | |
6854 | (set (match_operand:V4QI 2 "accg_operand" "=B") | |
6855 | (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA)) | |
6856 | (set (match_operand:V4QI 3 "accg_operand" "=B") | |
6857 | (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA))] | |
6858 | "TARGET_MEDIA && TARGET_ACC_8" | |
6859 | "mclracc acc0,#1" | |
6860 | [(set_attr "length" "4") | |
6861 | (set_attr "type" "mclracca")]) | |
6862 | ||
6863 | (define_insn "mclracca4_internal" | |
6864 | [(set (match_operand:V4SI 0 "quad_acc_operand" "=b") | |
6865 | (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA)) | |
6866 | (set (match_operand:V4QI 1 "accg_operand" "=B") | |
6867 | (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA))] | |
6868 | "TARGET_MEDIA && TARGET_ACC_4" | |
6869 | "mclracc acc0,#1" | |
6870 | [(set_attr "length" "4") | |
6871 | (set_attr "type" "mclracca")]) | |
6872 | ||
6873 | (define_expand "mclracca8" | |
6874 | [(parallel [(set (match_dup 0) (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA)) | |
6875 | (set (match_dup 1) (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA)) | |
6876 | (set (match_dup 2) (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA)) | |
6877 | (set (match_dup 3) (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA))])] | |
6878 | "TARGET_MEDIA && TARGET_ACC_8" | |
6879 | " | |
6880 | { | |
6881 | operands[0] = gen_rtx_REG (V4SImode, ACC_FIRST); | |
c557edf4 | 6882 | operands[1] = gen_rtx_REG (V4SImode, ACC_FIRST + (~3 & ACC_MASK)); |
36a05131 | 6883 | operands[2] = gen_rtx_REG (V4QImode, ACCG_FIRST); |
c557edf4 | 6884 | operands[3] = gen_rtx_REG (V4QImode, ACCG_FIRST + (~3 & ACC_MASK)); |
36a05131 BS |
6885 | }") |
6886 | ||
6887 | (define_expand "mclracca4" | |
6888 | [(parallel [(set (match_dup 0) (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA)) | |
6889 | (set (match_dup 1) (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA))])] | |
6890 | "TARGET_MEDIA && TARGET_ACC_4" | |
6891 | " | |
6892 | { | |
6893 | operands[0] = gen_rtx_REG (V4SImode, ACC_FIRST); | |
6894 | operands[1] = gen_rtx_REG (V4QImode, ACCG_FIRST); | |
6895 | }") | |
6896 | ||
6897 | (define_insn "mcop1" | |
6898 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
6899 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
6900 | (match_operand:SI 2 "fpr_operand" "f")] UNSPEC_MCOP1))] | |
6901 | "TARGET_MEDIA_REV1" | |
6902 | "mcop1 %1, %2, %0" | |
6903 | [(set_attr "length" "4") | |
6904 | ;; What is the class of the insn ??? | |
6905 | (set_attr "type" "multi")]) | |
6906 | ||
6907 | (define_insn "mcop2" | |
6908 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
6909 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") | |
6910 | (match_operand:SI 2 "fpr_operand" "f")] UNSPEC_MCOP2))] | |
6911 | "TARGET_MEDIA_REV1" | |
6912 | "mcop2 %1, %2, %0" | |
6913 | [(set_attr "length" "4") | |
6914 | ;; What is the class of the insn ??? | |
6915 | (set_attr "type" "multi")]) | |
6916 | ||
6917 | (define_insn "*mdunpackh_internal" | |
6918 | [(set (match_operand:V4SI 0 "quad_fpr_operand" "=x") | |
6919 | (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h")] | |
6920 | UNSPEC_MDUNPACKH_INTERNAL))] | |
6921 | "TARGET_MEDIA_REV1" | |
6922 | "mdunpackh %1, %0" | |
6923 | [(set_attr "length" "4") | |
6924 | (set_attr "type" "mdunpackh")]) | |
6925 | ||
6926 | (define_insn_and_split "mdunpackh" | |
6927 | [(set (match_operand:V4SI 0 "memory_operand" "=o") | |
6928 | (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h")] | |
6929 | UNSPEC_MDUNPACKH)) | |
6930 | (clobber (match_scratch:V4SI 2 "=x"))] | |
6931 | "TARGET_MEDIA_REV1" | |
6932 | "#" | |
6933 | "reload_completed" | |
6934 | [(set (match_dup 2) | |
6935 | (unspec:V4SI [(match_dup 1)] UNSPEC_MDUNPACKH_INTERNAL)) | |
6936 | (set (match_dup 3) | |
6937 | (match_dup 4)) | |
6938 | (set (match_dup 5) | |
6939 | (match_dup 6))] | |
6940 | " | |
6941 | { | |
6942 | operands[3] = change_address (operands[0], DImode, NULL_RTX); | |
6943 | operands[4] = gen_rtx_REG (DImode, REGNO (operands[2])); | |
6944 | operands[5] = frv_index_memory (operands[0], DImode, 1); | |
6945 | operands[6] = gen_rtx_REG (DImode, REGNO (operands[2])+2); | |
6946 | }" | |
6947 | [(set_attr "length" "20") | |
6948 | (set_attr "type" "multi")]) | |
6949 | ||
6950 | (define_insn "*mbtohe_internal" | |
6951 | [(set (match_operand:V4SI 0 "quad_fpr_operand" "=x") | |
6952 | (unspec:V4SI [(match_operand:SI 1 "fpr_operand" "f")] | |
6953 | UNSPEC_MBTOHE_INTERNAL))] | |
6954 | "TARGET_MEDIA_REV1" | |
6955 | "mbtohe %1, %0" | |
6956 | [(set_attr "length" "4") | |
6957 | (set_attr "type" "mbhconve")]) | |
6958 | ||
6959 | (define_insn_and_split "mbtohe" | |
6960 | [(set (match_operand:V4SI 0 "memory_operand" "=o") | |
6961 | (unspec:V4SI [(match_operand:SI 1 "fpr_operand" "f")] | |
6962 | UNSPEC_MBTOHE)) | |
6963 | (clobber (match_scratch:V4SI 2 "=x"))] | |
6964 | "TARGET_MEDIA_REV1" | |
6965 | "#" | |
6966 | "reload_completed" | |
6967 | [(set (match_dup 2) | |
6968 | (unspec:V4SI [(match_dup 1)] UNSPEC_MBTOHE_INTERNAL)) | |
6969 | (set (match_dup 3) | |
6970 | (match_dup 4)) | |
6971 | (set (match_dup 5) | |
6972 | (match_dup 6))] | |
6973 | " | |
6974 | { | |
6975 | operands[3] = change_address (operands[0], DImode, NULL_RTX); | |
6976 | operands[4] = gen_rtx_REG (DImode, REGNO (operands[2])); | |
6977 | operands[5] = frv_index_memory (operands[0], DImode, 1); | |
6978 | operands[6] = gen_rtx_REG (DImode, REGNO (operands[2])+2); | |
6979 | }" | |
6980 | [(set_attr "length" "20") | |
6981 | (set_attr "type" "multi")]) | |
6982 | ||
6983 | ;; Quad product-sum (halfword) instructions only found on the FR400. | |
6984 | ;; type "mqmach" | |
6985 | ||
6986 | (define_expand "mqxmachs" | |
6987 | [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "") | |
6988 | (unspec:V4SI [(match_dup 0) | |
6989 | (match_operand:DI 1 "even_fpr_operand" "") | |
6990 | (match_operand:DI 2 "even_fpr_operand" "") | |
6991 | (match_operand:V4QI 3 "accg_operand" "") | |
6992 | (match_dup 4)] | |
6993 | UNSPEC_MQMACH2)) | |
6994 | (set (match_dup 3) | |
6995 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH2))])] | |
6996 | "TARGET_MEDIA_REV2" | |
6997 | "operands[4] = GEN_INT (FRV_BUILTIN_MQXMACHS);") | |
6998 | ||
6999 | (define_expand "mqxmacxhs" | |
7000 | [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "") | |
7001 | (unspec:V4SI [(match_dup 0) | |
7002 | (match_operand:DI 1 "even_fpr_operand" "") | |
7003 | (match_operand:DI 2 "even_fpr_operand" "") | |
7004 | (match_operand:V4QI 3 "accg_operand" "") | |
7005 | (match_dup 4)] | |
7006 | UNSPEC_MQMACH2)) | |
7007 | (set (match_dup 3) | |
7008 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH2))])] | |
7009 | "TARGET_MEDIA_REV2" | |
7010 | "operands[4] = GEN_INT (FRV_BUILTIN_MQXMACXHS);") | |
7011 | ||
7012 | (define_expand "mqmacxhs" | |
7013 | [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "") | |
7014 | (unspec:V4SI [(match_dup 0) | |
7015 | (match_operand:DI 1 "even_fpr_operand" "") | |
7016 | (match_operand:DI 2 "even_fpr_operand" "") | |
7017 | (match_operand:V4QI 3 "accg_operand" "") | |
7018 | (match_dup 4)] | |
7019 | UNSPEC_MQMACH2)) | |
7020 | (set (match_dup 3) | |
7021 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH2))])] | |
7022 | "TARGET_MEDIA_REV2" | |
7023 | "operands[4] = GEN_INT (FRV_BUILTIN_MQMACXHS);") | |
7024 | ||
7025 | (define_insn "*mqmach2" | |
7026 | [(set (match_operand:V4SI 0 "quad_acc_operand" "+A") | |
7027 | (unspec:V4SI [(match_dup 0) | |
7028 | (match_operand:DI 1 "even_fpr_operand" "h") | |
7029 | (match_operand:DI 2 "even_fpr_operand" "h") | |
7030 | (match_operand:V4QI 3 "accg_operand" "+B") | |
7031 | (match_operand:SI 4 "const_int_operand" "n")] | |
7032 | UNSPEC_MQMACH2)) | |
7033 | (set (match_dup 3) | |
7034 | (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH2))] | |
7035 | "TARGET_MEDIA_REV2" | |
7036 | "* | |
7037 | { | |
7038 | switch (INTVAL (operands[4])) | |
7039 | { | |
7040 | default: break; | |
7041 | case FRV_BUILTIN_MQXMACHS: return \"mqxmachs %1, %2, %0\"; | |
7042 | case FRV_BUILTIN_MQXMACXHS: return \"mqxmacxhs %1, %2, %0\"; | |
7043 | case FRV_BUILTIN_MQMACXHS: return \"mqmacxhs %1, %2, %0\"; | |
7044 | } | |
7045 | ||
7046 | fatal_insn (\"Bad media insn, mqmach2\", insn); | |
7047 | }" | |
7048 | [(set_attr "length" "4") | |
7049 | (set_attr "type" "mqmach")]) | |
7050 | ||
7051 | ;; Accumulator addition/subtraction: type "maddacc" | |
7052 | ||
7053 | (define_expand "maddaccs" | |
094e84fa RS |
7054 | [(parallel [(set (match_operand:SI 0 "acc_operand" "") |
7055 | (unspec:SI [(match_operand:DI 1 "even_acc_operand" "")] | |
36a05131 | 7056 | UNSPEC_MADDACC)) |
094e84fa RS |
7057 | (set (match_operand:QI 2 "accg_operand" "") |
7058 | (unspec:QI [(match_operand:HI 3 "accg_operand" "") | |
36a05131 BS |
7059 | (match_dup 4)] |
7060 | UNSPEC_MADDACC))])] | |
7061 | "TARGET_MEDIA_REV2" | |
7062 | "operands[4] = GEN_INT (FRV_BUILTIN_MADDACCS);") | |
7063 | ||
7064 | (define_expand "msubaccs" | |
094e84fa RS |
7065 | [(parallel [(set (match_operand:SI 0 "acc_operand" "") |
7066 | (unspec:SI [(match_operand:DI 1 "even_acc_operand" "")] | |
36a05131 | 7067 | UNSPEC_MADDACC)) |
094e84fa RS |
7068 | (set (match_operand:QI 2 "accg_operand" "") |
7069 | (unspec:QI [(match_operand:HI 3 "accg_operand" "") | |
36a05131 BS |
7070 | (match_dup 4)] |
7071 | UNSPEC_MADDACC))])] | |
7072 | "TARGET_MEDIA_REV2" | |
7073 | "operands[4] = GEN_INT (FRV_BUILTIN_MSUBACCS);") | |
7074 | ||
094e84fa RS |
7075 | (define_insn "masaccs" |
7076 | [(set (match_operand:DI 0 "even_acc_operand" "=b") | |
7077 | (unspec:DI [(match_operand:DI 1 "even_acc_operand" "b")] | |
7078 | UNSPEC_MASACCS)) | |
7079 | (set (match_operand:HI 2 "accg_operand" "=B") | |
7080 | (unspec:HI [(match_operand:HI 3 "accg_operand" "B")] | |
7081 | UNSPEC_MASACCS))] | |
36a05131 | 7082 | "TARGET_MEDIA_REV2" |
094e84fa RS |
7083 | "masaccs %1, %0" |
7084 | [(set_attr "length" "4") | |
7085 | (set_attr "type" "maddacc")]) | |
36a05131 BS |
7086 | |
7087 | (define_insn "*maddacc" | |
094e84fa RS |
7088 | [(set (match_operand:SI 0 "acc_operand" "=a") |
7089 | (unspec:SI [(match_operand:DI 1 "even_acc_operand" "b")] | |
36a05131 | 7090 | UNSPEC_MADDACC)) |
094e84fa RS |
7091 | (set (match_operand:QI 2 "accg_operand" "=B") |
7092 | (unspec:QI [(match_operand:HI 3 "accg_operand" "B") | |
36a05131 BS |
7093 | (match_operand:SI 4 "const_int_operand" "n")] |
7094 | UNSPEC_MADDACC))] | |
7095 | "TARGET_MEDIA_REV2" | |
7096 | "* | |
7097 | { | |
7098 | switch (INTVAL (operands[4])) | |
7099 | { | |
7100 | default: break; | |
7101 | case FRV_BUILTIN_MADDACCS: return \"maddaccs %1, %0\"; | |
7102 | case FRV_BUILTIN_MSUBACCS: return \"msubaccs %1, %0\"; | |
36a05131 BS |
7103 | } |
7104 | ||
7105 | fatal_insn (\"Bad media insn, maddacc\", insn); | |
7106 | }" | |
7107 | [(set_attr "length" "4") | |
7108 | (set_attr "type" "maddacc")]) | |
7109 | ||
7110 | ;; Dual accumulator addition/subtraction: type "mdaddacc" | |
7111 | ||
7112 | (define_expand "mdaddaccs" | |
094e84fa RS |
7113 | [(parallel [(set (match_operand:DI 0 "even_acc_operand" "") |
7114 | (unspec:DI [(match_operand:V4SI 1 "quad_acc_operand" "")] | |
7115 | UNSPEC_MDADDACC)) | |
7116 | (set (match_operand:HI 2 "accg_operand" "") | |
7117 | (unspec:HI [(match_operand:V4QI 3 "accg_operand" "") | |
7118 | (match_dup 4)] | |
7119 | UNSPEC_MDADDACC))])] | |
36a05131 BS |
7120 | "TARGET_MEDIA_REV2" |
7121 | "operands[4] = GEN_INT (FRV_BUILTIN_MDADDACCS);") | |
7122 | ||
7123 | (define_expand "mdsubaccs" | |
094e84fa RS |
7124 | [(parallel [(set (match_operand:DI 0 "even_acc_operand" "") |
7125 | (unspec:DI [(match_operand:V4SI 1 "quad_acc_operand" "")] | |
7126 | UNSPEC_MDADDACC)) | |
7127 | (set (match_operand:HI 2 "accg_operand" "") | |
7128 | (unspec:HI [(match_operand:V4QI 3 "accg_operand" "") | |
7129 | (match_dup 4)] | |
7130 | UNSPEC_MDADDACC))])] | |
36a05131 BS |
7131 | "TARGET_MEDIA_REV2" |
7132 | "operands[4] = GEN_INT (FRV_BUILTIN_MDSUBACCS);") | |
7133 | ||
094e84fa RS |
7134 | (define_insn "mdasaccs" |
7135 | [(set (match_operand:V4SI 0 "quad_acc_operand" "=A") | |
7136 | (unspec:V4SI [(match_operand:V4SI 1 "quad_acc_operand" "A")] | |
7137 | UNSPEC_MDASACCS)) | |
7138 | (set (match_operand:V4QI 2 "accg_operand" "=B") | |
7139 | (unspec:V4QI [(match_operand:V4QI 3 "accg_operand" "B")] | |
7140 | UNSPEC_MDASACCS))] | |
36a05131 | 7141 | "TARGET_MEDIA_REV2" |
094e84fa RS |
7142 | "mdasaccs %1, %0" |
7143 | [(set_attr "length" "4") | |
7144 | (set_attr "type" "mdaddacc")]) | |
36a05131 BS |
7145 | |
7146 | (define_insn "*mdaddacc" | |
094e84fa RS |
7147 | [(set (match_operand:DI 0 "even_acc_operand" "=b") |
7148 | (unspec:DI [(match_operand:V4SI 1 "quad_acc_operand" "A")] | |
7149 | UNSPEC_MDADDACC)) | |
7150 | (set (match_operand:HI 2 "accg_operand" "=B") | |
7151 | (unspec:HI [(match_operand:V4QI 3 "accg_operand" "B") | |
7152 | (match_operand:SI 4 "const_int_operand" "n")] | |
7153 | UNSPEC_MDADDACC))] | |
36a05131 BS |
7154 | "TARGET_MEDIA_REV2" |
7155 | "* | |
7156 | { | |
7157 | switch (INTVAL (operands[4])) | |
7158 | { | |
7159 | default: break; | |
7160 | case FRV_BUILTIN_MDADDACCS: return \"mdaddaccs %1, %0\"; | |
7161 | case FRV_BUILTIN_MDSUBACCS: return \"mdsubaccs %1, %0\"; | |
36a05131 BS |
7162 | } |
7163 | ||
7164 | fatal_insn (\"Bad media insn, mdaddacc\", insn); | |
7165 | }" | |
7166 | [(set_attr "length" "4") | |
7167 | (set_attr "type" "mdaddacc")]) | |
7168 | ||
7169 | ;; Dual absolute (halfword): type "mabsh" | |
7170 | ||
7171 | (define_insn "mabshs" | |
7172 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
7173 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")] UNSPEC_MABSHS))] | |
7174 | "TARGET_MEDIA_REV2" | |
7175 | "mabshs %1, %0" | |
7176 | [(set_attr "length" "4") | |
7177 | (set_attr "type" "mabsh")]) | |
7178 | ||
7179 | ;; Dual rotate: type "mdrot" | |
7180 | ||
7181 | (define_insn "mdrotli" | |
7182 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
7183 | (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") | |
7184 | (match_operand:SI 2 "uint5_operand" "I")] | |
7185 | UNSPEC_MDROTLI))] | |
7186 | "TARGET_MEDIA_REV2" | |
7187 | "mdrotli %1, %2, %0" | |
7188 | [(set_attr "length" "4") | |
7189 | (set_attr "type" "mdrot")]) | |
7190 | ||
7191 | ;; Dual coupling (concatenation): type "mcpl" | |
7192 | ||
7193 | (define_insn "mcplhi" | |
7194 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
7195 | (unspec:SI [(match_operand:DI 1 "fpr_operand" "h") | |
7196 | (match_operand:SI 2 "uint4_operand" "I")] | |
7197 | UNSPEC_MCPLHI))] | |
7198 | "TARGET_MEDIA_REV2" | |
7199 | "mcplhi %1, %2, %0" | |
7200 | [(set_attr "length" "4") | |
7201 | (set_attr "type" "mcpl")]) | |
7202 | ||
7203 | (define_insn "mcpli" | |
7204 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
7205 | (unspec:SI [(match_operand:DI 1 "fpr_operand" "h") | |
7206 | (match_operand:SI 2 "uint5_operand" "I")] | |
7207 | UNSPEC_MCPLI))] | |
7208 | "TARGET_MEDIA_REV2" | |
7209 | "mcpli %1, %2, %0" | |
7210 | [(set_attr "length" "4") | |
7211 | (set_attr "type" "mcpl")]) | |
7212 | ||
7213 | ;; Dual cut: type "mdcut" | |
7214 | ||
7215 | (define_insn "mdcutssi" | |
7216 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
7217 | (unspec:DI [(match_operand:DI 1 "even_acc_operand" "b") | |
7218 | (match_operand:SI 2 "int6_operand" "I") | |
7219 | (match_operand:HI 3 "accg_operand" "B")] | |
7220 | UNSPEC_MDCUTSSI))] | |
7221 | "TARGET_MEDIA_REV2" | |
7222 | "mdcutssi %1, %2, %0" | |
7223 | [(set_attr "length" "4") | |
7224 | (set_attr "type" "mdcut")]) | |
7225 | ||
7226 | ;; Quad saturate (halfword): type "mqsath" | |
7227 | ||
7228 | (define_insn "mqsaths" | |
7229 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
7230 | (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") | |
7231 | (match_operand:DI 2 "even_fpr_operand" "h")] | |
7232 | UNSPEC_MQSATHS))] | |
7233 | "TARGET_MEDIA_REV2" | |
7234 | "mqsaths %1, %2, %0" | |
7235 | [(set_attr "length" "4") | |
7236 | (set_attr "type" "mqsath")]) | |
7237 | ||
c557edf4 RS |
7238 | ;; Quad limit instructions: type "mqlimh" |
7239 | ||
7240 | (define_insn "mqlclrhs" | |
7241 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
7242 | (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") | |
7243 | (match_operand:DI 2 "even_fpr_operand" "h")] | |
7244 | UNSPEC_MQLCLRHS))] | |
7245 | "TARGET_MEDIA_FR450" | |
7246 | "mqlclrhs %1, %2, %0" | |
7247 | [(set_attr "length" "4") | |
7248 | (set_attr "type" "mqlimh")]) | |
7249 | ||
7250 | (define_insn "mqlmths" | |
7251 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
7252 | (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") | |
7253 | (match_operand:DI 2 "even_fpr_operand" "h")] | |
7254 | UNSPEC_MQLMTHS))] | |
7255 | "TARGET_MEDIA_FR450" | |
7256 | "mqlmths %1, %2, %0" | |
7257 | [(set_attr "length" "4") | |
7258 | (set_attr "type" "mqlimh")]) | |
7259 | ||
7260 | (define_insn "mqsllhi" | |
7261 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
7262 | (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") | |
7263 | (match_operand:SI 2 "int6_operand" "I")] | |
7264 | UNSPEC_MQSLLHI))] | |
7265 | "TARGET_MEDIA_FR450" | |
7266 | "mqsllhi %1, %2, %0" | |
7267 | [(set_attr "length" "4") | |
7268 | (set_attr "type" "mqshift")]) | |
7269 | ||
7270 | (define_insn "mqsrahi" | |
7271 | [(set (match_operand:DI 0 "even_fpr_operand" "=h") | |
7272 | (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") | |
7273 | (match_operand:SI 2 "int6_operand" "I")] | |
7274 | UNSPEC_MQSRAHI))] | |
7275 | "TARGET_MEDIA_FR450" | |
7276 | "mqsrahi %1, %2, %0" | |
7277 | [(set_attr "length" "4") | |
7278 | (set_attr "type" "mqshift")]) | |
7279 | ||
839a4992 | 7280 | ;; Set hi/lo instructions: type "mset" |
36a05131 BS |
7281 | |
7282 | (define_insn "mhsetlos" | |
7283 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
7284 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "0") | |
7285 | (match_operand:SI 2 "int12_operand" "NOP")] | |
7286 | UNSPEC_MHSETLOS))] | |
7287 | "TARGET_MEDIA_REV2" | |
7288 | "mhsetlos %2, %0" | |
7289 | [(set_attr "length" "4") | |
7290 | (set_attr "type" "mset")]) | |
7291 | ||
7292 | (define_insn "mhsetloh" | |
7293 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
7294 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "0") | |
7295 | (match_operand:SI 2 "int5_operand" "I")] | |
7296 | UNSPEC_MHSETLOH))] | |
7297 | "TARGET_MEDIA_REV2" | |
7298 | "mhsetloh %2, %0" | |
7299 | [(set_attr "length" "4") | |
7300 | (set_attr "type" "mset")]) | |
7301 | ||
7302 | (define_insn "mhsethis" | |
7303 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
7304 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "0") | |
7305 | (match_operand:SI 2 "int12_operand" "NOP")] | |
7306 | UNSPEC_MHSETHIS))] | |
7307 | "TARGET_MEDIA_REV2" | |
7308 | "mhsethis %2, %0" | |
7309 | [(set_attr "length" "4") | |
7310 | (set_attr "type" "mset")]) | |
7311 | ||
7312 | (define_insn "mhsethih" | |
7313 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
7314 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "0") | |
7315 | (match_operand:SI 2 "int5_operand" "I")] | |
7316 | UNSPEC_MHSETHIH))] | |
7317 | "TARGET_MEDIA_REV2" | |
7318 | "mhsethih %2, %0" | |
7319 | [(set_attr "length" "4") | |
7320 | (set_attr "type" "mset")]) | |
7321 | ||
7322 | (define_insn "mhdsets" | |
7323 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
7324 | (unspec:SI [(match_operand:SI 1 "int12_operand" "NOP")] | |
7325 | UNSPEC_MHDSETS))] | |
7326 | "TARGET_MEDIA_REV2" | |
7327 | "mhdsets %1, %0" | |
7328 | [(set_attr "length" "4") | |
7329 | (set_attr "type" "mset")]) | |
7330 | ||
7331 | (define_insn "mhdseth" | |
7332 | [(set (match_operand:SI 0 "fpr_operand" "=f") | |
7333 | (unspec:SI [(match_operand:SI 1 "fpr_operand" "0") | |
7334 | (match_operand:SI 2 "int5_operand" "I")] | |
7335 | UNSPEC_MHDSETH))] | |
7336 | "TARGET_MEDIA_REV2" | |
7337 | "mhdseth %2, %0" | |
7338 | [(set_attr "length" "4") | |
7339 | (set_attr "type" "mset")]) | |
34208acf AO |
7340 | |
7341 | ;;----------------------------------------------------------------------------- | |
7342 | ||
7343 | (define_expand "symGOT2reg" | |
7344 | [(match_operand:SI 0 "" "") | |
7345 | (match_operand:SI 1 "" "") | |
7346 | (match_operand:SI 2 "" "") | |
7347 | (match_operand:SI 3 "" "")] | |
7348 | "" | |
7349 | " | |
7350 | { | |
d8485bdb TS |
7351 | rtx_insn *insn = emit_insn (gen_symGOT2reg_i (operands[0], operands[1], |
7352 | operands[2], operands[3])); | |
34208acf | 7353 | |
389fdba0 | 7354 | MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1; |
34208acf | 7355 | |
bd94cb6e | 7356 | set_unique_reg_note (insn, REG_EQUAL, operands[1]); |
34208acf AO |
7357 | |
7358 | DONE; | |
7359 | }") | |
7360 | ||
7361 | (define_expand "symGOT2reg_i" | |
7362 | [(set (match_operand:SI 0 "" "") | |
7363 | (mem:SI (plus:SI (match_operand:SI 2 "" "") | |
7364 | (const:SI (unspec:SI [(match_operand:SI 1 "" "") | |
7365 | (match_operand:SI 3 "" "")] | |
7366 | UNSPEC_GOT)))))] | |
7367 | "" | |
7368 | "") | |
7369 | ||
7370 | (define_expand "symGOT2reg_hilo" | |
7371 | [(set (match_dup 6) | |
7372 | (high:SI (const:SI (unspec:SI [(match_operand:SI 1 "" "") | |
7373 | (match_dup 4)] UNSPEC_GOT)))) | |
7374 | (set (match_dup 5) | |
7375 | (lo_sum:SI (match_dup 6) | |
7376 | (const:SI (unspec:SI [(match_dup 1) | |
7377 | (match_operand:SI 3 "" "")] | |
7378 | UNSPEC_GOT)))) | |
7379 | (set (match_operand:SI 0 "" "") | |
7380 | (mem:SI (plus:SI (match_dup 5) | |
7381 | (match_operand:SI 2 "" "")))) | |
7382 | ] | |
7383 | "" | |
7384 | " | |
7385 | { | |
b3a13419 | 7386 | if (!can_create_pseudo_p ()) |
34208acf AO |
7387 | operands[6] = operands[5] = operands[0]; |
7388 | else | |
7389 | { | |
7390 | operands[6] = gen_reg_rtx (SImode); | |
7391 | operands[5] = gen_reg_rtx (SImode); | |
7392 | } | |
7393 | ||
7394 | operands[4] = GEN_INT (INTVAL (operands[3]) + 1); | |
7395 | operands[3] = GEN_INT (INTVAL (operands[3]) + 2); | |
7396 | }") | |
7397 | ||
7398 | (define_expand "symGOTOFF2reg_hilo" | |
7399 | [(set (match_dup 6) | |
7400 | (high:SI (const:SI (unspec:SI [(match_operand:SI 1 "" "") | |
7401 | (match_dup 4)] UNSPEC_GOT)))) | |
7402 | (set (match_dup 5) | |
7403 | (lo_sum:SI (match_dup 6) | |
7404 | (const:SI (unspec:SI [(match_dup 1) | |
7405 | (match_operand:SI 3 "" "")] | |
7406 | UNSPEC_GOT)))) | |
7407 | (set (match_operand:SI 0 "" "") | |
7408 | (plus:SI (match_dup 5) | |
7409 | (match_operand:SI 2 "" ""))) | |
7410 | ] | |
7411 | "" | |
7412 | " | |
7413 | { | |
b3a13419 | 7414 | if (!can_create_pseudo_p ()) |
34208acf AO |
7415 | operands[6] = operands[5] = operands[0]; |
7416 | else | |
7417 | { | |
7418 | operands[6] = gen_reg_rtx (SImode); | |
7419 | operands[5] = gen_reg_rtx (SImode); | |
7420 | } | |
7421 | ||
7422 | operands[4] = GEN_INT (INTVAL (operands[3]) + 1); | |
7423 | operands[3] = GEN_INT (INTVAL (operands[3]) + 2); | |
7424 | }") | |
7425 | ||
7426 | (define_expand "symGOTOFF2reg" | |
7427 | [(match_operand:SI 0 "" "") | |
7428 | (match_operand:SI 1 "" "") | |
7429 | (match_operand:SI 2 "" "") | |
7430 | (match_operand:SI 3 "" "")] | |
7431 | "" | |
7432 | " | |
7433 | { | |
d8485bdb TS |
7434 | rtx_insn *insn = emit_insn (gen_symGOTOFF2reg_i (operands[0], operands[1], |
7435 | operands[2], operands[3])); | |
34208acf | 7436 | |
bd94cb6e | 7437 | set_unique_reg_note (insn, REG_EQUAL, operands[1]); |
34208acf AO |
7438 | |
7439 | DONE; | |
7440 | }") | |
7441 | ||
7442 | (define_expand "symGOTOFF2reg_i" | |
7443 | [(set (match_operand:SI 0 "" "") | |
7444 | (plus:SI (match_operand:SI 2 "" "") | |
7445 | (const:SI | |
7446 | (unspec:SI [(match_operand:SI 1 "" "") | |
7447 | (match_operand:SI 3 "" "")] | |
7448 | UNSPEC_GOT))))] | |
7449 | "" | |
7450 | "") | |
7451 | ||
7452 | (define_expand "symGPREL2reg" | |
7453 | [(match_operand:SI 0 "" "") | |
7454 | (match_operand:SI 1 "" "") | |
7455 | (match_operand:SI 2 "" "") | |
7456 | (match_operand:SI 3 "" "") | |
7457 | (match_dup 4)] | |
7458 | "" | |
7459 | " | |
7460 | { | |
b3a13419 | 7461 | if (!can_create_pseudo_p ()) |
34208acf AO |
7462 | operands[4] = operands[0]; |
7463 | else | |
7464 | operands[4] = gen_reg_rtx (SImode); | |
7465 | ||
7466 | emit_insn (frv_gen_GPsym2reg (operands[4], operands[2])); | |
7467 | ||
d8485bdb TS |
7468 | rtx_insn *insn = emit_insn (gen_symGOTOFF2reg_i (operands[0], operands[1], |
7469 | operands[4], operands[3])); | |
34208acf | 7470 | |
bd94cb6e | 7471 | set_unique_reg_note (insn, REG_EQUAL, operands[1]); |
34208acf AO |
7472 | |
7473 | DONE; | |
7474 | }") | |
7475 | ||
7476 | (define_expand "symGPREL2reg_hilo" | |
7477 | [(match_operand:SI 0 "" "") | |
7478 | (match_operand:SI 1 "" "") | |
7479 | (match_operand:SI 2 "" "") | |
7480 | (match_operand:SI 3 "" "") | |
7481 | (match_dup 4)] | |
7482 | "" | |
7483 | " | |
7484 | { | |
b3a13419 | 7485 | if (!can_create_pseudo_p ()) |
34208acf AO |
7486 | { |
7487 | emit_insn (gen_symGOT2reg (operands[0], operands[1], operands[2], | |
7488 | GEN_INT (R_FRV_GOT12))); | |
7489 | DONE; | |
7490 | } | |
7491 | ||
7492 | operands[4] = gen_reg_rtx (SImode); | |
7493 | ||
7494 | emit_insn (frv_gen_GPsym2reg (operands[4], operands[2])); | |
7495 | ||
d8485bdb TS |
7496 | rtx_insn *insn = emit_insn (gen_symGOTOFF2reg_hilo (operands[0], operands[1], |
7497 | operands[4], operands[3])); | |
34208acf | 7498 | |
bd94cb6e | 7499 | set_unique_reg_note (insn, REG_EQUAL, operands[1]); |
34208acf AO |
7500 | |
7501 | DONE; | |
7502 | }") | |
c557edf4 RS |
7503 | \f |
7504 | (define_constants | |
7505 | [ | |
7506 | (UNSPEC_SMUL 154) | |
7507 | (UNSPEC_UMUL 155) | |
7508 | (UNSPEC_SMU 156) | |
7509 | (UNSPEC_ADDSS 157) | |
7510 | (UNSPEC_SUBSS 158) | |
7511 | (UNSPEC_SLASS 159) | |
7512 | (UNSPEC_SCAN 160) | |
7513 | (UNSPEC_INTSS 161) | |
7514 | (UNSPEC_SCUTSS 162) | |
7515 | (UNSPEC_PREFETCH0 163) | |
7516 | (UNSPEC_PREFETCH 164) | |
7517 | (UNSPEC_IACCreadll 165) | |
7518 | (UNSPEC_IACCreadl 166) | |
7519 | (UNSPEC_IACCsetll 167) | |
7520 | (UNSPEC_IACCsetl 168) | |
7521 | (UNSPEC_SMASS 169) | |
7522 | (UNSPEC_SMSSS 170) | |
7523 | (UNSPEC_IMUL 171) | |
7524 | ||
7525 | (IACC0_REG 171) | |
7526 | ]) | |
7527 | ||
7528 | (define_insn "smul" | |
7529 | [(set (match_operand:DI 0 "integer_register_operand" "=d") | |
7530 | (unspec:DI [(match_operand:SI 1 "integer_register_operand" "d") | |
7531 | (match_operand:SI 2 "integer_register_operand" "d")] | |
7532 | UNSPEC_SMUL))] | |
7533 | "" | |
7534 | "smul %1, %2, %0" | |
7535 | [(set_attr "length" "4") | |
7536 | (set_attr "type" "mul")]) | |
7537 | ||
7538 | (define_insn "umul" | |
7539 | [(set (match_operand:DI 0 "integer_register_operand" "=d") | |
7540 | (unspec:DI [(match_operand:SI 1 "integer_register_operand" "d") | |
7541 | (match_operand:SI 2 "integer_register_operand" "d")] | |
7542 | UNSPEC_UMUL))] | |
7543 | "" | |
7544 | "umul %1, %2, %0" | |
7545 | [(set_attr "length" "4") | |
7546 | (set_attr "type" "mul")]) | |
7547 | ||
7548 | (define_insn "smass" | |
7549 | [(set (reg:DI IACC0_REG) | |
7550 | (unspec:DI [(match_operand:SI 0 "integer_register_operand" "d") | |
7551 | (match_operand:SI 1 "integer_register_operand" "d") | |
7552 | (reg:DI IACC0_REG)] | |
7553 | UNSPEC_SMASS))] | |
7554 | "TARGET_FR405_BUILTINS" | |
7555 | "smass %1, %0" | |
7556 | [(set_attr "length" "4") | |
7557 | (set_attr "type" "macc")]) | |
7558 | ||
7559 | (define_insn "smsss" | |
7560 | [(set (reg:DI IACC0_REG) | |
7561 | (unspec:DI [(match_operand:SI 0 "integer_register_operand" "d") | |
7562 | (match_operand:SI 1 "integer_register_operand" "d") | |
7563 | (reg:DI IACC0_REG)] | |
7564 | UNSPEC_SMSSS))] | |
7565 | "TARGET_FR405_BUILTINS" | |
7566 | "smsss %1, %0" | |
7567 | [(set_attr "length" "4") | |
7568 | (set_attr "type" "macc")]) | |
7569 | ||
7570 | (define_insn "smu" | |
7571 | [(set (reg:DI IACC0_REG) | |
7572 | (unspec:DI [(match_operand:SI 0 "integer_register_operand" "d") | |
7573 | (match_operand:SI 1 "integer_register_operand" "d")] | |
7574 | UNSPEC_SMU))] | |
7575 | "TARGET_FR405_BUILTINS" | |
7576 | "smu %1, %0" | |
7577 | [(set_attr "length" "4") | |
7578 | (set_attr "type" "macc")]) | |
7579 | ||
7580 | (define_insn "addss" | |
7581 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
7582 | (unspec:SI [(match_operand:SI 1 "integer_register_operand" "d") | |
7583 | (match_operand:SI 2 "integer_register_operand" "d")] | |
7584 | UNSPEC_ADDSS))] | |
7585 | "TARGET_FR405_BUILTINS" | |
7586 | "addss %1, %2, %0" | |
7587 | [(set_attr "length" "4") | |
7588 | (set_attr "type" "int")]) | |
7589 | ||
7590 | (define_insn "subss" | |
7591 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
7592 | (unspec:SI [(match_operand:SI 1 "integer_register_operand" "d") | |
7593 | (match_operand:SI 2 "integer_register_operand" "d")] | |
7594 | UNSPEC_SUBSS))] | |
7595 | "TARGET_FR405_BUILTINS" | |
7596 | "subss %1, %2, %0" | |
7597 | [(set_attr "length" "4") | |
7598 | (set_attr "type" "int")]) | |
7599 | ||
7600 | (define_insn "slass" | |
7601 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
7602 | (unspec:SI [(match_operand:SI 1 "integer_register_operand" "d") | |
7603 | (match_operand:SI 2 "integer_register_operand" "d")] | |
7604 | UNSPEC_SLASS))] | |
7605 | "TARGET_FR405_BUILTINS" | |
7606 | "slass %1, %2, %0" | |
7607 | [(set_attr "length" "4") | |
7608 | (set_attr "type" "int")]) | |
7609 | ||
7610 | (define_insn "scan" | |
7611 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
7612 | (unspec:SI [(match_operand:SI 1 "integer_register_operand" "d") | |
7613 | (match_operand:SI 2 "integer_register_operand" "d")] | |
7614 | UNSPEC_SCAN))] | |
7615 | "" | |
7616 | "scan %1, %2, %0" | |
7617 | [(set_attr "length" "4") | |
7618 | (set_attr "type" "scan")]) | |
7619 | ||
7620 | (define_insn "scutss" | |
7621 | [(set (match_operand:SI 0 "integer_register_operand" "=d") | |
7622 | (unspec:SI [(match_operand:SI 1 "integer_register_operand" "d") | |
7623 | (reg:DI IACC0_REG)] | |
7624 | UNSPEC_SCUTSS))] | |
7625 | "TARGET_FR405_BUILTINS" | |
7626 | "scutss %1,%0" | |
7627 | [(set_attr "length" "4") | |
7628 | (set_attr "type" "cut")]) | |
7629 | ||
7630 | (define_insn "frv_prefetch0" | |
7631 | [(prefetch (unspec:SI [(match_operand:SI 0 "register_operand" "r")] | |
7632 | UNSPEC_PREFETCH0) | |
7633 | (const_int 0) | |
7634 | (const_int 0))] | |
7635 | "" | |
7636 | "dcpl %0, gr0, #0" | |
7637 | [(set_attr "length" "4")]) | |
7638 | ||
7639 | (define_insn "frv_prefetch" | |
7640 | [(prefetch (unspec:SI [(match_operand:SI 0 "register_operand" "r")] | |
7641 | UNSPEC_PREFETCH) | |
7642 | (const_int 0) | |
7643 | (const_int 0))] | |
7644 | "TARGET_FR500_FR550_BUILTINS" | |
7645 | "nop.p\\n\\tnldub @(%0, gr0), gr0" | |
7646 | [(set_attr "length" "8")]) | |
bef8809e AH |
7647 | |
7648 | ;; TLS patterns | |
7649 | ||
7650 | (define_insn "call_gettlsoff" | |
7651 | [(set (match_operand:SI 0 "register_operand" "=D09") | |
7652 | (unspec:SI | |
7653 | [(match_operand:SI 1 "symbolic_operand" "")] | |
7654 | UNSPEC_GETTLSOFF)) | |
7655 | (clobber (reg:SI GR8_REG)) | |
7656 | (clobber (reg:SI LRREG)) | |
7657 | (use (match_operand:SI 2 "register_operand" "D15"))] | |
7658 | "HAVE_AS_TLS" | |
7659 | "call #gettlsoff(%a1)" | |
7660 | [(set_attr "length" "4") | |
7661 | (set_attr "type" "load_or_call")]) | |
7662 | ||
a701780f AO |
7663 | ;; We have to expand this like a libcall (it sort of actually is) |
7664 | ;; because otherwise sched may move, for example, an insn that sets up | |
7665 | ;; GR8 for a subsequence call before the *tls_indirect_call insn, and | |
7666 | ;; then reload won't be able to fix things up. | |
7667 | (define_expand "tls_indirect_call" | |
7668 | [(set (reg:DI GR8_REG) | |
7669 | (match_operand:DI 2 "register_operand" "")) | |
7670 | (parallel | |
7671 | [(set (reg:SI GR9_REG) | |
7672 | (unspec:SI | |
7673 | [(match_operand:SI 1 "symbolic_operand" "") | |
7674 | (reg:DI GR8_REG)] | |
7675 | UNSPEC_TLS_INDIRECT_CALL)) | |
7676 | (clobber (reg:SI GR8_REG)) | |
7677 | (clobber (reg:SI LRREG)) | |
7678 | (use (match_operand:SI 3 "register_operand" ""))]) | |
7679 | (set (match_operand:SI 0 "register_operand" "") | |
7680 | (reg:SI GR9_REG))] | |
7681 | "HAVE_AS_TLS") | |
7682 | ||
7683 | (define_insn "*tls_indirect_call" | |
7684 | [(set (reg:SI GR9_REG) | |
bef8809e | 7685 | (unspec:SI |
a701780f AO |
7686 | [(match_operand:SI 0 "symbolic_operand" "") |
7687 | (reg:DI GR8_REG)] | |
bef8809e | 7688 | UNSPEC_TLS_INDIRECT_CALL)) |
a701780f | 7689 | (clobber (reg:SI GR8_REG)) |
bef8809e AH |
7690 | (clobber (reg:SI LRREG)) |
7691 | ;; If there was a way to represent the fact that we don't need GR9 | |
7692 | ;; or GR15 to be set before this instruction (it could be in | |
7693 | ;; parallel), we could use it here. This change wouldn't apply to | |
7694 | ;; call_gettlsoff, thought, since the linker may turn the latter | |
7695 | ;; into ldi @(gr15,offset),gr9. | |
a701780f | 7696 | (use (match_operand:SI 1 "register_operand" "D15"))] |
bef8809e | 7697 | "HAVE_AS_TLS" |
a701780f | 7698 | "calll #gettlsoff(%a0)@(gr8,gr0)" |
bef8809e AH |
7699 | [(set_attr "length" "4") |
7700 | (set_attr "type" "jumpl")]) | |
7701 | ||
7702 | (define_insn "tls_load_gottlsoff12" | |
7703 | [(set (match_operand:SI 0 "register_operand" "=r") | |
7704 | (unspec:SI | |
7705 | [(match_operand:SI 1 "symbolic_operand" "") | |
7706 | (match_operand:SI 2 "register_operand" "r")] | |
7707 | UNSPEC_TLS_LOAD_GOTTLSOFF12))] | |
7708 | "HAVE_AS_TLS" | |
7709 | "ldi @(%2, #gottlsoff12(%1)), %0" | |
7710 | [(set_attr "length" "4")]) | |
7711 | ||
7712 | (define_expand "tlsoff_hilo" | |
7713 | [(set (match_operand:SI 0 "register_operand" "=r") | |
7714 | (high:SI (const:SI (unspec:SI | |
7715 | [(match_operand:SI 1 "symbolic_operand" "") | |
7716 | (match_operand:SI 2 "immediate_operand" "n")] | |
7717 | UNSPEC_GOT)))) | |
7718 | (set (match_dup 0) | |
7719 | (lo_sum:SI (match_dup 0) | |
7720 | (const:SI (unspec:SI [(match_dup 1) | |
7721 | (match_dup 3)] UNSPEC_GOT))))] | |
7722 | "" | |
7723 | " | |
7724 | { | |
7725 | operands[3] = GEN_INT (INTVAL (operands[2]) + 1); | |
7726 | }") | |
7727 | ||
7728 | ;; Just like movdi_ldd, but with relaxation annotations. | |
7729 | (define_insn "tls_tlsdesc_ldd" | |
7730 | [(set (match_operand:DI 0 "register_operand" "=r") | |
7731 | (unspec:DI [(mem:DI (unspec:SI | |
7732 | [(match_operand:SI 1 "register_operand" "r") | |
7733 | (match_operand:SI 2 "register_operand" "r") | |
7734 | (match_operand:SI 3 "symbolic_operand" "")] | |
7735 | UNSPEC_TLS_TLSDESC_LDD_AUX))] | |
7736 | UNSPEC_TLS_TLSDESC_LDD))] | |
7737 | "" | |
7738 | "ldd #tlsdesc(%a3)@(%1,%2), %0" | |
7739 | [(set_attr "length" "4") | |
7740 | (set_attr "type" "gload")]) | |
7741 | ||
7742 | (define_insn "tls_tlsoff_ld" | |
7743 | [(set (match_operand:SI 0 "register_operand" "=r") | |
7744 | (mem:SI (unspec:SI | |
7745 | [(match_operand:SI 1 "register_operand" "r") | |
7746 | (match_operand:SI 2 "register_operand" "r") | |
7747 | (match_operand:SI 3 "symbolic_operand" "")] | |
7748 | UNSPEC_TLS_TLSOFF_LD)))] | |
7749 | "" | |
7750 | "ld #tlsoff(%a3)@(%1,%2), %0" | |
7751 | [(set_attr "length" "4") | |
7752 | (set_attr "type" "gload")]) | |
7753 | ||
7754 | (define_insn "tls_lddi" | |
7755 | [(set (match_operand:DI 0 "register_operand" "=r") | |
7756 | (unspec:DI [(match_operand:SI 1 "symbolic_operand" "") | |
7757 | (match_operand:SI 2 "register_operand" "d")] | |
7758 | UNSPEC_TLS_LDDI))] | |
7759 | "" | |
7760 | "lddi @(%2, #gottlsdesc12(%a1)), %0" | |
7761 | [(set_attr "length" "4") | |
7762 | (set_attr "type" "gload")]) |