1 ;; Machine description for ST Microelectronics Loongson-2E/2F.
2 ;; Copyright (C) 2008 Free Software Foundation, Inc.
3 ;; Contributed by CodeSourcery.
5 ;; This file is part of GCC.
7 ;; GCC 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 3, or (at your option)
12 ;; GCC 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.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
21 ;; Mode iterators and attributes.
23 ;; 64-bit vectors of bytes.
24 (define_mode_iterator VB [V8QI])
26 ;; 64-bit vectors of halfwords.
27 (define_mode_iterator VH [V4HI])
29 ;; 64-bit vectors of words.
30 (define_mode_iterator VW [V2SI])
32 ;; 64-bit vectors of halfwords and bytes.
33 (define_mode_iterator VHB [V4HI V8QI])
35 ;; 64-bit vectors of words and halfwords.
36 (define_mode_iterator VWH [V2SI V4HI])
38 ;; 64-bit vectors of words, halfwords and bytes.
39 (define_mode_iterator VWHB [V2SI V4HI V8QI])
41 ;; 64-bit vectors of words, halfwords and bytes; and DImode.
42 (define_mode_iterator VWHBDI [V2SI V4HI V8QI DI])
44 ;; The Loongson instruction suffixes corresponding to the modes in the
46 (define_mode_attr V_suffix [(V2SI "w") (V4HI "h") (V8QI "b") (DI "d")])
48 ;; Given a vector type T, the mode of a vector half the size of T
49 ;; and with the same number of elements.
50 (define_mode_attr V_squash [(V2SI "V2HI") (V4HI "V4QI")])
52 ;; Given a vector type T, the mode of a vector the same size as T
53 ;; but with half as many elements.
54 (define_mode_attr V_stretch_half [(V2SI "DI") (V4HI "V2SI") (V8QI "V4HI")])
56 ;; The Loongson instruction suffixes corresponding to the transformation
57 ;; expressed by V_stretch_half.
58 (define_mode_attr V_stretch_half_suffix [(V2SI "wd") (V4HI "hw") (V8QI "bh")])
60 ;; Given a vector type T, the mode of a vector the same size as T
61 ;; but with twice as many elements.
62 (define_mode_attr V_squash_double [(V2SI "V4HI") (V4HI "V8QI")])
64 ;; The Loongson instruction suffixes corresponding to the conversions
65 ;; specified by V_half_width.
66 (define_mode_attr V_squash_double_suffix [(V2SI "wh") (V4HI "hb")])
70 ;; Expander to legitimize moves involving values of vector modes.
71 (define_expand "mov<mode>"
72 [(set (match_operand:VWHB 0)
73 (match_operand:VWHB 1))]
74 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
76 if (mips_legitimize_move (<MODE>mode, operands[0], operands[1]))
80 ;; Handle legitimized moves between values of vector modes.
81 (define_insn "mov<mode>_internal"
82 [(set (match_operand:VWHB 0 "nonimmediate_operand" "=m,f,d,f, d, m, d")
83 (match_operand:VWHB 1 "move_operand" "f,m,f,dYG,dYG,dYG,m"))]
84 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
85 { return mips_output_move (operands[0], operands[1]); }
86 [(set_attr "move_type" "fpstore,fpload,mfc,mtc,move,store,load")
87 (set_attr "mode" "DI")])
89 ;; Initialization of a vector.
91 (define_expand "vec_init<mode>"
92 [(set (match_operand:VWHB 0 "register_operand")
93 (match_operand 1 ""))]
94 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
96 mips_expand_vector_init (operands[0], operands[1]);
100 ;; Instruction patterns for SIMD instructions.
102 ;; Pack with signed saturation.
103 (define_insn "vec_pack_ssat_<mode>"
104 [(set (match_operand:<V_squash_double> 0 "register_operand" "=f")
105 (vec_concat:<V_squash_double>
106 (ss_truncate:<V_squash>
107 (match_operand:VWH 1 "register_operand" "f"))
108 (ss_truncate:<V_squash>
109 (match_operand:VWH 2 "register_operand" "f"))))]
110 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
111 "packss<V_squash_double_suffix>\t%0,%1,%2"
112 [(set_attr "type" "fmul")])
114 ;; Pack with unsigned saturation.
115 (define_insn "vec_pack_usat_<mode>"
116 [(set (match_operand:<V_squash_double> 0 "register_operand" "=f")
117 (vec_concat:<V_squash_double>
118 (us_truncate:<V_squash>
119 (match_operand:VH 1 "register_operand" "f"))
120 (us_truncate:<V_squash>
121 (match_operand:VH 2 "register_operand" "f"))))]
122 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
123 "packus<V_squash_double_suffix>\t%0,%1,%2"
124 [(set_attr "type" "fmul")])
126 ;; Addition, treating overflow by wraparound.
127 (define_insn "add<mode>3"
128 [(set (match_operand:VWHB 0 "register_operand" "=f")
129 (plus:VWHB (match_operand:VWHB 1 "register_operand" "f")
130 (match_operand:VWHB 2 "register_operand" "f")))]
131 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
132 "padd<V_suffix>\t%0,%1,%2"
133 [(set_attr "type" "fadd")])
135 ;; Addition of doubleword integers stored in FP registers.
136 ;; Overflow is treated by wraparound.
137 ;; We use 'unspec' instead of 'plus' here to avoid clash with
138 ;; mips.md::add<mode>3. If 'plus' was used, then such instruction
139 ;; would be recognized as adddi3 and reload would make it use
140 ;; GPRs instead of FPRs.
141 (define_insn "loongson_paddd"
142 [(set (match_operand:DI 0 "register_operand" "=f")
143 (unspec:DI [(match_operand:DI 1 "register_operand" "f")
144 (match_operand:DI 2 "register_operand" "f")]
145 UNSPEC_LOONGSON_PADDD))]
146 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
148 [(set_attr "type" "fadd")])
150 ;; Addition, treating overflow by signed saturation.
151 (define_insn "ssadd<mode>3"
152 [(set (match_operand:VHB 0 "register_operand" "=f")
153 (ss_plus:VHB (match_operand:VHB 1 "register_operand" "f")
154 (match_operand:VHB 2 "register_operand" "f")))]
155 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
156 "padds<V_suffix>\t%0,%1,%2"
157 [(set_attr "type" "fadd")])
159 ;; Addition, treating overflow by unsigned saturation.
160 (define_insn "usadd<mode>3"
161 [(set (match_operand:VHB 0 "register_operand" "=f")
162 (us_plus:VHB (match_operand:VHB 1 "register_operand" "f")
163 (match_operand:VHB 2 "register_operand" "f")))]
164 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
165 "paddus<V_suffix>\t%0,%1,%2"
166 [(set_attr "type" "fadd")])
169 (define_insn "loongson_pandn_<V_suffix>"
170 [(set (match_operand:VWHBDI 0 "register_operand" "=f")
172 (not:VWHBDI (match_operand:VWHBDI 1 "register_operand" "f"))
173 (match_operand:VWHBDI 2 "register_operand" "f")))]
174 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
176 [(set_attr "type" "fmul")])
179 (define_insn "loongson_pavg<V_suffix>"
180 [(set (match_operand:VHB 0 "register_operand" "=f")
181 (unspec:VHB [(match_operand:VHB 1 "register_operand" "f")
182 (match_operand:VHB 2 "register_operand" "f")]
183 UNSPEC_LOONGSON_PAVG))]
184 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
185 "pavg<V_suffix>\t%0,%1,%2"
186 [(set_attr "type" "fadd")])
189 (define_insn "loongson_pcmpeq<V_suffix>"
190 [(set (match_operand:VWHB 0 "register_operand" "=f")
191 (unspec:VWHB [(match_operand:VWHB 1 "register_operand" "f")
192 (match_operand:VWHB 2 "register_operand" "f")]
193 UNSPEC_LOONGSON_PCMPEQ))]
194 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
195 "pcmpeq<V_suffix>\t%0,%1,%2"
196 [(set_attr "type" "fadd")])
198 ;; Greater-than test.
199 (define_insn "loongson_pcmpgt<V_suffix>"
200 [(set (match_operand:VWHB 0 "register_operand" "=f")
201 (unspec:VWHB [(match_operand:VWHB 1 "register_operand" "f")
202 (match_operand:VWHB 2 "register_operand" "f")]
203 UNSPEC_LOONGSON_PCMPGT))]
204 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
205 "pcmpgt<V_suffix>\t%0,%1,%2"
206 [(set_attr "type" "fadd")])
209 (define_insn "loongson_pextr<V_suffix>"
210 [(set (match_operand:VH 0 "register_operand" "=f")
211 (unspec:VH [(match_operand:VH 1 "register_operand" "f")
212 (match_operand:SI 2 "register_operand" "f")]
213 UNSPEC_LOONGSON_PEXTR))]
214 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
215 "pextr<V_suffix>\t%0,%1,%2"
216 [(set_attr "type" "fmul")])
219 (define_insn "loongson_pinsr<V_suffix>_0"
220 [(set (match_operand:VH 0 "register_operand" "=f")
221 (unspec:VH [(match_operand:VH 1 "register_operand" "f")
222 (match_operand:VH 2 "register_operand" "f")]
223 UNSPEC_LOONGSON_PINSR_0))]
224 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
225 "pinsr<V_suffix>_0\t%0,%1,%2"
226 [(set_attr "type" "fdiv")])
228 (define_insn "loongson_pinsr<V_suffix>_1"
229 [(set (match_operand:VH 0 "register_operand" "=f")
230 (unspec:VH [(match_operand:VH 1 "register_operand" "f")
231 (match_operand:VH 2 "register_operand" "f")]
232 UNSPEC_LOONGSON_PINSR_1))]
233 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
234 "pinsr<V_suffix>_1\t%0,%1,%2"
235 [(set_attr "type" "fdiv")])
237 (define_insn "loongson_pinsr<V_suffix>_2"
238 [(set (match_operand:VH 0 "register_operand" "=f")
239 (unspec:VH [(match_operand:VH 1 "register_operand" "f")
240 (match_operand:VH 2 "register_operand" "f")]
241 UNSPEC_LOONGSON_PINSR_2))]
242 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
243 "pinsr<V_suffix>_2\t%0,%1,%2"
244 [(set_attr "type" "fdiv")])
246 (define_insn "loongson_pinsr<V_suffix>_3"
247 [(set (match_operand:VH 0 "register_operand" "=f")
248 (unspec:VH [(match_operand:VH 1 "register_operand" "f")
249 (match_operand:VH 2 "register_operand" "f")]
250 UNSPEC_LOONGSON_PINSR_3))]
251 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
252 "pinsr<V_suffix>_3\t%0,%1,%2"
253 [(set_attr "type" "fdiv")])
255 ;; Multiply and add packed integers.
256 (define_insn "loongson_pmadd<V_stretch_half_suffix>"
257 [(set (match_operand:<V_stretch_half> 0 "register_operand" "=f")
258 (unspec:<V_stretch_half> [(match_operand:VH 1 "register_operand" "f")
259 (match_operand:VH 2 "register_operand" "f")]
260 UNSPEC_LOONGSON_PMADD))]
261 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
262 "pmadd<V_stretch_half_suffix>\t%0,%1,%2"
263 [(set_attr "type" "fmul")])
265 ;; Maximum of signed halfwords.
266 (define_insn "smax<mode>3"
267 [(set (match_operand:VH 0 "register_operand" "=f")
268 (smax:VH (match_operand:VH 1 "register_operand" "f")
269 (match_operand:VH 2 "register_operand" "f")))]
270 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
271 "pmaxs<V_suffix>\t%0,%1,%2"
272 [(set_attr "type" "fadd")])
274 ;; Maximum of unsigned bytes.
275 (define_insn "umax<mode>3"
276 [(set (match_operand:VB 0 "register_operand" "=f")
277 (umax:VB (match_operand:VB 1 "register_operand" "f")
278 (match_operand:VB 2 "register_operand" "f")))]
279 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
280 "pmaxu<V_suffix>\t%0,%1,%2"
281 [(set_attr "type" "fadd")])
283 ;; Minimum of signed halfwords.
284 (define_insn "smin<mode>3"
285 [(set (match_operand:VH 0 "register_operand" "=f")
286 (smin:VH (match_operand:VH 1 "register_operand" "f")
287 (match_operand:VH 2 "register_operand" "f")))]
288 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
289 "pmins<V_suffix>\t%0,%1,%2"
290 [(set_attr "type" "fadd")])
292 ;; Minimum of unsigned bytes.
293 (define_insn "umin<mode>3"
294 [(set (match_operand:VB 0 "register_operand" "=f")
295 (umin:VB (match_operand:VB 1 "register_operand" "f")
296 (match_operand:VB 2 "register_operand" "f")))]
297 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
298 "pminu<V_suffix>\t%0,%1,%2"
299 [(set_attr "type" "fadd")])
302 (define_insn "loongson_pmovmsk<V_suffix>"
303 [(set (match_operand:VB 0 "register_operand" "=f")
304 (unspec:VB [(match_operand:VB 1 "register_operand" "f")]
305 UNSPEC_LOONGSON_PMOVMSK))]
306 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
307 "pmovmsk<V_suffix>\t%0,%1"
308 [(set_attr "type" "fabs")])
310 ;; Multiply unsigned integers and store high result.
311 (define_insn "umul<mode>3_highpart"
312 [(set (match_operand:VH 0 "register_operand" "=f")
313 (unspec:VH [(match_operand:VH 1 "register_operand" "f")
314 (match_operand:VH 2 "register_operand" "f")]
315 UNSPEC_LOONGSON_PMULHU))]
316 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
317 "pmulhu<V_suffix>\t%0,%1,%2"
318 [(set_attr "type" "fmul")])
320 ;; Multiply signed integers and store high result.
321 (define_insn "smul<mode>3_highpart"
322 [(set (match_operand:VH 0 "register_operand" "=f")
323 (unspec:VH [(match_operand:VH 1 "register_operand" "f")
324 (match_operand:VH 2 "register_operand" "f")]
325 UNSPEC_LOONGSON_PMULH))]
326 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
327 "pmulh<V_suffix>\t%0,%1,%2"
328 [(set_attr "type" "fmul")])
330 ;; Multiply signed integers and store low result.
331 (define_insn "loongson_pmull<V_suffix>"
332 [(set (match_operand:VH 0 "register_operand" "=f")
333 (unspec:VH [(match_operand:VH 1 "register_operand" "f")
334 (match_operand:VH 2 "register_operand" "f")]
335 UNSPEC_LOONGSON_PMULL))]
336 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
337 "pmull<V_suffix>\t%0,%1,%2"
338 [(set_attr "type" "fmul")])
340 ;; Multiply unsigned word integers.
341 (define_insn "loongson_pmulu<V_suffix>"
342 [(set (match_operand:DI 0 "register_operand" "=f")
343 (unspec:DI [(match_operand:VW 1 "register_operand" "f")
344 (match_operand:VW 2 "register_operand" "f")]
345 UNSPEC_LOONGSON_PMULU))]
346 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
347 "pmulu<V_suffix>\t%0,%1,%2"
348 [(set_attr "type" "fmul")])
350 ;; Absolute difference.
351 (define_insn "loongson_pasubub"
352 [(set (match_operand:VB 0 "register_operand" "=f")
353 (unspec:VB [(match_operand:VB 1 "register_operand" "f")
354 (match_operand:VB 2 "register_operand" "f")]
355 UNSPEC_LOONGSON_PASUBUB))]
356 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
358 [(set_attr "type" "fadd")])
360 ;; Sum of unsigned byte integers.
361 (define_insn "reduc_uplus_<mode>"
362 [(set (match_operand:<V_stretch_half> 0 "register_operand" "=f")
363 (unspec:<V_stretch_half> [(match_operand:VB 1 "register_operand" "f")]
364 UNSPEC_LOONGSON_BIADD))]
365 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
367 [(set_attr "type" "fabs")])
369 ;; Sum of absolute differences.
370 (define_insn "loongson_psadbh"
371 [(set (match_operand:<V_stretch_half> 0 "register_operand" "=f")
372 (unspec:<V_stretch_half> [(match_operand:VB 1 "register_operand" "f")
373 (match_operand:VB 2 "register_operand" "f")]
374 UNSPEC_LOONGSON_PSADBH))]
375 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
376 "pasubub\t%0,%1,%2;biadd\t%0,%0"
377 [(set_attr "type" "fadd")])
379 ;; Shuffle halfwords.
380 (define_insn "loongson_pshufh"
381 [(set (match_operand:VH 0 "register_operand" "=f")
382 (unspec:VH [(match_operand:VH 1 "register_operand" "0")
383 (match_operand:VH 2 "register_operand" "f")
384 (match_operand:SI 3 "register_operand" "f")]
385 UNSPEC_LOONGSON_PSHUFH))]
386 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
388 [(set_attr "type" "fmul")])
390 ;; Shift left logical.
391 (define_insn "loongson_psll<V_suffix>"
392 [(set (match_operand:VWH 0 "register_operand" "=f")
393 (ashift:VWH (match_operand:VWH 1 "register_operand" "f")
394 (match_operand:SI 2 "register_operand" "f")))]
395 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
396 "psll<V_suffix>\t%0,%1,%2"
397 [(set_attr "type" "fmul")])
399 ;; Shift right arithmetic.
400 (define_insn "loongson_psra<V_suffix>"
401 [(set (match_operand:VWH 0 "register_operand" "=f")
402 (ashiftrt:VWH (match_operand:VWH 1 "register_operand" "f")
403 (match_operand:SI 2 "register_operand" "f")))]
404 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
405 "psra<V_suffix>\t%0,%1,%2"
406 [(set_attr "type" "fdiv")])
408 ;; Shift right logical.
409 (define_insn "loongson_psrl<V_suffix>"
410 [(set (match_operand:VWH 0 "register_operand" "=f")
411 (lshiftrt:VWH (match_operand:VWH 1 "register_operand" "f")
412 (match_operand:SI 2 "register_operand" "f")))]
413 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
414 "psrl<V_suffix>\t%0,%1,%2"
415 [(set_attr "type" "fdiv")])
417 ;; Subtraction, treating overflow by wraparound.
418 (define_insn "sub<mode>3"
419 [(set (match_operand:VWHB 0 "register_operand" "=f")
420 (minus:VWHB (match_operand:VWHB 1 "register_operand" "f")
421 (match_operand:VWHB 2 "register_operand" "f")))]
422 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
423 "psub<V_suffix>\t%0,%1,%2"
424 [(set_attr "type" "fadd")])
426 ;; Subtraction of doubleword integers stored in FP registers.
427 ;; Overflow is treated by wraparound.
428 ;; See loongson_paddd for the reason we use 'unspec' rather than
430 (define_insn "loongson_psubd"
431 [(set (match_operand:DI 0 "register_operand" "=f")
432 (unspec:DI [(match_operand:DI 1 "register_operand" "f")
433 (match_operand:DI 2 "register_operand" "f")]
434 UNSPEC_LOONGSON_PSUBD))]
435 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
437 [(set_attr "type" "fadd")])
439 ;; Subtraction, treating overflow by signed saturation.
440 (define_insn "sssub<mode>3"
441 [(set (match_operand:VHB 0 "register_operand" "=f")
442 (ss_minus:VHB (match_operand:VHB 1 "register_operand" "f")
443 (match_operand:VHB 2 "register_operand" "f")))]
444 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
445 "psubs<V_suffix>\t%0,%1,%2"
446 [(set_attr "type" "fadd")])
448 ;; Subtraction, treating overflow by unsigned saturation.
449 (define_insn "ussub<mode>3"
450 [(set (match_operand:VHB 0 "register_operand" "=f")
451 (us_minus:VHB (match_operand:VHB 1 "register_operand" "f")
452 (match_operand:VHB 2 "register_operand" "f")))]
453 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
454 "psubus<V_suffix>\t%0,%1,%2"
455 [(set_attr "type" "fadd")])
458 (define_insn "vec_interleave_high<mode>"
459 [(set (match_operand:VWHB 0 "register_operand" "=f")
460 (unspec:VWHB [(match_operand:VWHB 1 "register_operand" "f")
461 (match_operand:VWHB 2 "register_operand" "f")]
462 UNSPEC_LOONGSON_PUNPCKH))]
463 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
464 "punpckh<V_stretch_half_suffix>\t%0,%1,%2"
465 [(set_attr "type" "fdiv")])
468 (define_insn "vec_interleave_low<mode>"
469 [(set (match_operand:VWHB 0 "register_operand" "=f")
470 (unspec:VWHB [(match_operand:VWHB 1 "register_operand" "f")
471 (match_operand:VWHB 2 "register_operand" "f")]
472 UNSPEC_LOONGSON_PUNPCKL))]
473 "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
474 "punpckl<V_stretch_half_suffix>\t%0,%1,%2"
475 [(set_attr "type" "fdiv")])