]>
Commit | Line | Data |
---|---|---|
1c2bdc60 | 1 | ;; Machine description for DEC Alpha for GNU C compiler |
34627ce6 | 2 | ;; Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc. |
1c2bdc60 | 3 | ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) |
36f8f642 RK |
4 | |
5 | ;; This file is part of GNU CC. | |
6 | ||
7 | ;; GNU CC is free software; you can redistribute it and/or modify | |
8 | ;; it under the terms of the GNU General Public License as published by | |
9 | ;; the Free Software Foundation; either version 2, or (at your option) | |
10 | ;; any later version. | |
11 | ||
12 | ;; GNU CC is distributed in the hope that it will be useful, | |
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 | |
18 | ;; along with GNU CC; see the file COPYING. If not, write to | |
c15c9075 RK |
19 | ;; the Free Software Foundation, 59 Temple Place - Suite 330, |
20 | ;; Boston, MA 02111-1307, USA. | |
36f8f642 RK |
21 | |
22 | ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. | |
4ed43ff8 RH |
23 | |
24 | ;; Uses of UNSPEC in this file: | |
25 | ;; | |
26 | ;; 0 arg_home | |
27 | ;; 1 cttz | |
28 | ;; 2 insxh | |
29 | ;; 3 mskxh | |
30 | ;; 4 cvtlq | |
e83015a9 | 31 | ;; 5 cvtql |
37679e06 | 32 | ;; 6 nt_lda |
4ed43ff8 RH |
33 | ;; |
34 | ;; UNSPEC_VOLATILE: | |
35 | ;; | |
36 | ;; 0 imb | |
37 | ;; 1 blockage | |
38 | ;; 2 builtin_setjmp_receiver | |
39 | ;; 3 builtin_longjmp | |
40 | ;; 4 trapb | |
9c0e94a5 | 41 | ;; 5 prologue_stack_probe_loop |
68aed21b | 42 | ;; 6 realign |
6abc6f40 | 43 | ;; 7 exception_receiver |
36f8f642 | 44 | \f |
745466f2 RK |
45 | ;; Processor type -- this attribute must exactly match the processor_type |
46 | ;; enumeration in alpha.h. | |
47 | ||
71d9b493 | 48 | (define_attr "cpu" "ev4,ev5,ev6" |
745466f2 RK |
49 | (const (symbol_ref "alpha_cpu"))) |
50 | ||
36f8f642 RK |
51 | ;; Define an insn type attribute. This is used in function unit delay |
52 | ;; computations, among other purposes. For the most part, we use the names | |
53 | ;; defined in the EV4 documentation, but add a few that we have to know about | |
54 | ;; separately. | |
55 | ||
56 | (define_attr "type" | |
68aed21b | 57 | "ild,fld,ldsym,ist,fst,ibr,fbr,jsr,iadd,ilog,shift,icmov,fcmov,icmp,imul,fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" |
745466f2 | 58 | (const_string "iadd")) |
36f8f642 | 59 | |
68aed21b RH |
60 | ;; Describe a user's asm statement. |
61 | (define_asm_attributes | |
62 | [(set_attr "type" "multi")]) | |
63 | ||
9c0e94a5 RH |
64 | ;; Define the operand size an insn operates on. Used primarily by mul |
65 | ;; and div operations that have size dependant timings. | |
66 | ||
71d9b493 RH |
67 | (define_attr "opsize" "si,di,udi" (const_string "di")) |
68 | ||
0d4ae18a | 69 | ;; The TRAP_TYPE attribute marks instructions that may generate traps |
956d6950 | 70 | ;; (which are imprecise and may need a trapb if software completion |
0d4ae18a | 71 | ;; is desired). |
9c0e94a5 | 72 | |
f4e31cf5 | 73 | (define_attr "trap" "no,yes" (const_string "no")) |
0d4ae18a | 74 | |
9c0e94a5 RH |
75 | ;; The length of an instruction sequence in bytes. |
76 | ||
77 | (define_attr "length" "" (const_int 4)) | |
71d9b493 RH |
78 | \f |
79 | ;; On EV4 there are two classes of resources to consider: resources needed | |
80 | ;; to issue, and resources needed to execute. IBUS[01] are in the first | |
81 | ;; category. ABOX, BBOX, EBOX, FBOX, IMUL & FDIV make up the second. | |
38e01259 | 82 | ;; (There are a few other register-like resources, but ...) |
71d9b493 RH |
83 | |
84 | ; First, describe all of the issue constraints with single cycle delays. | |
85 | ; All insns need a bus, but all except loads require one or the other. | |
86 | (define_function_unit "ev4_ibus0" 1 0 | |
87 | (and (eq_attr "cpu" "ev4") | |
88 | (eq_attr "type" "fst,fbr,iadd,imul,ilog,shift,icmov,icmp")) | |
89 | 1 1) | |
90 | ||
91 | (define_function_unit "ev4_ibus1" 1 0 | |
92 | (and (eq_attr "cpu" "ev4") | |
93 | (eq_attr "type" "ist,ibr,jsr,fadd,fcmov,fcpys,fmul,fdiv,misc")) | |
94 | 1 1) | |
36f8f642 | 95 | |
71d9b493 RH |
96 | ; Memory delivers its result in three cycles. Actually return one and |
97 | ; take care of this in adjust_cost, since we want to handle user-defined | |
98 | ; memory latencies. | |
745466f2 RK |
99 | (define_function_unit "ev4_abox" 1 0 |
100 | (and (eq_attr "cpu" "ev4") | |
71d9b493 | 101 | (eq_attr "type" "ild,fld,ldsym,ist,fst")) |
bcbbac26 | 102 | 1 1) |
36f8f642 | 103 | |
71d9b493 | 104 | ; Branches have no delay cost, but do tie up the unit for two cycles. |
745466f2 RK |
105 | (define_function_unit "ev4_bbox" 1 1 |
106 | (and (eq_attr "cpu" "ev4") | |
107 | (eq_attr "type" "ibr,fbr,jsr")) | |
74835ed8 | 108 | 2 2) |
36f8f642 | 109 | |
71d9b493 RH |
110 | ; Arithmetic insns are normally have their results available after |
111 | ; two cycles. There are a number of exceptions. They are encoded in | |
112 | ; ADJUST_COST. Some of the other insns have similar exceptions. | |
745466f2 RK |
113 | (define_function_unit "ev4_ebox" 1 0 |
114 | (and (eq_attr "cpu" "ev4") | |
71d9b493 | 115 | (eq_attr "type" "iadd,ilog,shift,icmov,icmp,misc")) |
74835ed8 | 116 | 2 1) |
36f8f642 | 117 | |
71d9b493 | 118 | (define_function_unit "imul" 1 0 |
745466f2 | 119 | (and (eq_attr "cpu" "ev4") |
71d9b493 RH |
120 | (and (eq_attr "type" "imul") |
121 | (eq_attr "opsize" "si"))) | |
74835ed8 | 122 | 21 19) |
745466f2 | 123 | |
71d9b493 | 124 | (define_function_unit "imul" 1 0 |
745466f2 | 125 | (and (eq_attr "cpu" "ev4") |
71d9b493 RH |
126 | (and (eq_attr "type" "imul") |
127 | (eq_attr "opsize" "!si"))) | |
74835ed8 | 128 | 23 21) |
745466f2 RK |
129 | |
130 | (define_function_unit "ev4_fbox" 1 0 | |
131 | (and (eq_attr "cpu" "ev4") | |
71d9b493 | 132 | (eq_attr "type" "fadd,fmul,fcpys,fcmov")) |
74835ed8 | 133 | 6 1) |
745466f2 | 134 | |
71d9b493 | 135 | (define_function_unit "fdiv" 1 0 |
745466f2 | 136 | (and (eq_attr "cpu" "ev4") |
71d9b493 RH |
137 | (and (eq_attr "type" "fdiv") |
138 | (eq_attr "opsize" "si"))) | |
74835ed8 | 139 | 34 30) |
745466f2 | 140 | |
71d9b493 | 141 | (define_function_unit "fdiv" 1 0 |
745466f2 | 142 | (and (eq_attr "cpu" "ev4") |
71d9b493 RH |
143 | (and (eq_attr "type" "fdiv") |
144 | (eq_attr "opsize" "di"))) | |
145 | 63 59) | |
745466f2 RK |
146 | \f |
147 | ;; EV5 scheduling. EV5 can issue 4 insns per clock. | |
71d9b493 RH |
148 | ;; |
149 | ;; EV5 has two asymetric integer units. Model this with E0 & E1 along | |
150 | ;; with the combined resource EBOX. | |
74835ed8 | 151 | |
745466f2 | 152 | (define_function_unit "ev5_ebox" 2 0 |
26250081 | 153 | (and (eq_attr "cpu" "ev5") |
71d9b493 | 154 | (eq_attr "type" "!fbr,fcmov,fadd,fmul,fcpys,fdiv")) |
74835ed8 | 155 | 1 1) |
745466f2 | 156 | |
71d9b493 RH |
157 | ; Memory takes at least 2 clocks. Return one from here and fix up with |
158 | ; user-defined latencies in adjust_cost. | |
745466f2 | 159 | (define_function_unit "ev5_ebox" 2 0 |
26250081 | 160 | (and (eq_attr "cpu" "ev5") |
71d9b493 | 161 | (eq_attr "type" "ild,fld,ldsym")) |
bcbbac26 | 162 | 1 1) |
745466f2 | 163 | |
827e80cc RH |
164 | ; Loads can dual issue with one another, but loads and stores do not mix. |
165 | (define_function_unit "ev5_e0" 1 0 | |
166 | (and (eq_attr "cpu" "ev5") | |
167 | (eq_attr "type" "ild,fld,ldsym")) | |
168 | 1 1 | |
169 | [(eq_attr "type" "ist,fst")]) | |
170 | ||
71d9b493 | 171 | ; Stores, shifts, multiplies can only issue to E0 |
74835ed8 | 172 | (define_function_unit "ev5_e0" 1 0 |
26250081 | 173 | (and (eq_attr "cpu" "ev5") |
71d9b493 | 174 | (eq_attr "type" "ist,fst,shift,imul")) |
74835ed8 | 175 | 1 1) |
745466f2 | 176 | |
71d9b493 | 177 | ; Motion video insns also issue only to E0, and take two ticks. |
26250081 RH |
178 | (define_function_unit "ev5_e0" 1 0 |
179 | (and (eq_attr "cpu" "ev5") | |
180 | (eq_attr "type" "mvi")) | |
181 | 2 1) | |
182 | ||
71d9b493 RH |
183 | ; Conditional moves always take 2 ticks. |
184 | (define_function_unit "ev5_ebox" 2 0 | |
26250081 | 185 | (and (eq_attr "cpu" "ev5") |
71d9b493 RH |
186 | (eq_attr "type" "icmov")) |
187 | 2 1) | |
745466f2 | 188 | |
71d9b493 | 189 | ; Branches can only issue to E1 |
74835ed8 | 190 | (define_function_unit "ev5_e1" 1 0 |
26250081 | 191 | (and (eq_attr "cpu" "ev5") |
74835ed8 RH |
192 | (eq_attr "type" "ibr,jsr")) |
193 | 1 1) | |
745466f2 | 194 | |
71d9b493 RH |
195 | ; Multiplies also use the integer multiplier. |
196 | ; ??? How to: "No instruction can be issued to pipe E0 exactly two | |
197 | ; cycles before an integer multiplication completes." | |
198 | (define_function_unit "imul" 1 0 | |
26250081 | 199 | (and (eq_attr "cpu" "ev5") |
71d9b493 RH |
200 | (and (eq_attr "type" "imul") |
201 | (eq_attr "opsize" "si"))) | |
74835ed8 | 202 | 8 4) |
745466f2 | 203 | |
71d9b493 | 204 | (define_function_unit "imul" 1 0 |
26250081 | 205 | (and (eq_attr "cpu" "ev5") |
71d9b493 RH |
206 | (and (eq_attr "type" "imul") |
207 | (eq_attr "opsize" "di"))) | |
74835ed8 | 208 | 12 8) |
745466f2 | 209 | |
71d9b493 | 210 | (define_function_unit "imul" 1 0 |
26250081 | 211 | (and (eq_attr "cpu" "ev5") |
71d9b493 RH |
212 | (and (eq_attr "type" "imul") |
213 | (eq_attr "opsize" "udi"))) | |
74835ed8 RH |
214 | 14 8) |
215 | ||
216 | ;; Similarly for the FPU we have two asymetric units. But fcpys can issue | |
217 | ;; on either so we have to play the game again. | |
745466f2 | 218 | |
71d9b493 | 219 | (define_function_unit "ev5_fbox" 2 0 |
26250081 | 220 | (and (eq_attr "cpu" "ev5") |
71d9b493 | 221 | (eq_attr "type" "fadd,fcmov,fmul,fcpys,fbr,fdiv")) |
74835ed8 | 222 | 4 1) |
745466f2 | 223 | |
74835ed8 | 224 | (define_function_unit "ev5_fm" 1 0 |
26250081 | 225 | (and (eq_attr "cpu" "ev5") |
745466f2 | 226 | (eq_attr "type" "fmul")) |
74835ed8 | 227 | 4 1) |
745466f2 | 228 | |
71d9b493 RH |
229 | ; Add and cmov as you would expect; fbr never produces a result; |
230 | ; fdiv issues through fa to the divider, | |
74835ed8 | 231 | (define_function_unit "ev5_fa" 1 0 |
26250081 | 232 | (and (eq_attr "cpu" "ev5") |
71d9b493 | 233 | (eq_attr "type" "fadd,fcmov,fbr,fdiv")) |
74835ed8 | 234 | 4 1) |
745466f2 | 235 | |
71d9b493 RH |
236 | ; ??? How to: "No instruction can be issued to pipe FA exactly five |
237 | ; cycles before a floating point divide completes." | |
238 | (define_function_unit "fdiv" 1 0 | |
26250081 | 239 | (and (eq_attr "cpu" "ev5") |
71d9b493 RH |
240 | (and (eq_attr "type" "fdiv") |
241 | (eq_attr "opsize" "si"))) | |
242 | 15 15) ; 15 to 31 data dependant | |
745466f2 | 243 | |
71d9b493 | 244 | (define_function_unit "fdiv" 1 0 |
26250081 | 245 | (and (eq_attr "cpu" "ev5") |
71d9b493 RH |
246 | (and (eq_attr "type" "fdiv") |
247 | (eq_attr "opsize" "di"))) | |
248 | 22 22) ; 22 to 60 data dependant | |
249 | \f | |
250 | ;; EV6 scheduling. EV6 can issue 4 insns per clock. | |
251 | ;; | |
252 | ;; EV6 has two symmetric pairs ("clusters") of two asymetric integer units | |
253 | ;; ("upper" and "lower"), yielding pipe names U0, U1, L0, L1. | |
254 | ||
255 | ;; Conditional moves decompose into two independant primitives, each | |
256 | ;; taking one cycle. Since ev6 is out-of-order, we can't see anything | |
257 | ;; but two cycles. | |
258 | (define_function_unit "ev6_ebox" 4 0 | |
259 | (and (eq_attr "cpu" "ev6") | |
260 | (eq_attr "type" "icmov")) | |
261 | 2 1) | |
262 | ||
263 | (define_function_unit "ev6_ebox" 4 0 | |
264 | (and (eq_attr "cpu" "ev6") | |
265 | (eq_attr "type" "!fbr,fcmov,fadd,fmul,fcpys,fdiv,fsqrt")) | |
266 | 1 1) | |
267 | ||
268 | ;; Integer loads take at least 3 clocks, and only issue to lower units. | |
269 | ;; Return one from here and fix up with user-defined latencies in adjust_cost. | |
270 | (define_function_unit "ev6_l" 2 0 | |
271 | (and (eq_attr "cpu" "ev6") | |
272 | (eq_attr "type" "ild,ldsym,ist,fst")) | |
273 | 1 1) | |
274 | ||
275 | ;; FP loads take at least 4 clocks. Return two from here... | |
276 | (define_function_unit "ev6_l" 2 0 | |
277 | (and (eq_attr "cpu" "ev6") | |
278 | (eq_attr "type" "fld")) | |
279 | 2 1) | |
280 | ||
281 | ;; Motion video insns also issue only to U0, and take three ticks. | |
282 | (define_function_unit "ev6_u0" 1 0 | |
283 | (and (eq_attr "cpu" "ev6") | |
284 | (eq_attr "type" "mvi")) | |
285 | 3 1) | |
286 | ||
287 | (define_function_unit "ev6_u" 2 0 | |
288 | (and (eq_attr "cpu" "ev6") | |
289 | (eq_attr "type" "mvi")) | |
290 | 3 1) | |
291 | ||
292 | ;; Shifts issue to either upper pipe. | |
293 | (define_function_unit "ev6_u" 2 0 | |
294 | (and (eq_attr "cpu" "ev6") | |
295 | (eq_attr "type" "shift")) | |
296 | 1 1) | |
297 | ||
298 | ;; Multiplies issue only to U1, and all take 7 ticks. | |
299 | ;; Rather than create a new function unit just for U1, reuse IMUL | |
300 | (define_function_unit "imul" 1 0 | |
301 | (and (eq_attr "cpu" "ev6") | |
302 | (eq_attr "type" "imul")) | |
303 | 7 1) | |
304 | ||
305 | (define_function_unit "ev6_u" 2 0 | |
306 | (and (eq_attr "cpu" "ev6") | |
307 | (eq_attr "type" "imul")) | |
308 | 7 1) | |
309 | ||
310 | ;; Branches issue to either upper pipe | |
311 | (define_function_unit "ev6_u" 2 0 | |
312 | (and (eq_attr "cpu" "ev6") | |
313 | (eq_attr "type" "ibr")) | |
314 | 3 1) | |
315 | ||
316 | ;; Calls only issue to L0. | |
317 | (define_function_unit "ev6_l0" 1 0 | |
318 | (and (eq_attr "cpu" "ev6") | |
319 | (eq_attr "type" "jsr")) | |
320 | 1 1) | |
321 | ||
322 | (define_function_unit "ev6_l" 2 0 | |
323 | (and (eq_attr "cpu" "ev6") | |
324 | (eq_attr "type" "jsr")) | |
325 | 1 1) | |
326 | ||
327 | ;; Ftoi/itof only issue to lower pipes | |
328 | (define_function_unit "ev6_l" 2 0 | |
329 | (and (eq_attr "cpu" "ev6") | |
330 | (eq_attr "type" "ftoi")) | |
331 | 3 1) | |
332 | ||
333 | (define_function_unit "ev6_l" 2 0 | |
334 | (and (eq_attr "cpu" "ev6") | |
335 | (eq_attr "type" "itof")) | |
336 | 4 1) | |
337 | ||
338 | ;; For the FPU we are very similar to EV5, except there's no insn that | |
339 | ;; can issue to fm & fa, so we get to leave that out. | |
340 | ||
341 | (define_function_unit "ev6_fm" 1 0 | |
342 | (and (eq_attr "cpu" "ev6") | |
343 | (eq_attr "type" "fmul")) | |
344 | 4 1) | |
345 | ||
346 | (define_function_unit "ev6_fa" 1 0 | |
347 | (and (eq_attr "cpu" "ev6") | |
348 | (eq_attr "type" "fadd,fcpys,fbr,fdiv,fsqrt")) | |
349 | 4 1) | |
350 | ||
351 | (define_function_unit "ev6_fa" 1 0 | |
352 | (and (eq_attr "cpu" "ev6") | |
353 | (eq_attr "type" "fcmov")) | |
354 | 8 1) | |
355 | ||
356 | (define_function_unit "fdiv" 1 0 | |
357 | (and (eq_attr "cpu" "ev6") | |
358 | (and (eq_attr "type" "fdiv") | |
359 | (eq_attr "opsize" "si"))) | |
360 | 12 10) | |
361 | ||
362 | (define_function_unit "fdiv" 1 0 | |
363 | (and (eq_attr "cpu" "ev6") | |
364 | (and (eq_attr "type" "fdiv") | |
365 | (eq_attr "opsize" "di"))) | |
366 | 15 13) | |
367 | ||
368 | (define_function_unit "fsqrt" 1 0 | |
369 | (and (eq_attr "cpu" "ev6") | |
370 | (and (eq_attr "type" "fsqrt") | |
371 | (eq_attr "opsize" "si"))) | |
372 | 16 14) | |
373 | ||
374 | (define_function_unit "fsqrt" 1 0 | |
375 | (and (eq_attr "cpu" "ev6") | |
376 | (and (eq_attr "type" "fsqrt") | |
377 | (eq_attr "opsize" "di"))) | |
378 | 32 30) | |
379 | ||
380 | ; ??? The FPU communicates with memory and the integer register file | |
381 | ; via two fp store units. We need a slot in the fst immediately, and | |
382 | ; a slot in LOW after the operand data is ready. At which point the | |
4ed43ff8 | 383 | ; data may be moved either to the store queue or the integer register |
71d9b493 | 384 | ; file and the insn retired. |
745466f2 | 385 | |
36f8f642 RK |
386 | \f |
387 | ;; First define the arithmetic insns. Note that the 32-bit forms also | |
388 | ;; sign-extend. | |
389 | ||
4ed43ff8 RH |
390 | ;; Handle 32-64 bit extension from memory to a floating point register |
391 | ;; specially, since this ocurrs frequently in int->double conversions. | |
392 | ;; This is done with a define_split after reload converting the plain | |
393 | ;; sign-extension into a load+unspec, which of course results in lds+cvtlq. | |
394 | ;; | |
395 | ;; Note that while we must retain the =f case in the insn for reload's | |
396 | ;; benefit, it should be eliminated after reload, so we should never emit | |
397 | ;; code for that case. But we don't reject the possibility. | |
398 | ||
36f8f642 | 399 | (define_insn "extendsidi2" |
4ed43ff8 RH |
400 | [(set (match_operand:DI 0 "register_operand" "=r,r,?f") |
401 | (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,m")))] | |
36f8f642 RK |
402 | "" |
403 | "@ | |
404 | addl %1,$31,%0 | |
405 | ldl %0,%1 | |
4ed43ff8 | 406 | lds %0,%1\;cvtlq %0,%0" |
9c0e94a5 RH |
407 | [(set_attr "type" "iadd,ild,fld") |
408 | (set_attr "length" "*,*,8")]) | |
4ed43ff8 RH |
409 | |
410 | ;; Due to issues with CLASS_CANNOT_CHANGE_SIZE, we cannot use a subreg here. | |
411 | (define_split | |
412 | [(set (match_operand:DI 0 "hard_fp_register_operand" "") | |
413 | (sign_extend:DI (match_operand:SI 1 "memory_operand" "")))] | |
414 | "reload_completed" | |
415 | [(set (match_dup 2) (match_dup 1)) | |
416 | (set (match_dup 0) (unspec:DI [(match_dup 2)] 4))] | |
417 | "operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]));") | |
418 | ||
419 | (define_insn "" | |
420 | [(set (match_operand:DI 0 "register_operand" "=f") | |
421 | (unspec:DI [(match_operand:SI 1 "register_operand" "f")] 4))] | |
422 | "" | |
423 | "cvtlq %1,%0" | |
424 | [(set_attr "type" "fadd")]) | |
36f8f642 | 425 | |
c9325fd6 RK |
426 | ;; Do addsi3 the way expand_binop would do if we didn't have one. This |
427 | ;; generates better code. We have the anonymous addsi3 pattern below in | |
428 | ;; case combine wants to make it. | |
429 | (define_expand "addsi3" | |
430 | [(set (match_operand:SI 0 "register_operand" "") | |
431 | (plus:SI (match_operand:SI 1 "reg_or_0_operand" "") | |
432 | (match_operand:SI 2 "add_operand" "")))] | |
433 | "" | |
434 | " | |
8f5d6855 | 435 | { |
bd8dc165 | 436 | if (optimize) |
6c61c2bb | 437 | { |
bd8dc165 RH |
438 | rtx op1 = gen_lowpart (DImode, operands[1]); |
439 | rtx op2 = gen_lowpart (DImode, operands[2]); | |
440 | ||
441 | if (! cse_not_expected) | |
442 | { | |
443 | rtx tmp = gen_reg_rtx (DImode); | |
444 | emit_insn (gen_adddi3 (tmp, op1, op2)); | |
445 | emit_move_insn (gen_lowpart (DImode, operands[0]), tmp); | |
446 | } | |
447 | else | |
448 | emit_insn (gen_adddi3 (gen_lowpart (DImode, operands[0]), op1, op2)); | |
449 | DONE; | |
6c61c2bb | 450 | } |
bd8dc165 | 451 | }") |
c9325fd6 RK |
452 | |
453 | (define_insn "" | |
26958509 | 454 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") |
55ff92b8 | 455 | (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ,rJ,rJ,rJ") |
26958509 | 456 | (match_operand:SI 2 "add_operand" "rI,O,K,L")))] |
36f8f642 RK |
457 | "" |
458 | "@ | |
459 | addl %r1,%2,%0 | |
26958509 | 460 | subl %r1,%n2,%0 |
36f8f642 | 461 | lda %0,%2(%r1) |
745466f2 | 462 | ldah %0,%h2(%r1)") |
36f8f642 RK |
463 | |
464 | (define_split | |
465 | [(set (match_operand:SI 0 "register_operand" "") | |
466 | (plus:SI (match_operand:SI 1 "register_operand" "") | |
467 | (match_operand:SI 2 "const_int_operand" "")))] | |
468 | "! add_operand (operands[2], SImode)" | |
469 | [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3))) | |
470 | (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))] | |
471 | " | |
472 | { | |
473 | HOST_WIDE_INT val = INTVAL (operands[2]); | |
474 | HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000); | |
475 | HOST_WIDE_INT rest = val - low; | |
476 | ||
477 | operands[3] = GEN_INT (rest); | |
478 | operands[4] = GEN_INT (low); | |
479 | }") | |
480 | ||
481 | (define_insn "" | |
482 | [(set (match_operand:DI 0 "register_operand" "=r,r") | |
483 | (sign_extend:DI | |
484 | (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ,rJ") | |
485 | (match_operand:SI 2 "sext_add_operand" "rI,O"))))] | |
486 | "" | |
487 | "@ | |
488 | addl %r1,%2,%0 | |
745466f2 | 489 | subl %r1,%n2,%0") |
36f8f642 | 490 | |
9cea6503 RK |
491 | (define_split |
492 | [(set (match_operand:DI 0 "register_operand" "") | |
493 | (sign_extend:DI | |
c5c76735 | 494 | (plus:SI (match_operand:SI 1 "reg_not_elim_operand" "") |
9cea6503 | 495 | (match_operand:SI 2 "const_int_operand" "")))) |
40b80dad | 496 | (clobber (match_operand:SI 3 "reg_not_elim_operand" ""))] |
26958509 | 497 | "! sext_add_operand (operands[2], SImode) && INTVAL (operands[2]) > 0 |
9cea6503 RK |
498 | && INTVAL (operands[2]) % 4 == 0" |
499 | [(set (match_dup 3) (match_dup 4)) | |
500 | (set (match_dup 0) (sign_extend:DI (plus:SI (mult:SI (match_dup 3) | |
501 | (match_dup 5)) | |
502 | (match_dup 1))))] | |
503 | " | |
504 | { | |
505 | HOST_WIDE_INT val = INTVAL (operands[2]) / 4; | |
506 | int mult = 4; | |
507 | ||
508 | if (val % 2 == 0) | |
509 | val /= 2, mult = 8; | |
510 | ||
511 | operands[4] = GEN_INT (val); | |
512 | operands[5] = GEN_INT (mult); | |
513 | }") | |
514 | ||
5c72c15e RK |
515 | (define_split |
516 | [(set (match_operand:DI 0 "register_operand" "") | |
517 | (sign_extend:DI | |
518 | (plus:SI (match_operator:SI 1 "comparison_operator" | |
519 | [(match_operand 2 "" "") | |
520 | (match_operand 3 "" "")]) | |
521 | (match_operand:SI 4 "add_operand" "")))) | |
522 | (clobber (match_operand:DI 5 "register_operand" ""))] | |
523 | "" | |
524 | [(set (match_dup 5) (match_dup 6)) | |
525 | (set (match_dup 0) (sign_extend:DI (plus:SI (match_dup 7) (match_dup 4))))] | |
526 | " | |
527 | { | |
38a448ca RH |
528 | operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[1]), DImode, |
529 | operands[2], operands[3]); | |
5c72c15e RK |
530 | operands[7] = gen_lowpart (SImode, operands[5]); |
531 | }") | |
532 | ||
36f8f642 | 533 | (define_insn "adddi3" |
26958509 | 534 | [(set (match_operand:DI 0 "register_operand" "=r,r,r,r") |
55ff92b8 | 535 | (plus:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ,rJ,rJ") |
26958509 | 536 | (match_operand:DI 2 "add_operand" "rI,O,K,L")))] |
36f8f642 | 537 | "" |
f9d7e5cd RH |
538 | "* |
539 | { | |
540 | const char * const pattern[4] = { | |
541 | \"addq %r1,%2,%0\", | |
542 | \"subq %r1,%n2,%0\", | |
543 | \"lda %0,%2(%r1)\", | |
544 | \"ldah %0,%h2(%r1)\" | |
545 | }; | |
546 | ||
547 | /* The NT stack unwind code can't handle a subq to adjust the stack | |
548 | (that's a bug, but not one we can do anything about). As of NT4.0 SP3, | |
549 | the exception handling code will loop if a subq is used and an | |
550 | exception occurs. | |
551 | ||
552 | The 19980616 change to emit prologues as RTL also confused some | |
553 | versions of GDB, which also interprets prologues. This has been | |
554 | fixed as of GDB 4.18, but it does not harm to unconditionally | |
555 | use lda here. */ | |
556 | ||
557 | int which = which_alternative; | |
558 | ||
559 | if (operands[0] == stack_pointer_rtx | |
560 | && GET_CODE (operands[2]) == CONST_INT | |
561 | && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')) | |
562 | which = 2; | |
563 | ||
564 | return pattern[which]; | |
565 | }") | |
36f8f642 | 566 | |
5d02b6c2 RH |
567 | ;; ??? Allow large constants when basing off the frame pointer or some |
568 | ;; virtual register that may eliminate to the frame pointer. This is | |
569 | ;; done because register elimination offsets will change the hi/lo split, | |
570 | ;; and if we split before reload, we will require additional instructions. | |
571 | ||
572 | (define_insn "" | |
573 | [(set (match_operand:DI 0 "register_operand" "=r") | |
574 | (plus:DI (match_operand:DI 1 "reg_no_subreg_operand" "r") | |
575 | (match_operand:DI 2 "const_int_operand" "n")))] | |
576 | "REG_OK_FP_BASE_P (operands[1])" | |
577 | "#") | |
578 | ||
579 | ;; Don't do this if we are adjusting SP since we don't want to do it | |
580 | ;; in two steps. Don't split FP sources for the reason listed above. | |
36f8f642 RK |
581 | (define_split |
582 | [(set (match_operand:DI 0 "register_operand" "") | |
583 | (plus:DI (match_operand:DI 1 "register_operand" "") | |
584 | (match_operand:DI 2 "const_int_operand" "")))] | |
26958509 | 585 | "! add_operand (operands[2], DImode) |
5d02b6c2 RH |
586 | && operands[0] != stack_pointer_rtx |
587 | && operands[1] != frame_pointer_rtx | |
588 | && operands[1] != arg_pointer_rtx" | |
36f8f642 RK |
589 | [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 3))) |
590 | (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))] | |
591 | " | |
592 | { | |
593 | HOST_WIDE_INT val = INTVAL (operands[2]); | |
594 | HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000); | |
595 | HOST_WIDE_INT rest = val - low; | |
596 | ||
597 | operands[3] = GEN_INT (rest); | |
598 | operands[4] = GEN_INT (low); | |
599 | }") | |
600 | ||
601 | (define_insn "" | |
26958509 | 602 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
40b80dad | 603 | (plus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r,r") |
26958509 RK |
604 | (match_operand:SI 2 "const48_operand" "I,I")) |
605 | (match_operand:SI 3 "sext_add_operand" "rI,O")))] | |
36f8f642 | 606 | "" |
26958509 | 607 | "@ |
40b80dad RH |
608 | s%2addl %1,%3,%0 |
609 | s%2subl %1,%n3,%0") | |
36f8f642 RK |
610 | |
611 | (define_insn "" | |
26958509 | 612 | [(set (match_operand:DI 0 "register_operand" "=r,r") |
36f8f642 | 613 | (sign_extend:DI |
40b80dad | 614 | (plus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r,r") |
26958509 RK |
615 | (match_operand:SI 2 "const48_operand" "I,I")) |
616 | (match_operand:SI 3 "sext_add_operand" "rI,O"))))] | |
36f8f642 | 617 | "" |
26958509 | 618 | "@ |
40b80dad RH |
619 | s%2addl %1,%3,%0 |
620 | s%2subl %1,%n3,%0") | |
36f8f642 | 621 | |
d0c84fda RK |
622 | (define_split |
623 | [(set (match_operand:DI 0 "register_operand" "") | |
624 | (sign_extend:DI | |
625 | (plus:SI (mult:SI (match_operator:SI 1 "comparison_operator" | |
626 | [(match_operand 2 "" "") | |
627 | (match_operand 3 "" "")]) | |
628 | (match_operand:SI 4 "const48_operand" "")) | |
c5c76735 | 629 | (match_operand:SI 5 "sext_add_operand" "")))) |
40b80dad | 630 | (clobber (match_operand:DI 6 "reg_not_elim_operand" ""))] |
d0c84fda RK |
631 | "" |
632 | [(set (match_dup 6) (match_dup 7)) | |
633 | (set (match_dup 0) | |
634 | (sign_extend:DI (plus:SI (mult:SI (match_dup 8) (match_dup 4)) | |
635 | (match_dup 5))))] | |
636 | " | |
637 | { | |
38a448ca RH |
638 | operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[1]), DImode, |
639 | operands[2], operands[3]); | |
d0c84fda RK |
640 | operands[8] = gen_lowpart (SImode, operands[6]); |
641 | }") | |
642 | ||
36f8f642 | 643 | (define_insn "" |
26958509 | 644 | [(set (match_operand:DI 0 "register_operand" "=r,r") |
40b80dad | 645 | (plus:DI (mult:DI (match_operand:DI 1 "reg_not_elim_operand" "r,r") |
26958509 | 646 | (match_operand:DI 2 "const48_operand" "I,I")) |
80df65c9 | 647 | (match_operand:DI 3 "sext_add_operand" "rI,O")))] |
36f8f642 | 648 | "" |
26958509 | 649 | "@ |
40b80dad | 650 | s%2addq %1,%3,%0 |
745466f2 | 651 | s%2subq %1,%n3,%0") |
36f8f642 | 652 | |
36f8f642 RK |
653 | (define_insn "negsi2" |
654 | [(set (match_operand:SI 0 "register_operand" "=r") | |
655 | (neg:SI (match_operand:SI 1 "reg_or_8bit_operand" "rI")))] | |
656 | "" | |
745466f2 | 657 | "subl $31,%1,%0") |
36f8f642 RK |
658 | |
659 | (define_insn "" | |
660 | [(set (match_operand:DI 0 "register_operand" "=r") | |
661 | (sign_extend:DI (neg:SI | |
662 | (match_operand:SI 1 "reg_or_8bit_operand" "rI"))))] | |
663 | "" | |
745466f2 | 664 | "subl $31,%1,%0") |
36f8f642 RK |
665 | |
666 | (define_insn "negdi2" | |
667 | [(set (match_operand:DI 0 "register_operand" "=r") | |
668 | (neg:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")))] | |
669 | "" | |
745466f2 | 670 | "subq $31,%1,%0") |
36f8f642 | 671 | |
c9325fd6 RK |
672 | (define_expand "subsi3" |
673 | [(set (match_operand:SI 0 "register_operand" "") | |
674 | (minus:SI (match_operand:SI 1 "reg_or_0_operand" "") | |
675 | (match_operand:SI 2 "reg_or_8bit_operand" "")))] | |
676 | "" | |
677 | " | |
8f5d6855 | 678 | { |
bd8dc165 | 679 | if (optimize) |
6c61c2bb | 680 | { |
bd8dc165 RH |
681 | rtx op1 = gen_lowpart (DImode, operands[1]); |
682 | rtx op2 = gen_lowpart (DImode, operands[2]); | |
683 | ||
684 | if (! cse_not_expected) | |
685 | { | |
686 | rtx tmp = gen_reg_rtx (DImode); | |
687 | emit_insn (gen_subdi3 (tmp, op1, op2)); | |
688 | emit_move_insn (gen_lowpart (DImode, operands[0]), tmp); | |
689 | } | |
690 | else | |
691 | emit_insn (gen_subdi3 (gen_lowpart (DImode, operands[0]), op1, op2)); | |
692 | DONE; | |
6c61c2bb | 693 | } |
c9325fd6 RK |
694 | } ") |
695 | ||
696 | (define_insn "" | |
36f8f642 RK |
697 | [(set (match_operand:SI 0 "register_operand" "=r") |
698 | (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") | |
699 | (match_operand:SI 2 "reg_or_8bit_operand" "rI")))] | |
700 | "" | |
745466f2 | 701 | "subl %r1,%2,%0") |
36f8f642 RK |
702 | |
703 | (define_insn "" | |
704 | [(set (match_operand:DI 0 "register_operand" "=r") | |
705 | (sign_extend:DI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") | |
706 | (match_operand:SI 2 "reg_or_8bit_operand" "rI"))))] | |
707 | "" | |
745466f2 | 708 | "subl %r1,%2,%0") |
36f8f642 RK |
709 | |
710 | (define_insn "subdi3" | |
711 | [(set (match_operand:DI 0 "register_operand" "=r") | |
712 | (minus:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") | |
713 | (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] | |
714 | "" | |
745466f2 | 715 | "subq %r1,%2,%0") |
36f8f642 RK |
716 | |
717 | (define_insn "" | |
718 | [(set (match_operand:SI 0 "register_operand" "=r") | |
40b80dad | 719 | (minus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r") |
36f8f642 RK |
720 | (match_operand:SI 2 "const48_operand" "I")) |
721 | (match_operand:SI 3 "reg_or_8bit_operand" "rI")))] | |
722 | "" | |
40b80dad | 723 | "s%2subl %1,%3,%0") |
36f8f642 RK |
724 | |
725 | (define_insn "" | |
726 | [(set (match_operand:DI 0 "register_operand" "=r") | |
727 | (sign_extend:DI | |
40b80dad | 728 | (minus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r") |
36f8f642 RK |
729 | (match_operand:SI 2 "const48_operand" "I")) |
730 | (match_operand:SI 3 "reg_or_8bit_operand" "rI"))))] | |
731 | "" | |
40b80dad | 732 | "s%2subl %1,%3,%0") |
36f8f642 RK |
733 | |
734 | (define_insn "" | |
735 | [(set (match_operand:DI 0 "register_operand" "=r") | |
40b80dad | 736 | (minus:DI (mult:DI (match_operand:DI 1 "reg_not_elim_operand" "r") |
36f8f642 RK |
737 | (match_operand:DI 2 "const48_operand" "I")) |
738 | (match_operand:DI 3 "reg_or_8bit_operand" "rI")))] | |
739 | "" | |
40b80dad | 740 | "s%2subq %1,%3,%0") |
36f8f642 RK |
741 | |
742 | (define_insn "mulsi3" | |
743 | [(set (match_operand:SI 0 "register_operand" "=r") | |
744 | (mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ") | |
80df65c9 | 745 | (match_operand:SI 2 "reg_or_8bit_operand" "rI")))] |
36f8f642 | 746 | "" |
80df65c9 | 747 | "mull %r1,%2,%0" |
71d9b493 RH |
748 | [(set_attr "type" "imul") |
749 | (set_attr "opsize" "si")]) | |
36f8f642 RK |
750 | |
751 | (define_insn "" | |
752 | [(set (match_operand:DI 0 "register_operand" "=r") | |
80df65c9 RH |
753 | (sign_extend:DI |
754 | (mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ") | |
755 | (match_operand:SI 2 "reg_or_8bit_operand" "rI"))))] | |
36f8f642 | 756 | "" |
80df65c9 | 757 | "mull %r1,%2,%0" |
71d9b493 RH |
758 | [(set_attr "type" "imul") |
759 | (set_attr "opsize" "si")]) | |
36f8f642 RK |
760 | |
761 | (define_insn "muldi3" | |
762 | [(set (match_operand:DI 0 "register_operand" "=r") | |
763 | (mult:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ") | |
80df65c9 | 764 | (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] |
36f8f642 | 765 | "" |
80df65c9 | 766 | "mulq %r1,%2,%0" |
71d9b493 | 767 | [(set_attr "type" "imul")]) |
74a61069 TG |
768 | |
769 | (define_insn "umuldi3_highpart" | |
770 | [(set (match_operand:DI 0 "register_operand" "=r") | |
771 | (truncate:DI | |
772 | (lshiftrt:TI | |
80df65c9 RH |
773 | (mult:TI (zero_extend:TI |
774 | (match_operand:DI 1 "reg_or_0_operand" "%rJ")) | |
775 | (zero_extend:TI | |
776 | (match_operand:DI 2 "reg_or_8bit_operand" "rI"))) | |
74a61069 TG |
777 | (const_int 64))))] |
778 | "" | |
80df65c9 | 779 | "umulh %r1,%2,%0" |
71d9b493 RH |
780 | [(set_attr "type" "imul") |
781 | (set_attr "opsize" "udi")]) | |
74a61069 TG |
782 | |
783 | (define_insn "" | |
784 | [(set (match_operand:DI 0 "register_operand" "=r") | |
785 | (truncate:DI | |
786 | (lshiftrt:TI | |
787 | (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand" "r")) | |
788 | (match_operand:TI 2 "cint8_operand" "I")) | |
789 | (const_int 64))))] | |
790 | "" | |
791 | "umulh %1,%2,%0" | |
71d9b493 RH |
792 | [(set_attr "type" "imul") |
793 | (set_attr "opsize" "udi")]) | |
36f8f642 RK |
794 | \f |
795 | ;; The divide and remainder operations always take their inputs from | |
df065f1d | 796 | ;; r24 and r25, put their output in r27, and clobber r23 and r28. |
36f8f642 | 797 | |
d46f7484 RH |
798 | ;; ??? Force sign-extension here because some versions of OSF/1 don't |
799 | ;; do the right thing if the inputs are not properly sign-extended. | |
800 | ;; But Linux, for instance, does not have this problem. Is it worth | |
801 | ;; the complication here to eliminate the sign extension? | |
615c8231 | 802 | ;; Interix/NT has the same sign-extension problem. |
d46f7484 RH |
803 | |
804 | (define_expand "divsi3" | |
805 | [(set (reg:DI 24) | |
806 | (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" ""))) | |
807 | (set (reg:DI 25) | |
808 | (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))) | |
809 | (parallel [(set (reg:DI 27) | |
810 | (sign_extend:DI (div:SI (reg:DI 24) (reg:DI 25)))) | |
811 | (clobber (reg:DI 23)) | |
812 | (clobber (reg:DI 28))]) | |
813 | (set (match_operand:SI 0 "general_operand" "") | |
814 | (subreg:SI (reg:DI 27) 0))] | |
815 | "!TARGET_OPEN_VMS" | |
816 | "") | |
817 | ||
818 | (define_expand "udivsi3" | |
819 | [(set (reg:DI 24) | |
820 | (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" ""))) | |
821 | (set (reg:DI 25) | |
822 | (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))) | |
823 | (parallel [(set (reg:DI 27) | |
824 | (sign_extend:DI (udiv:SI (reg:DI 24) (reg:DI 25)))) | |
825 | (clobber (reg:DI 23)) | |
826 | (clobber (reg:DI 28))]) | |
827 | (set (match_operand:SI 0 "general_operand" "") | |
828 | (subreg:SI (reg:DI 27) 0))] | |
829 | "!TARGET_OPEN_VMS" | |
830 | "") | |
831 | ||
832 | (define_expand "modsi3" | |
833 | [(set (reg:DI 24) | |
834 | (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" ""))) | |
835 | (set (reg:DI 25) | |
836 | (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))) | |
837 | (parallel [(set (reg:DI 27) | |
838 | (sign_extend:DI (mod:SI (reg:DI 24) (reg:DI 25)))) | |
839 | (clobber (reg:DI 23)) | |
840 | (clobber (reg:DI 28))]) | |
841 | (set (match_operand:SI 0 "general_operand" "") | |
842 | (subreg:SI (reg:DI 27) 0))] | |
843 | "!TARGET_OPEN_VMS" | |
844 | "") | |
845 | ||
846 | (define_expand "umodsi3" | |
847 | [(set (reg:DI 24) | |
848 | (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" ""))) | |
849 | (set (reg:DI 25) | |
850 | (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))) | |
851 | (parallel [(set (reg:DI 27) | |
852 | (sign_extend:DI (umod:SI (reg:DI 24) (reg:DI 25)))) | |
853 | (clobber (reg:DI 23)) | |
854 | (clobber (reg:DI 28))]) | |
855 | (set (match_operand:SI 0 "general_operand" "") | |
856 | (subreg:SI (reg:DI 27) 0))] | |
857 | "!TARGET_OPEN_VMS" | |
858 | "") | |
36f8f642 RK |
859 | |
860 | (define_expand "divdi3" | |
98ff4808 TG |
861 | [(set (reg:DI 24) (match_operand:DI 1 "input_operand" "")) |
862 | (set (reg:DI 25) (match_operand:DI 2 "input_operand" "")) | |
863 | (parallel [(set (reg:DI 27) | |
864 | (div:DI (reg:DI 24) | |
865 | (reg:DI 25))) | |
5ce6bbdb BK |
866 | (clobber (reg:DI 23)) |
867 | (clobber (reg:DI 28))]) | |
36f8f642 RK |
868 | (set (match_operand:DI 0 "general_operand" "") |
869 | (reg:DI 27))] | |
477c16e3 | 870 | "!TARGET_OPEN_VMS" |
98ff4808 | 871 | "") |
36f8f642 RK |
872 | |
873 | (define_expand "udivdi3" | |
98ff4808 TG |
874 | [(set (reg:DI 24) (match_operand:DI 1 "input_operand" "")) |
875 | (set (reg:DI 25) (match_operand:DI 2 "input_operand" "")) | |
876 | (parallel [(set (reg:DI 27) | |
877 | (udiv:DI (reg:DI 24) | |
878 | (reg:DI 25))) | |
5ce6bbdb BK |
879 | (clobber (reg:DI 23)) |
880 | (clobber (reg:DI 28))]) | |
36f8f642 RK |
881 | (set (match_operand:DI 0 "general_operand" "") |
882 | (reg:DI 27))] | |
477c16e3 | 883 | "!TARGET_OPEN_VMS" |
98ff4808 | 884 | "") |
36f8f642 RK |
885 | |
886 | (define_expand "moddi3" | |
98ff4808 TG |
887 | [(set (reg:DI 24) (match_operand:DI 1 "input_operand" "")) |
888 | (set (reg:DI 25) (match_operand:DI 2 "input_operand" "")) | |
889 | (parallel [(set (reg:DI 27) | |
890 | (mod:DI (reg:DI 24) | |
891 | (reg:DI 25))) | |
5ce6bbdb BK |
892 | (clobber (reg:DI 23)) |
893 | (clobber (reg:DI 28))]) | |
36f8f642 RK |
894 | (set (match_operand:DI 0 "general_operand" "") |
895 | (reg:DI 27))] | |
477c16e3 | 896 | "!TARGET_OPEN_VMS" |
98ff4808 | 897 | "") |
36f8f642 RK |
898 | |
899 | (define_expand "umoddi3" | |
98ff4808 TG |
900 | [(set (reg:DI 24) (match_operand:DI 1 "input_operand" "")) |
901 | (set (reg:DI 25) (match_operand:DI 2 "input_operand" "")) | |
902 | (parallel [(set (reg:DI 27) | |
903 | (umod:DI (reg:DI 24) | |
904 | (reg:DI 25))) | |
5ce6bbdb BK |
905 | (clobber (reg:DI 23)) |
906 | (clobber (reg:DI 28))]) | |
36f8f642 RK |
907 | (set (match_operand:DI 0 "general_operand" "") |
908 | (reg:DI 27))] | |
477c16e3 | 909 | "!TARGET_OPEN_VMS" |
98ff4808 | 910 | "") |
36f8f642 | 911 | |
9c0e94a5 RH |
912 | ;; Lengths of 8 for ldq $t12,__divq($gp); jsr $t9,($t12),__divq as |
913 | ;; expanded by the assembler. | |
d46f7484 RH |
914 | (define_insn "" |
915 | [(set (reg:DI 27) | |
916 | (sign_extend:DI (match_operator:SI 1 "divmod_operator" | |
917 | [(reg:DI 24) (reg:DI 25)]))) | |
918 | (clobber (reg:DI 23)) | |
919 | (clobber (reg:DI 28))] | |
920 | "!TARGET_OPEN_VMS" | |
921 | "%E1 $24,$25,$27" | |
9c0e94a5 RH |
922 | [(set_attr "type" "jsr") |
923 | (set_attr "length" "8")]) | |
36f8f642 RK |
924 | |
925 | (define_insn "" | |
926 | [(set (reg:DI 27) | |
927 | (match_operator:DI 1 "divmod_operator" | |
928 | [(reg:DI 24) (reg:DI 25)])) | |
df065f1d BK |
929 | (clobber (reg:DI 23)) |
930 | (clobber (reg:DI 28))] | |
477c16e3 | 931 | "!TARGET_OPEN_VMS" |
454f33b9 | 932 | "%E1 $24,$25,$27" |
9c0e94a5 RH |
933 | [(set_attr "type" "jsr") |
934 | (set_attr "length" "8")]) | |
36f8f642 RK |
935 | \f |
936 | ;; Next are the basic logical operations. These only exist in DImode. | |
937 | ||
938 | (define_insn "anddi3" | |
939 | [(set (match_operand:DI 0 "register_operand" "=r,r,r") | |
940 | (and:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ,rJ") | |
941 | (match_operand:DI 2 "and_operand" "rI,N,MH")))] | |
942 | "" | |
943 | "@ | |
944 | and %r1,%2,%0 | |
945 | bic %r1,%N2,%0 | |
946 | zapnot %r1,%m2,%0" | |
745466f2 | 947 | [(set_attr "type" "ilog,ilog,shift")]) |
36f8f642 | 948 | |
11e87727 | 949 | ;; There are times when we can split an AND into two AND insns. This occurs |
36f8f642 RK |
950 | ;; when we can first clear any bytes and then clear anything else. For |
951 | ;; example "I & 0xffff07" is "(I & 0xffffff) & 0xffffffffffffff07". | |
11e87727 | 952 | ;; Only do this when running on 64-bit host since the computations are |
36f8f642 RK |
953 | ;; too messy otherwise. |
954 | ||
955 | (define_split | |
956 | [(set (match_operand:DI 0 "register_operand" "") | |
957 | (and:DI (match_operand:DI 1 "register_operand" "") | |
958 | (match_operand:DI 2 "const_int_operand" "")))] | |
959 | "HOST_BITS_PER_WIDE_INT == 64 && ! and_operand (operands[2], DImode)" | |
960 | [(set (match_dup 0) (and:DI (match_dup 1) (match_dup 3))) | |
961 | (set (match_dup 0) (and:DI (match_dup 0) (match_dup 4)))] | |
962 | " | |
963 | { | |
964 | unsigned HOST_WIDE_INT mask1 = INTVAL (operands[2]); | |
965 | unsigned HOST_WIDE_INT mask2 = mask1; | |
966 | int i; | |
967 | ||
968 | /* For each byte that isn't all zeros, make it all ones. */ | |
969 | for (i = 0; i < 64; i += 8) | |
970 | if ((mask1 & ((HOST_WIDE_INT) 0xff << i)) != 0) | |
971 | mask1 |= (HOST_WIDE_INT) 0xff << i; | |
972 | ||
973 | /* Now turn on any bits we've just turned off. */ | |
974 | mask2 |= ~ mask1; | |
975 | ||
976 | operands[3] = GEN_INT (mask1); | |
977 | operands[4] = GEN_INT (mask2); | |
978 | }") | |
979 | ||
980 | (define_insn "zero_extendqihi2" | |
981 | [(set (match_operand:HI 0 "register_operand" "=r") | |
982 | (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))] | |
983 | "" | |
55a9eb72 | 984 | "and %1,0xff,%0" |
5e21ac7a | 985 | [(set_attr "type" "ilog")]) |
36f8f642 | 986 | |
ec0fb163 TG |
987 | (define_insn "" |
988 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
989 | (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] | |
e9a25f70 | 990 | "TARGET_BWX" |
ec0fb163 | 991 | "@ |
55a9eb72 | 992 | and %1,0xff,%0 |
ec0fb163 | 993 | ldbu %0,%1" |
71d9b493 | 994 | [(set_attr "type" "ilog,ild")]) |
ec0fb163 | 995 | |
b9a2d591 | 996 | (define_insn "" |
36f8f642 RK |
997 | [(set (match_operand:SI 0 "register_operand" "=r") |
998 | (zero_extend:SI (match_operand:QI 1 "register_operand" "r")))] | |
e9a25f70 | 999 | "! TARGET_BWX" |
55a9eb72 | 1000 | "and %1,0xff,%0" |
5e21ac7a | 1001 | [(set_attr "type" "ilog")]) |
36f8f642 | 1002 | |
b9a2d591 RK |
1003 | (define_expand "zero_extendqisi2" |
1004 | [(set (match_operand:SI 0 "register_operand" "") | |
1005 | (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] | |
1006 | "" | |
1007 | "") | |
1008 | ||
ec0fb163 TG |
1009 | (define_insn "" |
1010 | [(set (match_operand:DI 0 "register_operand" "=r,r") | |
1011 | (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] | |
e9a25f70 | 1012 | "TARGET_BWX" |
ec0fb163 | 1013 | "@ |
55a9eb72 | 1014 | and %1,0xff,%0 |
ec0fb163 | 1015 | ldbu %0,%1" |
71d9b493 | 1016 | [(set_attr "type" "ilog,ild")]) |
ec0fb163 | 1017 | |
b9a2d591 | 1018 | (define_insn "" |
36f8f642 RK |
1019 | [(set (match_operand:DI 0 "register_operand" "=r") |
1020 | (zero_extend:DI (match_operand:QI 1 "register_operand" "r")))] | |
e9a25f70 | 1021 | "! TARGET_BWX" |
55a9eb72 | 1022 | "and %1,0xff,%0" |
5e21ac7a | 1023 | [(set_attr "type" "ilog")]) |
ec0fb163 | 1024 | |
b9a2d591 RK |
1025 | (define_expand "zero_extendqidi2" |
1026 | [(set (match_operand:DI 0 "register_operand" "") | |
1027 | (zero_extend:DI (match_operand:QI 1 "register_operand" "")))] | |
1028 | "" | |
1029 | "") | |
1030 | ||
ec0fb163 TG |
1031 | (define_insn "" |
1032 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1033 | (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] | |
e9a25f70 | 1034 | "TARGET_BWX" |
ec0fb163 TG |
1035 | "@ |
1036 | zapnot %1,3,%0 | |
1037 | ldwu %0,%1" | |
71d9b493 | 1038 | [(set_attr "type" "shift,ild")]) |
36f8f642 | 1039 | |
b9a2d591 | 1040 | (define_insn "" |
36f8f642 RK |
1041 | [(set (match_operand:SI 0 "register_operand" "=r") |
1042 | (zero_extend:SI (match_operand:HI 1 "register_operand" "r")))] | |
e9a25f70 | 1043 | "! TARGET_BWX" |
36f8f642 | 1044 | "zapnot %1,3,%0" |
745466f2 | 1045 | [(set_attr "type" "shift")]) |
36f8f642 | 1046 | |
b9a2d591 RK |
1047 | (define_expand "zero_extendhisi2" |
1048 | [(set (match_operand:SI 0 "register_operand" "") | |
1049 | (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] | |
1050 | "" | |
1051 | "") | |
1052 | ||
ec0fb163 TG |
1053 | (define_insn "" |
1054 | [(set (match_operand:DI 0 "register_operand" "=r,r") | |
1055 | (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] | |
e9a25f70 | 1056 | "TARGET_BWX" |
ec0fb163 TG |
1057 | "@ |
1058 | zapnot %1,3,%0 | |
1059 | ldwu %0,%1" | |
71d9b493 | 1060 | [(set_attr "type" "shift,ild")]) |
ec0fb163 | 1061 | |
b9a2d591 | 1062 | (define_insn "" |
36f8f642 RK |
1063 | [(set (match_operand:DI 0 "register_operand" "=r") |
1064 | (zero_extend:DI (match_operand:HI 1 "register_operand" "r")))] | |
1065 | "" | |
1066 | "zapnot %1,3,%0" | |
745466f2 | 1067 | [(set_attr "type" "shift")]) |
36f8f642 | 1068 | |
b9a2d591 RK |
1069 | (define_expand "zero_extendhidi2" |
1070 | [(set (match_operand:DI 0 "register_operand" "") | |
1071 | (zero_extend:DI (match_operand:HI 1 "register_operand" "")))] | |
1072 | "" | |
1073 | "") | |
1074 | ||
36f8f642 RK |
1075 | (define_insn "zero_extendsidi2" |
1076 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1077 | (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))] | |
1078 | "" | |
1079 | "zapnot %1,15,%0" | |
745466f2 | 1080 | [(set_attr "type" "shift")]) |
36f8f642 RK |
1081 | |
1082 | (define_insn "" | |
1083 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1084 | (and:DI (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")) | |
1085 | (match_operand:DI 2 "reg_or_0_operand" "rJ")))] | |
1086 | "" | |
1087 | "bic %r2,%1,%0" | |
745466f2 | 1088 | [(set_attr "type" "ilog")]) |
36f8f642 RK |
1089 | |
1090 | (define_insn "iordi3" | |
60614fdd RK |
1091 | [(set (match_operand:DI 0 "register_operand" "=r,r") |
1092 | (ior:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ") | |
d46f42a5 | 1093 | (match_operand:DI 2 "or_operand" "rI,N")))] |
36f8f642 | 1094 | "" |
60614fdd RK |
1095 | "@ |
1096 | bis %r1,%2,%0 | |
1097 | ornot %r1,%N2,%0" | |
745466f2 | 1098 | [(set_attr "type" "ilog")]) |
36f8f642 RK |
1099 | |
1100 | (define_insn "one_cmpldi2" | |
1101 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1102 | (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")))] | |
1103 | "" | |
1104 | "ornot $31,%1,%0" | |
745466f2 | 1105 | [(set_attr "type" "ilog")]) |
36f8f642 RK |
1106 | |
1107 | (define_insn "" | |
1108 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1109 | (ior:DI (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")) | |
1110 | (match_operand:DI 2 "reg_or_0_operand" "rJ")))] | |
1111 | "" | |
1112 | "ornot %r2,%1,%0" | |
745466f2 | 1113 | [(set_attr "type" "ilog")]) |
36f8f642 RK |
1114 | |
1115 | (define_insn "xordi3" | |
d46f42a5 RK |
1116 | [(set (match_operand:DI 0 "register_operand" "=r,r") |
1117 | (xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ") | |
1118 | (match_operand:DI 2 "or_operand" "rI,N")))] | |
36f8f642 | 1119 | "" |
d46f42a5 RK |
1120 | "@ |
1121 | xor %r1,%2,%0 | |
1122 | eqv %r1,%N2,%0" | |
745466f2 | 1123 | [(set_attr "type" "ilog")]) |
36f8f642 RK |
1124 | |
1125 | (define_insn "" | |
1126 | [(set (match_operand:DI 0 "register_operand" "=r") | |
d46f42a5 RK |
1127 | (not:DI (xor:DI (match_operand:DI 1 "register_operand" "%rJ") |
1128 | (match_operand:DI 2 "register_operand" "rI"))))] | |
36f8f642 RK |
1129 | "" |
1130 | "eqv %r1,%2,%0" | |
745466f2 | 1131 | [(set_attr "type" "ilog")]) |
36f8f642 | 1132 | \f |
de4abb91 RH |
1133 | ;; Handle the FFS insn iff we support CIX. |
1134 | ;; | |
1135 | ;; These didn't make it into EV6 pass 2 as planned. Instead they | |
1136 | ;; cropped cttz/ctlz/ctpop from the old CIX and renamed it FIX for | |
1137 | ;; "Square Root and Floating Point Convert Extension". | |
1138 | ;; | |
1139 | ;; I'm assured that these insns will make it into EV67 (first pass | |
1140 | ;; due Summer 1999), presumably with a new AMASK bit, and presumably | |
1141 | ;; will still be named CIX. | |
e9a25f70 JL |
1142 | |
1143 | (define_expand "ffsdi2" | |
1144 | [(set (match_dup 2) | |
1145 | (unspec [(match_operand:DI 1 "register_operand" "")] 1)) | |
1146 | (set (match_dup 3) | |
1147 | (plus:DI (match_dup 2) (const_int 1))) | |
1148 | (set (match_operand:DI 0 "register_operand" "") | |
1149 | (if_then_else:DI (eq (match_dup 1) (const_int 0)) | |
1150 | (const_int 0) (match_dup 3)))] | |
1151 | "TARGET_CIX" | |
1152 | " | |
1153 | { | |
1154 | operands[2] = gen_reg_rtx (DImode); | |
1155 | operands[3] = gen_reg_rtx (DImode); | |
1156 | }") | |
1157 | ||
1158 | (define_insn "" | |
1159 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1160 | (unspec [(match_operand:DI 1 "register_operand" "r")] 1))] | |
1161 | "TARGET_CIX" | |
1162 | "cttz %1,%0" | |
de4abb91 | 1163 | ; EV6 calls all mvi and cttz/ctlz/popc class imisc, so just |
71d9b493 RH |
1164 | ; reuse the existing type name. |
1165 | [(set_attr "type" "mvi")]) | |
e9a25f70 | 1166 | \f |
36f8f642 RK |
1167 | ;; Next come the shifts and the various extract and insert operations. |
1168 | ||
1169 | (define_insn "ashldi3" | |
1170 | [(set (match_operand:DI 0 "register_operand" "=r,r") | |
1171 | (ashift:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,rJ") | |
9ec36da5 | 1172 | (match_operand:DI 2 "reg_or_6bit_operand" "P,rS")))] |
36f8f642 RK |
1173 | "" |
1174 | "* | |
1175 | { | |
1176 | switch (which_alternative) | |
1177 | { | |
1178 | case 0: | |
1179 | if (operands[2] == const1_rtx) | |
1180 | return \"addq %r1,%r1,%0\"; | |
1181 | else | |
1182 | return \"s%P2addq %r1,0,%0\"; | |
1183 | case 1: | |
1184 | return \"sll %r1,%2,%0\"; | |
3c303f52 KG |
1185 | default: |
1186 | abort(); | |
36f8f642 RK |
1187 | } |
1188 | }" | |
745466f2 | 1189 | [(set_attr "type" "iadd,shift")]) |
36f8f642 | 1190 | |
03af65c4 RK |
1191 | ;; ??? The following pattern is made by combine, but earlier phases |
1192 | ;; (specifically flow) can't handle it. This occurs in jump.c. Deal | |
1193 | ;; with this in a better way at some point. | |
1194 | ;;(define_insn "" | |
1195 | ;; [(set (match_operand:DI 0 "register_operand" "=r") | |
1196 | ;; (sign_extend:DI | |
1197 | ;; (subreg:SI (ashift:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") | |
1198 | ;; (match_operand:DI 2 "const_int_operand" "P")) | |
1199 | ;; 0)))] | |
1200 | ;; "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3" | |
1201 | ;; "* | |
1202 | ;;{ | |
1203 | ;; if (operands[2] == const1_rtx) | |
1204 | ;; return \"addl %r1,%r1,%0\"; | |
1205 | ;; else | |
1206 | ;; return \"s%P2addl %r1,0,%0\"; | |
1207 | ;; }" | |
745466f2 | 1208 | ;; [(set_attr "type" "iadd")]) |
36f8f642 RK |
1209 | |
1210 | (define_insn "lshrdi3" | |
1211 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1212 | (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") | |
9ec36da5 | 1213 | (match_operand:DI 2 "reg_or_6bit_operand" "rS")))] |
36f8f642 | 1214 | "" |
745466f2 RK |
1215 | "srl %r1,%2,%0" |
1216 | [(set_attr "type" "shift")]) | |
36f8f642 RK |
1217 | |
1218 | (define_insn "ashrdi3" | |
1219 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1220 | (ashiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") | |
9ec36da5 | 1221 | (match_operand:DI 2 "reg_or_6bit_operand" "rS")))] |
36f8f642 | 1222 | "" |
745466f2 RK |
1223 | "sra %r1,%2,%0" |
1224 | [(set_attr "type" "shift")]) | |
36f8f642 RK |
1225 | |
1226 | (define_expand "extendqihi2" | |
1227 | [(set (match_dup 2) | |
b9a2d591 | 1228 | (ashift:DI (match_operand:QI 1 "some_operand" "") |
36f8f642 RK |
1229 | (const_int 56))) |
1230 | (set (match_operand:HI 0 "register_operand" "") | |
1231 | (ashiftrt:DI (match_dup 2) | |
1232 | (const_int 56)))] | |
1233 | "" | |
1234 | " | |
2206e904 | 1235 | { |
e9a25f70 | 1236 | if (TARGET_BWX) |
b9a2d591 RK |
1237 | { |
1238 | emit_insn (gen_extendqihi2x (operands[0], | |
1239 | force_reg (QImode, operands[1]))); | |
1240 | DONE; | |
1241 | } | |
1242 | ||
1243 | /* If we have an unaligned MEM, extend to DImode (which we do | |
ec0fb163 | 1244 | specially) and then copy to the result. */ |
b9a2d591 | 1245 | if (unaligned_memory_operand (operands[1], HImode)) |
2206e904 RK |
1246 | { |
1247 | rtx temp = gen_reg_rtx (DImode); | |
1248 | ||
1249 | emit_insn (gen_extendqidi2 (temp, operands[1])); | |
1250 | emit_move_insn (operands[0], gen_lowpart (HImode, temp)); | |
1251 | DONE; | |
1252 | } | |
1253 | ||
1254 | operands[0] = gen_lowpart (DImode, operands[0]); | |
5d38efae | 1255 | operands[1] = gen_lowpart (DImode, force_reg (QImode, operands[1])); |
36f8f642 RK |
1256 | operands[2] = gen_reg_rtx (DImode); |
1257 | }") | |
1258 | ||
ec0fb163 | 1259 | (define_insn "extendqidi2x" |
b9a2d591 | 1260 | [(set (match_operand:DI 0 "register_operand" "=r") |
ec0fb163 | 1261 | (sign_extend:DI (match_operand:QI 1 "register_operand" "r")))] |
e9a25f70 | 1262 | "TARGET_BWX" |
ec0fb163 | 1263 | "sextb %1,%0" |
b9a2d591 | 1264 | [(set_attr "type" "shift")]) |
ec0fb163 TG |
1265 | |
1266 | (define_insn "extendhidi2x" | |
b9a2d591 | 1267 | [(set (match_operand:DI 0 "register_operand" "=r") |
ec0fb163 | 1268 | (sign_extend:DI (match_operand:HI 1 "register_operand" "r")))] |
e9a25f70 | 1269 | "TARGET_BWX" |
ec0fb163 TG |
1270 | "sextw %1,%0" |
1271 | [(set_attr "type" "shift")]) | |
1272 | ||
b9a2d591 RK |
1273 | (define_insn "extendqisi2x" |
1274 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1275 | (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))] | |
e9a25f70 | 1276 | "TARGET_BWX" |
b9a2d591 RK |
1277 | "sextb %1,%0" |
1278 | [(set_attr "type" "shift")]) | |
1279 | ||
1280 | (define_insn "extendhisi2x" | |
1281 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1282 | (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))] | |
e9a25f70 | 1283 | "TARGET_BWX" |
b9a2d591 RK |
1284 | "sextw %1,%0" |
1285 | [(set_attr "type" "shift")]) | |
1286 | ||
1287 | (define_insn "extendqihi2x" | |
1288 | [(set (match_operand:HI 0 "register_operand" "=r") | |
1289 | (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))] | |
e9a25f70 | 1290 | "TARGET_BWX" |
b9a2d591 RK |
1291 | "sextb %1,%0" |
1292 | [(set_attr "type" "shift")]) | |
1293 | ||
36f8f642 RK |
1294 | (define_expand "extendqisi2" |
1295 | [(set (match_dup 2) | |
b9a2d591 | 1296 | (ashift:DI (match_operand:QI 1 "some_operand" "") |
36f8f642 RK |
1297 | (const_int 56))) |
1298 | (set (match_operand:SI 0 "register_operand" "") | |
1299 | (ashiftrt:DI (match_dup 2) | |
1300 | (const_int 56)))] | |
1301 | "" | |
1302 | " | |
2206e904 | 1303 | { |
e9a25f70 | 1304 | if (TARGET_BWX) |
b9a2d591 RK |
1305 | { |
1306 | emit_insn (gen_extendqisi2x (operands[0], | |
1307 | force_reg (QImode, operands[1]))); | |
1308 | DONE; | |
1309 | } | |
1310 | ||
1311 | /* If we have an unaligned MEM, extend to a DImode form of | |
2206e904 | 1312 | the result (which we do specially). */ |
b9a2d591 | 1313 | if (unaligned_memory_operand (operands[1], QImode)) |
2206e904 RK |
1314 | { |
1315 | rtx temp = gen_reg_rtx (DImode); | |
1316 | ||
1317 | emit_insn (gen_extendqidi2 (temp, operands[1])); | |
1318 | emit_move_insn (operands[0], gen_lowpart (SImode, temp)); | |
1319 | DONE; | |
1320 | } | |
1321 | ||
1322 | operands[0] = gen_lowpart (DImode, operands[0]); | |
b9a2d591 | 1323 | operands[1] = gen_lowpart (DImode, force_reg (QImode, operands[1])); |
36f8f642 RK |
1324 | operands[2] = gen_reg_rtx (DImode); |
1325 | }") | |
1326 | ||
1327 | (define_expand "extendqidi2" | |
1328 | [(set (match_dup 2) | |
b9a2d591 | 1329 | (ashift:DI (match_operand:QI 1 "some_operand" "") |
36f8f642 RK |
1330 | (const_int 56))) |
1331 | (set (match_operand:DI 0 "register_operand" "") | |
1332 | (ashiftrt:DI (match_dup 2) | |
1333 | (const_int 56)))] | |
1334 | "" | |
1335 | " | |
47747e53 | 1336 | { |
e9a25f70 | 1337 | if (TARGET_BWX) |
ec0fb163 | 1338 | { |
b9a2d591 RK |
1339 | emit_insn (gen_extendqidi2x (operands[0], |
1340 | force_reg (QImode, operands[1]))); | |
ec0fb163 TG |
1341 | DONE; |
1342 | } | |
1343 | ||
b9a2d591 | 1344 | if (unaligned_memory_operand (operands[1], QImode)) |
2206e904 RK |
1345 | { |
1346 | rtx seq | |
1347 | = gen_unaligned_extendqidi (operands[0], | |
1348 | get_unaligned_address (operands[1], 1)); | |
1349 | ||
1350 | alpha_set_memflags (seq, operands[1]); | |
1351 | emit_insn (seq); | |
1352 | DONE; | |
1353 | } | |
1354 | ||
b9a2d591 | 1355 | operands[1] = gen_lowpart (DImode, force_reg (QImode, operands[1])); |
36f8f642 RK |
1356 | operands[2] = gen_reg_rtx (DImode); |
1357 | }") | |
1358 | ||
1359 | (define_expand "extendhisi2" | |
1360 | [(set (match_dup 2) | |
b9a2d591 | 1361 | (ashift:DI (match_operand:HI 1 "some_operand" "") |
36f8f642 RK |
1362 | (const_int 48))) |
1363 | (set (match_operand:SI 0 "register_operand" "") | |
1364 | (ashiftrt:DI (match_dup 2) | |
1365 | (const_int 48)))] | |
1366 | "" | |
1367 | " | |
2206e904 | 1368 | { |
e9a25f70 | 1369 | if (TARGET_BWX) |
b9a2d591 RK |
1370 | { |
1371 | emit_insn (gen_extendhisi2x (operands[0], | |
1372 | force_reg (HImode, operands[1]))); | |
1373 | DONE; | |
1374 | } | |
1375 | ||
1376 | /* If we have an unaligned MEM, extend to a DImode form of | |
2206e904 | 1377 | the result (which we do specially). */ |
b9a2d591 | 1378 | if (unaligned_memory_operand (operands[1], HImode)) |
2206e904 RK |
1379 | { |
1380 | rtx temp = gen_reg_rtx (DImode); | |
1381 | ||
1382 | emit_insn (gen_extendhidi2 (temp, operands[1])); | |
1383 | emit_move_insn (operands[0], gen_lowpart (SImode, temp)); | |
1384 | DONE; | |
1385 | } | |
1386 | ||
1387 | operands[0] = gen_lowpart (DImode, operands[0]); | |
b9a2d591 | 1388 | operands[1] = gen_lowpart (DImode, force_reg (HImode, operands[1])); |
36f8f642 RK |
1389 | operands[2] = gen_reg_rtx (DImode); |
1390 | }") | |
1391 | ||
1392 | (define_expand "extendhidi2" | |
1393 | [(set (match_dup 2) | |
b9a2d591 | 1394 | (ashift:DI (match_operand:HI 1 "some_operand" "") |
36f8f642 RK |
1395 | (const_int 48))) |
1396 | (set (match_operand:DI 0 "register_operand" "") | |
1397 | (ashiftrt:DI (match_dup 2) | |
1398 | (const_int 48)))] | |
1399 | "" | |
1400 | " | |
47747e53 | 1401 | { |
e9a25f70 | 1402 | if (TARGET_BWX) |
ec0fb163 | 1403 | { |
b9a2d591 RK |
1404 | emit_insn (gen_extendhidi2x (operands[0], |
1405 | force_reg (HImode, operands[1]))); | |
ec0fb163 TG |
1406 | DONE; |
1407 | } | |
1408 | ||
b9a2d591 | 1409 | if (unaligned_memory_operand (operands[1], HImode)) |
2206e904 RK |
1410 | { |
1411 | rtx seq | |
1412 | = gen_unaligned_extendhidi (operands[0], | |
1413 | get_unaligned_address (operands[1], 2)); | |
1414 | ||
1415 | alpha_set_memflags (seq, operands[1]); | |
1416 | emit_insn (seq); | |
1417 | DONE; | |
1418 | } | |
1419 | ||
b9a2d591 | 1420 | operands[1] = gen_lowpart (DImode, force_reg (HImode, operands[1])); |
36f8f642 RK |
1421 | operands[2] = gen_reg_rtx (DImode); |
1422 | }") | |
1423 | ||
2206e904 RK |
1424 | ;; Here's how we sign extend an unaligned byte and halfword. Doing this |
1425 | ;; as a pattern saves one instruction. The code is similar to that for | |
1426 | ;; the unaligned loads (see below). | |
1427 | ;; | |
1428 | ;; Operand 1 is the address + 1 (+2 for HI), operand 0 is the result. | |
1429 | (define_expand "unaligned_extendqidi" | |
1430 | [(set (match_dup 2) (match_operand:DI 1 "address_operand" "")) | |
1431 | (set (match_dup 3) | |
1432 | (mem:DI (and:DI (plus:DI (match_dup 2) (const_int -1)) | |
1433 | (const_int -8)))) | |
1434 | (set (match_dup 4) | |
1435 | (ashift:DI (match_dup 3) | |
786d6092 | 1436 | (minus:DI (const_int 64) |
2206e904 | 1437 | (ashift:DI |
786d6092 | 1438 | (and:DI (match_dup 2) (const_int 7)) |
2206e904 RK |
1439 | (const_int 3))))) |
1440 | (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) | |
1441 | (ashiftrt:DI (match_dup 4) (const_int 56)))] | |
1442 | "" | |
1443 | " | |
1444 | { operands[2] = gen_reg_rtx (DImode); | |
1445 | operands[3] = gen_reg_rtx (DImode); | |
1446 | operands[4] = gen_reg_rtx (DImode); | |
1447 | }") | |
1448 | ||
1449 | (define_expand "unaligned_extendhidi" | |
1450 | [(set (match_dup 2) (match_operand:DI 1 "address_operand" "")) | |
1451 | (set (match_dup 3) | |
1452 | (mem:DI (and:DI (plus:DI (match_dup 2) (const_int -2)) | |
1453 | (const_int -8)))) | |
1454 | (set (match_dup 4) | |
1455 | (ashift:DI (match_dup 3) | |
786d6092 | 1456 | (minus:DI (const_int 64) |
2206e904 | 1457 | (ashift:DI |
786d6092 | 1458 | (and:DI (match_dup 2) (const_int 7)) |
2206e904 RK |
1459 | (const_int 3))))) |
1460 | (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) | |
1461 | (ashiftrt:DI (match_dup 4) (const_int 48)))] | |
1462 | "" | |
1463 | " | |
1464 | { operands[2] = gen_reg_rtx (DImode); | |
1465 | operands[3] = gen_reg_rtx (DImode); | |
1466 | operands[4] = gen_reg_rtx (DImode); | |
1467 | }") | |
1468 | ||
36f8f642 RK |
1469 | (define_insn "" |
1470 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1471 | (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") | |
1472 | (match_operand:DI 2 "mode_width_operand" "n") | |
1473 | (match_operand:DI 3 "mul8_operand" "I")))] | |
1474 | "" | |
745466f2 RK |
1475 | "ext%M2l %r1,%s3,%0" |
1476 | [(set_attr "type" "shift")]) | |
36f8f642 | 1477 | |
6c174fc0 | 1478 | (define_insn "extxl" |
36f8f642 RK |
1479 | [(set (match_operand:DI 0 "register_operand" "=r") |
1480 | (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") | |
1481 | (match_operand:DI 2 "mode_width_operand" "n") | |
1482 | (ashift:DI (match_operand:DI 3 "reg_or_8bit_operand" "rI") | |
1483 | (const_int 3))))] | |
1484 | "" | |
745466f2 RK |
1485 | "ext%M2l %r1,%3,%0" |
1486 | [(set_attr "type" "shift")]) | |
36f8f642 | 1487 | |
b08b85c4 RH |
1488 | ;; Combine has some strange notion of preserving existing undefined behaviour |
1489 | ;; in shifts larger than a word size. So capture these patterns that it | |
1490 | ;; should have turned into zero_extracts. | |
1491 | ||
1492 | (define_insn "" | |
1493 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1494 | (and (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") | |
1495 | (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") | |
1496 | (const_int 3))) | |
1497 | (match_operand:DI 3 "mode_mask_operand" "n")))] | |
1498 | "" | |
1499 | "ext%U3l %1,%2,%0" | |
1500 | [(set_attr "type" "shift")]) | |
1501 | ||
1502 | (define_insn "" | |
1503 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1504 | (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") | |
1505 | (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") | |
1506 | (const_int 3))))] | |
1507 | "" | |
1508 | "extql %1,%2,%0" | |
1509 | [(set_attr "type" "shift")]) | |
1510 | ||
6c174fc0 | 1511 | (define_insn "extqh" |
36f8f642 RK |
1512 | [(set (match_operand:DI 0 "register_operand" "=r") |
1513 | (ashift:DI | |
2206e904 | 1514 | (match_operand:DI 1 "reg_or_0_operand" "rJ") |
786d6092 | 1515 | (minus:DI (const_int 64) |
2206e904 RK |
1516 | (ashift:DI |
1517 | (and:DI | |
786d6092 | 1518 | (match_operand:DI 2 "reg_or_8bit_operand" "rI") |
2206e904 RK |
1519 | (const_int 7)) |
1520 | (const_int 3)))))] | |
36f8f642 | 1521 | "" |
745466f2 RK |
1522 | "extqh %r1,%2,%0" |
1523 | [(set_attr "type" "shift")]) | |
36f8f642 | 1524 | |
6c174fc0 | 1525 | (define_insn "extlh" |
36f8f642 RK |
1526 | [(set (match_operand:DI 0 "register_operand" "=r") |
1527 | (ashift:DI | |
2206e904 RK |
1528 | (and:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") |
1529 | (const_int 2147483647)) | |
786d6092 | 1530 | (minus:DI (const_int 64) |
2206e904 RK |
1531 | (ashift:DI |
1532 | (and:DI | |
786d6092 | 1533 | (match_operand:DI 2 "reg_or_8bit_operand" "rI") |
2206e904 RK |
1534 | (const_int 7)) |
1535 | (const_int 3)))))] | |
36f8f642 | 1536 | "" |
745466f2 RK |
1537 | "extlh %r1,%2,%0" |
1538 | [(set_attr "type" "shift")]) | |
36f8f642 | 1539 | |
6c174fc0 | 1540 | (define_insn "extwh" |
36f8f642 RK |
1541 | [(set (match_operand:DI 0 "register_operand" "=r") |
1542 | (ashift:DI | |
2206e904 RK |
1543 | (and:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") |
1544 | (const_int 65535)) | |
786d6092 | 1545 | (minus:DI (const_int 64) |
2206e904 RK |
1546 | (ashift:DI |
1547 | (and:DI | |
786d6092 | 1548 | (match_operand:DI 2 "reg_or_8bit_operand" "rI") |
2206e904 RK |
1549 | (const_int 7)) |
1550 | (const_int 3)))))] | |
36f8f642 | 1551 | "" |
745466f2 RK |
1552 | "extwh %r1,%2,%0" |
1553 | [(set_attr "type" "shift")]) | |
2206e904 | 1554 | |
36f8f642 RK |
1555 | ;; This converts an extXl into an extXh with an appropriate adjustment |
1556 | ;; to the address calculation. | |
1557 | ||
2206e904 RK |
1558 | ;;(define_split |
1559 | ;; [(set (match_operand:DI 0 "register_operand" "") | |
1560 | ;; (ashift:DI (zero_extract:DI (match_operand:DI 1 "register_operand" "") | |
1561 | ;; (match_operand:DI 2 "mode_width_operand" "") | |
1562 | ;; (ashift:DI (match_operand:DI 3 "" "") | |
1563 | ;; (const_int 3))) | |
1564 | ;; (match_operand:DI 4 "const_int_operand" ""))) | |
1565 | ;; (clobber (match_operand:DI 5 "register_operand" ""))] | |
1566 | ;; "INTVAL (operands[4]) == 64 - INTVAL (operands[2])" | |
1567 | ;; [(set (match_dup 5) (match_dup 6)) | |
1568 | ;; (set (match_dup 0) | |
1569 | ;; (ashift:DI (zero_extract:DI (match_dup 1) (match_dup 2) | |
1570 | ;; (ashift:DI (plus:DI (match_dup 5) | |
1571 | ;; (match_dup 7)) | |
1572 | ;; (const_int 3))) | |
1573 | ;; (match_dup 4)))] | |
1574 | ;; " | |
1575 | ;;{ | |
1576 | ;; operands[6] = plus_constant (operands[3], | |
1577 | ;; INTVAL (operands[2]) / BITS_PER_UNIT); | |
1578 | ;; operands[7] = GEN_INT (- INTVAL (operands[2]) / BITS_PER_UNIT); | |
1579 | ;;}") | |
36f8f642 RK |
1580 | |
1581 | (define_insn "" | |
1582 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1583 | (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "r")) | |
1584 | (match_operand:DI 2 "mul8_operand" "I")))] | |
1585 | "" | |
745466f2 RK |
1586 | "insbl %1,%s2,%0" |
1587 | [(set_attr "type" "shift")]) | |
36f8f642 RK |
1588 | |
1589 | (define_insn "" | |
1590 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1591 | (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "r")) | |
1592 | (match_operand:DI 2 "mul8_operand" "I")))] | |
1593 | "" | |
745466f2 RK |
1594 | "inswl %1,%s2,%0" |
1595 | [(set_attr "type" "shift")]) | |
36f8f642 RK |
1596 | |
1597 | (define_insn "" | |
1598 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1599 | (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) | |
1600 | (match_operand:DI 2 "mul8_operand" "I")))] | |
1601 | "" | |
745466f2 RK |
1602 | "insll %1,%s2,%0" |
1603 | [(set_attr "type" "shift")]) | |
36f8f642 | 1604 | |
6c174fc0 | 1605 | (define_insn "insbl" |
36f8f642 RK |
1606 | [(set (match_operand:DI 0 "register_operand" "=r") |
1607 | (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "r")) | |
1608 | (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") | |
1609 | (const_int 3))))] | |
1610 | "" | |
745466f2 RK |
1611 | "insbl %1,%2,%0" |
1612 | [(set_attr "type" "shift")]) | |
36f8f642 | 1613 | |
6c174fc0 | 1614 | (define_insn "inswl" |
36f8f642 RK |
1615 | [(set (match_operand:DI 0 "register_operand" "=r") |
1616 | (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "r")) | |
1617 | (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") | |
1618 | (const_int 3))))] | |
1619 | "" | |
745466f2 RK |
1620 | "inswl %1,%2,%0" |
1621 | [(set_attr "type" "shift")]) | |
36f8f642 | 1622 | |
6c174fc0 | 1623 | (define_insn "insll" |
36f8f642 RK |
1624 | [(set (match_operand:DI 0 "register_operand" "=r") |
1625 | (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) | |
1626 | (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") | |
1627 | (const_int 3))))] | |
1628 | "" | |
745466f2 RK |
1629 | "insll %1,%2,%0" |
1630 | [(set_attr "type" "shift")]) | |
36f8f642 | 1631 | |
6c174fc0 RH |
1632 | (define_insn "insql" |
1633 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1634 | (ashift:DI (match_operand:DI 1 "register_operand" "r") | |
1635 | (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") | |
1636 | (const_int 3))))] | |
1637 | "" | |
1638 | "insql %1,%2,%0" | |
1639 | [(set_attr "type" "shift")]) | |
1640 | ||
989f090c RH |
1641 | ;; Combine has this sometimes habit of moving the and outside of the |
1642 | ;; shift, making life more interesting. | |
1643 | ||
1644 | (define_insn "" | |
1645 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1646 | (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r") | |
1647 | (match_operand:DI 2 "mul8_operand" "I")) | |
1648 | (match_operand:DI 3 "immediate_operand" "i")))] | |
1649 | "HOST_BITS_PER_WIDE_INT == 64 | |
1650 | && GET_CODE (operands[3]) == CONST_INT | |
1651 | && (((unsigned HOST_WIDE_INT) 0xff << INTVAL (operands[2]) | |
df45c7ea | 1652 | == (unsigned HOST_WIDE_INT) INTVAL (operands[3])) |
989f090c | 1653 | || ((unsigned HOST_WIDE_INT) 0xffff << INTVAL (operands[2]) |
df45c7ea | 1654 | == (unsigned HOST_WIDE_INT) INTVAL (operands[3])) |
989f090c | 1655 | || ((unsigned HOST_WIDE_INT) 0xffffffff << INTVAL (operands[2]) |
df45c7ea | 1656 | == (unsigned HOST_WIDE_INT) INTVAL (operands[3])))" |
989f090c RH |
1657 | "* |
1658 | { | |
1659 | #if HOST_BITS_PER_WIDE_INT == 64 | |
1660 | if ((unsigned HOST_WIDE_INT) 0xff << INTVAL (operands[2]) | |
df45c7ea | 1661 | == (unsigned HOST_WIDE_INT) INTVAL (operands[3])) |
989f090c RH |
1662 | return \"insbl %1,%s2,%0\"; |
1663 | if ((unsigned HOST_WIDE_INT) 0xffff << INTVAL (operands[2]) | |
df45c7ea | 1664 | == (unsigned HOST_WIDE_INT) INTVAL (operands[3])) |
989f090c RH |
1665 | return \"inswl %1,%s2,%0\"; |
1666 | if ((unsigned HOST_WIDE_INT) 0xffffffff << INTVAL (operands[2]) | |
df45c7ea | 1667 | == (unsigned HOST_WIDE_INT) INTVAL (operands[3])) |
989f090c RH |
1668 | return \"insll %1,%s2,%0\"; |
1669 | #endif | |
1670 | abort(); | |
1671 | }" | |
1672 | [(set_attr "type" "shift")]) | |
1673 | ||
36f8f642 RK |
1674 | ;; We do not include the insXh insns because they are complex to express |
1675 | ;; and it does not appear that we would ever want to generate them. | |
6c174fc0 RH |
1676 | ;; |
1677 | ;; Since we need them for block moves, though, cop out and use unspec. | |
36f8f642 | 1678 | |
6c174fc0 RH |
1679 | (define_insn "insxh" |
1680 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1681 | (unspec [(match_operand:DI 1 "register_operand" "r") | |
1682 | (match_operand:DI 2 "mode_width_operand" "n") | |
1683 | (match_operand:DI 3 "reg_or_8bit_operand" "rI")] 2))] | |
1684 | "" | |
1685 | "ins%M2h %1,%3,%0" | |
1686 | [(set_attr "type" "shift")]) | |
1687 | ||
1688 | (define_insn "mskxl" | |
36f8f642 | 1689 | [(set (match_operand:DI 0 "register_operand" "=r") |
027b95a6 RK |
1690 | (and:DI (not:DI (ashift:DI |
1691 | (match_operand:DI 2 "mode_mask_operand" "n") | |
1692 | (ashift:DI | |
1693 | (match_operand:DI 3 "reg_or_8bit_operand" "rI") | |
1694 | (const_int 3)))) | |
36f8f642 RK |
1695 | (match_operand:DI 1 "reg_or_0_operand" "rJ")))] |
1696 | "" | |
745466f2 RK |
1697 | "msk%U2l %r1,%3,%0" |
1698 | [(set_attr "type" "shift")]) | |
36f8f642 | 1699 | |
6c174fc0 RH |
1700 | ;; We do not include the mskXh insns because it does not appear we would |
1701 | ;; ever generate one. | |
1702 | ;; | |
1703 | ;; Again, we do for block moves and we use unspec again. | |
1704 | ||
1705 | (define_insn "mskxh" | |
1706 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1707 | (unspec [(match_operand:DI 1 "register_operand" "r") | |
1708 | (match_operand:DI 2 "mode_width_operand" "n") | |
1709 | (match_operand:DI 3 "reg_or_8bit_operand" "rI")] 3))] | |
1710 | "" | |
1711 | "msk%M2h %1,%3,%0" | |
1712 | [(set_attr "type" "shift")]) | |
36f8f642 RK |
1713 | \f |
1714 | ;; Floating-point operations. All the double-precision insns can extend | |
1715 | ;; from single, so indicate that. The exception are the ones that simply | |
1716 | ;; play with the sign bits; it's not clear what to do there. | |
1717 | ||
1718 | (define_insn "abssf2" | |
1719 | [(set (match_operand:SF 0 "register_operand" "=f") | |
1720 | (abs:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))] | |
5e4aab97 | 1721 | "TARGET_FP" |
36f8f642 | 1722 | "cpys $f31,%R1,%0" |
745466f2 | 1723 | [(set_attr "type" "fcpys")]) |
36f8f642 RK |
1724 | |
1725 | (define_insn "absdf2" | |
1726 | [(set (match_operand:DF 0 "register_operand" "=f") | |
1727 | (abs:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] | |
5e4aab97 | 1728 | "TARGET_FP" |
36f8f642 | 1729 | "cpys $f31,%R1,%0" |
745466f2 | 1730 | [(set_attr "type" "fcpys")]) |
36f8f642 RK |
1731 | |
1732 | (define_insn "negsf2" | |
1733 | [(set (match_operand:SF 0 "register_operand" "=f") | |
1734 | (neg:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))] | |
ea56ab2a | 1735 | "TARGET_FP" |
59e60927 | 1736 | "cpysn %R1,%R1,%0" |
745466f2 | 1737 | [(set_attr "type" "fadd")]) |
36f8f642 RK |
1738 | |
1739 | (define_insn "negdf2" | |
1740 | [(set (match_operand:DF 0 "register_operand" "=f") | |
1741 | (neg:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] | |
1742 | "TARGET_FP" | |
59e60927 | 1743 | "cpysn %R1,%R1,%0" |
745466f2 | 1744 | [(set_attr "type" "fadd")]) |
36f8f642 | 1745 | |
0d4ae18a RK |
1746 | (define_insn "" |
1747 | [(set (match_operand:SF 0 "register_operand" "=&f") | |
1748 | (plus:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") | |
1749 | (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] | |
981a828e | 1750 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
477c16e3 | 1751 | "add%,%)%& %R1,%R2,%0" |
745466f2 | 1752 | [(set_attr "type" "fadd") |
0d4ae18a RK |
1753 | (set_attr "trap" "yes")]) |
1754 | ||
36f8f642 RK |
1755 | (define_insn "addsf3" |
1756 | [(set (match_operand:SF 0 "register_operand" "=f") | |
1757 | (plus:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") | |
1758 | (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] | |
1759 | "TARGET_FP" | |
477c16e3 | 1760 | "add%,%)%& %R1,%R2,%0" |
745466f2 | 1761 | [(set_attr "type" "fadd") |
0d4ae18a RK |
1762 | (set_attr "trap" "yes")]) |
1763 | ||
1764 | (define_insn "" | |
1765 | [(set (match_operand:DF 0 "register_operand" "=&f") | |
1766 | (plus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") | |
1767 | (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] | |
981a828e | 1768 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
477c16e3 | 1769 | "add%-%)%& %R1,%R2,%0" |
745466f2 | 1770 | [(set_attr "type" "fadd") |
0d4ae18a | 1771 | (set_attr "trap" "yes")]) |
36f8f642 RK |
1772 | |
1773 | (define_insn "adddf3" | |
1774 | [(set (match_operand:DF 0 "register_operand" "=f") | |
1775 | (plus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") | |
1776 | (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] | |
1777 | "TARGET_FP" | |
477c16e3 | 1778 | "add%-%)%& %R1,%R2,%0" |
745466f2 | 1779 | [(set_attr "type" "fadd") |
0d4ae18a RK |
1780 | (set_attr "trap" "yes")]) |
1781 | ||
36f8f642 RK |
1782 | (define_insn "" |
1783 | [(set (match_operand:DF 0 "register_operand" "=f") | |
1784 | (plus:DF (float_extend:DF | |
55ff92b8 | 1785 | (match_operand:SF 1 "reg_or_fp0_operand" "fG")) |
36f8f642 | 1786 | (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] |
981a828e | 1787 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
477c16e3 | 1788 | "add%-%)%& %R1,%R2,%0" |
745466f2 | 1789 | [(set_attr "type" "fadd") |
0d4ae18a | 1790 | (set_attr "trap" "yes")]) |
36f8f642 RK |
1791 | |
1792 | (define_insn "" | |
1793 | [(set (match_operand:DF 0 "register_operand" "=f") | |
1794 | (plus:DF (float_extend:DF | |
1795 | (match_operand:SF 1 "reg_or_fp0_operand" "%fG")) | |
1796 | (float_extend:DF | |
1797 | (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] | |
981a828e | 1798 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
477c16e3 | 1799 | "add%-%)%& %R1,%R2,%0" |
745466f2 | 1800 | [(set_attr "type" "fadd") |
0d4ae18a | 1801 | (set_attr "trap" "yes")]) |
36f8f642 | 1802 | |
e83015a9 RH |
1803 | ;; Define conversion operators between DFmode and SImode, using the cvtql |
1804 | ;; instruction. To allow combine et al to do useful things, we keep the | |
1805 | ;; operation as a unit until after reload, at which point we split the | |
1806 | ;; instructions. | |
1ca2e73f RH |
1807 | ;; |
1808 | ;; Note that we (attempt to) only consider this optimization when the | |
1809 | ;; ultimate destination is memory. If we will be doing further integer | |
1810 | ;; processing, it is cheaper to do the truncation in the int regs. | |
1811 | ||
1812 | (define_insn "*cvtql" | |
1813 | [(set (match_operand:SI 0 "register_operand" "=f") | |
1814 | (unspec:SI [(match_operand:DI 1 "reg_or_fp0_operand" "fG")] 5))] | |
1815 | "TARGET_FP" | |
1816 | "cvtql%` %R1,%0" | |
1817 | [(set_attr "type" "fadd") | |
1818 | (set_attr "trap" "yes")]) | |
e83015a9 RH |
1819 | |
1820 | (define_split | |
1ca2e73f RH |
1821 | [(set (match_operand:SI 0 "memory_operand" "") |
1822 | (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "")) 0)) | |
1823 | (clobber (match_scratch:DI 2 "")) | |
1824 | (clobber (match_scratch:SI 3 ""))] | |
e83015a9 RH |
1825 | "TARGET_FP && reload_completed" |
1826 | [(set (match_dup 2) (fix:DI (match_dup 1))) | |
1ca2e73f RH |
1827 | (set (match_dup 3) (unspec:SI [(match_dup 2)] 5)) |
1828 | (set (match_dup 0) (match_dup 3))] | |
e83015a9 RH |
1829 | "") |
1830 | ||
e83015a9 | 1831 | (define_split |
1ca2e73f RH |
1832 | [(set (match_operand:SI 0 "memory_operand" "") |
1833 | (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "")) 0)) | |
1834 | (clobber (match_scratch:DI 2 ""))] | |
e83015a9 RH |
1835 | "TARGET_FP && reload_completed" |
1836 | [(set (match_dup 2) (fix:DI (match_dup 1))) | |
1ca2e73f RH |
1837 | (set (match_dup 3) (unspec:SI [(match_dup 2)] 5)) |
1838 | (set (match_dup 0) (match_dup 3))] | |
1839 | ;; Due to REG_CANNOT_CHANGE_SIZE issues, we cannot simply use SUBREG. | |
1840 | "operands[3] = gen_rtx_REG (SImode, REGNO (operands[2]));") | |
e83015a9 RH |
1841 | |
1842 | (define_insn "" | |
1ca2e73f RH |
1843 | [(set (match_operand:SI 0 "memory_operand" "=m") |
1844 | (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")) 0)) | |
1845 | (clobber (match_scratch:DI 2 "=&f")) | |
1846 | (clobber (match_scratch:SI 3 "=&f"))] | |
981a828e | 1847 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
e83015a9 RH |
1848 | "#" |
1849 | [(set_attr "type" "fadd") | |
1850 | (set_attr "trap" "yes")]) | |
1851 | ||
1852 | (define_insn "" | |
1ca2e73f RH |
1853 | [(set (match_operand:SI 0 "memory_operand" "=m") |
1854 | (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")) 0)) | |
1855 | (clobber (match_scratch:DI 2 "=f"))] | |
981a828e | 1856 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
e83015a9 RH |
1857 | "#" |
1858 | [(set_attr "type" "fadd") | |
1859 | (set_attr "trap" "yes")]) | |
1860 | ||
0022a940 | 1861 | (define_insn "" |
be5090b0 | 1862 | [(set (match_operand:DI 0 "reg_no_subreg_operand" "=&f") |
0022a940 | 1863 | (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] |
981a828e | 1864 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
0022a940 DMT |
1865 | "cvt%-q%(c %R1,%0" |
1866 | [(set_attr "type" "fadd") | |
1867 | (set_attr "trap" "yes")]) | |
1868 | ||
36f8f642 | 1869 | (define_insn "fix_truncdfdi2" |
be5090b0 | 1870 | [(set (match_operand:DI 0 "reg_no_subreg_operand" "=f") |
36f8f642 RK |
1871 | (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] |
1872 | "TARGET_FP" | |
0022a940 DMT |
1873 | "cvt%-q%(c %R1,%0" |
1874 | [(set_attr "type" "fadd") | |
1875 | (set_attr "trap" "yes")]) | |
1876 | ||
e83015a9 RH |
1877 | ;; Likewise between SFmode and SImode. |
1878 | ||
1879 | (define_split | |
1ca2e73f RH |
1880 | [(set (match_operand:SI 0 "memory_operand" "") |
1881 | (subreg:SI (fix:DI (float_extend:DF | |
1882 | (match_operand:SF 1 "reg_or_fp0_operand" ""))) 0)) | |
1883 | (clobber (match_scratch:DI 2 "")) | |
1884 | (clobber (match_scratch:SI 3 ""))] | |
e83015a9 RH |
1885 | "TARGET_FP && reload_completed" |
1886 | [(set (match_dup 2) (fix:DI (float_extend:DF (match_dup 1)))) | |
1ca2e73f RH |
1887 | (set (match_dup 3) (unspec:SI [(match_dup 2)] 5)) |
1888 | (set (match_dup 0) (match_dup 3))] | |
e83015a9 RH |
1889 | "") |
1890 | ||
e83015a9 | 1891 | (define_split |
1ca2e73f RH |
1892 | [(set (match_operand:SI 0 "memory_operand" "") |
1893 | (subreg:SI (fix:DI (float_extend:DF | |
1894 | (match_operand:SF 1 "reg_or_fp0_operand" ""))) 0)) | |
1895 | (clobber (match_scratch:DI 2 ""))] | |
e83015a9 RH |
1896 | "TARGET_FP && reload_completed" |
1897 | [(set (match_dup 2) (fix:DI (float_extend:DF (match_dup 1)))) | |
1ca2e73f RH |
1898 | (set (match_dup 3) (unspec:SI [(match_dup 2)] 5)) |
1899 | (set (match_dup 0) (match_dup 3))] | |
1900 | ;; Due to REG_CANNOT_CHANGE_SIZE issues, we cannot simply use SUBREG. | |
1901 | "operands[3] = gen_rtx_REG (SImode, REGNO (operands[2]));") | |
1902 | ||
1903 | (define_insn "" | |
1904 | [(set (match_operand:SI 0 "memory_operand" "=m") | |
1905 | (subreg:SI (fix:DI (float_extend:DF | |
1906 | (match_operand:SF 1 "reg_or_fp0_operand" "fG"))) 0)) | |
1907 | (clobber (match_scratch:DI 2 "=&f")) | |
1908 | (clobber (match_scratch:SI 3 "=&f"))] | |
981a828e | 1909 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
e83015a9 RH |
1910 | "#" |
1911 | [(set_attr "type" "fadd") | |
1912 | (set_attr "trap" "yes")]) | |
1913 | ||
1914 | (define_insn "" | |
1ca2e73f RH |
1915 | [(set (match_operand:SI 0 "memory_operand" "=m") |
1916 | (subreg:SI (fix:DI (float_extend:DF | |
1917 | (match_operand:SF 1 "reg_or_fp0_operand" "fG"))) 0)) | |
1918 | (clobber (match_scratch:DI 2 "=f"))] | |
981a828e | 1919 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
e83015a9 RH |
1920 | "#" |
1921 | [(set_attr "type" "fadd") | |
1922 | (set_attr "trap" "yes")]) | |
1923 | ||
0022a940 | 1924 | (define_insn "" |
be5090b0 | 1925 | [(set (match_operand:DI 0 "reg_no_subreg_operand" "=&f") |
0022a940 DMT |
1926 | (fix:DI (float_extend:DF |
1927 | (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))] | |
981a828e | 1928 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
0022a940 DMT |
1929 | "cvt%-q%(c %R1,%0" |
1930 | [(set_attr "type" "fadd") | |
1931 | (set_attr "trap" "yes")]) | |
36f8f642 RK |
1932 | |
1933 | (define_insn "fix_truncsfdi2" | |
be5090b0 | 1934 | [(set (match_operand:DI 0 "reg_no_subreg_operand" "=f") |
36f8f642 RK |
1935 | (fix:DI (float_extend:DF |
1936 | (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))] | |
1937 | "TARGET_FP" | |
0022a940 DMT |
1938 | "cvt%-q%(c %R1,%0" |
1939 | [(set_attr "type" "fadd") | |
1940 | (set_attr "trap" "yes")]) | |
36f8f642 | 1941 | |
8cf02b47 JW |
1942 | (define_insn "" |
1943 | [(set (match_operand:SF 0 "register_operand" "=&f") | |
67070f5c | 1944 | (float:SF (match_operand:DI 1 "reg_no_subreg_operand" "f")))] |
981a828e | 1945 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
8cf02b47 JW |
1946 | "cvtq%,%+%& %1,%0" |
1947 | [(set_attr "type" "fadd") | |
1948 | (set_attr "trap" "yes")]) | |
1949 | ||
36f8f642 RK |
1950 | (define_insn "floatdisf2" |
1951 | [(set (match_operand:SF 0 "register_operand" "=f") | |
67070f5c | 1952 | (float:SF (match_operand:DI 1 "reg_no_subreg_operand" "f")))] |
36f8f642 | 1953 | "TARGET_FP" |
477c16e3 | 1954 | "cvtq%,%+%& %1,%0" |
745466f2 | 1955 | [(set_attr "type" "fadd") |
0d4ae18a RK |
1956 | (set_attr "trap" "yes")]) |
1957 | ||
1958 | (define_insn "" | |
1959 | [(set (match_operand:DF 0 "register_operand" "=&f") | |
67070f5c | 1960 | (float:DF (match_operand:DI 1 "reg_no_subreg_operand" "f")))] |
981a828e | 1961 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
477c16e3 | 1962 | "cvtq%-%+%& %1,%0" |
745466f2 | 1963 | [(set_attr "type" "fadd") |
0d4ae18a | 1964 | (set_attr "trap" "yes")]) |
36f8f642 RK |
1965 | |
1966 | (define_insn "floatdidf2" | |
1967 | [(set (match_operand:DF 0 "register_operand" "=f") | |
67070f5c | 1968 | (float:DF (match_operand:DI 1 "reg_no_subreg_operand" "f")))] |
36f8f642 | 1969 | "TARGET_FP" |
477c16e3 | 1970 | "cvtq%-%+%& %1,%0" |
745466f2 | 1971 | [(set_attr "type" "fadd") |
0d4ae18a RK |
1972 | (set_attr "trap" "yes")]) |
1973 | ||
5556bc5b RK |
1974 | (define_expand "extendsfdf2" |
1975 | [(use (match_operand:DF 0 "register_operand" "")) | |
1976 | (use (match_operand:SF 1 "nonimmediate_operand" ""))] | |
1977 | "TARGET_FP" | |
1978 | " | |
1979 | { | |
981a828e | 1980 | if (alpha_fptm >= ALPHA_FPTM_SU) |
5556bc5b RK |
1981 | emit_insn (gen_extendsfdf2_tp (operands[0], |
1982 | force_reg (SFmode, operands[1]))); | |
1983 | else | |
1984 | emit_insn (gen_extendsfdf2_no_tp (operands[0], operands[1])); | |
1985 | ||
1986 | DONE; | |
1987 | }") | |
477c16e3 | 1988 | ;; FIXME |
5556bc5b RK |
1989 | (define_insn "extendsfdf2_tp" |
1990 | [(set (match_operand:DF 0 "register_operand" "=&f") | |
1991 | (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] | |
981a828e | 1992 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
5556bc5b RK |
1993 | "cvtsts %1,%0" |
1994 | [(set_attr "type" "fadd") | |
0d4ae18a | 1995 | (set_attr "trap" "yes")]) |
36f8f642 | 1996 | |
5556bc5b | 1997 | (define_insn "extendsfdf2_no_tp" |
70ee78ec RK |
1998 | [(set (match_operand:DF 0 "register_operand" "=f,f,m") |
1999 | (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "f,m,f")))] | |
981a828e | 2000 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
36f8f642 | 2001 | "@ |
6ce652e0 | 2002 | fmov %1,%0 |
70ee78ec RK |
2003 | ld%, %0,%1 |
2004 | st%- %1,%0" | |
71d9b493 | 2005 | [(set_attr "type" "fcpys,fld,fst") |
0d4ae18a RK |
2006 | (set_attr "trap" "yes")]) |
2007 | ||
2008 | (define_insn "" | |
2009 | [(set (match_operand:SF 0 "register_operand" "=&f") | |
2010 | (float_truncate:SF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] | |
981a828e | 2011 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
477c16e3 | 2012 | "cvt%-%,%)%& %R1,%0" |
745466f2 | 2013 | [(set_attr "type" "fadd") |
0d4ae18a | 2014 | (set_attr "trap" "yes")]) |
36f8f642 RK |
2015 | |
2016 | (define_insn "truncdfsf2" | |
2017 | [(set (match_operand:SF 0 "register_operand" "=f") | |
2018 | (float_truncate:SF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] | |
2019 | "TARGET_FP" | |
477c16e3 | 2020 | "cvt%-%,%)%& %R1,%0" |
745466f2 | 2021 | [(set_attr "type" "fadd") |
0d4ae18a RK |
2022 | (set_attr "trap" "yes")]) |
2023 | ||
2024 | (define_insn "" | |
2025 | [(set (match_operand:SF 0 "register_operand" "=&f") | |
2026 | (div:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") | |
2027 | (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] | |
981a828e | 2028 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
477c16e3 | 2029 | "div%,%)%& %R1,%R2,%0" |
71d9b493 RH |
2030 | [(set_attr "type" "fdiv") |
2031 | (set_attr "opsize" "si") | |
0d4ae18a | 2032 | (set_attr "trap" "yes")]) |
36f8f642 RK |
2033 | |
2034 | (define_insn "divsf3" | |
2035 | [(set (match_operand:SF 0 "register_operand" "=f") | |
2036 | (div:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") | |
2037 | (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] | |
2038 | "TARGET_FP" | |
477c16e3 | 2039 | "div%,%)%& %R1,%R2,%0" |
71d9b493 RH |
2040 | [(set_attr "type" "fdiv") |
2041 | (set_attr "opsize" "si") | |
0d4ae18a RK |
2042 | (set_attr "trap" "yes")]) |
2043 | ||
2044 | (define_insn "" | |
2045 | [(set (match_operand:DF 0 "register_operand" "=&f") | |
2046 | (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") | |
2047 | (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] | |
981a828e | 2048 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
477c16e3 | 2049 | "div%-%)%& %R1,%R2,%0" |
71d9b493 | 2050 | [(set_attr "type" "fdiv") |
0d4ae18a | 2051 | (set_attr "trap" "yes")]) |
36f8f642 RK |
2052 | |
2053 | (define_insn "divdf3" | |
2054 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2055 | (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") | |
2056 | (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] | |
2057 | "TARGET_FP" | |
477c16e3 | 2058 | "div%-%)%& %R1,%R2,%0" |
71d9b493 | 2059 | [(set_attr "type" "fdiv") |
0d4ae18a RK |
2060 | (set_attr "trap" "yes")]) |
2061 | ||
36f8f642 RK |
2062 | (define_insn "" |
2063 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2064 | (div:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG")) | |
2065 | (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] | |
981a828e | 2066 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
477c16e3 | 2067 | "div%-%)%& %R1,%R2,%0" |
71d9b493 | 2068 | [(set_attr "type" "fdiv") |
0d4ae18a | 2069 | (set_attr "trap" "yes")]) |
36f8f642 RK |
2070 | |
2071 | (define_insn "" | |
2072 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2073 | (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") | |
2074 | (float_extend:DF | |
2075 | (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] | |
981a828e | 2076 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
477c16e3 | 2077 | "div%-%)%& %R1,%R2,%0" |
71d9b493 | 2078 | [(set_attr "type" "fdiv") |
0d4ae18a | 2079 | (set_attr "trap" "yes")]) |
36f8f642 RK |
2080 | |
2081 | (define_insn "" | |
2082 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2083 | (div:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG")) | |
2084 | (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] | |
981a828e | 2085 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
477c16e3 | 2086 | "div%-%)%& %R1,%R2,%0" |
71d9b493 | 2087 | [(set_attr "type" "fdiv") |
0d4ae18a RK |
2088 | (set_attr "trap" "yes")]) |
2089 | ||
2090 | (define_insn "" | |
2091 | [(set (match_operand:SF 0 "register_operand" "=&f") | |
2092 | (mult:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") | |
2093 | (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] | |
981a828e | 2094 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
477c16e3 | 2095 | "mul%,%)%& %R1,%R2,%0" |
745466f2 | 2096 | [(set_attr "type" "fmul") |
0d4ae18a | 2097 | (set_attr "trap" "yes")]) |
36f8f642 RK |
2098 | |
2099 | (define_insn "mulsf3" | |
2100 | [(set (match_operand:SF 0 "register_operand" "=f") | |
55ff92b8 | 2101 | (mult:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") |
36f8f642 RK |
2102 | (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] |
2103 | "TARGET_FP" | |
477c16e3 | 2104 | "mul%,%)%& %R1,%R2,%0" |
745466f2 | 2105 | [(set_attr "type" "fmul") |
0d4ae18a RK |
2106 | (set_attr "trap" "yes")]) |
2107 | ||
2108 | (define_insn "" | |
2109 | [(set (match_operand:DF 0 "register_operand" "=&f") | |
2110 | (mult:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") | |
2111 | (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] | |
981a828e | 2112 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
477c16e3 | 2113 | "mul%-%)%& %R1,%R2,%0" |
745466f2 | 2114 | [(set_attr "type" "fmul") |
0d4ae18a | 2115 | (set_attr "trap" "yes")]) |
36f8f642 RK |
2116 | |
2117 | (define_insn "muldf3" | |
2118 | [(set (match_operand:DF 0 "register_operand" "=f") | |
55ff92b8 | 2119 | (mult:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") |
36f8f642 RK |
2120 | (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] |
2121 | "TARGET_FP" | |
477c16e3 | 2122 | "mul%-%)%& %R1,%R2,%0" |
745466f2 | 2123 | [(set_attr "type" "fmul") |
0d4ae18a RK |
2124 | (set_attr "trap" "yes")]) |
2125 | ||
36f8f642 RK |
2126 | (define_insn "" |
2127 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2128 | (mult:DF (float_extend:DF | |
2129 | (match_operand:SF 1 "reg_or_fp0_operand" "fG")) | |
2130 | (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] | |
981a828e | 2131 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
477c16e3 | 2132 | "mul%-%)%& %R1,%R2,%0" |
745466f2 | 2133 | [(set_attr "type" "fmul") |
0d4ae18a | 2134 | (set_attr "trap" "yes")]) |
36f8f642 RK |
2135 | |
2136 | (define_insn "" | |
2137 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2138 | (mult:DF (float_extend:DF | |
55ff92b8 | 2139 | (match_operand:SF 1 "reg_or_fp0_operand" "%fG")) |
36f8f642 RK |
2140 | (float_extend:DF |
2141 | (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] | |
981a828e | 2142 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
477c16e3 | 2143 | "mul%-%)%& %R1,%R2,%0" |
745466f2 | 2144 | [(set_attr "type" "fmul") |
0d4ae18a RK |
2145 | (set_attr "trap" "yes")]) |
2146 | ||
2147 | (define_insn "" | |
2148 | [(set (match_operand:SF 0 "register_operand" "=&f") | |
2149 | (minus:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") | |
2150 | (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] | |
981a828e | 2151 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
477c16e3 | 2152 | "sub%,%)%& %R1,%R2,%0" |
745466f2 | 2153 | [(set_attr "type" "fadd") |
0d4ae18a | 2154 | (set_attr "trap" "yes")]) |
36f8f642 RK |
2155 | |
2156 | (define_insn "subsf3" | |
2157 | [(set (match_operand:SF 0 "register_operand" "=f") | |
55ff92b8 | 2158 | (minus:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") |
36f8f642 RK |
2159 | (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] |
2160 | "TARGET_FP" | |
477c16e3 | 2161 | "sub%,%)%& %R1,%R2,%0" |
745466f2 | 2162 | [(set_attr "type" "fadd") |
0d4ae18a RK |
2163 | (set_attr "trap" "yes")]) |
2164 | ||
2165 | (define_insn "" | |
2166 | [(set (match_operand:DF 0 "register_operand" "=&f") | |
2167 | (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") | |
2168 | (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] | |
981a828e | 2169 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
477c16e3 | 2170 | "sub%-%)%& %R1,%R2,%0" |
745466f2 | 2171 | [(set_attr "type" "fadd") |
0d4ae18a | 2172 | (set_attr "trap" "yes")]) |
36f8f642 RK |
2173 | |
2174 | (define_insn "subdf3" | |
2175 | [(set (match_operand:DF 0 "register_operand" "=f") | |
55ff92b8 | 2176 | (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") |
36f8f642 RK |
2177 | (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] |
2178 | "TARGET_FP" | |
477c16e3 | 2179 | "sub%-%)%& %R1,%R2,%0" |
745466f2 | 2180 | [(set_attr "type" "fadd") |
0d4ae18a RK |
2181 | (set_attr "trap" "yes")]) |
2182 | ||
36f8f642 RK |
2183 | (define_insn "" |
2184 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2185 | (minus:DF (float_extend:DF | |
55ff92b8 | 2186 | (match_operand:SF 1 "reg_or_fp0_operand" "fG")) |
36f8f642 | 2187 | (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] |
981a828e | 2188 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
477c16e3 | 2189 | "sub%-%)%& %R1,%R2,%0" |
745466f2 | 2190 | [(set_attr "type" "fadd") |
0d4ae18a | 2191 | (set_attr "trap" "yes")]) |
36f8f642 RK |
2192 | |
2193 | (define_insn "" | |
2194 | [(set (match_operand:DF 0 "register_operand" "=f") | |
55ff92b8 | 2195 | (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") |
36f8f642 RK |
2196 | (float_extend:DF |
2197 | (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] | |
981a828e | 2198 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
477c16e3 | 2199 | "sub%-%)%& %R1,%R2,%0" |
745466f2 | 2200 | [(set_attr "type" "fadd") |
0d4ae18a | 2201 | (set_attr "trap" "yes")]) |
36f8f642 RK |
2202 | |
2203 | (define_insn "" | |
2204 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2205 | (minus:DF (float_extend:DF | |
55ff92b8 | 2206 | (match_operand:SF 1 "reg_or_fp0_operand" "fG")) |
36f8f642 RK |
2207 | (float_extend:DF |
2208 | (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] | |
981a828e | 2209 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
477c16e3 | 2210 | "sub%-%)%& %R1,%R2,%0" |
745466f2 | 2211 | [(set_attr "type" "fadd") |
0d4ae18a | 2212 | (set_attr "trap" "yes")]) |
e9a25f70 | 2213 | |
71d9b493 RH |
2214 | (define_insn "" |
2215 | [(set (match_operand:SF 0 "register_operand" "=&f") | |
2216 | (sqrt:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))] | |
981a828e | 2217 | "TARGET_FP && TARGET_FIX && alpha_fptm >= ALPHA_FPTM_SU" |
71d9b493 RH |
2218 | "sqrt%,%)%& %R1,%0" |
2219 | [(set_attr "type" "fsqrt") | |
2220 | (set_attr "opsize" "si") | |
2221 | (set_attr "trap" "yes")]) | |
2222 | ||
e9a25f70 JL |
2223 | (define_insn "sqrtsf2" |
2224 | [(set (match_operand:SF 0 "register_operand" "=f") | |
2225 | (sqrt:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))] | |
de4abb91 | 2226 | "TARGET_FP && TARGET_FIX" |
71d9b493 RH |
2227 | "sqrt%,%)%& %R1,%0" |
2228 | [(set_attr "type" "fsqrt") | |
2229 | (set_attr "opsize" "si") | |
e9a25f70 JL |
2230 | (set_attr "trap" "yes")]) |
2231 | ||
71d9b493 RH |
2232 | (define_insn "" |
2233 | [(set (match_operand:DF 0 "register_operand" "=&f") | |
e9a25f70 | 2234 | (sqrt:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] |
981a828e | 2235 | "TARGET_FP && TARGET_FIX && alpha_fptm >= ALPHA_FPTM_SU" |
71d9b493 RH |
2236 | "sqrt%-%)%& %R1,%0" |
2237 | [(set_attr "type" "fsqrt") | |
e9a25f70 JL |
2238 | (set_attr "trap" "yes")]) |
2239 | ||
71d9b493 | 2240 | (define_insn "sqrtdf2" |
e9a25f70 | 2241 | [(set (match_operand:DF 0 "register_operand" "=f") |
71d9b493 | 2242 | (sqrt:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] |
de4abb91 | 2243 | "TARGET_FP && TARGET_FIX" |
71d9b493 RH |
2244 | "sqrt%-%)%& %1,%0" |
2245 | [(set_attr "type" "fsqrt") | |
e9a25f70 | 2246 | (set_attr "trap" "yes")]) |
36f8f642 RK |
2247 | \f |
2248 | ;; Next are all the integer comparisons, and conditional moves and branches | |
2249 | ;; and some of the related define_expand's and define_split's. | |
2250 | ||
2251 | (define_insn "" | |
2252 | [(set (match_operand:DI 0 "register_operand" "=r") | |
2253 | (match_operator:DI 1 "alpha_comparison_operator" | |
2254 | [(match_operand:DI 2 "reg_or_0_operand" "rJ") | |
2255 | (match_operand:DI 3 "reg_or_8bit_operand" "rI")]))] | |
2256 | "" | |
2257 | "cmp%C1 %r2,%3,%0" | |
2258 | [(set_attr "type" "icmp")]) | |
2259 | ||
5e2a751a RK |
2260 | (define_insn "" |
2261 | [(set (match_operand:DI 0 "register_operand" "=r") | |
86ff8230 RK |
2262 | (match_operator:DI 1 "alpha_swapped_comparison_operator" |
2263 | [(match_operand:DI 2 "reg_or_8bit_operand" "rI") | |
2264 | (match_operand:DI 3 "reg_or_0_operand" "rJ")]))] | |
5e2a751a | 2265 | "" |
5148abe9 | 2266 | "cmp%c1 %r3,%2,%0" |
5e2a751a RK |
2267 | [(set_attr "type" "icmp")]) |
2268 | ||
2ee5c7a8 DE |
2269 | ;; This pattern exists so conditional moves of SImode values are handled. |
2270 | ;; Comparisons are still done in DImode though. | |
2271 | ||
2272 | (define_insn "" | |
2273 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") | |
141dba98 | 2274 | (if_then_else:SI |
2ee5c7a8 DE |
2275 | (match_operator 2 "signed_comparison_operator" |
2276 | [(match_operand:DI 3 "reg_or_0_operand" "rJ,rJ,J,J") | |
2277 | (match_operand:DI 4 "reg_or_0_operand" "J,J,rJ,rJ")]) | |
2278 | (match_operand:SI 1 "reg_or_8bit_operand" "rI,0,rI,0") | |
2279 | (match_operand:SI 5 "reg_or_8bit_operand" "0,rI,0,rI")))] | |
2280 | "operands[3] == const0_rtx || operands[4] == const0_rtx" | |
2281 | "@ | |
2282 | cmov%C2 %r3,%1,%0 | |
2283 | cmov%D2 %r3,%5,%0 | |
2284 | cmov%c2 %r4,%1,%0 | |
745466f2 | 2285 | cmov%d2 %r4,%5,%0" |
71d9b493 | 2286 | [(set_attr "type" "icmov")]) |
2ee5c7a8 | 2287 | |
36f8f642 | 2288 | (define_insn "" |
03af65c4 | 2289 | [(set (match_operand:DI 0 "register_operand" "=r,r,r,r") |
36f8f642 RK |
2290 | (if_then_else:DI |
2291 | (match_operator 2 "signed_comparison_operator" | |
03af65c4 RK |
2292 | [(match_operand:DI 3 "reg_or_0_operand" "rJ,rJ,J,J") |
2293 | (match_operand:DI 4 "reg_or_0_operand" "J,J,rJ,rJ")]) | |
2294 | (match_operand:DI 1 "reg_or_8bit_operand" "rI,0,rI,0") | |
2295 | (match_operand:DI 5 "reg_or_8bit_operand" "0,rI,0,rI")))] | |
2296 | "operands[3] == const0_rtx || operands[4] == const0_rtx" | |
36f8f642 RK |
2297 | "@ |
2298 | cmov%C2 %r3,%1,%0 | |
03af65c4 RK |
2299 | cmov%D2 %r3,%5,%0 |
2300 | cmov%c2 %r4,%1,%0 | |
745466f2 | 2301 | cmov%d2 %r4,%5,%0" |
71d9b493 | 2302 | [(set_attr "type" "icmov")]) |
36f8f642 RK |
2303 | |
2304 | (define_insn "" | |
2305 | [(set (match_operand:DI 0 "register_operand" "=r,r") | |
2306 | (if_then_else:DI | |
2307 | (eq (zero_extract:DI (match_operand:DI 2 "reg_or_0_operand" "rJ,rJ") | |
2308 | (const_int 1) | |
2309 | (const_int 0)) | |
2310 | (const_int 0)) | |
2311 | (match_operand:DI 1 "reg_or_8bit_operand" "rI,0") | |
2312 | (match_operand:DI 3 "reg_or_8bit_operand" "0,rI")))] | |
2313 | "" | |
2314 | "@ | |
2315 | cmovlbc %r2,%1,%0 | |
745466f2 | 2316 | cmovlbs %r2,%3,%0" |
71d9b493 | 2317 | [(set_attr "type" "icmov")]) |
36f8f642 RK |
2318 | |
2319 | (define_insn "" | |
2320 | [(set (match_operand:DI 0 "register_operand" "=r,r") | |
2321 | (if_then_else:DI | |
2322 | (ne (zero_extract:DI (match_operand:DI 2 "reg_or_0_operand" "rJ,rJ") | |
2323 | (const_int 1) | |
2324 | (const_int 0)) | |
2325 | (const_int 0)) | |
2326 | (match_operand:DI 1 "reg_or_8bit_operand" "rI,0") | |
2327 | (match_operand:DI 3 "reg_or_8bit_operand" "0,rI")))] | |
2328 | "" | |
2329 | "@ | |
2330 | cmovlbs %r2,%1,%0 | |
745466f2 | 2331 | cmovlbc %r2,%3,%0" |
71d9b493 | 2332 | [(set_attr "type" "icmov")]) |
36f8f642 | 2333 | |
36f8f642 RK |
2334 | ;; For ABS, we have two choices, depending on whether the input and output |
2335 | ;; registers are the same or not. | |
2336 | (define_expand "absdi2" | |
2337 | [(set (match_operand:DI 0 "register_operand" "") | |
2338 | (abs:DI (match_operand:DI 1 "register_operand" "")))] | |
2339 | "" | |
2340 | " | |
2341 | { if (rtx_equal_p (operands[0], operands[1])) | |
2342 | emit_insn (gen_absdi2_same (operands[0], gen_reg_rtx (DImode))); | |
2343 | else | |
2344 | emit_insn (gen_absdi2_diff (operands[0], operands[1])); | |
2345 | ||
2346 | DONE; | |
2347 | }") | |
2348 | ||
2349 | (define_expand "absdi2_same" | |
2350 | [(set (match_operand:DI 1 "register_operand" "") | |
2351 | (neg:DI (match_operand:DI 0 "register_operand" ""))) | |
2352 | (set (match_dup 0) | |
2353 | (if_then_else:DI (ge (match_dup 0) (const_int 0)) | |
2354 | (match_dup 0) | |
2355 | (match_dup 1)))] | |
2356 | "" | |
2357 | "") | |
2358 | ||
2359 | (define_expand "absdi2_diff" | |
2360 | [(set (match_operand:DI 0 "register_operand" "") | |
2361 | (neg:DI (match_operand:DI 1 "register_operand" ""))) | |
2362 | (set (match_dup 0) | |
2363 | (if_then_else:DI (lt (match_dup 1) (const_int 0)) | |
2364 | (match_dup 0) | |
2365 | (match_dup 1)))] | |
2366 | "" | |
2367 | "") | |
2368 | ||
2369 | (define_split | |
2370 | [(set (match_operand:DI 0 "register_operand" "") | |
2371 | (abs:DI (match_dup 0))) | |
2372 | (clobber (match_operand:DI 2 "register_operand" ""))] | |
2373 | "" | |
2374 | [(set (match_dup 1) (neg:DI (match_dup 0))) | |
2375 | (set (match_dup 0) (if_then_else:DI (ge (match_dup 0) (const_int 0)) | |
2376 | (match_dup 0) (match_dup 1)))] | |
2377 | "") | |
2378 | ||
2379 | (define_split | |
2380 | [(set (match_operand:DI 0 "register_operand" "") | |
2381 | (abs:DI (match_operand:DI 1 "register_operand" "")))] | |
2382 | "! rtx_equal_p (operands[0], operands[1])" | |
2383 | [(set (match_dup 0) (neg:DI (match_dup 1))) | |
2384 | (set (match_dup 0) (if_then_else:DI (lt (match_dup 1) (const_int 0)) | |
2385 | (match_dup 0) (match_dup 1)))] | |
2386 | "") | |
2387 | ||
2388 | (define_split | |
2389 | [(set (match_operand:DI 0 "register_operand" "") | |
2390 | (neg:DI (abs:DI (match_dup 0)))) | |
2391 | (clobber (match_operand:DI 2 "register_operand" ""))] | |
2392 | "" | |
2393 | [(set (match_dup 1) (neg:DI (match_dup 0))) | |
2394 | (set (match_dup 0) (if_then_else:DI (le (match_dup 0) (const_int 0)) | |
2395 | (match_dup 0) (match_dup 1)))] | |
2396 | "") | |
2397 | ||
2398 | (define_split | |
2399 | [(set (match_operand:DI 0 "register_operand" "") | |
2400 | (neg:DI (abs:DI (match_operand:DI 1 "register_operand" ""))))] | |
2401 | "! rtx_equal_p (operands[0], operands[1])" | |
2402 | [(set (match_dup 0) (neg:DI (match_dup 1))) | |
2403 | (set (match_dup 0) (if_then_else:DI (gt (match_dup 1) (const_int 0)) | |
2404 | (match_dup 0) (match_dup 1)))] | |
2405 | "") | |
2406 | ||
e9a25f70 JL |
2407 | (define_insn "sminqi3" |
2408 | [(set (match_operand:QI 0 "register_operand" "=r") | |
141dba98 | 2409 | (smin:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ") |
e9a25f70 JL |
2410 | (match_operand:QI 2 "reg_or_8bit_operand" "rI")))] |
2411 | "TARGET_MAX" | |
2412 | "minsb8 %r1,%2,%0" | |
26250081 | 2413 | [(set_attr "type" "mvi")]) |
e9a25f70 JL |
2414 | |
2415 | (define_insn "uminqi3" | |
2416 | [(set (match_operand:QI 0 "register_operand" "=r") | |
141dba98 | 2417 | (umin:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ") |
e9a25f70 JL |
2418 | (match_operand:QI 2 "reg_or_8bit_operand" "rI")))] |
2419 | "TARGET_MAX" | |
2420 | "minub8 %r1,%2,%0" | |
26250081 | 2421 | [(set_attr "type" "mvi")]) |
e9a25f70 JL |
2422 | |
2423 | (define_insn "smaxqi3" | |
2424 | [(set (match_operand:QI 0 "register_operand" "=r") | |
141dba98 | 2425 | (smax:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ") |
e9a25f70 JL |
2426 | (match_operand:QI 2 "reg_or_8bit_operand" "rI")))] |
2427 | "TARGET_MAX" | |
2428 | "maxsb8 %r1,%2,%0" | |
26250081 | 2429 | [(set_attr "type" "mvi")]) |
e9a25f70 JL |
2430 | |
2431 | (define_insn "umaxqi3" | |
2432 | [(set (match_operand:QI 0 "register_operand" "=r") | |
141dba98 | 2433 | (umax:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ") |
e9a25f70 JL |
2434 | (match_operand:QI 2 "reg_or_8bit_operand" "rI")))] |
2435 | "TARGET_MAX" | |
2436 | "maxub8 %r1,%2,%0" | |
26250081 | 2437 | [(set_attr "type" "mvi")]) |
e9a25f70 JL |
2438 | |
2439 | (define_insn "sminhi3" | |
2440 | [(set (match_operand:HI 0 "register_operand" "=r") | |
141dba98 | 2441 | (smin:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ") |
e9a25f70 JL |
2442 | (match_operand:HI 2 "reg_or_8bit_operand" "rI")))] |
2443 | "TARGET_MAX" | |
2444 | "minsw4 %r1,%2,%0" | |
26250081 | 2445 | [(set_attr "type" "mvi")]) |
e9a25f70 JL |
2446 | |
2447 | (define_insn "uminhi3" | |
2448 | [(set (match_operand:HI 0 "register_operand" "=r") | |
141dba98 | 2449 | (umin:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ") |
e9a25f70 JL |
2450 | (match_operand:HI 2 "reg_or_8bit_operand" "rI")))] |
2451 | "TARGET_MAX" | |
2452 | "minuw4 %r1,%2,%0" | |
26250081 | 2453 | [(set_attr "type" "mvi")]) |
e9a25f70 JL |
2454 | |
2455 | (define_insn "smaxhi3" | |
2456 | [(set (match_operand:HI 0 "register_operand" "=r") | |
141dba98 | 2457 | (smax:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ") |
e9a25f70 JL |
2458 | (match_operand:HI 2 "reg_or_8bit_operand" "rI")))] |
2459 | "TARGET_MAX" | |
2460 | "maxsw4 %r1,%2,%0" | |
26250081 | 2461 | [(set_attr "type" "mvi")]) |
e9a25f70 JL |
2462 | |
2463 | (define_insn "umaxhi3" | |
2464 | [(set (match_operand:HI 0 "register_operand" "=r") | |
141dba98 | 2465 | (umax:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ") |
e9a25f70 JL |
2466 | (match_operand:HI 2 "reg_or_8bit_operand" "rI")))] |
2467 | "TARGET_MAX" | |
2468 | "maxuw4 %r1,%2,%0" | |
2469 | [(set_attr "type" "shift")]) | |
2470 | ||
6412a77e | 2471 | (define_expand "smaxdi3" |
36f8f642 RK |
2472 | [(set (match_dup 3) |
2473 | (le:DI (match_operand:DI 1 "reg_or_0_operand" "") | |
2474 | (match_operand:DI 2 "reg_or_8bit_operand" ""))) | |
2475 | (set (match_operand:DI 0 "register_operand" "") | |
2476 | (if_then_else:DI (eq (match_dup 3) (const_int 0)) | |
2477 | (match_dup 1) (match_dup 2)))] | |
2478 | "" | |
2479 | " | |
2480 | { operands[3] = gen_reg_rtx (DImode); | |
2481 | }") | |
2482 | ||
2483 | (define_split | |
2484 | [(set (match_operand:DI 0 "register_operand" "") | |
2485 | (smax:DI (match_operand:DI 1 "reg_or_0_operand" "") | |
2486 | (match_operand:DI 2 "reg_or_8bit_operand" ""))) | |
2487 | (clobber (match_operand:DI 3 "register_operand" ""))] | |
2488 | "operands[2] != const0_rtx" | |
2489 | [(set (match_dup 3) (le:DI (match_dup 1) (match_dup 2))) | |
2490 | (set (match_dup 0) (if_then_else:DI (eq (match_dup 3) (const_int 0)) | |
2491 | (match_dup 1) (match_dup 2)))] | |
2492 | "") | |
2493 | ||
2494 | (define_insn "" | |
2495 | [(set (match_operand:DI 0 "register_operand" "=r") | |
2496 | (smax:DI (match_operand:DI 1 "register_operand" "0") | |
2497 | (const_int 0)))] | |
2498 | "" | |
745466f2 | 2499 | "cmovlt %0,0,%0" |
71d9b493 | 2500 | [(set_attr "type" "icmov")]) |
36f8f642 RK |
2501 | |
2502 | (define_expand "smindi3" | |
2503 | [(set (match_dup 3) | |
2504 | (lt:DI (match_operand:DI 1 "reg_or_0_operand" "") | |
2505 | (match_operand:DI 2 "reg_or_8bit_operand" ""))) | |
2506 | (set (match_operand:DI 0 "register_operand" "") | |
2507 | (if_then_else:DI (ne (match_dup 3) (const_int 0)) | |
2508 | (match_dup 1) (match_dup 2)))] | |
2509 | "" | |
2510 | " | |
2511 | { operands[3] = gen_reg_rtx (DImode); | |
2512 | }") | |
2513 | ||
2514 | (define_split | |
2515 | [(set (match_operand:DI 0 "register_operand" "") | |
2516 | (smin:DI (match_operand:DI 1 "reg_or_0_operand" "") | |
2517 | (match_operand:DI 2 "reg_or_8bit_operand" ""))) | |
2518 | (clobber (match_operand:DI 3 "register_operand" ""))] | |
2519 | "operands[2] != const0_rtx" | |
2520 | [(set (match_dup 3) (lt:DI (match_dup 1) (match_dup 2))) | |
2521 | (set (match_dup 0) (if_then_else:DI (ne (match_dup 3) (const_int 0)) | |
2522 | (match_dup 1) (match_dup 2)))] | |
2523 | "") | |
2524 | ||
2525 | (define_insn "" | |
2526 | [(set (match_operand:DI 0 "register_operand" "=r") | |
2527 | (smin:DI (match_operand:DI 1 "register_operand" "0") | |
2528 | (const_int 0)))] | |
2529 | "" | |
745466f2 | 2530 | "cmovgt %0,0,%0" |
71d9b493 | 2531 | [(set_attr "type" "icmov")]) |
36f8f642 RK |
2532 | |
2533 | (define_expand "umaxdi3" | |
2534 | [(set (match_dup 3) | |
2535 | (leu:DI (match_operand:DI 1 "reg_or_0_operand" "") | |
2536 | (match_operand:DI 2 "reg_or_8bit_operand" ""))) | |
2537 | (set (match_operand:DI 0 "register_operand" "") | |
2538 | (if_then_else:DI (eq (match_dup 3) (const_int 0)) | |
2539 | (match_dup 1) (match_dup 2)))] | |
2540 | "" | |
2541 | " | |
2542 | { operands[3] = gen_reg_rtx (DImode); | |
2543 | }") | |
2544 | ||
2545 | (define_split | |
2546 | [(set (match_operand:DI 0 "register_operand" "") | |
2547 | (umax:DI (match_operand:DI 1 "reg_or_0_operand" "") | |
2548 | (match_operand:DI 2 "reg_or_8bit_operand" ""))) | |
2549 | (clobber (match_operand:DI 3 "register_operand" ""))] | |
2550 | "operands[2] != const0_rtx" | |
2551 | [(set (match_dup 3) (leu:DI (match_dup 1) (match_dup 2))) | |
2552 | (set (match_dup 0) (if_then_else:DI (eq (match_dup 3) (const_int 0)) | |
2553 | (match_dup 1) (match_dup 2)))] | |
2554 | "") | |
2555 | ||
2556 | (define_expand "umindi3" | |
2557 | [(set (match_dup 3) | |
2558 | (ltu:DI (match_operand:DI 1 "reg_or_0_operand" "") | |
2559 | (match_operand:DI 2 "reg_or_8bit_operand" ""))) | |
2560 | (set (match_operand:DI 0 "register_operand" "") | |
2561 | (if_then_else:DI (ne (match_dup 3) (const_int 0)) | |
2562 | (match_dup 1) (match_dup 2)))] | |
2563 | "" | |
2564 | " | |
2565 | { operands[3] = gen_reg_rtx (DImode); | |
2566 | }") | |
2567 | ||
2568 | (define_split | |
2569 | [(set (match_operand:DI 0 "register_operand" "") | |
2570 | (umin:DI (match_operand:DI 1 "reg_or_0_operand" "") | |
2571 | (match_operand:DI 2 "reg_or_8bit_operand" ""))) | |
2572 | (clobber (match_operand:DI 3 "register_operand" ""))] | |
2573 | "operands[2] != const0_rtx" | |
2574 | [(set (match_dup 3) (ltu:DI (match_dup 1) (match_dup 2))) | |
2575 | (set (match_dup 0) (if_then_else:DI (ne (match_dup 3) (const_int 0)) | |
2576 | (match_dup 1) (match_dup 2)))] | |
2577 | "") | |
2578 | ||
2579 | (define_insn "" | |
2580 | [(set (pc) | |
2581 | (if_then_else | |
2582 | (match_operator 1 "signed_comparison_operator" | |
2583 | [(match_operand:DI 2 "reg_or_0_operand" "rJ") | |
2584 | (const_int 0)]) | |
2585 | (label_ref (match_operand 0 "" "")) | |
2586 | (pc)))] | |
2587 | "" | |
2588 | "b%C1 %r2,%0" | |
2589 | [(set_attr "type" "ibr")]) | |
2590 | ||
86ff8230 RK |
2591 | (define_insn "" |
2592 | [(set (pc) | |
2593 | (if_then_else | |
2594 | (match_operator 1 "signed_comparison_operator" | |
2595 | [(const_int 0) | |
2596 | (match_operand:DI 2 "register_operand" "r")]) | |
2597 | (label_ref (match_operand 0 "" "")) | |
2598 | (pc)))] | |
2599 | "" | |
2600 | "b%c1 %2,%0" | |
2601 | [(set_attr "type" "ibr")]) | |
2602 | ||
36f8f642 RK |
2603 | (define_insn "" |
2604 | [(set (pc) | |
2605 | (if_then_else | |
2606 | (ne (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") | |
2607 | (const_int 1) | |
2608 | (const_int 0)) | |
2609 | (const_int 0)) | |
2610 | (label_ref (match_operand 0 "" "")) | |
2611 | (pc)))] | |
2612 | "" | |
2613 | "blbs %r1,%0" | |
2614 | [(set_attr "type" "ibr")]) | |
2615 | ||
2616 | (define_insn "" | |
2617 | [(set (pc) | |
2618 | (if_then_else | |
2619 | (eq (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") | |
2620 | (const_int 1) | |
2621 | (const_int 0)) | |
2622 | (const_int 0)) | |
2623 | (label_ref (match_operand 0 "" "")) | |
2624 | (pc)))] | |
2625 | "" | |
2626 | "blbc %r1,%0" | |
2627 | [(set_attr "type" "ibr")]) | |
2628 | ||
2629 | (define_split | |
2630 | [(parallel | |
2631 | [(set (pc) | |
2632 | (if_then_else | |
2633 | (match_operator 1 "comparison_operator" | |
2634 | [(zero_extract:DI (match_operand:DI 2 "register_operand" "") | |
2635 | (const_int 1) | |
2636 | (match_operand:DI 3 "const_int_operand" "")) | |
2637 | (const_int 0)]) | |
2638 | (label_ref (match_operand 0 "" "")) | |
2639 | (pc))) | |
2640 | (clobber (match_operand:DI 4 "register_operand" ""))])] | |
2641 | "INTVAL (operands[3]) != 0" | |
2642 | [(set (match_dup 4) | |
2643 | (lshiftrt:DI (match_dup 2) (match_dup 3))) | |
2644 | (set (pc) | |
2645 | (if_then_else (match_op_dup 1 | |
2646 | [(zero_extract:DI (match_dup 4) | |
2647 | (const_int 1) | |
2648 | (const_int 0)) | |
2649 | (const_int 0)]) | |
2650 | (label_ref (match_dup 0)) | |
2651 | (pc)))] | |
2652 | "") | |
2653 | \f | |
2654 | ;; The following are the corresponding floating-point insns. Recall | |
2655 | ;; we need to have variants that expand the arguments from SF mode | |
2656 | ;; to DFmode. | |
2657 | ||
0d4ae18a RK |
2658 | (define_insn "" |
2659 | [(set (match_operand:DF 0 "register_operand" "=&f") | |
2660 | (match_operator:DF 1 "alpha_comparison_operator" | |
2661 | [(match_operand:DF 2 "reg_or_fp0_operand" "fG") | |
2662 | (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))] | |
981a828e | 2663 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
477c16e3 | 2664 | "cmp%-%C1%' %R2,%R3,%0" |
745466f2 | 2665 | [(set_attr "type" "fadd") |
0d4ae18a RK |
2666 | (set_attr "trap" "yes")]) |
2667 | ||
36f8f642 RK |
2668 | (define_insn "" |
2669 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2670 | (match_operator:DF 1 "alpha_comparison_operator" | |
2671 | [(match_operand:DF 2 "reg_or_fp0_operand" "fG") | |
2672 | (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))] | |
981a828e | 2673 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
477c16e3 | 2674 | "cmp%-%C1%' %R2,%R3,%0" |
745466f2 | 2675 | [(set_attr "type" "fadd") |
0d4ae18a | 2676 | (set_attr "trap" "yes")]) |
36f8f642 | 2677 | |
30e2dcbf RH |
2678 | (define_insn "" |
2679 | [(set (match_operand:DF 0 "register_operand" "=&f") | |
2680 | (match_operator:DF 1 "alpha_comparison_operator" | |
2681 | [(float_extend:DF | |
2682 | (match_operand:SF 2 "reg_or_fp0_operand" "fG")) | |
2683 | (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))] | |
981a828e | 2684 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
30e2dcbf RH |
2685 | "cmp%-%C1%' %R2,%R3,%0" |
2686 | [(set_attr "type" "fadd") | |
2687 | (set_attr "trap" "yes")]) | |
2688 | ||
36f8f642 RK |
2689 | (define_insn "" |
2690 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2691 | (match_operator:DF 1 "alpha_comparison_operator" | |
2692 | [(float_extend:DF | |
2693 | (match_operand:SF 2 "reg_or_fp0_operand" "fG")) | |
2694 | (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))] | |
981a828e | 2695 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
477c16e3 | 2696 | "cmp%-%C1%' %R2,%R3,%0" |
745466f2 | 2697 | [(set_attr "type" "fadd") |
0d4ae18a | 2698 | (set_attr "trap" "yes")]) |
36f8f642 | 2699 | |
30e2dcbf RH |
2700 | (define_insn "" |
2701 | [(set (match_operand:DF 0 "register_operand" "=&f") | |
2702 | (match_operator:DF 1 "alpha_comparison_operator" | |
2703 | [(match_operand:DF 2 "reg_or_fp0_operand" "fG") | |
2704 | (float_extend:DF | |
2705 | (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))] | |
981a828e | 2706 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
30e2dcbf RH |
2707 | "cmp%-%C1%' %R2,%R3,%0" |
2708 | [(set_attr "type" "fadd") | |
2709 | (set_attr "trap" "yes")]) | |
2710 | ||
36f8f642 RK |
2711 | (define_insn "" |
2712 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2713 | (match_operator:DF 1 "alpha_comparison_operator" | |
2714 | [(match_operand:DF 2 "reg_or_fp0_operand" "fG") | |
2715 | (float_extend:DF | |
2716 | (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))] | |
981a828e | 2717 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
477c16e3 | 2718 | "cmp%-%C1%' %R2,%R3,%0" |
745466f2 | 2719 | [(set_attr "type" "fadd") |
0d4ae18a | 2720 | (set_attr "trap" "yes")]) |
36f8f642 RK |
2721 | |
2722 | (define_insn "" | |
30e2dcbf | 2723 | [(set (match_operand:DF 0 "register_operand" "=&f") |
36f8f642 RK |
2724 | (match_operator:DF 1 "alpha_comparison_operator" |
2725 | [(float_extend:DF | |
2726 | (match_operand:SF 2 "reg_or_fp0_operand" "fG")) | |
2727 | (float_extend:DF | |
2728 | (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))] | |
981a828e | 2729 | "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" |
477c16e3 | 2730 | "cmp%-%C1%' %R2,%R3,%0" |
745466f2 | 2731 | [(set_attr "type" "fadd") |
0d4ae18a RK |
2732 | (set_attr "trap" "yes")]) |
2733 | ||
2734 | (define_insn "" | |
30e2dcbf RH |
2735 | [(set (match_operand:DF 0 "register_operand" "=f") |
2736 | (match_operator:DF 1 "alpha_comparison_operator" | |
2737 | [(float_extend:DF | |
2738 | (match_operand:SF 2 "reg_or_fp0_operand" "fG")) | |
2739 | (float_extend:DF | |
2740 | (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))] | |
981a828e | 2741 | "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" |
30e2dcbf RH |
2742 | "cmp%-%C1%' %R2,%R3,%0" |
2743 | [(set_attr "type" "fadd") | |
2744 | (set_attr "trap" "yes")]) | |
36f8f642 RK |
2745 | |
2746 | (define_insn "" | |
2747 | [(set (match_operand:DF 0 "register_operand" "=f,f") | |
2748 | (if_then_else:DF | |
2749 | (match_operator 3 "signed_comparison_operator" | |
2750 | [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG") | |
2751 | (match_operand:DF 2 "fp0_operand" "G,G")]) | |
2752 | (match_operand:DF 1 "reg_or_fp0_operand" "fG,0") | |
2753 | (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))] | |
30e2dcbf | 2754 | "TARGET_FP" |
0d4ae18a RK |
2755 | "@ |
2756 | fcmov%C3 %R4,%R1,%0 | |
2757 | fcmov%D3 %R4,%R5,%0" | |
71d9b493 | 2758 | [(set_attr "type" "fcmov")]) |
0d4ae18a | 2759 | |
36f8f642 RK |
2760 | (define_insn "" |
2761 | [(set (match_operand:SF 0 "register_operand" "=f,f") | |
2762 | (if_then_else:SF | |
2763 | (match_operator 3 "signed_comparison_operator" | |
2764 | [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG") | |
2765 | (match_operand:DF 2 "fp0_operand" "G,G")]) | |
2766 | (match_operand:SF 1 "reg_or_fp0_operand" "fG,0") | |
2767 | (match_operand:SF 5 "reg_or_fp0_operand" "0,fG")))] | |
30e2dcbf | 2768 | "TARGET_FP" |
0d4ae18a RK |
2769 | "@ |
2770 | fcmov%C3 %R4,%R1,%0 | |
2771 | fcmov%D3 %R4,%R5,%0" | |
71d9b493 | 2772 | [(set_attr "type" "fcmov")]) |
0d4ae18a | 2773 | |
36f8f642 RK |
2774 | (define_insn "" |
2775 | [(set (match_operand:DF 0 "register_operand" "=f,f") | |
2776 | (if_then_else:DF | |
2777 | (match_operator 3 "signed_comparison_operator" | |
161cca9a | 2778 | [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG") |
36f8f642 | 2779 | (match_operand:DF 2 "fp0_operand" "G,G")]) |
161cca9a | 2780 | (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG,0")) |
36f8f642 | 2781 | (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))] |
30e2dcbf | 2782 | "TARGET_FP" |
36f8f642 RK |
2783 | "@ |
2784 | fcmov%C3 %R4,%R1,%0 | |
2785 | fcmov%D3 %R4,%R5,%0" | |
71d9b493 | 2786 | [(set_attr "type" "fcmov")]) |
36f8f642 RK |
2787 | |
2788 | (define_insn "" | |
2789 | [(set (match_operand:DF 0 "register_operand" "=f,f") | |
2790 | (if_then_else:DF | |
2791 | (match_operator 3 "signed_comparison_operator" | |
2792 | [(float_extend:DF | |
2793 | (match_operand:SF 4 "reg_or_fp0_operand" "fG,fG")) | |
2794 | (match_operand:DF 2 "fp0_operand" "G,G")]) | |
2795 | (match_operand:DF 1 "reg_or_fp0_operand" "fG,0") | |
2796 | (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))] | |
30e2dcbf | 2797 | "TARGET_FP" |
0d4ae18a RK |
2798 | "@ |
2799 | fcmov%C3 %R4,%R1,%0 | |
2800 | fcmov%D3 %R4,%R5,%0" | |
71d9b493 | 2801 | [(set_attr "type" "fcmov")]) |
0d4ae18a | 2802 | |
36f8f642 RK |
2803 | (define_insn "" |
2804 | [(set (match_operand:SF 0 "register_operand" "=f,f") | |
2805 | (if_then_else:SF | |
2806 | (match_operator 3 "signed_comparison_operator" | |
2807 | [(float_extend:DF | |
2808 | (match_operand:SF 4 "reg_or_fp0_operand" "fG,fG")) | |
2809 | (match_operand:DF 2 "fp0_operand" "G,G")]) | |
2810 | (match_operand:SF 1 "reg_or_fp0_operand" "fG,0") | |
2811 | (match_operand:SF 5 "reg_or_fp0_operand" "0,fG")))] | |
30e2dcbf | 2812 | "TARGET_FP" |
0d4ae18a RK |
2813 | "@ |
2814 | fcmov%C3 %R4,%R1,%0 | |
2815 | fcmov%D3 %R4,%R5,%0" | |
71d9b493 | 2816 | [(set_attr "type" "fcmov")]) |
0d4ae18a | 2817 | |
36f8f642 RK |
2818 | (define_insn "" |
2819 | [(set (match_operand:DF 0 "register_operand" "=f,f") | |
2820 | (if_then_else:DF | |
2821 | (match_operator 3 "signed_comparison_operator" | |
2822 | [(float_extend:DF | |
2823 | (match_operand:SF 4 "reg_or_fp0_operand" "fG,fG")) | |
2824 | (match_operand:DF 2 "fp0_operand" "G,G")]) | |
2825 | (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG,0")) | |
2826 | (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))] | |
30e2dcbf | 2827 | "TARGET_FP" |
36f8f642 RK |
2828 | "@ |
2829 | fcmov%C3 %R4,%R1,%0 | |
2830 | fcmov%D3 %R4,%R5,%0" | |
71d9b493 | 2831 | [(set_attr "type" "fcmov")]) |
36f8f642 | 2832 | |
f1644e9a | 2833 | (define_expand "maxdf3" |
36f8f642 RK |
2834 | [(set (match_dup 3) |
2835 | (le:DF (match_operand:DF 1 "reg_or_fp0_operand" "") | |
2836 | (match_operand:DF 2 "reg_or_fp0_operand" ""))) | |
2837 | (set (match_operand:DF 0 "register_operand" "") | |
6db77abd | 2838 | (if_then_else:DF (eq (match_dup 3) (match_dup 4)) |
36f8f642 RK |
2839 | (match_dup 1) (match_dup 2)))] |
2840 | "TARGET_FP" | |
2841 | " | |
2842 | { operands[3] = gen_reg_rtx (DFmode); | |
6db77abd | 2843 | operands[4] = CONST0_RTX (DFmode); |
36f8f642 RK |
2844 | }") |
2845 | ||
f1644e9a | 2846 | (define_expand "mindf3" |
36f8f642 RK |
2847 | [(set (match_dup 3) |
2848 | (lt:DF (match_operand:DF 1 "reg_or_fp0_operand" "") | |
2849 | (match_operand:DF 2 "reg_or_fp0_operand" ""))) | |
2850 | (set (match_operand:DF 0 "register_operand" "") | |
6db77abd | 2851 | (if_then_else:DF (ne (match_dup 3) (match_dup 4)) |
36f8f642 RK |
2852 | (match_dup 1) (match_dup 2)))] |
2853 | "TARGET_FP" | |
2854 | " | |
2855 | { operands[3] = gen_reg_rtx (DFmode); | |
6db77abd | 2856 | operands[4] = CONST0_RTX (DFmode); |
36f8f642 RK |
2857 | }") |
2858 | ||
f1644e9a | 2859 | (define_expand "maxsf3" |
36f8f642 | 2860 | [(set (match_dup 3) |
2bbc163f | 2861 | (le:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "")) |
36f8f642 RK |
2862 | (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "")))) |
2863 | (set (match_operand:SF 0 "register_operand" "") | |
2bbc163f | 2864 | (if_then_else:SF (eq (match_dup 3) (match_dup 4)) |
36f8f642 RK |
2865 | (match_dup 1) (match_dup 2)))] |
2866 | "TARGET_FP" | |
2867 | " | |
2bbc163f RK |
2868 | { operands[3] = gen_reg_rtx (DFmode); |
2869 | operands[4] = CONST0_RTX (DFmode); | |
36f8f642 RK |
2870 | }") |
2871 | ||
f1644e9a | 2872 | (define_expand "minsf3" |
36f8f642 | 2873 | [(set (match_dup 3) |
2bbc163f | 2874 | (lt:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "")) |
36f8f642 RK |
2875 | (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "")))) |
2876 | (set (match_operand:SF 0 "register_operand" "") | |
6db77abd | 2877 | (if_then_else:SF (ne (match_dup 3) (match_dup 4)) |
36f8f642 RK |
2878 | (match_dup 1) (match_dup 2)))] |
2879 | "TARGET_FP" | |
2880 | " | |
2bbc163f RK |
2881 | { operands[3] = gen_reg_rtx (DFmode); |
2882 | operands[4] = CONST0_RTX (DFmode); | |
36f8f642 RK |
2883 | }") |
2884 | ||
2885 | (define_insn "" | |
2886 | [(set (pc) | |
2887 | (if_then_else | |
2888 | (match_operator 1 "signed_comparison_operator" | |
2889 | [(match_operand:DF 2 "reg_or_fp0_operand" "fG") | |
2890 | (match_operand:DF 3 "fp0_operand" "G")]) | |
2891 | (label_ref (match_operand 0 "" "")) | |
2892 | (pc)))] | |
2893 | "TARGET_FP" | |
2894 | "fb%C1 %R2,%0" | |
2895 | [(set_attr "type" "fbr")]) | |
2896 | ||
2897 | (define_insn "" | |
2898 | [(set (pc) | |
2899 | (if_then_else | |
2900 | (match_operator 1 "signed_comparison_operator" | |
2901 | [(float_extend:DF | |
2902 | (match_operand:SF 2 "reg_or_fp0_operand" "fG")) | |
2903 | (match_operand:DF 3 "fp0_operand" "G")]) | |
2904 | (label_ref (match_operand 0 "" "")) | |
2905 | (pc)))] | |
2906 | "TARGET_FP" | |
2907 | "fb%C1 %R2,%0" | |
2908 | [(set_attr "type" "fbr")]) | |
2909 | \f | |
2910 | ;; These are the main define_expand's used to make conditional branches | |
2911 | ;; and compares. | |
2912 | ||
2913 | (define_expand "cmpdf" | |
2914 | [(set (cc0) (compare (match_operand:DF 0 "reg_or_fp0_operand" "") | |
2915 | (match_operand:DF 1 "reg_or_fp0_operand" "")))] | |
0331e642 | 2916 | "TARGET_FP" |
36f8f642 RK |
2917 | " |
2918 | { | |
2919 | alpha_compare_op0 = operands[0]; | |
2920 | alpha_compare_op1 = operands[1]; | |
2921 | alpha_compare_fp_p = 1; | |
2922 | DONE; | |
2923 | }") | |
2924 | ||
2925 | (define_expand "cmpdi" | |
2926 | [(set (cc0) (compare (match_operand:DI 0 "reg_or_0_operand" "") | |
2927 | (match_operand:DI 1 "reg_or_8bit_operand" "")))] | |
2928 | "" | |
2929 | " | |
2930 | { | |
2931 | alpha_compare_op0 = operands[0]; | |
2932 | alpha_compare_op1 = operands[1]; | |
2933 | alpha_compare_fp_p = 0; | |
2934 | DONE; | |
2935 | }") | |
2936 | ||
2937 | (define_expand "beq" | |
f283421d RH |
2938 | [(set (pc) |
2939 | (if_then_else (match_dup 1) | |
36f8f642 RK |
2940 | (label_ref (match_operand 0 "" "")) |
2941 | (pc)))] | |
2942 | "" | |
f283421d | 2943 | "{ operands[1] = alpha_emit_conditional_branch (EQ); }") |
36f8f642 RK |
2944 | |
2945 | (define_expand "bne" | |
f283421d RH |
2946 | [(set (pc) |
2947 | (if_then_else (match_dup 1) | |
36f8f642 RK |
2948 | (label_ref (match_operand 0 "" "")) |
2949 | (pc)))] | |
2950 | "" | |
f283421d | 2951 | "{ operands[1] = alpha_emit_conditional_branch (NE); }") |
36f8f642 RK |
2952 | |
2953 | (define_expand "blt" | |
f283421d RH |
2954 | [(set (pc) |
2955 | (if_then_else (match_dup 1) | |
36f8f642 RK |
2956 | (label_ref (match_operand 0 "" "")) |
2957 | (pc)))] | |
2958 | "" | |
f283421d | 2959 | "{ operands[1] = alpha_emit_conditional_branch (LT); }") |
36f8f642 RK |
2960 | |
2961 | (define_expand "ble" | |
f283421d RH |
2962 | [(set (pc) |
2963 | (if_then_else (match_dup 1) | |
36f8f642 RK |
2964 | (label_ref (match_operand 0 "" "")) |
2965 | (pc)))] | |
2966 | "" | |
f283421d | 2967 | "{ operands[1] = alpha_emit_conditional_branch (LE); }") |
36f8f642 RK |
2968 | |
2969 | (define_expand "bgt" | |
f283421d RH |
2970 | [(set (pc) |
2971 | (if_then_else (match_dup 1) | |
36f8f642 RK |
2972 | (label_ref (match_operand 0 "" "")) |
2973 | (pc)))] | |
2974 | "" | |
f283421d | 2975 | "{ operands[1] = alpha_emit_conditional_branch (GT); }") |
36f8f642 RK |
2976 | |
2977 | (define_expand "bge" | |
f283421d RH |
2978 | [(set (pc) |
2979 | (if_then_else (match_dup 1) | |
36f8f642 RK |
2980 | (label_ref (match_operand 0 "" "")) |
2981 | (pc)))] | |
2982 | "" | |
f283421d | 2983 | "{ operands[1] = alpha_emit_conditional_branch (GE); }") |
36f8f642 RK |
2984 | |
2985 | (define_expand "bltu" | |
f283421d RH |
2986 | [(set (pc) |
2987 | (if_then_else (match_dup 1) | |
36f8f642 RK |
2988 | (label_ref (match_operand 0 "" "")) |
2989 | (pc)))] | |
2990 | "" | |
f283421d | 2991 | "{ operands[1] = alpha_emit_conditional_branch (LTU); }") |
36f8f642 RK |
2992 | |
2993 | (define_expand "bleu" | |
f283421d RH |
2994 | [(set (pc) |
2995 | (if_then_else (match_dup 1) | |
36f8f642 RK |
2996 | (label_ref (match_operand 0 "" "")) |
2997 | (pc)))] | |
2998 | "" | |
f283421d | 2999 | "{ operands[1] = alpha_emit_conditional_branch (LEU); }") |
36f8f642 RK |
3000 | |
3001 | (define_expand "bgtu" | |
f283421d RH |
3002 | [(set (pc) |
3003 | (if_then_else (match_dup 1) | |
36f8f642 RK |
3004 | (label_ref (match_operand 0 "" "")) |
3005 | (pc)))] | |
3006 | "" | |
f283421d | 3007 | "{ operands[1] = alpha_emit_conditional_branch (GTU); }") |
36f8f642 RK |
3008 | |
3009 | (define_expand "bgeu" | |
f283421d RH |
3010 | [(set (pc) |
3011 | (if_then_else (match_dup 1) | |
36f8f642 RK |
3012 | (label_ref (match_operand 0 "" "")) |
3013 | (pc)))] | |
3014 | "" | |
f283421d | 3015 | "{ operands[1] = alpha_emit_conditional_branch (GEU); }") |
36f8f642 RK |
3016 | |
3017 | (define_expand "seq" | |
3018 | [(set (match_operand:DI 0 "register_operand" "") | |
3019 | (match_dup 1))] | |
3020 | "" | |
3021 | " | |
3022 | { | |
3023 | if (alpha_compare_fp_p) | |
3024 | FAIL; | |
3025 | ||
38a448ca | 3026 | operands[1] = gen_rtx_EQ (DImode, alpha_compare_op0, alpha_compare_op1); |
36f8f642 RK |
3027 | }") |
3028 | ||
3029 | (define_expand "sne" | |
3030 | [(set (match_operand:DI 0 "register_operand" "") | |
3031 | (match_dup 1)) | |
3032 | (set (match_dup 0) (xor:DI (match_dup 0) (const_int 1)))] | |
3033 | "" | |
3034 | " | |
3035 | { | |
3036 | if (alpha_compare_fp_p) | |
3037 | FAIL; | |
3038 | ||
38a448ca | 3039 | operands[1] = gen_rtx_EQ (DImode, alpha_compare_op0, alpha_compare_op1); |
36f8f642 RK |
3040 | }") |
3041 | ||
3042 | (define_expand "slt" | |
3043 | [(set (match_operand:DI 0 "register_operand" "") | |
3044 | (match_dup 1))] | |
3045 | "" | |
3046 | " | |
3047 | { | |
3048 | if (alpha_compare_fp_p) | |
3049 | FAIL; | |
3050 | ||
38a448ca | 3051 | operands[1] = gen_rtx_LT (DImode, alpha_compare_op0, alpha_compare_op1); |
36f8f642 RK |
3052 | }") |
3053 | ||
3054 | (define_expand "sle" | |
3055 | [(set (match_operand:DI 0 "register_operand" "") | |
3056 | (match_dup 1))] | |
3057 | "" | |
3058 | " | |
3059 | { | |
3060 | if (alpha_compare_fp_p) | |
3061 | FAIL; | |
3062 | ||
38a448ca | 3063 | operands[1] = gen_rtx_LE (DImode, alpha_compare_op0, alpha_compare_op1); |
36f8f642 RK |
3064 | }") |
3065 | ||
3066 | (define_expand "sgt" | |
3067 | [(set (match_operand:DI 0 "register_operand" "") | |
3068 | (match_dup 1))] | |
3069 | "" | |
3070 | " | |
3071 | { | |
3072 | if (alpha_compare_fp_p) | |
3073 | FAIL; | |
3074 | ||
38a448ca RH |
3075 | operands[1] = gen_rtx_LT (DImode, force_reg (DImode, alpha_compare_op1), |
3076 | alpha_compare_op0); | |
36f8f642 RK |
3077 | }") |
3078 | ||
3079 | (define_expand "sge" | |
3080 | [(set (match_operand:DI 0 "register_operand" "") | |
3081 | (match_dup 1))] | |
3082 | "" | |
3083 | " | |
3084 | { | |
3085 | if (alpha_compare_fp_p) | |
3086 | FAIL; | |
3087 | ||
38a448ca RH |
3088 | operands[1] = gen_rtx_LE (DImode, force_reg (DImode, alpha_compare_op1), |
3089 | alpha_compare_op0); | |
36f8f642 RK |
3090 | }") |
3091 | ||
3092 | (define_expand "sltu" | |
3093 | [(set (match_operand:DI 0 "register_operand" "") | |
3094 | (match_dup 1))] | |
3095 | "" | |
3096 | " | |
3097 | { | |
3098 | if (alpha_compare_fp_p) | |
3099 | FAIL; | |
3100 | ||
38a448ca | 3101 | operands[1] = gen_rtx_LTU (DImode, alpha_compare_op0, alpha_compare_op1); |
36f8f642 RK |
3102 | }") |
3103 | ||
3104 | (define_expand "sleu" | |
3105 | [(set (match_operand:DI 0 "register_operand" "") | |
3106 | (match_dup 1))] | |
3107 | "" | |
3108 | " | |
3109 | { | |
3110 | if (alpha_compare_fp_p) | |
3111 | FAIL; | |
3112 | ||
38a448ca | 3113 | operands[1] = gen_rtx_LEU (DImode, alpha_compare_op0, alpha_compare_op1); |
36f8f642 RK |
3114 | }") |
3115 | ||
3116 | (define_expand "sgtu" | |
3117 | [(set (match_operand:DI 0 "register_operand" "") | |
3118 | (match_dup 1))] | |
3119 | "" | |
3120 | " | |
3121 | { | |
3122 | if (alpha_compare_fp_p) | |
3123 | FAIL; | |
3124 | ||
38a448ca RH |
3125 | operands[1] = gen_rtx_LTU (DImode, force_reg (DImode, alpha_compare_op1), |
3126 | alpha_compare_op0); | |
36f8f642 RK |
3127 | }") |
3128 | ||
3129 | (define_expand "sgeu" | |
3130 | [(set (match_operand:DI 0 "register_operand" "") | |
3131 | (match_dup 1))] | |
3132 | "" | |
3133 | " | |
3134 | { | |
3135 | if (alpha_compare_fp_p) | |
3136 | FAIL; | |
3137 | ||
38a448ca RH |
3138 | operands[1] = gen_rtx_LEU (DImode, force_reg (DImode, alpha_compare_op1), |
3139 | alpha_compare_op0); | |
36f8f642 RK |
3140 | }") |
3141 | \f | |
2ee5c7a8 DE |
3142 | ;; These are the main define_expand's used to make conditional moves. |
3143 | ||
3144 | (define_expand "movsicc" | |
3cabb540 | 3145 | [(set (match_operand:SI 0 "register_operand" "") |
c7dec7c2 | 3146 | (if_then_else:SI (match_operand 1 "comparison_operator" "") |
2ee5c7a8 DE |
3147 | (match_operand:SI 2 "reg_or_8bit_operand" "") |
3148 | (match_operand:SI 3 "reg_or_8bit_operand" "")))] | |
3149 | "" | |
3150 | " | |
3151 | { | |
3cabb540 | 3152 | if ((operands[1] = alpha_emit_conditional_move (operands[1], SImode)) == 0) |
2ee5c7a8 | 3153 | FAIL; |
2ee5c7a8 DE |
3154 | }") |
3155 | ||
3156 | (define_expand "movdicc" | |
3cabb540 RK |
3157 | [(set (match_operand:DI 0 "register_operand" "") |
3158 | (if_then_else:DI (match_operand 1 "comparison_operator" "") | |
2ee5c7a8 DE |
3159 | (match_operand:DI 2 "reg_or_8bit_operand" "") |
3160 | (match_operand:DI 3 "reg_or_8bit_operand" "")))] | |
3161 | "" | |
3162 | " | |
3163 | { | |
3cabb540 | 3164 | if ((operands[1] = alpha_emit_conditional_move (operands[1], DImode)) == 0) |
2ee5c7a8 | 3165 | FAIL; |
2ee5c7a8 DE |
3166 | }") |
3167 | ||
3168 | (define_expand "movsfcc" | |
3cabb540 RK |
3169 | [(set (match_operand:SF 0 "register_operand" "") |
3170 | (if_then_else:SF (match_operand 1 "comparison_operator" "") | |
3171 | (match_operand:SF 2 "reg_or_8bit_operand" "") | |
3172 | (match_operand:SF 3 "reg_or_8bit_operand" "")))] | |
2ee5c7a8 DE |
3173 | "" |
3174 | " | |
3175 | { | |
3cabb540 | 3176 | if ((operands[1] = alpha_emit_conditional_move (operands[1], SFmode)) == 0) |
2ee5c7a8 | 3177 | FAIL; |
2ee5c7a8 DE |
3178 | }") |
3179 | ||
3180 | (define_expand "movdfcc" | |
3cabb540 RK |
3181 | [(set (match_operand:DF 0 "register_operand" "") |
3182 | (if_then_else:DF (match_operand 1 "comparison_operator" "") | |
3183 | (match_operand:DF 2 "reg_or_8bit_operand" "") | |
3184 | (match_operand:DF 3 "reg_or_8bit_operand" "")))] | |
2ee5c7a8 DE |
3185 | "" |
3186 | " | |
3187 | { | |
3cabb540 | 3188 | if ((operands[1] = alpha_emit_conditional_move (operands[1], DFmode)) == 0) |
2ee5c7a8 | 3189 | FAIL; |
2ee5c7a8 DE |
3190 | }") |
3191 | \f | |
36f8f642 RK |
3192 | ;; These define_split definitions are used in cases when comparisons have |
3193 | ;; not be stated in the correct way and we need to reverse the second | |
3194 | ;; comparison. For example, x >= 7 has to be done as x < 6 with the | |
3195 | ;; comparison that tests the result being reversed. We have one define_split | |
3196 | ;; for each use of a comparison. They do not match valid insns and need | |
3197 | ;; not generate valid insns. | |
3198 | ;; | |
3199 | ;; We can also handle equality comparisons (and inequality comparisons in | |
26958509 RK |
3200 | ;; cases where the resulting add cannot overflow) by doing an add followed by |
3201 | ;; a comparison with zero. This is faster since the addition takes one | |
3202 | ;; less cycle than a compare when feeding into a conditional move. | |
3203 | ;; For this case, we also have an SImode pattern since we can merge the add | |
3204 | ;; and sign extend and the order doesn't matter. | |
36f8f642 RK |
3205 | ;; |
3206 | ;; We do not do this for floating-point, since it isn't clear how the "wrong" | |
3207 | ;; operation could have been generated. | |
3208 | ||
3209 | (define_split | |
3210 | [(set (match_operand:DI 0 "register_operand" "") | |
3211 | (if_then_else:DI | |
3212 | (match_operator 1 "comparison_operator" | |
3213 | [(match_operand:DI 2 "reg_or_0_operand" "") | |
3214 | (match_operand:DI 3 "reg_or_cint_operand" "")]) | |
3215 | (match_operand:DI 4 "reg_or_cint_operand" "") | |
3216 | (match_operand:DI 5 "reg_or_cint_operand" ""))) | |
3217 | (clobber (match_operand:DI 6 "register_operand" ""))] | |
3218 | "operands[3] != const0_rtx" | |
3219 | [(set (match_dup 6) (match_dup 7)) | |
3220 | (set (match_dup 0) | |
3221 | (if_then_else:DI (match_dup 8) (match_dup 4) (match_dup 5)))] | |
3222 | " | |
3223 | { enum rtx_code code = GET_CODE (operands[1]); | |
3224 | int unsignedp = (code == GEU || code == LEU || code == GTU || code == LTU); | |
3225 | ||
3226 | /* If we are comparing for equality with a constant and that constant | |
3227 | appears in the arm when the register equals the constant, use the | |
3228 | register since that is more likely to match (and to produce better code | |
3229 | if both would). */ | |
3230 | ||
3231 | if (code == EQ && GET_CODE (operands[3]) == CONST_INT | |
3232 | && rtx_equal_p (operands[4], operands[3])) | |
3233 | operands[4] = operands[2]; | |
3234 | ||
3235 | else if (code == NE && GET_CODE (operands[3]) == CONST_INT | |
3236 | && rtx_equal_p (operands[5], operands[3])) | |
3237 | operands[5] = operands[2]; | |
3238 | ||
26958509 RK |
3239 | if (code == NE || code == EQ |
3240 | || (extended_count (operands[2], DImode, unsignedp) >= 1 | |
3241 | && extended_count (operands[3], DImode, unsignedp) >= 1)) | |
36f8f642 | 3242 | { |
26958509 | 3243 | if (GET_CODE (operands[3]) == CONST_INT) |
38a448ca RH |
3244 | operands[7] = gen_rtx_PLUS (DImode, operands[2], |
3245 | GEN_INT (- INTVAL (operands[3]))); | |
26958509 | 3246 | else |
38a448ca | 3247 | operands[7] = gen_rtx_MINUS (DImode, operands[2], operands[3]); |
26958509 | 3248 | |
38a448ca | 3249 | operands[8] = gen_rtx_fmt_ee (code, VOIDmode, operands[6], const0_rtx); |
36f8f642 RK |
3250 | } |
3251 | ||
3252 | else if (code == EQ || code == LE || code == LT | |
3253 | || code == LEU || code == LTU) | |
3254 | { | |
38a448ca RH |
3255 | operands[7] = gen_rtx_fmt_ee (code, DImode, operands[2], operands[3]); |
3256 | operands[8] = gen_rtx_NE (VOIDmode, operands[6], const0_rtx); | |
36f8f642 RK |
3257 | } |
3258 | else | |
3259 | { | |
38a448ca RH |
3260 | operands[7] = gen_rtx_fmt_ee (reverse_condition (code), DImode, |
3261 | operands[2], operands[3]); | |
3262 | operands[8] = gen_rtx_EQ (VOIDmode, operands[6], const0_rtx); | |
36f8f642 RK |
3263 | } |
3264 | }") | |
3265 | ||
3266 | (define_split | |
3267 | [(set (match_operand:DI 0 "register_operand" "") | |
3268 | (if_then_else:DI | |
3269 | (match_operator 1 "comparison_operator" | |
3270 | [(match_operand:SI 2 "reg_or_0_operand" "") | |
26958509 | 3271 | (match_operand:SI 3 "reg_or_cint_operand" "")]) |
36f8f642 RK |
3272 | (match_operand:DI 4 "reg_or_8bit_operand" "") |
3273 | (match_operand:DI 5 "reg_or_8bit_operand" ""))) | |
3274 | (clobber (match_operand:DI 6 "register_operand" ""))] | |
26958509 RK |
3275 | "operands[3] != const0_rtx |
3276 | && (GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)" | |
36f8f642 RK |
3277 | [(set (match_dup 6) (match_dup 7)) |
3278 | (set (match_dup 0) | |
3279 | (if_then_else:DI (match_dup 8) (match_dup 4) (match_dup 5)))] | |
3280 | " | |
3281 | { enum rtx_code code = GET_CODE (operands[1]); | |
3282 | int unsignedp = (code == GEU || code == LEU || code == GTU || code == LTU); | |
26958509 | 3283 | rtx tem; |
36f8f642 RK |
3284 | |
3285 | if ((code != NE && code != EQ | |
3286 | && ! (extended_count (operands[2], DImode, unsignedp) >= 1 | |
3287 | && extended_count (operands[3], DImode, unsignedp) >= 1))) | |
3288 | FAIL; | |
3289 | ||
26958509 | 3290 | if (GET_CODE (operands[3]) == CONST_INT) |
38a448ca RH |
3291 | tem = gen_rtx_PLUS (SImode, operands[2], |
3292 | GEN_INT (- INTVAL (operands[3]))); | |
26958509 | 3293 | else |
38a448ca | 3294 | tem = gen_rtx_MINUS (SImode, operands[2], operands[3]); |
26958509 | 3295 | |
38a448ca RH |
3296 | operands[7] = gen_rtx_SIGN_EXTEND (DImode, tem); |
3297 | operands[8] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode, | |
3298 | operands[6], const0_rtx); | |
36f8f642 RK |
3299 | }") |
3300 | ||
3301 | (define_split | |
3302 | [(set (pc) | |
3303 | (if_then_else | |
3304 | (match_operator 1 "comparison_operator" | |
3305 | [(match_operand:DI 2 "reg_or_0_operand" "") | |
3306 | (match_operand:DI 3 "reg_or_cint_operand" "")]) | |
3307 | (label_ref (match_operand 0 "" "")) | |
3308 | (pc))) | |
3309 | (clobber (match_operand:DI 4 "register_operand" ""))] | |
3310 | "operands[3] != const0_rtx" | |
3311 | [(set (match_dup 4) (match_dup 5)) | |
3312 | (set (pc) (if_then_else (match_dup 6) (label_ref (match_dup 0)) (pc)))] | |
3313 | " | |
3314 | { enum rtx_code code = GET_CODE (operands[1]); | |
3315 | int unsignedp = (code == GEU || code == LEU || code == GTU || code == LTU); | |
3316 | ||
26958509 RK |
3317 | if (code == NE || code == EQ |
3318 | || (extended_count (operands[2], DImode, unsignedp) >= 1 | |
3319 | && extended_count (operands[3], DImode, unsignedp) >= 1)) | |
36f8f642 | 3320 | { |
26958509 | 3321 | if (GET_CODE (operands[3]) == CONST_INT) |
38a448ca RH |
3322 | operands[5] = gen_rtx_PLUS (DImode, operands[2], |
3323 | GEN_INT (- INTVAL (operands[3]))); | |
26958509 | 3324 | else |
38a448ca | 3325 | operands[5] = gen_rtx_MINUS (DImode, operands[2], operands[3]); |
26958509 | 3326 | |
38a448ca | 3327 | operands[6] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx); |
36f8f642 RK |
3328 | } |
3329 | ||
3330 | else if (code == EQ || code == LE || code == LT | |
3331 | || code == LEU || code == LTU) | |
3332 | { | |
38a448ca RH |
3333 | operands[5] = gen_rtx_fmt_ee (code, DImode, operands[2], operands[3]); |
3334 | operands[6] = gen_rtx_NE (VOIDmode, operands[4], const0_rtx); | |
36f8f642 RK |
3335 | } |
3336 | else | |
3337 | { | |
38a448ca RH |
3338 | operands[5] = gen_rtx_fmt_ee (reverse_condition (code), DImode, |
3339 | operands[2], operands[3]); | |
3340 | operands[6] = gen_rtx_EQ (VOIDmode, operands[4], const0_rtx); | |
36f8f642 RK |
3341 | } |
3342 | }") | |
3343 | ||
3344 | (define_split | |
3345 | [(set (pc) | |
3346 | (if_then_else | |
3347 | (match_operator 1 "comparison_operator" | |
3348 | [(match_operand:SI 2 "reg_or_0_operand" "") | |
3349 | (match_operand:SI 3 "const_int_operand" "")]) | |
3350 | (label_ref (match_operand 0 "" "")) | |
3351 | (pc))) | |
3352 | (clobber (match_operand:DI 4 "register_operand" ""))] | |
26958509 | 3353 | "operands[3] != const0_rtx |
36f8f642 RK |
3354 | && (GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)" |
3355 | [(set (match_dup 4) (match_dup 5)) | |
3356 | (set (pc) (if_then_else (match_dup 6) (label_ref (match_dup 0)) (pc)))] | |
3357 | " | |
26958509 RK |
3358 | { rtx tem; |
3359 | ||
3360 | if (GET_CODE (operands[3]) == CONST_INT) | |
38a448ca RH |
3361 | tem = gen_rtx_PLUS (SImode, operands[2], |
3362 | GEN_INT (- INTVAL (operands[3]))); | |
26958509 | 3363 | else |
38a448ca | 3364 | tem = gen_rtx_MINUS (SImode, operands[2], operands[3]); |
26958509 | 3365 | |
38a448ca RH |
3366 | operands[5] = gen_rtx_SIGN_EXTEND (DImode, tem); |
3367 | operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode, | |
3368 | operands[4], const0_rtx); | |
36f8f642 | 3369 | }") |
3797f4d4 | 3370 | |
1c2bdc60 | 3371 | ;; We can convert such things as "a > 0xffff" to "t = a & ~ 0xffff; t != 0". |
3797f4d4 RK |
3372 | ;; This eliminates one, and sometimes two, insns when the AND can be done |
3373 | ;; with a ZAP. | |
3374 | (define_split | |
3375 | [(set (match_operand:DI 0 "register_operand" "") | |
3376 | (match_operator 1 "comparison_operator" | |
3377 | [(match_operand:DI 2 "register_operand" "") | |
3378 | (match_operand:DI 3 "const_int_operand" "")])) | |
3379 | (clobber (match_operand:DI 4 "register_operand" ""))] | |
3380 | "exact_log2 (INTVAL (operands[3]) + 1) >= 0 | |
3381 | && (GET_CODE (operands[1]) == GTU | |
3382 | || GET_CODE (operands[1]) == LEU | |
3383 | || ((GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == LE) | |
3384 | && extended_count (operands[2], DImode, 1) > 0))" | |
1c2bdc60 RK |
3385 | [(set (match_dup 4) (and:DI (match_dup 2) (match_dup 5))) |
3386 | (set (match_dup 0) (match_dup 6))] | |
3797f4d4 RK |
3387 | " |
3388 | { | |
1c2bdc60 | 3389 | operands[5] = GEN_INT (~ INTVAL (operands[3])); |
38a448ca RH |
3390 | operands[6] = gen_rtx_fmt_ee (((GET_CODE (operands[1]) == GTU |
3391 | || GET_CODE (operands[1]) == GT) | |
3392 | ? NE : EQ), | |
3393 | DImode, operands[4], const0_rtx); | |
3797f4d4 | 3394 | }") |
36f8f642 | 3395 | \f |
55e70146 RK |
3396 | ;; Here are the CALL and unconditional branch insns. Calls on NT and OSF |
3397 | ;; work differently, so we have different patterns for each. | |
36f8f642 RK |
3398 | |
3399 | (define_expand "call" | |
55e70146 | 3400 | [(use (match_operand:DI 0 "" "")) |
477c16e3 RK |
3401 | (use (match_operand 1 "" "")) |
3402 | (use (match_operand 2 "" "")) | |
3403 | (use (match_operand 3 "" ""))] | |
55e70146 RK |
3404 | "" |
3405 | " | |
5421b3d0 | 3406 | { if (TARGET_WINDOWS_NT) |
55e70146 | 3407 | emit_call_insn (gen_call_nt (operands[0], operands[1])); |
477c16e3 RK |
3408 | else if (TARGET_OPEN_VMS) |
3409 | emit_call_insn (gen_call_vms (operands[0], operands[2])); | |
55e70146 RK |
3410 | else |
3411 | emit_call_insn (gen_call_osf (operands[0], operands[1])); | |
3412 | ||
3413 | DONE; | |
3414 | }") | |
3415 | ||
3416 | (define_expand "call_osf" | |
cc2394a4 | 3417 | [(parallel [(call (mem:DI (match_operand 0 "" "")) |
36f8f642 | 3418 | (match_operand 1 "" "")) |
cc2394a4 | 3419 | (clobber (reg:DI 27)) |
36f8f642 RK |
3420 | (clobber (reg:DI 26))])] |
3421 | "" | |
3422 | " | |
3423 | { if (GET_CODE (operands[0]) != MEM) | |
3424 | abort (); | |
36f8f642 | 3425 | |
cc2394a4 | 3426 | operands[0] = XEXP (operands[0], 0); |
36f8f642 | 3427 | |
cc2394a4 RK |
3428 | if (GET_CODE (operands[0]) != SYMBOL_REF |
3429 | && ! (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 27)) | |
3430 | { | |
38a448ca | 3431 | rtx tem = gen_rtx_REG (DImode, 27); |
cc2394a4 RK |
3432 | emit_move_insn (tem, operands[0]); |
3433 | operands[0] = tem; | |
3434 | } | |
36f8f642 RK |
3435 | }") |
3436 | ||
55e70146 | 3437 | (define_expand "call_nt" |
202f590e | 3438 | [(parallel [(call (mem:DI (match_operand 0 "" "")) |
55e70146 RK |
3439 | (match_operand 1 "" "")) |
3440 | (clobber (reg:DI 26))])] | |
3441 | "" | |
3442 | " | |
3443 | { if (GET_CODE (operands[0]) != MEM) | |
3444 | abort (); | |
55e70146 | 3445 | |
202f590e RH |
3446 | operands[0] = XEXP (operands[0], 0); |
3447 | if (GET_CODE (operands[0]) != SYMBOL_REF && GET_CODE (operands[0]) != REG) | |
3448 | operands[0] = force_reg (DImode, operands[0]); | |
55e70146 RK |
3449 | }") |
3450 | ||
477c16e3 RK |
3451 | ;; |
3452 | ;; call openvms/alpha | |
3453 | ;; op 0: symbol ref for called function | |
3454 | ;; op 1: next_arg_reg (argument information value for R25) | |
3455 | ;; | |
3456 | (define_expand "call_vms" | |
3457 | [(parallel [(call (mem:DI (match_operand 0 "" "")) | |
3458 | (match_operand 1 "" "")) | |
3459 | (use (match_dup 2)) | |
3460 | (use (reg:DI 25)) | |
3461 | (use (reg:DI 26)) | |
3462 | (clobber (reg:DI 27))])] | |
3463 | "" | |
3464 | " | |
3465 | { if (GET_CODE (operands[0]) != MEM) | |
3466 | abort (); | |
3467 | ||
3468 | operands[0] = XEXP (operands[0], 0); | |
3469 | ||
3470 | /* Always load AI with argument information, then handle symbolic and | |
3471 | indirect call differently. Load RA and set operands[2] to PV in | |
3472 | both cases. */ | |
3473 | ||
38a448ca | 3474 | emit_move_insn (gen_rtx_REG (DImode, 25), operands[1]); |
477c16e3 RK |
3475 | if (GET_CODE (operands[0]) == SYMBOL_REF) |
3476 | { | |
3477 | extern char *savealloc (); | |
a59fb797 | 3478 | char *linksym, *symbol = XSTR (operands[0], 0); |
477c16e3 RK |
3479 | rtx linkage; |
3480 | ||
a59fb797 KK |
3481 | if (*symbol == '*') |
3482 | symbol++; | |
3483 | linksym = savealloc (strlen (symbol) + 6); | |
3484 | ||
477c16e3 RK |
3485 | alpha_need_linkage (symbol, 0); |
3486 | ||
531ea24e RH |
3487 | linksym[0] = '$'; |
3488 | strcpy (linksym+1, symbol); | |
477c16e3 | 3489 | strcat (linksym, \"..lk\"); |
38a448ca | 3490 | linkage = gen_rtx_SYMBOL_REF (Pmode, linksym); |
477c16e3 | 3491 | |
38a448ca | 3492 | emit_move_insn (gen_rtx_REG (Pmode, 26), gen_rtx_MEM (Pmode, linkage)); |
477c16e3 RK |
3493 | |
3494 | operands[2] | |
38a448ca | 3495 | = validize_mem (gen_rtx_MEM (Pmode, plus_constant (linkage, 8))); |
477c16e3 RK |
3496 | } |
3497 | else | |
3498 | { | |
38a448ca RH |
3499 | emit_move_insn (gen_rtx_REG (Pmode, 26), |
3500 | gen_rtx_MEM (Pmode, plus_constant (operands[0], 8))); | |
477c16e3 RK |
3501 | |
3502 | operands[2] = operands[0]; | |
3503 | } | |
3504 | ||
3505 | }") | |
3506 | ||
36f8f642 | 3507 | (define_expand "call_value" |
55e70146 RK |
3508 | [(use (match_operand 0 "" "")) |
3509 | (use (match_operand:DI 1 "" "")) | |
477c16e3 RK |
3510 | (use (match_operand 2 "" "")) |
3511 | (use (match_operand 3 "" "")) | |
3512 | (use (match_operand 4 "" ""))] | |
55e70146 RK |
3513 | "" |
3514 | " | |
5421b3d0 | 3515 | { if (TARGET_WINDOWS_NT) |
55e70146 | 3516 | emit_call_insn (gen_call_value_nt (operands[0], operands[1], operands[2])); |
477c16e3 RK |
3517 | else if (TARGET_OPEN_VMS) |
3518 | emit_call_insn (gen_call_value_vms (operands[0], operands[1], | |
3519 | operands[3])); | |
55e70146 RK |
3520 | else |
3521 | emit_call_insn (gen_call_value_osf (operands[0], operands[1], | |
3522 | operands[2])); | |
3523 | DONE; | |
3524 | }") | |
3525 | ||
3526 | (define_expand "call_value_osf" | |
36f8f642 | 3527 | [(parallel [(set (match_operand 0 "" "") |
cc2394a4 | 3528 | (call (mem:DI (match_operand 1 "" "")) |
36f8f642 | 3529 | (match_operand 2 "" ""))) |
cc2394a4 | 3530 | (clobber (reg:DI 27)) |
36f8f642 RK |
3531 | (clobber (reg:DI 26))])] |
3532 | "" | |
3533 | " | |
3534 | { if (GET_CODE (operands[1]) != MEM) | |
3535 | abort (); | |
3536 | ||
3537 | operands[1] = XEXP (operands[1], 0); | |
3538 | ||
cc2394a4 RK |
3539 | if (GET_CODE (operands[1]) != SYMBOL_REF |
3540 | && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 27)) | |
3541 | { | |
38a448ca | 3542 | rtx tem = gen_rtx_REG (DImode, 27); |
cc2394a4 RK |
3543 | emit_move_insn (tem, operands[1]); |
3544 | operands[1] = tem; | |
3545 | } | |
36f8f642 RK |
3546 | }") |
3547 | ||
55e70146 RK |
3548 | (define_expand "call_value_nt" |
3549 | [(parallel [(set (match_operand 0 "" "") | |
202f590e | 3550 | (call (mem:DI (match_operand 1 "" "")) |
55e70146 RK |
3551 | (match_operand 2 "" ""))) |
3552 | (clobber (reg:DI 26))])] | |
3553 | "" | |
3554 | " | |
3555 | { if (GET_CODE (operands[1]) != MEM) | |
3556 | abort (); | |
3557 | ||
3558 | operands[1] = XEXP (operands[1], 0); | |
5b9ba539 | 3559 | if (GET_CODE (operands[1]) != SYMBOL_REF && GET_CODE (operands[1]) != REG) |
202f590e | 3560 | operands[1] = force_reg (DImode, operands[1]); |
55e70146 RK |
3561 | }") |
3562 | ||
477c16e3 RK |
3563 | (define_expand "call_value_vms" |
3564 | [(parallel [(set (match_operand 0 "" "") | |
3565 | (call (mem:DI (match_operand:DI 1 "" "")) | |
3566 | (match_operand 2 "" ""))) | |
3567 | (use (match_dup 3)) | |
3568 | (use (reg:DI 25)) | |
3569 | (use (reg:DI 26)) | |
3570 | (clobber (reg:DI 27))])] | |
3571 | "" | |
3572 | " | |
3573 | { if (GET_CODE (operands[1]) != MEM) | |
3574 | abort (); | |
3575 | ||
3576 | operands[1] = XEXP (operands[1], 0); | |
3577 | ||
3578 | /* Always load AI with argument information, then handle symbolic and | |
3579 | indirect call differently. Load RA and set operands[3] to PV in | |
3580 | both cases. */ | |
3581 | ||
38a448ca | 3582 | emit_move_insn (gen_rtx_REG (DImode, 25), operands[2]); |
477c16e3 RK |
3583 | if (GET_CODE (operands[1]) == SYMBOL_REF) |
3584 | { | |
3585 | extern char *savealloc (); | |
a59fb797 | 3586 | char *linksym, *symbol = XSTR (operands[1], 0); |
477c16e3 RK |
3587 | rtx linkage; |
3588 | ||
a59fb797 KK |
3589 | if (*symbol == '*') |
3590 | symbol++; | |
3591 | linksym = savealloc (strlen (symbol) + 6); | |
3592 | ||
477c16e3 | 3593 | alpha_need_linkage (symbol, 0); |
531ea24e RH |
3594 | linksym[0] = '$'; |
3595 | strcpy (linksym+1, symbol); | |
477c16e3 | 3596 | strcat (linksym, \"..lk\"); |
38a448ca | 3597 | linkage = gen_rtx_SYMBOL_REF (Pmode, linksym); |
477c16e3 | 3598 | |
38a448ca | 3599 | emit_move_insn (gen_rtx_REG (Pmode, 26), gen_rtx_MEM (Pmode, linkage)); |
477c16e3 RK |
3600 | |
3601 | operands[3] | |
38a448ca | 3602 | = validize_mem (gen_rtx_MEM (Pmode, plus_constant (linkage, 8))); |
477c16e3 RK |
3603 | } |
3604 | else | |
3605 | { | |
38a448ca RH |
3606 | emit_move_insn (gen_rtx_REG (Pmode, 26), |
3607 | gen_rtx_MEM (Pmode, plus_constant (operands[1], 8))); | |
477c16e3 RK |
3608 | |
3609 | operands[3] = operands[1]; | |
3610 | } | |
3611 | }") | |
3612 | ||
36f8f642 | 3613 | (define_insn "" |
cc2394a4 RK |
3614 | [(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,i")) |
3615 | (match_operand 1 "" "")) | |
3616 | (clobber (reg:DI 27)) | |
36f8f642 | 3617 | (clobber (reg:DI 26))] |
477c16e3 | 3618 | "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS" |
cc2394a4 RK |
3619 | "@ |
3620 | jsr $26,($27),0\;ldgp $29,0($26) | |
531ea24e | 3621 | bsr $26,$%0..ng |
cc2394a4 | 3622 | jsr $26,%0\;ldgp $29,0($26)" |
9c0e94a5 | 3623 | [(set_attr "type" "jsr") |
8cad673c | 3624 | (set_attr "length" "12,*,16")]) |
36f8f642 | 3625 | |
55e70146 | 3626 | (define_insn "" |
202f590e | 3627 | [(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,i")) |
55e70146 RK |
3628 | (match_operand 1 "" "")) |
3629 | (clobber (reg:DI 26))] | |
5421b3d0 | 3630 | "TARGET_WINDOWS_NT" |
55e70146 RK |
3631 | "@ |
3632 | jsr $26,(%0) | |
202f590e RH |
3633 | bsr $26,%0 |
3634 | jsr $26,%0" | |
9c0e94a5 RH |
3635 | [(set_attr "type" "jsr") |
3636 | (set_attr "length" "*,*,12")]) | |
55e70146 | 3637 | |
477c16e3 RK |
3638 | (define_insn "" |
3639 | [(call (mem:DI (match_operand:DI 0 "call_operand" "r,i")) | |
3640 | (match_operand 1 "" "")) | |
3641 | (use (match_operand:DI 2 "general_operand" "r,m")) | |
3642 | (use (reg:DI 25)) | |
3643 | (use (reg:DI 26)) | |
3644 | (clobber (reg:DI 27))] | |
3645 | "TARGET_OPEN_VMS" | |
3646 | "@ | |
6ce652e0 | 3647 | mov %2,$27\;jsr $26,0\;ldq $27,0($29) |
477c16e3 | 3648 | ldq $27,%2\;jsr $26,%0\;ldq $27,0($29)" |
9c0e94a5 RH |
3649 | [(set_attr "type" "jsr") |
3650 | (set_attr "length" "12,16")]) | |
477c16e3 | 3651 | |
36f8f642 | 3652 | (define_insn "" |
cc2394a4 RK |
3653 | [(set (match_operand 0 "register_operand" "=rf,rf,rf") |
3654 | (call (mem:DI (match_operand:DI 1 "call_operand" "r,R,i")) | |
36f8f642 | 3655 | (match_operand 2 "" ""))) |
cc2394a4 | 3656 | (clobber (reg:DI 27)) |
36f8f642 | 3657 | (clobber (reg:DI 26))] |
477c16e3 | 3658 | "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS" |
cc2394a4 RK |
3659 | "@ |
3660 | jsr $26,($27),0\;ldgp $29,0($26) | |
531ea24e | 3661 | bsr $26,$%1..ng |
cc2394a4 | 3662 | jsr $26,%1\;ldgp $29,0($26)" |
9c0e94a5 | 3663 | [(set_attr "type" "jsr") |
8cad673c | 3664 | (set_attr "length" "12,*,16")]) |
36f8f642 | 3665 | |
55e70146 | 3666 | (define_insn "" |
202f590e RH |
3667 | [(set (match_operand 0 "register_operand" "=rf,rf,rf") |
3668 | (call (mem:DI (match_operand:DI 1 "call_operand" "r,R,i")) | |
55e70146 RK |
3669 | (match_operand 2 "" ""))) |
3670 | (clobber (reg:DI 26))] | |
5421b3d0 | 3671 | "TARGET_WINDOWS_NT" |
55e70146 RK |
3672 | "@ |
3673 | jsr $26,(%1) | |
202f590e RH |
3674 | bsr $26,%1 |
3675 | jsr $26,%1" | |
9c0e94a5 RH |
3676 | [(set_attr "type" "jsr") |
3677 | (set_attr "length" "*,*,12")]) | |
55e70146 | 3678 | |
477c16e3 RK |
3679 | (define_insn "" |
3680 | [(set (match_operand 0 "register_operand" "") | |
3681 | (call (mem:DI (match_operand:DI 1 "call_operand" "r,i")) | |
3682 | (match_operand 2 "" ""))) | |
3683 | (use (match_operand:DI 3 "general_operand" "r,m")) | |
3684 | (use (reg:DI 25)) | |
3685 | (use (reg:DI 26)) | |
3686 | (clobber (reg:DI 27))] | |
3687 | "TARGET_OPEN_VMS" | |
3688 | "@ | |
6ce652e0 | 3689 | mov %3,$27\;jsr $26,0\;ldq $27,0($29) |
477c16e3 | 3690 | ldq $27,%3\;jsr $26,%1\;ldq $27,0($29)" |
9c0e94a5 RH |
3691 | [(set_attr "type" "jsr") |
3692 | (set_attr "length" "12,16")]) | |
477c16e3 | 3693 | |
e6f948e3 RK |
3694 | ;; Call subroutine returning any type. |
3695 | ||
3696 | (define_expand "untyped_call" | |
3697 | [(parallel [(call (match_operand 0 "" "") | |
3698 | (const_int 0)) | |
3699 | (match_operand 1 "" "") | |
3700 | (match_operand 2 "" "")])] | |
3701 | "" | |
3702 | " | |
3703 | { | |
3704 | int i; | |
3705 | ||
3706 | emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); | |
3707 | ||
3708 | for (i = 0; i < XVECLEN (operands[2], 0); i++) | |
3709 | { | |
3710 | rtx set = XVECEXP (operands[2], 0, i); | |
3711 | emit_move_insn (SET_DEST (set), SET_SRC (set)); | |
3712 | } | |
3713 | ||
3714 | /* The optimizer does not know that the call sets the function value | |
3715 | registers we stored in the result block. We avoid problems by | |
3716 | claiming that all hard registers are used and clobbered at this | |
3717 | point. */ | |
3718 | emit_insn (gen_blockage ()); | |
3719 | ||
3720 | DONE; | |
3721 | }") | |
3722 | ||
3723 | ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and | |
3724 | ;; all of memory. This blocks insns from being moved across this point. | |
3725 | ||
3726 | (define_insn "blockage" | |
818913ea | 3727 | [(unspec_volatile [(const_int 0)] 1)] |
e6f948e3 | 3728 | "" |
9c0e94a5 RH |
3729 | "" |
3730 | [(set_attr "length" "0")]) | |
e6f948e3 | 3731 | |
36f8f642 RK |
3732 | (define_insn "jump" |
3733 | [(set (pc) | |
3734 | (label_ref (match_operand 0 "" "")))] | |
3735 | "" | |
3736 | "br $31,%l0" | |
3737 | [(set_attr "type" "ibr")]) | |
3738 | ||
3739 | (define_insn "return" | |
3740 | [(return)] | |
3741 | "direct_return ()" | |
3742 | "ret $31,($26),1" | |
3743 | [(set_attr "type" "ibr")]) | |
3744 | ||
9c0e94a5 RH |
3745 | ;; Use a different pattern for functions which have non-trivial |
3746 | ;; epilogues so as not to confuse jump and reorg. | |
3747 | (define_insn "return_internal" | |
3748 | [(use (reg:DI 26)) | |
3749 | (return)] | |
3750 | "" | |
3751 | "ret $31,($26),1" | |
3752 | [(set_attr "type" "ibr")]) | |
3753 | ||
36f8f642 RK |
3754 | (define_insn "indirect_jump" |
3755 | [(set (pc) (match_operand:DI 0 "register_operand" "r"))] | |
3756 | "" | |
3757 | "jmp $31,(%0),0" | |
3758 | [(set_attr "type" "ibr")]) | |
3759 | ||
36f8f642 | 3760 | (define_expand "tablejump" |
55e70146 RK |
3761 | [(use (match_operand:SI 0 "register_operand" "")) |
3762 | (use (match_operand:SI 1 "" ""))] | |
3763 | "" | |
3764 | " | |
3765 | { | |
5421b3d0 | 3766 | if (TARGET_WINDOWS_NT) |
55e70146 | 3767 | emit_jump_insn (gen_tablejump_nt (operands[0], operands[1])); |
477c16e3 RK |
3768 | else if (TARGET_OPEN_VMS) |
3769 | emit_jump_insn (gen_tablejump_vms (operands[0], operands[1])); | |
55e70146 RK |
3770 | else |
3771 | emit_jump_insn (gen_tablejump_osf (operands[0], operands[1])); | |
3772 | ||
3773 | DONE; | |
3774 | }") | |
3775 | ||
3776 | (define_expand "tablejump_osf" | |
36f8f642 RK |
3777 | [(set (match_dup 3) |
3778 | (sign_extend:DI (match_operand:SI 0 "register_operand" ""))) | |
96c9d70d RK |
3779 | (parallel [(set (pc) |
3780 | (plus:DI (match_dup 3) | |
3781 | (label_ref:DI (match_operand 1 "" "")))) | |
36f8f642 RK |
3782 | (clobber (match_scratch:DI 2 "=r"))])] |
3783 | "" | |
3784 | " | |
3785 | { operands[3] = gen_reg_rtx (DImode); }") | |
3786 | ||
55e70146 RK |
3787 | (define_expand "tablejump_nt" |
3788 | [(set (match_dup 3) | |
3789 | (sign_extend:DI (match_operand:SI 0 "register_operand" ""))) | |
3790 | (parallel [(set (pc) | |
3791 | (match_dup 3)) | |
3792 | (use (label_ref (match_operand 1 "" "")))])] | |
3793 | "" | |
3794 | " | |
3795 | { operands[3] = gen_reg_rtx (DImode); }") | |
3796 | ||
477c16e3 RK |
3797 | ;; |
3798 | ;; tablejump, openVMS way | |
3799 | ;; op 0: offset | |
3800 | ;; op 1: label preceding jump-table | |
3801 | ;; | |
3802 | (define_expand "tablejump_vms" | |
3803 | [(set (match_dup 2) | |
3804 | (match_operand:DI 0 "register_operand" "")) | |
3805 | (set (pc) | |
3806 | (plus:DI (match_dup 2) | |
3807 | (label_ref:DI (match_operand 1 "" ""))))] | |
3808 | "" | |
3809 | " | |
3810 | { operands[2] = gen_reg_rtx (DImode); }") | |
3811 | ||
36f8f642 RK |
3812 | (define_insn "" |
3813 | [(set (pc) | |
3814 | (plus:DI (match_operand:DI 0 "register_operand" "r") | |
96c9d70d | 3815 | (label_ref:DI (match_operand 1 "" "")))) |
36f8f642 | 3816 | (clobber (match_scratch:DI 2 "=r"))] |
477c16e3 | 3817 | "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && next_active_insn (insn) != 0 |
96c9d70d RK |
3818 | && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC |
3819 | && PREV_INSN (next_active_insn (insn)) == operands[1]" | |
36f8f642 RK |
3820 | "* |
3821 | { rtx best_label = 0; | |
3822 | rtx jump_table_insn = next_active_insn (operands[1]); | |
3823 | ||
3824 | if (GET_CODE (jump_table_insn) == JUMP_INSN | |
96c9d70d | 3825 | && GET_CODE (PATTERN (jump_table_insn)) == ADDR_DIFF_VEC) |
36f8f642 RK |
3826 | { |
3827 | rtx jump_table = PATTERN (jump_table_insn); | |
96c9d70d | 3828 | int n_labels = XVECLEN (jump_table, 1); |
36f8f642 RK |
3829 | int best_count = -1; |
3830 | int i, j; | |
3831 | ||
3832 | for (i = 0; i < n_labels; i++) | |
3833 | { | |
3834 | int count = 1; | |
3835 | ||
3836 | for (j = i + 1; j < n_labels; j++) | |
96c9d70d RK |
3837 | if (XEXP (XVECEXP (jump_table, 1, i), 0) |
3838 | == XEXP (XVECEXP (jump_table, 1, j), 0)) | |
36f8f642 RK |
3839 | count++; |
3840 | ||
3841 | if (count > best_count) | |
96c9d70d | 3842 | best_count = count, best_label = XVECEXP (jump_table, 1, i); |
36f8f642 RK |
3843 | } |
3844 | } | |
3845 | ||
3846 | if (best_label) | |
3847 | { | |
3848 | operands[3] = best_label; | |
3849 | return \"addq %0,$29,%2\;jmp $31,(%2),%3\"; | |
3850 | } | |
3851 | else | |
3852 | return \"addq %0,$29,%2\;jmp $31,(%2),0\"; | |
3853 | }" | |
9c0e94a5 RH |
3854 | [(set_attr "type" "ibr") |
3855 | (set_attr "length" "8")]) | |
190315a7 | 3856 | |
55e70146 RK |
3857 | (define_insn "" |
3858 | [(set (pc) | |
3859 | (match_operand:DI 0 "register_operand" "r")) | |
3860 | (use (label_ref (match_operand 1 "" "")))] | |
5421b3d0 | 3861 | "TARGET_WINDOWS_NT && next_active_insn (insn) != 0 |
55e70146 RK |
3862 | && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC |
3863 | && PREV_INSN (next_active_insn (insn)) == operands[1]" | |
3864 | "* | |
3865 | { rtx best_label = 0; | |
3866 | rtx jump_table_insn = next_active_insn (operands[1]); | |
3867 | ||
3868 | if (GET_CODE (jump_table_insn) == JUMP_INSN | |
3869 | && GET_CODE (PATTERN (jump_table_insn)) == ADDR_DIFF_VEC) | |
3870 | { | |
3871 | rtx jump_table = PATTERN (jump_table_insn); | |
3872 | int n_labels = XVECLEN (jump_table, 1); | |
3873 | int best_count = -1; | |
3874 | int i, j; | |
3875 | ||
3876 | for (i = 0; i < n_labels; i++) | |
3877 | { | |
3878 | int count = 1; | |
3879 | ||
3880 | for (j = i + 1; j < n_labels; j++) | |
3881 | if (XEXP (XVECEXP (jump_table, 1, i), 0) | |
3882 | == XEXP (XVECEXP (jump_table, 1, j), 0)) | |
3883 | count++; | |
3884 | ||
3885 | if (count > best_count) | |
3886 | best_count = count, best_label = XVECEXP (jump_table, 1, i); | |
3887 | } | |
3888 | } | |
3889 | ||
3890 | if (best_label) | |
3891 | { | |
3892 | operands[2] = best_label; | |
3893 | return \"jmp $31,(%0),%2\"; | |
3894 | } | |
3895 | else | |
3896 | return \"jmp $31,(%0),0\"; | |
3897 | }" | |
3898 | [(set_attr "type" "ibr")]) | |
3899 | ||
477c16e3 RK |
3900 | ;; |
3901 | ;; op 0 is table offset | |
3902 | ;; op 1 is table label | |
3903 | ;; | |
3904 | ||
3905 | (define_insn "" | |
3906 | [(set (pc) | |
3907 | (plus:DI (match_operand 0 "register_operand" "r") | |
3908 | (label_ref (match_operand 1 "" ""))))] | |
3909 | "TARGET_OPEN_VMS" | |
3910 | "jmp $31,(%0),0" | |
3911 | [(set_attr "type" "ibr")]) | |
3912 | ||
190315a7 RK |
3913 | ;; Cache flush. Used by INITIALIZE_TRAMPOLINE. 0x86 is PAL_imb, but we don't |
3914 | ;; want to have to include pal.h in our .s file. | |
9ecc37f0 RH |
3915 | ;; |
3916 | ;; Technically the type for call_pal is jsr, but we use that for determining | |
71d9b493 | 3917 | ;; if we need a GP. Use ibr instead since it has the same EV5 scheduling |
9ecc37f0 | 3918 | ;; characteristics. |
c714f03d | 3919 | (define_insn "imb" |
190315a7 RK |
3920 | [(unspec_volatile [(const_int 0)] 0)] |
3921 | "" | |
745466f2 | 3922 | "call_pal 0x86" |
9ecc37f0 | 3923 | [(set_attr "type" "ibr")]) |
36f8f642 RK |
3924 | \f |
3925 | ;; Finally, we have the basic data motion insns. The byte and word insns | |
3926 | ;; are done via define_expand. Start with the floating-point insns, since | |
3927 | ;; they are simpler. | |
3928 | ||
3929 | (define_insn "" | |
be5090b0 RH |
3930 | [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,r,r,m,m") |
3931 | (match_operand:SF 1 "input_operand" "fG,m,rG,m,fG,r"))] | |
de4abb91 | 3932 | "! TARGET_FIX |
71d9b493 RH |
3933 | && (register_operand (operands[0], SFmode) |
3934 | || reg_or_fp0_operand (operands[1], SFmode))" | |
36f8f642 | 3935 | "@ |
6ce652e0 | 3936 | fmov %R1,%0 |
477c16e3 | 3937 | ld%, %0,%1 |
be5090b0 RH |
3938 | mov %r1,%0 |
3939 | ldl %0,%1 | |
3940 | st%, %R1,%0 | |
3941 | stl %r1,%0" | |
3942 | [(set_attr "type" "fcpys,fld,ilog,ild,fst,ist")]) | |
71d9b493 RH |
3943 | |
3944 | (define_insn "" | |
be5090b0 RH |
3945 | [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,r,r,m,m,f,*r") |
3946 | (match_operand:SF 1 "input_operand" "fG,m,rG,m,fG,r,r,*f"))] | |
de4abb91 | 3947 | "TARGET_FIX |
71d9b493 RH |
3948 | && (register_operand (operands[0], SFmode) |
3949 | || reg_or_fp0_operand (operands[1], SFmode))" | |
3950 | "@ | |
6ce652e0 | 3951 | fmov %R1,%0 |
71d9b493 | 3952 | ld%, %0,%1 |
be5090b0 RH |
3953 | mov %r1,%0 |
3954 | ldl %0,%1 | |
71d9b493 | 3955 | st%, %R1,%0 |
be5090b0 | 3956 | stl %r1,%0 |
71d9b493 RH |
3957 | itofs %1,%0 |
3958 | ftois %1,%0" | |
be5090b0 | 3959 | [(set_attr "type" "fcpys,fld,ilog,ild,fst,ist,itof,ftoi")]) |
36f8f642 RK |
3960 | |
3961 | (define_insn "" | |
be5090b0 RH |
3962 | [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,r,r,m,m") |
3963 | (match_operand:DF 1 "input_operand" "fG,m,rG,m,fG,r"))] | |
de4abb91 | 3964 | "! TARGET_FIX |
71d9b493 RH |
3965 | && (register_operand (operands[0], DFmode) |
3966 | || reg_or_fp0_operand (operands[1], DFmode))" | |
36f8f642 | 3967 | "@ |
6ce652e0 | 3968 | fmov %R1,%0 |
477c16e3 | 3969 | ld%- %0,%1 |
be5090b0 RH |
3970 | mov %r1,%0 |
3971 | ldq %0,%1 | |
3972 | st%- %R1,%0 | |
3973 | stq %r1,%0" | |
3974 | [(set_attr "type" "fcpys,fld,ilog,ild,fst,ist")]) | |
71d9b493 RH |
3975 | |
3976 | (define_insn "" | |
be5090b0 RH |
3977 | [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,r,r,m,m,f,*r") |
3978 | (match_operand:DF 1 "input_operand" "fG,m,rG,m,fG,r,r,*f"))] | |
de4abb91 | 3979 | "TARGET_FIX |
71d9b493 RH |
3980 | && (register_operand (operands[0], DFmode) |
3981 | || reg_or_fp0_operand (operands[1], DFmode))" | |
3982 | "@ | |
6ce652e0 | 3983 | fmov %R1,%0 |
71d9b493 | 3984 | ld%- %0,%1 |
be5090b0 RH |
3985 | mov %r1,%0 |
3986 | ldq %0,%1 | |
71d9b493 | 3987 | st%- %R1,%0 |
be5090b0 | 3988 | stq %r1,%0 |
71d9b493 RH |
3989 | itoft %1,%0 |
3990 | ftoit %1,%0" | |
be5090b0 | 3991 | [(set_attr "type" "fcpys,fld,ilog,ild,fst,ist,itof,ftoi")]) |
36f8f642 RK |
3992 | |
3993 | (define_expand "movsf" | |
3994 | [(set (match_operand:SF 0 "nonimmediate_operand" "") | |
3995 | (match_operand:SF 1 "general_operand" ""))] | |
3996 | "" | |
3997 | " | |
3998 | { | |
3999 | if (GET_CODE (operands[0]) == MEM | |
4000 | && ! reg_or_fp0_operand (operands[1], SFmode)) | |
4001 | operands[1] = force_reg (SFmode, operands[1]); | |
4002 | }") | |
4003 | ||
4004 | (define_expand "movdf" | |
4005 | [(set (match_operand:DF 0 "nonimmediate_operand" "") | |
4006 | (match_operand:DF 1 "general_operand" ""))] | |
4007 | "" | |
4008 | " | |
4009 | { | |
4010 | if (GET_CODE (operands[0]) == MEM | |
4011 | && ! reg_or_fp0_operand (operands[1], DFmode)) | |
4012 | operands[1] = force_reg (DFmode, operands[1]); | |
4013 | }") | |
4014 | ||
36f8f642 | 4015 | (define_insn "" |
6ce652e0 RH |
4016 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,f,f,m") |
4017 | (match_operand:SI 1 "input_operand" "rJ,K,L,m,rJ,fJ,m,f"))] | |
de4abb91 | 4018 | "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && ! TARGET_FIX |
477c16e3 RK |
4019 | && (register_operand (operands[0], SImode) |
4020 | || reg_or_0_operand (operands[1], SImode))" | |
36f8f642 | 4021 | "@ |
6ce652e0 | 4022 | mov %r1,%0 |
36f8f642 RK |
4023 | lda %0,%1 |
4024 | ldah %0,%h1 | |
4025 | ldl %0,%1 | |
4026 | stl %r1,%0 | |
6ce652e0 | 4027 | fmov %R1,%0 |
e9a25f70 JL |
4028 | ld%, %0,%1 |
4029 | st%, %R1,%0" | |
6ce652e0 | 4030 | [(set_attr "type" "ilog,iadd,iadd,ild,ist,fcpys,fld,fst")]) |
36f8f642 | 4031 | |
e9a25f70 | 4032 | (define_insn "" |
6ce652e0 RH |
4033 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,f,f,m,r,*f") |
4034 | (match_operand:SI 1 "input_operand" "rJ,K,L,m,rJ,fJ,m,f,f,*r"))] | |
de4abb91 | 4035 | "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && TARGET_FIX |
e9a25f70 JL |
4036 | && (register_operand (operands[0], SImode) |
4037 | || reg_or_0_operand (operands[1], SImode))" | |
4038 | "@ | |
6ce652e0 | 4039 | mov %r1,%0 |
e9a25f70 JL |
4040 | lda %0,%1 |
4041 | ldah %0,%h1 | |
4042 | ldl %0,%1 | |
4043 | stl %r1,%0 | |
6ce652e0 | 4044 | fmov %R1,%0 |
e9a25f70 JL |
4045 | ld%, %0,%1 |
4046 | st%, %R1,%0 | |
4047 | ftois %1,%0 | |
71d9b493 | 4048 | itofs %1,%0" |
6ce652e0 | 4049 | [(set_attr "type" "ilog,iadd,iadd,ild,ist,fcpys,fld,fst,ftoi,itof")]) |
e9a25f70 | 4050 | |
55e70146 | 4051 | (define_insn "" |
6ce652e0 RH |
4052 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,m,f,f,m") |
4053 | (match_operand:SI 1 "input_operand" "rJ,K,L,s,m,rJ,fJ,m,f"))] | |
477c16e3 | 4054 | "(TARGET_WINDOWS_NT || TARGET_OPEN_VMS) |
e9a25f70 JL |
4055 | && (register_operand (operands[0], SImode) |
4056 | || reg_or_0_operand (operands[1], SImode))" | |
55e70146 | 4057 | "@ |
6ce652e0 | 4058 | mov %1,%0 |
55e70146 RK |
4059 | lda %0,%1 |
4060 | ldah %0,%h1 | |
4061 | lda %0,%1 | |
4062 | ldl %0,%1 | |
4063 | stl %r1,%0 | |
6ce652e0 | 4064 | fmov %R1,%0 |
e9a25f70 JL |
4065 | ld%, %0,%1 |
4066 | st%, %R1,%0" | |
6ce652e0 | 4067 | [(set_attr "type" "ilog,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")]) |
55e70146 | 4068 | |
555919ac | 4069 | (define_insn "" |
8608bd56 RH |
4070 | [(set (match_operand:HI 0 "register_operand" "=r,r") |
4071 | (match_operand:HI 1 "input_operand" "rJ,n"))] | |
e9a25f70 | 4072 | "! TARGET_BWX |
555919ac RK |
4073 | && (register_operand (operands[0], HImode) |
4074 | || register_operand (operands[1], HImode))" | |
4075 | "@ | |
6ce652e0 | 4076 | mov %r1,%0 |
8608bd56 RH |
4077 | lda %0,%L1" |
4078 | [(set_attr "type" "ilog,iadd")]) | |
555919ac | 4079 | |
36f8f642 | 4080 | (define_insn "" |
8608bd56 RH |
4081 | [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m") |
4082 | (match_operand:HI 1 "input_operand" "rJ,n,m,rJ"))] | |
e9a25f70 | 4083 | "TARGET_BWX |
555919ac RK |
4084 | && (register_operand (operands[0], HImode) |
4085 | || reg_or_0_operand (operands[1], HImode))" | |
36f8f642 | 4086 | "@ |
6ce652e0 | 4087 | mov %r1,%0 |
6181e18d | 4088 | lda %0,%L1 |
ec0fb163 | 4089 | ldwu %0,%1 |
8608bd56 RH |
4090 | stw %r1,%0" |
4091 | [(set_attr "type" "ilog,iadd,ild,ist")]) | |
36f8f642 | 4092 | |
555919ac | 4093 | (define_insn "" |
8608bd56 RH |
4094 | [(set (match_operand:QI 0 "register_operand" "=r,r") |
4095 | (match_operand:QI 1 "input_operand" "rJ,n"))] | |
e9a25f70 | 4096 | "! TARGET_BWX |
555919ac RK |
4097 | && (register_operand (operands[0], QImode) |
4098 | || register_operand (operands[1], QImode))" | |
4099 | "@ | |
6ce652e0 | 4100 | mov %r1,%0 |
8608bd56 RH |
4101 | lda %0,%L1" |
4102 | [(set_attr "type" "ilog,iadd")]) | |
555919ac | 4103 | |
36f8f642 | 4104 | (define_insn "" |
8608bd56 RH |
4105 | [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m") |
4106 | (match_operand:QI 1 "input_operand" "rJ,n,m,rJ"))] | |
e9a25f70 | 4107 | "TARGET_BWX |
555919ac RK |
4108 | && (register_operand (operands[0], QImode) |
4109 | || reg_or_0_operand (operands[1], QImode))" | |
36f8f642 | 4110 | "@ |
6ce652e0 | 4111 | mov %r1,%0 |
6181e18d | 4112 | lda %0,%L1 |
ec0fb163 | 4113 | ldbu %0,%1 |
8608bd56 RH |
4114 | stb %r1,%0" |
4115 | [(set_attr "type" "ilog,iadd,ild,ist")]) | |
36f8f642 RK |
4116 | |
4117 | ;; We do two major things here: handle mem->mem and construct long | |
4118 | ;; constants. | |
4119 | ||
4120 | (define_expand "movsi" | |
4121 | [(set (match_operand:SI 0 "general_operand" "") | |
4122 | (match_operand:SI 1 "general_operand" ""))] | |
4123 | "" | |
4124 | " | |
4125 | { | |
4126 | if (GET_CODE (operands[0]) == MEM | |
4127 | && ! reg_or_0_operand (operands[1], SImode)) | |
4128 | operands[1] = force_reg (SImode, operands[1]); | |
4129 | ||
4130 | if (! CONSTANT_P (operands[1]) || input_operand (operands[1], SImode)) | |
4131 | ; | |
4132 | else if (GET_CODE (operands[1]) == CONST_INT) | |
4133 | { | |
7ac18cf6 RK |
4134 | operands[1] |
4135 | = alpha_emit_set_const (operands[0], SImode, INTVAL (operands[1]), 3); | |
4136 | if (rtx_equal_p (operands[0], operands[1])) | |
36f8f642 | 4137 | DONE; |
36f8f642 RK |
4138 | } |
4139 | }") | |
4140 | ||
4141 | ;; Split a load of a large constant into the appropriate two-insn | |
4142 | ;; sequence. | |
4143 | ||
4144 | (define_split | |
4145 | [(set (match_operand:SI 0 "register_operand" "") | |
4146 | (match_operand:SI 1 "const_int_operand" ""))] | |
4147 | "! add_operand (operands[1], SImode)" | |
4148 | [(set (match_dup 0) (match_dup 2)) | |
4149 | (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))] | |
4150 | " | |
7ac18cf6 RK |
4151 | { rtx tem |
4152 | = alpha_emit_set_const (operands[0], SImode, INTVAL (operands[1]), 2); | |
4153 | ||
4154 | if (tem == operands[0]) | |
36f8f642 RK |
4155 | DONE; |
4156 | else | |
4157 | FAIL; | |
4158 | }") | |
4159 | ||
4160 | (define_insn "" | |
6ce652e0 RH |
4161 | [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,m,f,f,Q") |
4162 | (match_operand:DI 1 "input_operand" "rJ,K,L,s,m,rJ,fJ,Q,f"))] | |
de4abb91 | 4163 | "! TARGET_FIX |
e9a25f70 JL |
4164 | && (register_operand (operands[0], DImode) |
4165 | || reg_or_0_operand (operands[1], DImode))" | |
36f8f642 | 4166 | "@ |
6ce652e0 | 4167 | mov %r1,%0 |
36f8f642 RK |
4168 | lda %0,%1 |
4169 | ldah %0,%h1 | |
4170 | lda %0,%1 | |
4171 | ldq%A1 %0,%1 | |
4172 | stq%A0 %r1,%0 | |
6ce652e0 | 4173 | fmov %R1,%0 |
36f8f642 RK |
4174 | ldt %0,%1 |
4175 | stt %R1,%0" | |
6ce652e0 | 4176 | [(set_attr "type" "ilog,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")]) |
36f8f642 | 4177 | |
e9a25f70 | 4178 | (define_insn "" |
6ce652e0 RH |
4179 | [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,m,f,f,Q,r,*f") |
4180 | (match_operand:DI 1 "input_operand" "rJ,K,L,s,m,rJ,fJ,Q,f,f,*r"))] | |
de4abb91 | 4181 | "TARGET_FIX |
e9a25f70 JL |
4182 | && (register_operand (operands[0], DImode) |
4183 | || reg_or_0_operand (operands[1], DImode))" | |
4184 | "@ | |
6ce652e0 | 4185 | mov %r1,%0 |
e9a25f70 JL |
4186 | lda %0,%1 |
4187 | ldah %0,%h1 | |
4188 | lda %0,%1 | |
4189 | ldq%A1 %0,%1 | |
4190 | stq%A0 %r1,%0 | |
6ce652e0 | 4191 | fmov %R1,%0 |
e9a25f70 JL |
4192 | ldt %0,%1 |
4193 | stt %R1,%0 | |
4194 | ftoit %1,%0 | |
4195 | itoft %1,%0" | |
6ce652e0 | 4196 | [(set_attr "type" "ilog,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst,ftoi,itof")]) |
e9a25f70 | 4197 | |
36f8f642 RK |
4198 | ;; We do three major things here: handle mem->mem, put 64-bit constants in |
4199 | ;; memory, and construct long 32-bit constants. | |
4200 | ||
4201 | (define_expand "movdi" | |
4202 | [(set (match_operand:DI 0 "general_operand" "") | |
4203 | (match_operand:DI 1 "general_operand" ""))] | |
4204 | "" | |
4205 | " | |
4206 | { | |
7ac18cf6 RK |
4207 | rtx tem; |
4208 | ||
36f8f642 RK |
4209 | if (GET_CODE (operands[0]) == MEM |
4210 | && ! reg_or_0_operand (operands[1], DImode)) | |
4211 | operands[1] = force_reg (DImode, operands[1]); | |
4212 | ||
4213 | if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode)) | |
4214 | ; | |
4215 | else if (GET_CODE (operands[1]) == CONST_INT | |
7ac18cf6 RK |
4216 | && (tem = alpha_emit_set_const (operands[0], DImode, |
4217 | INTVAL (operands[1]), 3)) != 0) | |
4218 | { | |
4219 | if (rtx_equal_p (tem, operands[0])) | |
4220 | DONE; | |
4221 | else | |
4222 | operands[1] = tem; | |
4223 | } | |
4bb43724 | 4224 | else if (CONSTANT_P (operands[1])) |
9e6c9f59 | 4225 | { |
4bb43724 RH |
4226 | if (TARGET_BUILD_CONSTANTS) |
4227 | { | |
3fe5612d | 4228 | HOST_WIDE_INT i0, i1; |
4bb43724 RH |
4229 | |
4230 | if (GET_CODE (operands[1]) == CONST_INT) | |
3fe5612d RH |
4231 | { |
4232 | i0 = INTVAL (operands[1]); | |
4233 | i1 = -(i0 < 0); | |
4234 | } | |
4bb43724 | 4235 | else if (GET_CODE (operands[1]) == CONST_DOUBLE) |
3fe5612d RH |
4236 | { |
4237 | #if HOST_BITS_PER_WIDE_INT >= 64 | |
4238 | i0 = CONST_DOUBLE_LOW (operands[1]); | |
4239 | i1 = -(i0 < 0); | |
4240 | #else | |
4241 | i0 = CONST_DOUBLE_LOW (operands[1]); | |
4242 | i1 = CONST_DOUBLE_HIGH (operands[1]); | |
4243 | #endif | |
4244 | } | |
4bb43724 RH |
4245 | else |
4246 | abort(); | |
4247 | ||
3fe5612d | 4248 | tem = alpha_emit_set_long_const (operands[0], i0, i1); |
4bb43724 RH |
4249 | if (rtx_equal_p (tem, operands[0])) |
4250 | DONE; | |
4251 | else | |
4252 | operands[1] = tem; | |
36f8f642 RK |
4253 | } |
4254 | else | |
4bb43724 RH |
4255 | { |
4256 | operands[1] = force_const_mem (DImode, operands[1]); | |
4257 | if (reload_in_progress) | |
4258 | { | |
4259 | emit_move_insn (operands[0], XEXP (operands[1], 0)); | |
4260 | operands[1] = copy_rtx (operands[1]); | |
4261 | XEXP (operands[1], 0) = operands[0]; | |
4262 | } | |
4263 | else | |
4264 | operands[1] = validize_mem (operands[1]); | |
4265 | } | |
36f8f642 RK |
4266 | } |
4267 | else | |
4268 | abort (); | |
4269 | }") | |
4270 | ||
4271 | ;; Split a load of a large constant into the appropriate two-insn | |
4272 | ;; sequence. | |
4273 | ||
4274 | (define_split | |
4275 | [(set (match_operand:DI 0 "register_operand" "") | |
4276 | (match_operand:DI 1 "const_int_operand" ""))] | |
4277 | "! add_operand (operands[1], DImode)" | |
4278 | [(set (match_dup 0) (match_dup 2)) | |
4279 | (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] | |
4280 | " | |
7ac18cf6 RK |
4281 | { rtx tem |
4282 | = alpha_emit_set_const (operands[0], DImode, INTVAL (operands[1]), 2); | |
4283 | ||
4284 | if (tem == operands[0]) | |
36f8f642 RK |
4285 | DONE; |
4286 | else | |
4287 | FAIL; | |
4288 | }") | |
4289 | ||
4290 | ;; These are the partial-word cases. | |
4291 | ;; | |
4292 | ;; First we have the code to load an aligned word. Operand 0 is the register | |
4293 | ;; in which to place the result. It's mode is QImode or HImode. Operand 1 | |
4294 | ;; is an SImode MEM at the low-order byte of the proper word. Operand 2 is the | |
4295 | ;; number of bits within the word that the value is. Operand 3 is an SImode | |
4296 | ;; scratch register. If operand 0 is a hard register, operand 3 may be the | |
4297 | ;; same register. It is allowed to conflict with operand 1 as well. | |
4298 | ||
4299 | (define_expand "aligned_loadqi" | |
4300 | [(set (match_operand:SI 3 "register_operand" "") | |
4301 | (match_operand:SI 1 "memory_operand" "")) | |
4302 | (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) | |
4303 | (zero_extract:DI (subreg:DI (match_dup 3) 0) | |
4304 | (const_int 8) | |
4305 | (match_operand:DI 2 "const_int_operand" "")))] | |
4306 | ||
4307 | "" | |
4308 | "") | |
4309 | ||
4310 | (define_expand "aligned_loadhi" | |
4311 | [(set (match_operand:SI 3 "register_operand" "") | |
4312 | (match_operand:SI 1 "memory_operand" "")) | |
4313 | (set (subreg:DI (match_operand:HI 0 "register_operand" "") 0) | |
4314 | (zero_extract:DI (subreg:DI (match_dup 3) 0) | |
4315 | (const_int 16) | |
4316 | (match_operand:DI 2 "const_int_operand" "")))] | |
4317 | ||
4318 | "" | |
4319 | "") | |
4320 | ||
2206e904 RK |
4321 | ;; Similar for unaligned loads, where we use the sequence from the |
4322 | ;; Alpha Architecture manual. | |
36f8f642 | 4323 | ;; |
2206e904 | 4324 | ;; Operand 1 is the address. Operands 2 and 3 are temporaries, where |
36f8f642 RK |
4325 | ;; operand 3 can overlap the input and output registers. |
4326 | ||
4327 | (define_expand "unaligned_loadqi" | |
4328 | [(set (match_operand:DI 2 "register_operand" "") | |
4329 | (mem:DI (and:DI (match_operand:DI 1 "address_operand" "") | |
4330 | (const_int -8)))) | |
4331 | (set (match_operand:DI 3 "register_operand" "") | |
4332 | (match_dup 1)) | |
4333 | (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) | |
4334 | (zero_extract:DI (match_dup 2) | |
4335 | (const_int 8) | |
4336 | (ashift:DI (match_dup 3) (const_int 3))))] | |
4337 | "" | |
4338 | "") | |
4339 | ||
36f8f642 RK |
4340 | (define_expand "unaligned_loadhi" |
4341 | [(set (match_operand:DI 2 "register_operand" "") | |
2206e904 RK |
4342 | (mem:DI (and:DI (match_operand:DI 1 "address_operand" "") |
4343 | (const_int -8)))) | |
36f8f642 | 4344 | (set (match_operand:DI 3 "register_operand" "") |
2206e904 RK |
4345 | (match_dup 1)) |
4346 | (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) | |
4347 | (zero_extract:DI (match_dup 2) | |
36f8f642 | 4348 | (const_int 16) |
2206e904 | 4349 | (ashift:DI (match_dup 3) (const_int 3))))] |
36f8f642 RK |
4350 | "" |
4351 | "") | |
2206e904 | 4352 | |
36f8f642 RK |
4353 | ;; Storing an aligned byte or word requires two temporaries. Operand 0 is the |
4354 | ;; aligned SImode MEM. Operand 1 is the register containing the | |
4355 | ;; byte or word to store. Operand 2 is the number of bits within the word that | |
4356 | ;; the value should be placed. Operands 3 and 4 are SImode temporaries. | |
4357 | ||
4358 | (define_expand "aligned_store" | |
4359 | [(set (match_operand:SI 3 "register_operand" "") | |
4360 | (match_operand:SI 0 "memory_operand" "")) | |
4361 | (set (subreg:DI (match_dup 3) 0) | |
4362 | (and:DI (subreg:DI (match_dup 3) 0) (match_dup 5))) | |
4363 | (set (subreg:DI (match_operand:SI 4 "register_operand" "") 0) | |
4364 | (ashift:DI (zero_extend:DI (match_operand 1 "register_operand" "")) | |
4365 | (match_operand:DI 2 "const_int_operand" ""))) | |
4366 | (set (subreg:DI (match_dup 4) 0) | |
4367 | (ior:DI (subreg:DI (match_dup 4) 0) (subreg:DI (match_dup 3) 0))) | |
4368 | (set (match_dup 0) (match_dup 4))] | |
4369 | "" | |
4370 | " | |
4371 | { operands[5] = GEN_INT (~ (GET_MODE_MASK (GET_MODE (operands[1])) | |
4372 | << INTVAL (operands[2]))); | |
4373 | }") | |
4374 | ||
2206e904 RK |
4375 | ;; For the unaligned byte and halfword cases, we use code similar to that |
4376 | ;; in the ;; Architecture book, but reordered to lower the number of registers | |
36f8f642 | 4377 | ;; required. Operand 0 is the address. Operand 1 is the data to store. |
53693fe5 | 4378 | ;; Operands 2, 3, and 4 are DImode temporaries, where operands 2 and 4 may |
36f8f642 RK |
4379 | ;; be the same temporary, if desired. If the address is in a register, |
4380 | ;; operand 2 can be that register. | |
4381 | ||
4382 | (define_expand "unaligned_storeqi" | |
4383 | [(set (match_operand:DI 3 "register_operand" "") | |
4384 | (mem:DI (and:DI (match_operand:DI 0 "address_operand" "") | |
4385 | (const_int -8)))) | |
4386 | (set (match_operand:DI 2 "register_operand" "") | |
4387 | (match_dup 0)) | |
4388 | (set (match_dup 3) | |
027b95a6 RK |
4389 | (and:DI (not:DI (ashift:DI (const_int 255) |
4390 | (ashift:DI (match_dup 2) (const_int 3)))) | |
36f8f642 RK |
4391 | (match_dup 3))) |
4392 | (set (match_operand:DI 4 "register_operand" "") | |
4393 | (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "")) | |
4394 | (ashift:DI (match_dup 2) (const_int 3)))) | |
4395 | (set (match_dup 4) (ior:DI (match_dup 4) (match_dup 3))) | |
4396 | (set (mem:DI (and:DI (match_dup 0) (const_int -8))) | |
4397 | (match_dup 4))] | |
4398 | "" | |
4399 | "") | |
4400 | ||
36f8f642 | 4401 | (define_expand "unaligned_storehi" |
2206e904 RK |
4402 | [(set (match_operand:DI 3 "register_operand" "") |
4403 | (mem:DI (and:DI (match_operand:DI 0 "address_operand" "") | |
4404 | (const_int -8)))) | |
4405 | (set (match_operand:DI 2 "register_operand" "") | |
4406 | (match_dup 0)) | |
4407 | (set (match_dup 3) | |
027b95a6 | 4408 | (and:DI (not:DI (ashift:DI (const_int 65535) |
2206e904 RK |
4409 | (ashift:DI (match_dup 2) (const_int 3)))) |
4410 | (match_dup 3))) | |
4411 | (set (match_operand:DI 4 "register_operand" "") | |
36f8f642 | 4412 | (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "")) |
2206e904 RK |
4413 | (ashift:DI (match_dup 2) (const_int 3)))) |
4414 | (set (match_dup 4) (ior:DI (match_dup 4) (match_dup 3))) | |
4415 | (set (mem:DI (and:DI (match_dup 0) (const_int -8))) | |
4416 | (match_dup 4))] | |
36f8f642 RK |
4417 | "" |
4418 | "") | |
4419 | \f | |
4420 | ;; Here are the define_expand's for QI and HI moves that use the above | |
4421 | ;; patterns. We have the normal sets, plus the ones that need scratch | |
4422 | ;; registers for reload. | |
4423 | ||
4424 | (define_expand "movqi" | |
4425 | [(set (match_operand:QI 0 "general_operand" "") | |
4426 | (match_operand:QI 1 "general_operand" ""))] | |
4427 | "" | |
4428 | " | |
47747e53 | 4429 | { |
e9a25f70 | 4430 | if (TARGET_BWX) |
ec0fb163 TG |
4431 | { |
4432 | if (GET_CODE (operands[0]) == MEM | |
4433 | && ! reg_or_0_operand (operands[1], QImode)) | |
4434 | operands[1] = force_reg (QImode, operands[1]); | |
4435 | ||
b9a2d591 RK |
4436 | if (GET_CODE (operands[1]) == CONST_INT |
4437 | && ! input_operand (operands[1], QImode)) | |
ec0fb163 | 4438 | { |
b9a2d591 RK |
4439 | operands[1] = alpha_emit_set_const (operands[0], QImode, |
4440 | INTVAL (operands[1]), 3); | |
4441 | ||
ec0fb163 TG |
4442 | if (rtx_equal_p (operands[0], operands[1])) |
4443 | DONE; | |
4444 | } | |
b9a2d591 | 4445 | |
ec0fb163 TG |
4446 | goto def; |
4447 | } | |
4448 | ||
36f8f642 RK |
4449 | /* If the output is not a register, the input must be. */ |
4450 | if (GET_CODE (operands[0]) == MEM) | |
4451 | operands[1] = force_reg (QImode, operands[1]); | |
4452 | ||
4453 | /* Handle four memory cases, unaligned and aligned for either the input | |
4454 | or the output. The only case where we can be called during reload is | |
4455 | for aligned loads; all other cases require temporaries. */ | |
4456 | ||
4457 | if (GET_CODE (operands[1]) == MEM | |
4458 | || (GET_CODE (operands[1]) == SUBREG | |
4459 | && GET_CODE (SUBREG_REG (operands[1])) == MEM) | |
4460 | || (reload_in_progress && GET_CODE (operands[1]) == REG | |
4461 | && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) | |
4462 | || (reload_in_progress && GET_CODE (operands[1]) == SUBREG | |
4463 | && GET_CODE (SUBREG_REG (operands[1])) == REG | |
4464 | && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER)) | |
4465 | { | |
4466 | if (aligned_memory_operand (operands[1], QImode)) | |
4467 | { | |
e221c183 RH |
4468 | if (reload_in_progress) |
4469 | { | |
4470 | emit_insn (gen_reload_inqi_help | |
4471 | (operands[0], operands[1], | |
4472 | gen_rtx_REG (SImode, REGNO (operands[0])))); | |
4473 | } | |
4474 | else | |
4475 | { | |
4476 | rtx aligned_mem, bitnum; | |
4477 | rtx scratch = gen_reg_rtx (SImode); | |
36f8f642 | 4478 | |
e221c183 | 4479 | get_aligned_mem (operands[1], &aligned_mem, &bitnum); |
36f8f642 | 4480 | |
e221c183 RH |
4481 | emit_insn (gen_aligned_loadqi (operands[0], aligned_mem, bitnum, |
4482 | scratch)); | |
4483 | } | |
36f8f642 RK |
4484 | } |
4485 | else | |
4486 | { | |
4487 | /* Don't pass these as parameters since that makes the generated | |
4488 | code depend on parameter evaluation order which will cause | |
4489 | bootstrap failures. */ | |
4490 | ||
4491 | rtx temp1 = gen_reg_rtx (DImode); | |
4492 | rtx temp2 = gen_reg_rtx (DImode); | |
2206e904 RK |
4493 | rtx seq |
4494 | = gen_unaligned_loadqi (operands[0], | |
4495 | get_unaligned_address (operands[1], 0), | |
4496 | temp1, temp2); | |
36f8f642 RK |
4497 | |
4498 | alpha_set_memflags (seq, operands[1]); | |
4499 | emit_insn (seq); | |
4500 | } | |
4501 | ||
4502 | DONE; | |
4503 | } | |
4504 | ||
4505 | else if (GET_CODE (operands[0]) == MEM | |
4506 | || (GET_CODE (operands[0]) == SUBREG | |
4507 | && GET_CODE (SUBREG_REG (operands[0])) == MEM) | |
4508 | || (reload_in_progress && GET_CODE (operands[0]) == REG | |
4509 | && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) | |
4510 | || (reload_in_progress && GET_CODE (operands[0]) == SUBREG | |
4511 | && GET_CODE (SUBREG_REG (operands[0])) == REG | |
4512 | && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)) | |
4513 | { | |
4514 | if (aligned_memory_operand (operands[0], QImode)) | |
4515 | { | |
4516 | rtx aligned_mem, bitnum; | |
4517 | rtx temp1 = gen_reg_rtx (SImode); | |
4518 | rtx temp2 = gen_reg_rtx (SImode); | |
4519 | ||
4e46365b | 4520 | get_aligned_mem (operands[0], &aligned_mem, &bitnum); |
36f8f642 RK |
4521 | |
4522 | emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum, | |
4523 | temp1, temp2)); | |
4524 | } | |
4525 | else | |
4526 | { | |
4527 | rtx temp1 = gen_reg_rtx (DImode); | |
4528 | rtx temp2 = gen_reg_rtx (DImode); | |
4529 | rtx temp3 = gen_reg_rtx (DImode); | |
2206e904 RK |
4530 | rtx seq |
4531 | = gen_unaligned_storeqi (get_unaligned_address (operands[0], 0), | |
4e46365b | 4532 | operands[1], temp1, temp2, temp3); |
36f8f642 RK |
4533 | |
4534 | alpha_set_memflags (seq, operands[0]); | |
4535 | emit_insn (seq); | |
4536 | } | |
4537 | DONE; | |
4538 | } | |
ec0fb163 | 4539 | def:; |
36f8f642 RK |
4540 | }") |
4541 | ||
4542 | (define_expand "movhi" | |
4543 | [(set (match_operand:HI 0 "general_operand" "") | |
4544 | (match_operand:HI 1 "general_operand" ""))] | |
4545 | "" | |
4546 | " | |
47747e53 | 4547 | { |
e9a25f70 | 4548 | if (TARGET_BWX) |
ec0fb163 TG |
4549 | { |
4550 | if (GET_CODE (operands[0]) == MEM | |
4551 | && ! reg_or_0_operand (operands[1], HImode)) | |
4552 | operands[1] = force_reg (HImode, operands[1]); | |
4553 | ||
b9a2d591 RK |
4554 | if (GET_CODE (operands[1]) == CONST_INT |
4555 | && ! input_operand (operands[1], HImode)) | |
ec0fb163 | 4556 | { |
b9a2d591 RK |
4557 | operands[1] = alpha_emit_set_const (operands[0], HImode, |
4558 | INTVAL (operands[1]), 3); | |
4559 | ||
ec0fb163 TG |
4560 | if (rtx_equal_p (operands[0], operands[1])) |
4561 | DONE; | |
4562 | } | |
b9a2d591 | 4563 | |
ec0fb163 TG |
4564 | goto def; |
4565 | } | |
4566 | ||
36f8f642 RK |
4567 | /* If the output is not a register, the input must be. */ |
4568 | if (GET_CODE (operands[0]) == MEM) | |
4569 | operands[1] = force_reg (HImode, operands[1]); | |
4570 | ||
4571 | /* Handle four memory cases, unaligned and aligned for either the input | |
4572 | or the output. The only case where we can be called during reload is | |
4573 | for aligned loads; all other cases require temporaries. */ | |
4574 | ||
4575 | if (GET_CODE (operands[1]) == MEM | |
4576 | || (GET_CODE (operands[1]) == SUBREG | |
4577 | && GET_CODE (SUBREG_REG (operands[1])) == MEM) | |
4578 | || (reload_in_progress && GET_CODE (operands[1]) == REG | |
4579 | && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) | |
4580 | || (reload_in_progress && GET_CODE (operands[1]) == SUBREG | |
4581 | && GET_CODE (SUBREG_REG (operands[1])) == REG | |
4582 | && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER)) | |
4583 | { | |
4584 | if (aligned_memory_operand (operands[1], HImode)) | |
4585 | { | |
e221c183 RH |
4586 | if (reload_in_progress) |
4587 | { | |
4588 | emit_insn (gen_reload_inhi_help | |
4589 | (operands[0], operands[1], | |
4590 | gen_rtx_REG (SImode, REGNO (operands[0])))); | |
4591 | } | |
4592 | else | |
4593 | { | |
4594 | rtx aligned_mem, bitnum; | |
4595 | rtx scratch = gen_reg_rtx (SImode); | |
36f8f642 | 4596 | |
e221c183 | 4597 | get_aligned_mem (operands[1], &aligned_mem, &bitnum); |
36f8f642 | 4598 | |
e221c183 RH |
4599 | emit_insn (gen_aligned_loadhi (operands[0], aligned_mem, bitnum, |
4600 | scratch)); | |
4601 | } | |
36f8f642 RK |
4602 | } |
4603 | else | |
4604 | { | |
2206e904 RK |
4605 | /* Don't pass these as parameters since that makes the generated |
4606 | code depend on parameter evaluation order which will cause | |
4607 | bootstrap failures. */ | |
26967318 | 4608 | |
2206e904 RK |
4609 | rtx temp1 = gen_reg_rtx (DImode); |
4610 | rtx temp2 = gen_reg_rtx (DImode); | |
4611 | rtx seq | |
4612 | = gen_unaligned_loadhi (operands[0], | |
4613 | get_unaligned_address (operands[1], 0), | |
4614 | temp1, temp2); | |
36f8f642 RK |
4615 | |
4616 | alpha_set_memflags (seq, operands[1]); | |
4617 | emit_insn (seq); | |
4618 | } | |
4619 | ||
4620 | DONE; | |
4621 | } | |
4622 | ||
4623 | else if (GET_CODE (operands[0]) == MEM | |
4624 | || (GET_CODE (operands[0]) == SUBREG | |
4625 | && GET_CODE (SUBREG_REG (operands[0])) == MEM) | |
4626 | || (reload_in_progress && GET_CODE (operands[0]) == REG | |
4627 | && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) | |
4628 | || (reload_in_progress && GET_CODE (operands[0]) == SUBREG | |
4629 | && GET_CODE (SUBREG_REG (operands[0])) == REG | |
4630 | && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)) | |
4631 | { | |
4632 | if (aligned_memory_operand (operands[0], HImode)) | |
4633 | { | |
4634 | rtx aligned_mem, bitnum; | |
4635 | rtx temp1 = gen_reg_rtx (SImode); | |
4636 | rtx temp2 = gen_reg_rtx (SImode); | |
4637 | ||
4e46365b | 4638 | get_aligned_mem (operands[0], &aligned_mem, &bitnum); |
36f8f642 RK |
4639 | |
4640 | emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum, | |
4641 | temp1, temp2)); | |
4642 | } | |
4643 | else | |
4644 | { | |
4645 | rtx temp1 = gen_reg_rtx (DImode); | |
4646 | rtx temp2 = gen_reg_rtx (DImode); | |
4647 | rtx temp3 = gen_reg_rtx (DImode); | |
2206e904 RK |
4648 | rtx seq |
4649 | = gen_unaligned_storehi (get_unaligned_address (operands[0], 0), | |
4650 | operands[1], temp1, temp2, temp3); | |
36f8f642 RK |
4651 | |
4652 | alpha_set_memflags (seq, operands[0]); | |
4653 | emit_insn (seq); | |
4654 | } | |
4655 | ||
4656 | DONE; | |
4657 | } | |
ec0fb163 | 4658 | def:; |
36f8f642 RK |
4659 | }") |
4660 | ||
4661 | ;; Here are the versions for reload. Note that in the unaligned cases | |
4662 | ;; we know that the operand must not be a pseudo-register because stack | |
4663 | ;; slots are always aligned references. | |
4664 | ||
4665 | (define_expand "reload_inqi" | |
4666 | [(parallel [(match_operand:QI 0 "register_operand" "=r") | |
4e46365b | 4667 | (match_operand:QI 1 "any_memory_operand" "m") |
53693fe5 | 4668 | (match_operand:TI 2 "register_operand" "=&r")])] |
e9a25f70 | 4669 | "! TARGET_BWX" |
36f8f642 | 4670 | " |
47747e53 | 4671 | { |
96043e7e | 4672 | rtx scratch, seq; |
f3352b9e | 4673 | |
4e46365b RH |
4674 | if (GET_CODE (operands[1]) != MEM) |
4675 | abort (); | |
4676 | ||
96043e7e RH |
4677 | if (aligned_memory_operand (operands[1], QImode)) |
4678 | { | |
e221c183 RH |
4679 | seq = gen_reload_inqi_help (operands[0], operands[1], |
4680 | gen_rtx_REG (SImode, REGNO (operands[2]))); | |
96043e7e RH |
4681 | } |
4682 | else | |
4683 | { | |
4684 | rtx addr; | |
4685 | ||
4686 | /* It is possible that one of the registers we got for operands[2] | |
4e46365b RH |
4687 | might coincide with that of operands[0] (which is why we made |
4688 | it TImode). Pick the other one to use as our scratch. */ | |
96043e7e RH |
4689 | if (REGNO (operands[0]) == REGNO (operands[2])) |
4690 | scratch = gen_rtx_REG (DImode, REGNO (operands[2]) + 1); | |
4691 | else | |
4692 | scratch = gen_rtx_REG (DImode, REGNO (operands[2])); | |
36f8f642 | 4693 | |
96043e7e RH |
4694 | addr = get_unaligned_address (operands[1], 0); |
4695 | seq = gen_unaligned_loadqi (operands[0], addr, scratch, | |
4e46365b RH |
4696 | gen_rtx_REG (DImode, REGNO (operands[0]))); |
4697 | alpha_set_memflags (seq, operands[1]); | |
96043e7e | 4698 | } |
36f8f642 RK |
4699 | emit_insn (seq); |
4700 | DONE; | |
4701 | }") | |
4702 | ||
4703 | (define_expand "reload_inhi" | |
4704 | [(parallel [(match_operand:HI 0 "register_operand" "=r") | |
96043e7e | 4705 | (match_operand:HI 1 "any_memory_operand" "m") |
36f8f642 | 4706 | (match_operand:TI 2 "register_operand" "=&r")])] |
e9a25f70 | 4707 | "! TARGET_BWX" |
36f8f642 | 4708 | " |
47747e53 | 4709 | { |
96043e7e | 4710 | rtx scratch, seq; |
f3352b9e | 4711 | |
4e46365b RH |
4712 | if (GET_CODE (operands[1]) != MEM) |
4713 | abort (); | |
4714 | ||
96043e7e RH |
4715 | if (aligned_memory_operand (operands[1], HImode)) |
4716 | { | |
e221c183 RH |
4717 | seq = gen_reload_inhi_help (operands[0], operands[1], |
4718 | gen_rtx_REG (SImode, REGNO (operands[2]))); | |
96043e7e RH |
4719 | } |
4720 | else | |
4721 | { | |
4722 | rtx addr; | |
4723 | ||
4724 | /* It is possible that one of the registers we got for operands[2] | |
4e46365b RH |
4725 | might coincide with that of operands[0] (which is why we made |
4726 | it TImode). Pick the other one to use as our scratch. */ | |
96043e7e RH |
4727 | if (REGNO (operands[0]) == REGNO (operands[2])) |
4728 | scratch = gen_rtx_REG (DImode, REGNO (operands[2]) + 1); | |
4729 | else | |
4730 | scratch = gen_rtx_REG (DImode, REGNO (operands[2])); | |
36f8f642 | 4731 | |
96043e7e RH |
4732 | addr = get_unaligned_address (operands[1], 0); |
4733 | seq = gen_unaligned_loadhi (operands[0], addr, scratch, | |
4e46365b RH |
4734 | gen_rtx_REG (DImode, REGNO (operands[0]))); |
4735 | alpha_set_memflags (seq, operands[1]); | |
96043e7e | 4736 | } |
36f8f642 RK |
4737 | emit_insn (seq); |
4738 | DONE; | |
4739 | }") | |
4740 | ||
4741 | (define_expand "reload_outqi" | |
4742 | [(parallel [(match_operand:QI 0 "any_memory_operand" "=m") | |
4743 | (match_operand:QI 1 "register_operand" "r") | |
4744 | (match_operand:TI 2 "register_operand" "=&r")])] | |
e9a25f70 | 4745 | "! TARGET_BWX" |
36f8f642 | 4746 | " |
47747e53 | 4747 | { |
4e46365b RH |
4748 | if (GET_CODE (operands[0]) != MEM) |
4749 | abort (); | |
4750 | ||
36f8f642 RK |
4751 | if (aligned_memory_operand (operands[0], QImode)) |
4752 | { | |
e221c183 RH |
4753 | emit_insn (gen_reload_outqi_help |
4754 | (operands[0], operands[1], | |
4755 | gen_rtx_REG (SImode, REGNO (operands[2])), | |
4756 | gen_rtx_REG (SImode, REGNO (operands[2]) + 1))); | |
36f8f642 RK |
4757 | } |
4758 | else | |
4759 | { | |
2206e904 | 4760 | rtx addr = get_unaligned_address (operands[0], 0); |
38a448ca RH |
4761 | rtx scratch1 = gen_rtx_REG (DImode, REGNO (operands[2])); |
4762 | rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1); | |
99d13c40 | 4763 | rtx scratch3 = scratch1; |
36f8f642 RK |
4764 | rtx seq; |
4765 | ||
4766 | if (GET_CODE (addr) == REG) | |
4767 | scratch1 = addr; | |
4768 | ||
4769 | seq = gen_unaligned_storeqi (addr, operands[1], scratch1, | |
99d13c40 | 4770 | scratch2, scratch3); |
36f8f642 RK |
4771 | alpha_set_memflags (seq, operands[0]); |
4772 | emit_insn (seq); | |
4773 | } | |
36f8f642 RK |
4774 | DONE; |
4775 | }") | |
4776 | ||
4777 | (define_expand "reload_outhi" | |
4778 | [(parallel [(match_operand:HI 0 "any_memory_operand" "=m") | |
4779 | (match_operand:HI 1 "register_operand" "r") | |
4780 | (match_operand:TI 2 "register_operand" "=&r")])] | |
e9a25f70 | 4781 | "! TARGET_BWX" |
36f8f642 | 4782 | " |
47747e53 | 4783 | { |
4e46365b RH |
4784 | if (GET_CODE (operands[0]) != MEM) |
4785 | abort (); | |
4786 | ||
36f8f642 RK |
4787 | if (aligned_memory_operand (operands[0], HImode)) |
4788 | { | |
e221c183 RH |
4789 | emit_insn (gen_reload_outhi_help |
4790 | (operands[0], operands[1], | |
4791 | gen_rtx_REG (SImode, REGNO (operands[2])), | |
4792 | gen_rtx_REG (SImode, REGNO (operands[2]) + 1))); | |
36f8f642 RK |
4793 | } |
4794 | else | |
4795 | { | |
2206e904 | 4796 | rtx addr = get_unaligned_address (operands[0], 0); |
38a448ca RH |
4797 | rtx scratch1 = gen_rtx_REG (DImode, REGNO (operands[2])); |
4798 | rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1); | |
2206e904 | 4799 | rtx scratch3 = scratch1; |
36f8f642 RK |
4800 | rtx seq; |
4801 | ||
2206e904 RK |
4802 | if (GET_CODE (addr) == REG) |
4803 | scratch1 = addr; | |
4804 | ||
4805 | seq = gen_unaligned_storehi (addr, operands[1], scratch1, | |
4806 | scratch2, scratch3); | |
36f8f642 RK |
4807 | alpha_set_memflags (seq, operands[0]); |
4808 | emit_insn (seq); | |
4809 | } | |
36f8f642 RK |
4810 | DONE; |
4811 | }") | |
e221c183 RH |
4812 | |
4813 | ;; Helpers for the above. The way reload is structured, we can't | |
4814 | ;; always get a proper address for a stack slot during reload_foo | |
4815 | ;; expansion, so we must delay our address manipulations until after. | |
4816 | ||
4817 | (define_insn "reload_inqi_help" | |
4818 | [(set (match_operand:QI 0 "register_operand" "r") | |
4819 | (match_operand:QI 1 "memory_operand" "m")) | |
4820 | (clobber (match_operand:SI 2 "register_operand" "r"))] | |
4821 | "! TARGET_BWX && (reload_in_progress || reload_completed)" | |
4822 | "#") | |
4823 | ||
4824 | (define_insn "reload_inhi_help" | |
4825 | [(set (match_operand:HI 0 "register_operand" "r") | |
4826 | (match_operand:HI 1 "memory_operand" "m")) | |
4827 | (clobber (match_operand:SI 2 "register_operand" "r"))] | |
4828 | "! TARGET_BWX && (reload_in_progress || reload_completed)" | |
4829 | "#") | |
4830 | ||
4831 | (define_insn "reload_outqi_help" | |
4832 | [(set (match_operand:QI 0 "memory_operand" "m") | |
4833 | (match_operand:QI 1 "register_operand" "r")) | |
4834 | (clobber (match_operand:SI 2 "register_operand" "r")) | |
4835 | (clobber (match_operand:SI 3 "register_operand" "r"))] | |
4836 | "! TARGET_BWX && (reload_in_progress || reload_completed)" | |
4837 | "#") | |
4838 | ||
4839 | (define_insn "reload_outhi_help" | |
4840 | [(set (match_operand:HI 0 "memory_operand" "m") | |
4841 | (match_operand:HI 1 "register_operand" "r")) | |
4842 | (clobber (match_operand:SI 2 "register_operand" "r")) | |
4843 | (clobber (match_operand:SI 3 "register_operand" "r"))] | |
4844 | "! TARGET_BWX && (reload_in_progress || reload_completed)" | |
4845 | "#") | |
4846 | ||
4847 | (define_split | |
4848 | [(set (match_operand:QI 0 "register_operand" "r") | |
4849 | (match_operand:QI 1 "memory_operand" "m")) | |
4850 | (clobber (match_operand:SI 2 "register_operand" "r"))] | |
4851 | "! TARGET_BWX && reload_completed" | |
4852 | [(const_int 0)] | |
4853 | " | |
4854 | { | |
4855 | rtx aligned_mem, bitnum; | |
4856 | get_aligned_mem (operands[1], &aligned_mem, &bitnum); | |
4857 | emit_insn (gen_aligned_loadqi (operands[0], aligned_mem, bitnum, | |
4858 | operands[2])); | |
4859 | DONE; | |
4860 | }") | |
4861 | ||
4862 | (define_split | |
4863 | [(set (match_operand:HI 0 "register_operand" "r") | |
4864 | (match_operand:HI 1 "memory_operand" "m")) | |
4865 | (clobber (match_operand:SI 2 "register_operand" "r"))] | |
4866 | "! TARGET_BWX && reload_completed" | |
4867 | [(const_int 0)] | |
4868 | " | |
4869 | { | |
4870 | rtx aligned_mem, bitnum; | |
4871 | get_aligned_mem (operands[1], &aligned_mem, &bitnum); | |
4872 | emit_insn (gen_aligned_loadhi (operands[0], aligned_mem, bitnum, | |
4873 | operands[2])); | |
4874 | DONE; | |
4875 | }") | |
4876 | ||
4877 | (define_split | |
4878 | [(set (match_operand:QI 0 "memory_operand" "m") | |
4879 | (match_operand:QI 1 "register_operand" "r")) | |
4880 | (clobber (match_operand:SI 2 "register_operand" "r")) | |
4881 | (clobber (match_operand:SI 3 "register_operand" "r"))] | |
4882 | "! TARGET_BWX && reload_completed" | |
4883 | [(const_int 0)] | |
4884 | " | |
4885 | { | |
4886 | rtx aligned_mem, bitnum; | |
4887 | get_aligned_mem (operands[0], &aligned_mem, &bitnum); | |
4888 | emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum, | |
4889 | operands[2], operands[3])); | |
4890 | DONE; | |
4891 | }") | |
4892 | ||
4893 | (define_split | |
4894 | [(set (match_operand:HI 0 "memory_operand" "m") | |
4895 | (match_operand:HI 1 "register_operand" "r")) | |
4896 | (clobber (match_operand:SI 2 "register_operand" "r")) | |
4897 | (clobber (match_operand:SI 3 "register_operand" "r"))] | |
4898 | "! TARGET_BWX && reload_completed" | |
4899 | [(const_int 0)] | |
4900 | " | |
4901 | { | |
4902 | rtx aligned_mem, bitnum; | |
4903 | get_aligned_mem (operands[0], &aligned_mem, &bitnum); | |
4904 | emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum, | |
4905 | operands[2], operands[3])); | |
4906 | DONE; | |
4907 | }") | |
26958509 | 4908 | \f |
6c174fc0 RH |
4909 | ;; Bit field extract patterns which use ext[wlq][lh] |
4910 | ||
4911 | (define_expand "extv" | |
4912 | [(set (match_operand:DI 0 "register_operand" "") | |
4913 | (sign_extract:DI (match_operand:QI 1 "memory_operand" "") | |
4914 | (match_operand:DI 2 "immediate_operand" "") | |
4915 | (match_operand:DI 3 "immediate_operand" "")))] | |
4916 | "" | |
4917 | " | |
4918 | { | |
4919 | /* We can do 16, 32 and 64 bit fields, if aligned on byte boundaries. */ | |
4920 | if (INTVAL (operands[3]) % 8 != 0 | |
4921 | || (INTVAL (operands[2]) != 16 | |
4922 | && INTVAL (operands[2]) != 32 | |
4923 | && INTVAL (operands[2]) != 64)) | |
4924 | FAIL; | |
4925 | ||
4926 | /* From mips.md: extract_bit_field doesn't verify that our source | |
4927 | matches the predicate, so we force it to be a MEM here. */ | |
4928 | if (GET_CODE (operands[1]) != MEM) | |
4929 | FAIL; | |
4930 | ||
4931 | alpha_expand_unaligned_load (operands[0], operands[1], | |
4932 | INTVAL (operands[2]) / 8, | |
4933 | INTVAL (operands[3]) / 8, 1); | |
4934 | DONE; | |
4935 | }") | |
4936 | ||
4937 | (define_expand "extzv" | |
4938 | [(set (match_operand:DI 0 "register_operand" "") | |
6ad90d66 | 4939 | (zero_extract:DI (match_operand:DI 1 "general_operand" "") |
6c174fc0 RH |
4940 | (match_operand:DI 2 "immediate_operand" "") |
4941 | (match_operand:DI 3 "immediate_operand" "")))] | |
4942 | "" | |
4943 | " | |
4944 | { | |
10a25232 | 4945 | /* We can do 8, 16, 32 and 64 bit fields, if aligned on byte boundaries. */ |
221a9f65 JW |
4946 | if (INTVAL (operands[3]) % 8 != 0 |
4947 | || (INTVAL (operands[2]) != 8 | |
4948 | && INTVAL (operands[2]) != 16 | |
4949 | && INTVAL (operands[2]) != 32 | |
4950 | && INTVAL (operands[2]) != 64)) | |
6c174fc0 RH |
4951 | FAIL; |
4952 | ||
10a25232 RH |
4953 | if (GET_CODE (operands[1]) == MEM) |
4954 | { | |
4955 | /* Fail 8 bit fields, falling back on a simple byte load. */ | |
4956 | if (INTVAL (operands[2]) == 8) | |
4957 | FAIL; | |
6c174fc0 | 4958 | |
10a25232 RH |
4959 | alpha_expand_unaligned_load (operands[0], operands[1], |
4960 | INTVAL (operands[2]) / 8, | |
4961 | INTVAL (operands[3]) / 8, 0); | |
4962 | DONE; | |
4963 | } | |
6c174fc0 RH |
4964 | }") |
4965 | ||
4966 | (define_expand "insv" | |
4967 | [(set (zero_extract:DI (match_operand:QI 0 "memory_operand" "") | |
4968 | (match_operand:DI 1 "immediate_operand" "") | |
4969 | (match_operand:DI 2 "immediate_operand" "")) | |
4970 | (match_operand:DI 3 "register_operand" ""))] | |
4971 | "" | |
4972 | " | |
4973 | { | |
4974 | /* We can do 16, 32 and 64 bit fields, if aligned on byte boundaries. */ | |
4975 | if (INTVAL (operands[2]) % 8 != 0 | |
4976 | || (INTVAL (operands[1]) != 16 | |
4977 | && INTVAL (operands[1]) != 32 | |
4978 | && INTVAL (operands[1]) != 64)) | |
4979 | FAIL; | |
4980 | ||
4981 | /* From mips.md: store_bit_field doesn't verify that our source | |
4982 | matches the predicate, so we force it to be a MEM here. */ | |
4983 | if (GET_CODE (operands[0]) != MEM) | |
4984 | FAIL; | |
4985 | ||
4986 | alpha_expand_unaligned_store (operands[0], operands[3], | |
4987 | INTVAL (operands[1]) / 8, | |
4988 | INTVAL (operands[2]) / 8); | |
4989 | DONE; | |
4990 | }") | |
4991 | ||
4992 | ||
4993 | ||
4994 | ;; Block move/clear, see alpha.c for more details. | |
4995 | ;; Argument 0 is the destination | |
4996 | ;; Argument 1 is the source | |
4997 | ;; Argument 2 is the length | |
4998 | ;; Argument 3 is the alignment | |
4999 | ||
5000 | (define_expand "movstrqi" | |
5001 | [(parallel [(set (match_operand:BLK 0 "general_operand" "") | |
5002 | (match_operand:BLK 1 "general_operand" "")) | |
5003 | (use (match_operand:DI 2 "immediate_operand" "")) | |
5004 | (use (match_operand:DI 3 "immediate_operand" ""))])] | |
5005 | "" | |
5006 | " | |
5007 | { | |
5008 | if (alpha_expand_block_move (operands)) | |
5009 | DONE; | |
5010 | else | |
5011 | FAIL; | |
5012 | }") | |
5013 | ||
5014 | (define_expand "clrstrqi" | |
5015 | [(parallel [(set (match_operand:BLK 0 "general_operand" "") | |
5016 | (const_int 0)) | |
5017 | (use (match_operand:DI 1 "immediate_operand" "")) | |
5018 | (use (match_operand:DI 2 "immediate_operand" ""))])] | |
5019 | "" | |
5020 | " | |
5021 | { | |
5022 | if (alpha_expand_block_clear (operands)) | |
5023 | DONE; | |
5024 | else | |
5025 | FAIL; | |
5026 | }") | |
5027 | \f | |
26958509 RK |
5028 | ;; Subroutine of stack space allocation. Perform a stack probe. |
5029 | (define_expand "probe_stack" | |
5030 | [(set (match_dup 1) (match_operand:DI 0 "const_int_operand" ""))] | |
5031 | "" | |
5032 | " | |
5033 | { | |
38a448ca RH |
5034 | operands[1] = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, |
5035 | INTVAL (operands[0]))); | |
13aa593c | 5036 | MEM_VOLATILE_P (operands[1]) = 1; |
26958509 | 5037 | |
13aa593c | 5038 | operands[0] = const0_rtx; |
26958509 RK |
5039 | }") |
5040 | ||
5041 | ;; This is how we allocate stack space. If we are allocating a | |
5042 | ;; constant amount of space and we know it is less than 4096 | |
5043 | ;; bytes, we need do nothing. | |
5044 | ;; | |
5045 | ;; If it is more than 4096 bytes, we need to probe the stack | |
5046 | ;; periodically. | |
5047 | (define_expand "allocate_stack" | |
5048 | [(set (reg:DI 30) | |
5049 | (plus:DI (reg:DI 30) | |
e9a25f70 JL |
5050 | (match_operand:DI 1 "reg_or_cint_operand" ""))) |
5051 | (set (match_operand:DI 0 "register_operand" "=r") | |
5052 | (match_dup 2))] | |
26958509 RK |
5053 | "" |
5054 | " | |
5055 | { | |
e9a25f70 JL |
5056 | if (GET_CODE (operands[1]) == CONST_INT |
5057 | && INTVAL (operands[1]) < 32768) | |
26958509 | 5058 | { |
e9a25f70 | 5059 | if (INTVAL (operands[1]) >= 4096) |
26958509 RK |
5060 | { |
5061 | /* We do this the same way as in the prologue and generate explicit | |
5062 | probes. Then we update the stack by the constant. */ | |
5063 | ||
5064 | int probed = 4096; | |
5065 | ||
5066 | emit_insn (gen_probe_stack (GEN_INT (- probed))); | |
e9a25f70 | 5067 | while (probed + 8192 < INTVAL (operands[1])) |
26958509 RK |
5068 | emit_insn (gen_probe_stack (GEN_INT (- (probed += 8192)))); |
5069 | ||
e9a25f70 JL |
5070 | if (probed + 4096 < INTVAL (operands[1])) |
5071 | emit_insn (gen_probe_stack (GEN_INT (- INTVAL(operands[1])))); | |
26958509 RK |
5072 | } |
5073 | ||
e9a25f70 JL |
5074 | operands[1] = GEN_INT (- INTVAL (operands[1])); |
5075 | operands[2] = virtual_stack_dynamic_rtx; | |
26958509 RK |
5076 | } |
5077 | else | |
5078 | { | |
5079 | rtx out_label = 0; | |
5080 | rtx loop_label = gen_label_rtx (); | |
13aa593c RK |
5081 | rtx want = gen_reg_rtx (Pmode); |
5082 | rtx tmp = gen_reg_rtx (Pmode); | |
5083 | rtx memref; | |
26958509 | 5084 | |
13aa593c | 5085 | emit_insn (gen_subdi3 (want, stack_pointer_rtx, |
e9a25f70 | 5086 | force_reg (Pmode, operands[1]))); |
13aa593c | 5087 | emit_insn (gen_adddi3 (tmp, stack_pointer_rtx, GEN_INT (-4096))); |
26958509 | 5088 | |
e9a25f70 | 5089 | if (GET_CODE (operands[1]) != CONST_INT) |
26958509 | 5090 | { |
26958509 | 5091 | out_label = gen_label_rtx (); |
13aa593c RK |
5092 | emit_insn (gen_cmpdi (want, tmp)); |
5093 | emit_jump_insn (gen_bgeu (out_label)); | |
26958509 | 5094 | } |
26958509 | 5095 | |
26958509 | 5096 | emit_label (loop_label); |
38a448ca | 5097 | memref = gen_rtx_MEM (DImode, tmp); |
13aa593c RK |
5098 | MEM_VOLATILE_P (memref) = 1; |
5099 | emit_move_insn (memref, const0_rtx); | |
5100 | emit_insn (gen_adddi3 (tmp, tmp, GEN_INT(-8192))); | |
5101 | emit_insn (gen_cmpdi (tmp, want)); | |
5102 | emit_jump_insn (gen_bgtu (loop_label)); | |
e9a25f70 | 5103 | if (obey_regdecls) |
38a448ca | 5104 | gen_rtx_USE (VOIDmode, tmp); |
e9a25f70 | 5105 | |
38a448ca | 5106 | memref = gen_rtx_MEM (DImode, want); |
13aa593c RK |
5107 | MEM_VOLATILE_P (memref) = 1; |
5108 | emit_move_insn (memref, const0_rtx); | |
26958509 RK |
5109 | |
5110 | if (out_label) | |
5111 | emit_label (out_label); | |
5112 | ||
13aa593c | 5113 | emit_move_insn (stack_pointer_rtx, want); |
e9a25f70 | 5114 | emit_move_insn (operands[0], virtual_stack_dynamic_rtx); |
26958509 RK |
5115 | DONE; |
5116 | } | |
5117 | }") | |
477c16e3 | 5118 | |
9c0e94a5 RH |
5119 | ;; This is used by alpha_expand_prolog to do the same thing as above, |
5120 | ;; except we cannot at that time generate new basic blocks, so we hide | |
5121 | ;; the loop in this one insn. | |
5122 | ||
5123 | (define_insn "prologue_stack_probe_loop" | |
5124 | [(unspec_volatile [(match_operand 0 "register_operand" "r") | |
5125 | (match_operand 1 "register_operand" "r")] 5)] | |
5126 | "" | |
5127 | "* | |
5128 | { | |
73d288ba RH |
5129 | operands[2] = gen_label_rtx (); |
5130 | ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", | |
5131 | CODE_LABEL_NUMBER (operands[2])); | |
5132 | ||
5133 | return \"stq $31,-8192(%1)\;subq %0,1,%0\;lda %1,-8192(%1)\;bne %0,%l2\"; | |
9c0e94a5 | 5134 | }" |
68aed21b RH |
5135 | [(set_attr "length" "16") |
5136 | (set_attr "type" "multi")]) | |
9c0e94a5 RH |
5137 | |
5138 | (define_expand "prologue" | |
5139 | [(clobber (const_int 0))] | |
5140 | "" | |
5141 | "alpha_expand_prologue (); DONE;") | |
5142 | ||
5143 | (define_insn "init_fp" | |
5144 | [(set (match_operand:DI 0 "register_operand" "r") | |
5145 | (match_operand:DI 1 "register_operand" "r")) | |
5146 | (clobber (mem:BLK (match_operand:DI 2 "register_operand" "r")))] | |
5147 | "" | |
6ce652e0 | 5148 | "mov %1,%0") |
9c0e94a5 RH |
5149 | |
5150 | (define_expand "epilogue" | |
5151 | [(clobber (const_int 0))] | |
5152 | "" | |
5153 | "alpha_expand_epilogue (); DONE;") | |
5154 | ||
71038426 RH |
5155 | (define_expand "eh_epilogue" |
5156 | [(use (match_operand:DI 0 "register_operand" "r")) | |
5157 | (use (match_operand:DI 1 "register_operand" "r")) | |
5158 | (use (match_operand:DI 2 "register_operand" "r"))] | |
5159 | "! TARGET_OPEN_VMS" | |
5160 | " | |
5161 | { | |
5162 | alpha_eh_epilogue_sp_ofs = operands[1]; | |
5163 | if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 26) | |
5164 | { | |
5165 | rtx ra = gen_rtx_REG (Pmode, 26); | |
5166 | emit_move_insn (ra, operands[2]); | |
5167 | operands[2] = ra; | |
5168 | } | |
5169 | }") | |
5170 | ||
37679e06 RH |
5171 | ;; In creating a large stack frame, NT _must_ use ldah+lda to load |
5172 | ;; the frame size into a register. We use this pattern to ensure | |
5173 | ;; we get lda instead of addq. | |
5174 | (define_insn "nt_lda" | |
5175 | [(set (match_operand:DI 0 "register_operand" "r") | |
5176 | (unspec:DI [(match_dup 0) | |
5177 | (match_operand:DI 1 "const_int_operand" "n")] 6))] | |
5178 | "" | |
5179 | "lda %0,%1(%0)") | |
5180 | ||
6fd1c67b RH |
5181 | (define_expand "builtin_longjmp" |
5182 | [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)] | |
c133e33c | 5183 | "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT" |
6fd1c67b RH |
5184 | " |
5185 | { | |
5186 | /* The elements of the buffer are, in order: */ | |
5187 | rtx fp = gen_rtx_MEM (Pmode, operands[0]); | |
5188 | rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 8)); | |
5189 | rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 16)); | |
5190 | rtx pv = gen_rtx_REG (Pmode, 27); | |
5191 | ||
5192 | /* This bit is the same as expand_builtin_longjmp. */ | |
5193 | emit_move_insn (hard_frame_pointer_rtx, fp); | |
5194 | emit_move_insn (pv, lab); | |
5195 | emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); | |
5196 | emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); | |
5197 | emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); | |
5198 | ||
5199 | /* Load the label we are jumping through into $27 so that we know | |
5200 | where to look for it when we get back to setjmp's function for | |
5201 | restoring the gp. */ | |
5202 | emit_indirect_jump (pv); | |
4b855767 | 5203 | DONE; |
6fd1c67b | 5204 | }") |
c133e33c | 5205 | |
6fd1c67b | 5206 | (define_insn "builtin_setjmp_receiver" |
039d4bce | 5207 | [(unspec_volatile [(label_ref (match_operand 0 "" ""))] 2)] |
9ba3994a | 5208 | "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT && TARGET_AS_CAN_SUBTRACT_LABELS" |
9c0e94a5 | 5209 | "\\n$LSJ%=:\;ldgp $29,$LSJ%=-%l0($27)" |
68aed21b RH |
5210 | [(set_attr "length" "8") |
5211 | (set_attr "type" "multi")]) | |
6fd1c67b | 5212 | |
9ba3994a | 5213 | (define_insn "" |
039d4bce | 5214 | [(unspec_volatile [(label_ref (match_operand 0 "" ""))] 2)] |
9ba3994a | 5215 | "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT" |
6abc6f40 RH |
5216 | "br $29,$LSJ%=\\n$LSJ%=:\;ldgp $29,0($29)" |
5217 | [(set_attr "length" "12") | |
5218 | (set_attr "type" "multi")]) | |
5219 | ||
5220 | (define_insn "exception_receiver" | |
5221 | [(unspec_volatile [(const_int 0)] 7)] | |
5222 | "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT" | |
5223 | "br $29,$LSJ%=\\n$LSJ%=:\;ldgp $29,0($29)" | |
68aed21b RH |
5224 | [(set_attr "length" "12") |
5225 | (set_attr "type" "multi")]) | |
9ba3994a | 5226 | |
6fd1c67b | 5227 | (define_expand "nonlocal_goto_receiver" |
477c16e3 RK |
5228 | [(unspec_volatile [(const_int 0)] 1) |
5229 | (set (reg:DI 27) (mem:DI (reg:DI 29))) | |
5230 | (unspec_volatile [(const_int 0)] 1) | |
5231 | (use (reg:DI 27))] | |
5232 | "TARGET_OPEN_VMS" | |
5233 | "") | |
5234 | ||
5235 | (define_insn "arg_home" | |
5236 | [(unspec [(const_int 0)] 0) | |
5237 | (use (reg:DI 1)) | |
5238 | (use (reg:DI 25)) | |
9b80d951 RK |
5239 | (use (reg:DI 16)) |
5240 | (use (reg:DI 17)) | |
5241 | (use (reg:DI 18)) | |
5242 | (use (reg:DI 19)) | |
5243 | (use (reg:DI 20)) | |
5244 | (use (reg:DI 21)) | |
5245 | (use (reg:DI 48)) | |
5246 | (use (reg:DI 49)) | |
5247 | (use (reg:DI 50)) | |
5248 | (use (reg:DI 51)) | |
5249 | (use (reg:DI 52)) | |
5250 | (use (reg:DI 53)) | |
5251 | (clobber (mem:BLK (const_int 0))) | |
477c16e3 RK |
5252 | (clobber (reg:DI 24)) |
5253 | (clobber (reg:DI 25)) | |
5254 | (clobber (reg:DI 0))] | |
5255 | "TARGET_OPEN_VMS" | |
9c0e94a5 | 5256 | "lda $0,OTS$HOME_ARGS\;ldq $0,8($0)\;jsr $0,OTS$HOME_ARGS" |
68aed21b RH |
5257 | [(set_attr "length" "16") |
5258 | (set_attr "type" "multi")]) | |
2ea844d3 RH |
5259 | |
5260 | ;; Close the trap shadow of preceeding instructions. This is generated | |
5261 | ;; by alpha_reorg. | |
5262 | ||
5263 | (define_insn "trapb" | |
4ed43ff8 | 5264 | [(unspec_volatile [(const_int 0)] 4)] |
2ea844d3 RH |
5265 | "" |
5266 | "trapb" | |
5267 | [(set_attr "type" "misc")]) | |
68aed21b RH |
5268 | |
5269 | ;; No-op instructions used by machine-dependant reorg to preserve | |
5270 | ;; alignment for instruction issue. | |
5271 | ||
5272 | (define_insn "nop" | |
5273 | [(const_int 0)] | |
5274 | "" | |
5275 | "nop" | |
5276 | [(set_attr "type" "ilog")]) | |
5277 | ||
5278 | (define_insn "fnop" | |
5279 | [(const_int 1)] | |
5280 | "TARGET_FP" | |
5281 | "fnop" | |
5282 | [(set_attr "type" "fcpys")]) | |
5283 | ||
5284 | (define_insn "unop" | |
5285 | [(const_int 2)] | |
5286 | "" | |
5287 | "unop") | |
5288 | ||
5289 | (define_insn "realign" | |
5290 | [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] 6)] | |
5291 | "" | |
5292 | ".align %0 #realign") | |
e83015a9 RH |
5293 | \f |
5294 | ;; Peepholes go at the end. | |
5295 | ||
5296 | ;; Optimize sign-extension of SImode loads. This shows up in the wake of | |
5297 | ;; reload when converting fp->int. | |
5298 | ;; | |
9c0e94a5 | 5299 | ;; ??? What to do now that we actually care about the packing and |
e83015a9 | 5300 | ;; alignment of instructions? Perhaps reload can be enlightened, or |
9c0e94a5 RH |
5301 | ;; the peephole pass moved up after reload but before sched2? |
5302 | ; | |
5303 | ;(define_peephole | |
5304 | ; [(set (match_operand:SI 0 "register_operand" "=r") | |
5305 | ; (match_operand:SI 1 "memory_operand" "m")) | |
5306 | ; (set (match_operand:DI 2 "register_operand" "=r") | |
5307 | ; (sign_extend:DI (match_dup 0)))] | |
5308 | ; "dead_or_set_p (insn, operands[0])" | |
5309 | ; "ldl %2,%1") | |
5310 | ; | |
5311 | ;(define_peephole | |
5312 | ; [(set (match_operand:SI 0 "register_operand" "=r") | |
5313 | ; (match_operand:SI 1 "hard_fp_register_operand" "f")) | |
5314 | ; (set (match_operand:DI 2 "register_operand" "=r") | |
5315 | ; (sign_extend:DI (match_dup 0)))] | |
de4abb91 | 5316 | ; "TARGET_FIX && dead_or_set_p (insn, operands[0])" |
9c0e94a5 | 5317 | ; "ftois %1,%2") |