1 ;; Machine description for Loongson MultiMedia extensions Instructions (MMI).
2 ;; Copyright (C) 2008-2021 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 (define_c_enum "unspec" [
23 UNSPEC_LOONGSON_PCMPEQ
24 UNSPEC_LOONGSON_PCMPGT
26 UNSPEC_LOONGSON_PINSRH
29 UNSPEC_LOONGSON_PMOVMSK
30 UNSPEC_LOONGSON_PMULHU
33 UNSPEC_LOONGSON_PASUBUB
35 UNSPEC_LOONGSON_PSADBH
36 UNSPEC_LOONGSON_PSHUFH
37 UNSPEC_LOONGSON_PUNPCKH
38 UNSPEC_LOONGSON_PUNPCKL
45 ;; Mode iterators and attributes.
47 ;; 64-bit vectors of bytes.
48 (define_mode_iterator VB [V8QI])
50 ;; 64-bit vectors of halfwords.
51 (define_mode_iterator VH [V4HI])
53 ;; 64-bit vectors of words.
54 (define_mode_iterator VW [V2SI])
56 ;; 64-bit vectors of halfwords and bytes.
57 (define_mode_iterator VHB [V4HI V8QI])
59 ;; 64-bit vectors of words and halfwords.
60 (define_mode_iterator VWH [V2SI V4HI])
62 ;; 64-bit vectors of words and bytes
63 (define_mode_iterator VWB [V2SI V8QI])
65 ;; 64-bit vectors of words, halfwords and bytes.
66 (define_mode_iterator VWHB [V2SI V4HI V8QI])
68 ;; 64-bit vectors of words, halfwords and bytes; and DImode.
69 (define_mode_iterator VWHBDI [V2SI V4HI V8QI DI])
71 ;; The Loongson instruction suffixes corresponding to the modes in the
73 (define_mode_attr V_suffix [(V2SI "w") (V4HI "h") (V8QI "b") (DI "d")])
75 ;; Given a vector type T, the mode of a vector half the size of T
76 ;; and with the same number of elements.
77 (define_mode_attr V_squash [(V2SI "V2HI") (V4HI "V4QI")])
79 ;; Given a vector type T, the mode of a vector the same size as T
80 ;; but with half as many elements.
81 (define_mode_attr V_stretch_half [(V2SI "DI") (V4HI "V2SI") (V8QI "V4HI")])
83 ;; The Loongson instruction suffixes corresponding to the transformation
84 ;; expressed by V_stretch_half.
85 (define_mode_attr V_stretch_half_suffix [(V2SI "wd") (V4HI "hw") (V8QI "bh")])
87 ;; Given a vector type T, the mode of a vector the same size as T
88 ;; but with twice as many elements.
89 (define_mode_attr V_squash_double [(V2SI "V4HI") (V4HI "V8QI")])
91 ;; Given a vector type T, the inner mode.
92 (define_mode_attr V_inner [(V8QI "QI") (V4HI "HI") (V2SI "SI")])
94 ;; The Loongson instruction suffixes corresponding to the conversions
95 ;; specified by V_half_width.
96 (define_mode_attr V_squash_double_suffix [(V2SI "wh") (V4HI "hb")])
100 ;; Expander to legitimize moves involving values of vector modes.
101 (define_expand "mov<mode>"
102 [(set (match_operand:VWHB 0)
103 (match_operand:VWHB 1))]
104 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
106 if (mips_legitimize_move (<MODE>mode, operands[0], operands[1]))
110 ;; Handle legitimized moves between values of vector modes.
111 (define_insn "mov<mode>_internal"
112 [(set (match_operand:VWHB 0 "nonimmediate_operand" "=m,f,d,f, d, m, d")
113 (match_operand:VWHB 1 "move_operand" "f,m,f,dYG,dYG,dYG,m"))]
114 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
115 { return mips_output_move (operands[0], operands[1]); }
116 [(set_attr "move_type" "fpstore,fpload,mfc,mtc,move,store,load")
117 (set_attr "mode" "DI")])
119 ;; Initialization of a vector.
121 (define_expand "vec_init<mode><unitmode>"
122 [(set (match_operand:VWHB 0 "register_operand")
123 (match_operand 1 ""))]
124 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
126 mips_expand_vector_init (operands[0], operands[1]);
130 ;; Helper for vec_init. Initialize element 0 of the output from the input.
131 ;; All other elements are undefined.
132 (define_insn "loongson_vec_init1_<mode>"
133 [(set (match_operand:VHB 0 "register_operand" "=f")
134 (unspec:VHB [(truncate:<V_inner>
135 (match_operand:DI 1 "reg_or_0_operand" "Jd"))]
136 UNSPEC_LOONGSON_VINIT))]
137 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
139 [(set_attr "move_type" "mtc")
140 (set_attr "mode" "DI")])
142 ;; Helper for vec_initv2si.
143 (define_insn "*vec_concatv2si"
144 [(set (match_operand:V2SI 0 "register_operand" "=f")
146 (match_operand:SI 1 "register_operand" "f")
147 (match_operand:SI 2 "register_operand" "f")))]
148 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
149 "punpcklwd\t%0,%1,%2"
150 [(set_attr "type" "fcvt")])
152 ;; Instruction patterns for SIMD instructions.
154 ;; Pack with signed saturation.
155 (define_insn "vec_pack_ssat_<mode>"
156 [(set (match_operand:<V_squash_double> 0 "register_operand" "=f")
157 (vec_concat:<V_squash_double>
158 (ss_truncate:<V_squash>
159 (match_operand:VWH 1 "register_operand" "f"))
160 (ss_truncate:<V_squash>
161 (match_operand:VWH 2 "register_operand" "f"))))]
162 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
163 "packss<V_squash_double_suffix>\t%0,%1,%2"
164 [(set_attr "type" "fmul")])
166 ;; Pack with unsigned saturation.
167 (define_insn "vec_pack_usat_<mode>"
168 [(set (match_operand:<V_squash_double> 0 "register_operand" "=f")
169 (vec_concat:<V_squash_double>
170 (us_truncate:<V_squash>
171 (match_operand:VH 1 "register_operand" "f"))
172 (us_truncate:<V_squash>
173 (match_operand:VH 2 "register_operand" "f"))))]
174 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
175 "packus<V_squash_double_suffix>\t%0,%1,%2"
176 [(set_attr "type" "fmul")])
178 ;; Addition, treating overflow by wraparound.
179 (define_insn "add<mode>3"
180 [(set (match_operand:VWHB 0 "register_operand" "=f")
181 (plus:VWHB (match_operand:VWHB 1 "register_operand" "f")
182 (match_operand:VWHB 2 "register_operand" "f")))]
183 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
184 "padd<V_suffix>\t%0,%1,%2"
185 [(set_attr "type" "fadd")])
187 ;; Addition of doubleword integers stored in FP registers.
188 ;; Overflow is treated by wraparound.
189 ;; We use 'unspec' instead of 'plus' here to avoid clash with
190 ;; mips.md::add<mode>3. If 'plus' was used, then such instruction
191 ;; would be recognized as adddi3 and reload would make it use
192 ;; GPRs instead of FPRs.
193 (define_insn "loongson_paddd"
194 [(set (match_operand:DI 0 "register_operand" "=f")
195 (unspec:DI [(match_operand:DI 1 "register_operand" "f")
196 (match_operand:DI 2 "register_operand" "f")]
197 UNSPEC_LOONGSON_PADDD))]
198 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
200 [(set_attr "type" "fadd")])
202 ;; Addition, treating overflow by signed saturation.
203 (define_insn "ssadd<mode>3"
204 [(set (match_operand:VHB 0 "register_operand" "=f")
205 (ss_plus:VHB (match_operand:VHB 1 "register_operand" "f")
206 (match_operand:VHB 2 "register_operand" "f")))]
207 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
208 "padds<V_suffix>\t%0,%1,%2"
209 [(set_attr "type" "fadd")])
211 ;; Addition, treating overflow by unsigned saturation.
212 (define_insn "usadd<mode>3"
213 [(set (match_operand:VHB 0 "register_operand" "=f")
214 (us_plus:VHB (match_operand:VHB 1 "register_operand" "f")
215 (match_operand:VHB 2 "register_operand" "f")))]
216 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
217 "paddus<V_suffix>\t%0,%1,%2"
218 [(set_attr "type" "fadd")])
221 (define_insn "loongson_pandn_<V_suffix>"
222 [(set (match_operand:VWHBDI 0 "register_operand" "=f")
224 (not:VWHBDI (match_operand:VWHBDI 1 "register_operand" "f"))
225 (match_operand:VWHBDI 2 "register_operand" "f")))]
226 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
228 [(set_attr "type" "fmul")])
231 (define_insn "and<mode>3"
232 [(set (match_operand:VWHB 0 "register_operand" "=f")
233 (and:VWHB (match_operand:VWHB 1 "register_operand" "f")
234 (match_operand:VWHB 2 "register_operand" "f")))]
235 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
237 [(set_attr "type" "fmul")])
240 (define_insn "ior<mode>3"
241 [(set (match_operand:VWHB 0 "register_operand" "=f")
242 (ior:VWHB (match_operand:VWHB 1 "register_operand" "f")
243 (match_operand:VWHB 2 "register_operand" "f")))]
244 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
246 [(set_attr "type" "fcvt")])
249 (define_insn "xor<mode>3"
250 [(set (match_operand:VWHB 0 "register_operand" "=f")
251 (xor:VWHB (match_operand:VWHB 1 "register_operand" "f")
252 (match_operand:VWHB 2 "register_operand" "f")))]
253 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
255 [(set_attr "type" "fmul")])
258 (define_insn "*loongson_nor"
259 [(set (match_operand:VWHB 0 "register_operand" "=f")
261 (not:VWHB (match_operand:VWHB 1 "register_operand" "f"))
262 (not:VWHB (match_operand:VWHB 2 "register_operand" "f"))))]
263 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
265 [(set_attr "type" "fmul")])
268 (define_insn "one_cmpl<mode>2"
269 [(set (match_operand:VWHB 0 "register_operand" "=f")
270 (not:VWHB (match_operand:VWHB 1 "register_operand" "f")))]
271 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
273 [(set_attr "type" "fmul")])
276 (define_insn "loongson_pavg<V_suffix>"
277 [(set (match_operand:VHB 0 "register_operand" "=f")
278 (unspec:VHB [(match_operand:VHB 1 "register_operand" "f")
279 (match_operand:VHB 2 "register_operand" "f")]
280 UNSPEC_LOONGSON_PAVG))]
281 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
282 "pavg<V_suffix>\t%0,%1,%2"
283 [(set_attr "type" "fadd")])
286 (define_insn "loongson_pcmpeq<V_suffix>"
287 [(set (match_operand:VWHB 0 "register_operand" "=f")
288 (unspec:VWHB [(match_operand:VWHB 1 "register_operand" "f")
289 (match_operand:VWHB 2 "register_operand" "f")]
290 UNSPEC_LOONGSON_PCMPEQ))]
291 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
292 "pcmpeq<V_suffix>\t%0,%1,%2"
293 [(set_attr "type" "fadd")])
295 ;; Greater-than test.
296 (define_insn "loongson_pcmpgt<V_suffix>"
297 [(set (match_operand:VWHB 0 "register_operand" "=f")
298 (unspec:VWHB [(match_operand:VWHB 1 "register_operand" "f")
299 (match_operand:VWHB 2 "register_operand" "f")]
300 UNSPEC_LOONGSON_PCMPGT))]
301 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
302 "pcmpgt<V_suffix>\t%0,%1,%2"
303 [(set_attr "type" "fadd")])
306 (define_insn "loongson_pextrh"
307 [(set (match_operand:V4HI 0 "register_operand" "=f")
308 (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "f")
309 (match_operand:SI 2 "register_operand" "f")]
310 UNSPEC_LOONGSON_PEXTR))]
311 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
313 [(set_attr "type" "fcvt")])
316 (define_insn "loongson_pinsrh_0"
317 [(set (match_operand:V4HI 0 "register_operand" "=f")
320 (match_operand:V4HI 1 "register_operand" "f")
321 (match_operand:V4HI 2 "register_operand" "f"))
322 (parallel [(const_int 4) (const_int 1)
323 (const_int 2) (const_int 3)])))]
324 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
326 [(set_attr "type" "fdiv")])
328 (define_insn "loongson_pinsrh_1"
329 [(set (match_operand:V4HI 0 "register_operand" "=f")
332 (match_operand:V4HI 1 "register_operand" "f")
333 (match_operand:V4HI 2 "register_operand" "f"))
334 (parallel [(const_int 0) (const_int 4)
335 (const_int 2) (const_int 3)])))]
336 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
338 [(set_attr "type" "fdiv")])
340 (define_insn "loongson_pinsrh_2"
341 [(set (match_operand:V4HI 0 "register_operand" "=f")
344 (match_operand:V4HI 1 "register_operand" "f")
345 (match_operand:V4HI 2 "register_operand" "f"))
346 (parallel [(const_int 0) (const_int 1)
347 (const_int 4) (const_int 3)])))]
348 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
350 [(set_attr "type" "fdiv")])
352 (define_insn "loongson_pinsrh_3"
353 [(set (match_operand:V4HI 0 "register_operand" "=f")
356 (match_operand:V4HI 1 "register_operand" "f")
357 (match_operand:V4HI 2 "register_operand" "f"))
358 (parallel [(const_int 0) (const_int 1)
359 (const_int 2) (const_int 4)])))]
360 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
362 [(set_attr "type" "fdiv")])
364 (define_insn "*vec_setv4hi"
365 [(set (match_operand:V4HI 0 "register_operand" "=f")
366 (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "f")
367 (match_operand:SI 2 "register_operand" "f")
368 (match_operand:SI 3 "const_0_to_3_operand" "")]
369 UNSPEC_LOONGSON_PINSRH))]
370 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
371 "pinsrh_%3\t%0,%1,%2"
372 [(set_attr "type" "fdiv")])
374 (define_expand "vec_setv4hi"
375 [(set (match_operand:V4HI 0 "register_operand" "=f")
376 (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "f")
377 (match_operand:HI 2 "register_operand" "f")
378 (match_operand:SI 3 "const_0_to_3_operand" "")]
379 UNSPEC_LOONGSON_PINSRH))]
380 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
382 rtx ext = gen_reg_rtx (SImode);
383 emit_move_insn (ext, gen_lowpart (SImode, operands[2]));
387 ;; Multiply and add packed integers.
388 (define_insn "loongson_pmaddhw"
389 [(set (match_operand:V2SI 0 "register_operand" "=f")
390 (unspec:V2SI [(match_operand:V4HI 1 "register_operand" "f")
391 (match_operand:V4HI 2 "register_operand" "f")]
392 UNSPEC_LOONGSON_PMADD))]
393 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
395 [(set_attr "type" "fmul")])
397 (define_expand "sdot_prodv4hi"
398 [(match_operand:V2SI 0 "register_operand" "")
399 (match_operand:V4HI 1 "register_operand" "")
400 (match_operand:V4HI 2 "register_operand" "")
401 (match_operand:V2SI 3 "register_operand" "")]
402 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
404 rtx t = gen_reg_rtx (V2SImode);
405 emit_insn (gen_loongson_pmaddhw (t, operands[1], operands[2]));
406 emit_insn (gen_addv2si3 (operands[0], t, operands[3]));
410 ;; Maximum of signed halfwords.
411 (define_insn "smaxv4hi3"
412 [(set (match_operand:V4HI 0 "register_operand" "=f")
413 (smax:V4HI (match_operand:V4HI 1 "register_operand" "f")
414 (match_operand:V4HI 2 "register_operand" "f")))]
415 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
417 [(set_attr "type" "fadd")])
419 (define_expand "smax<mode>3"
420 [(match_operand:VWB 0 "register_operand" "")
421 (match_operand:VWB 1 "register_operand" "")
422 (match_operand:VWB 2 "register_operand" "")]
423 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
425 mips_expand_vec_minmax (operands[0], operands[1], operands[2],
426 gen_loongson_pcmpgt<V_suffix>, false);
430 ;; Maximum of unsigned bytes.
431 (define_insn "umaxv8qi3"
432 [(set (match_operand:V8QI 0 "register_operand" "=f")
433 (umax:V8QI (match_operand:V8QI 1 "register_operand" "f")
434 (match_operand:V8QI 2 "register_operand" "f")))]
435 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
437 [(set_attr "type" "fadd")])
439 ;; Minimum of signed halfwords.
440 (define_insn "sminv4hi3"
441 [(set (match_operand:V4HI 0 "register_operand" "=f")
442 (smin:V4HI (match_operand:V4HI 1 "register_operand" "f")
443 (match_operand:V4HI 2 "register_operand" "f")))]
444 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
446 [(set_attr "type" "fadd")])
448 (define_expand "smin<mode>3"
449 [(match_operand:VWB 0 "register_operand" "")
450 (match_operand:VWB 1 "register_operand" "")
451 (match_operand:VWB 2 "register_operand" "")]
452 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
454 mips_expand_vec_minmax (operands[0], operands[1], operands[2],
455 gen_loongson_pcmpgt<V_suffix>, true);
459 ;; Minimum of unsigned bytes.
460 (define_insn "uminv8qi3"
461 [(set (match_operand:V8QI 0 "register_operand" "=f")
462 (umin:V8QI (match_operand:V8QI 1 "register_operand" "f")
463 (match_operand:V8QI 2 "register_operand" "f")))]
464 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
466 [(set_attr "type" "fadd")])
469 (define_insn "loongson_pmovmsk<V_suffix>"
470 [(set (match_operand:VB 0 "register_operand" "=f")
471 (unspec:VB [(match_operand:VB 1 "register_operand" "f")]
472 UNSPEC_LOONGSON_PMOVMSK))]
473 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
474 "pmovmsk<V_suffix>\t%0,%1"
475 [(set_attr "type" "fabs")])
477 ;; Multiply unsigned integers and store high result.
478 (define_insn "umul<mode>3_highpart"
479 [(set (match_operand:VH 0 "register_operand" "=f")
480 (unspec:VH [(match_operand:VH 1 "register_operand" "f")
481 (match_operand:VH 2 "register_operand" "f")]
482 UNSPEC_LOONGSON_PMULHU))]
483 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
484 "pmulhu<V_suffix>\t%0,%1,%2"
485 [(set_attr "type" "fmul")])
487 ;; Multiply signed integers and store high result.
488 (define_insn "smul<mode>3_highpart"
489 [(set (match_operand:VH 0 "register_operand" "=f")
490 (unspec:VH [(match_operand:VH 1 "register_operand" "f")
491 (match_operand:VH 2 "register_operand" "f")]
492 UNSPEC_LOONGSON_PMULH))]
493 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
494 "pmulh<V_suffix>\t%0,%1,%2"
495 [(set_attr "type" "fmul")])
497 ;; Multiply signed integers and store low result.
498 (define_insn "mul<mode>3"
499 [(set (match_operand:VH 0 "register_operand" "=f")
500 (mult:VH (match_operand:VH 1 "register_operand" "f")
501 (match_operand:VH 2 "register_operand" "f")))]
502 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
503 "pmull<V_suffix>\t%0,%1,%2"
504 [(set_attr "type" "fmul")])
506 ;; Multiply unsigned word integers.
507 (define_insn "loongson_pmulu<V_suffix>"
508 [(set (match_operand:DI 0 "register_operand" "=f")
509 (unspec:DI [(match_operand:VW 1 "register_operand" "f")
510 (match_operand:VW 2 "register_operand" "f")]
511 UNSPEC_LOONGSON_PMULU))]
512 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
513 "pmulu<V_suffix>\t%0,%1,%2"
514 [(set_attr "type" "fmul")])
516 ;; Absolute difference.
517 (define_insn "loongson_pasubub"
518 [(set (match_operand:VB 0 "register_operand" "=f")
519 (unspec:VB [(match_operand:VB 1 "register_operand" "f")
520 (match_operand:VB 2 "register_operand" "f")]
521 UNSPEC_LOONGSON_PASUBUB))]
522 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
524 [(set_attr "type" "fadd")])
526 ;; Sum of unsigned byte integers.
527 (define_insn "loongson_biadd"
528 [(set (match_operand:<V_stretch_half> 0 "register_operand" "=f")
529 (unspec:<V_stretch_half> [(match_operand:VB 1 "register_operand" "f")]
530 UNSPEC_LOONGSON_BIADD))]
531 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
533 [(set_attr "type" "fabs")])
535 (define_insn "reduc_uplus_v8qi"
536 [(set (match_operand:V8QI 0 "register_operand" "=f")
537 (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "f")]
538 UNSPEC_LOONGSON_BIADD))]
539 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
541 [(set_attr "type" "fabs")])
543 ;; Sum of absolute differences.
544 (define_insn "loongson_psadbh"
545 [(set (match_operand:<V_stretch_half> 0 "register_operand" "=f")
546 (unspec:<V_stretch_half> [(match_operand:VB 1 "register_operand" "f")
547 (match_operand:VB 2 "register_operand" "f")]
548 UNSPEC_LOONGSON_PSADBH))]
549 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
550 "pasubub\t%0,%1,%2;biadd\t%0,%0"
551 [(set_attr "type" "fadd")])
553 ;; Shuffle halfwords.
554 (define_insn "loongson_pshufh"
555 [(set (match_operand:VH 0 "register_operand" "=f")
556 (unspec:VH [(match_operand:VH 1 "register_operand" "f")
557 (match_operand:SI 2 "register_operand" "f")]
558 UNSPEC_LOONGSON_PSHUFH))]
559 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
561 [(set_attr "type" "fmul")])
563 ;; Shift left logical.
564 (define_insn "ashl<mode>3"
565 [(set (match_operand:VWH 0 "register_operand" "=f")
566 (ashift:VWH (match_operand:VWH 1 "register_operand" "f")
567 (match_operand:SI 2 "register_operand" "f")))]
568 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
569 "psll<V_suffix>\t%0,%1,%2"
570 [(set_attr "type" "fcvt")])
572 ;; Shift right arithmetic.
573 (define_insn "ashr<mode>3"
574 [(set (match_operand:VWH 0 "register_operand" "=f")
575 (ashiftrt:VWH (match_operand:VWH 1 "register_operand" "f")
576 (match_operand:SI 2 "register_operand" "f")))]
577 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
578 "psra<V_suffix>\t%0,%1,%2"
579 [(set_attr "type" "fcvt")])
581 ;; Shift right logical.
582 (define_insn "lshr<mode>3"
583 [(set (match_operand:VWH 0 "register_operand" "=f")
584 (lshiftrt:VWH (match_operand:VWH 1 "register_operand" "f")
585 (match_operand:SI 2 "register_operand" "f")))]
586 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
587 "psrl<V_suffix>\t%0,%1,%2"
588 [(set_attr "type" "fcvt")])
590 ;; Subtraction, treating overflow by wraparound.
591 (define_insn "sub<mode>3"
592 [(set (match_operand:VWHB 0 "register_operand" "=f")
593 (minus:VWHB (match_operand:VWHB 1 "register_operand" "f")
594 (match_operand:VWHB 2 "register_operand" "f")))]
595 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
596 "psub<V_suffix>\t%0,%1,%2"
597 [(set_attr "type" "fadd")])
599 ;; Subtraction of doubleword integers stored in FP registers.
600 ;; Overflow is treated by wraparound.
601 ;; See loongson_paddd for the reason we use 'unspec' rather than
603 (define_insn "loongson_psubd"
604 [(set (match_operand:DI 0 "register_operand" "=f")
605 (unspec:DI [(match_operand:DI 1 "register_operand" "f")
606 (match_operand:DI 2 "register_operand" "f")]
607 UNSPEC_LOONGSON_PSUBD))]
608 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
610 [(set_attr "type" "fadd")])
612 ;; Subtraction, treating overflow by signed saturation.
613 (define_insn "sssub<mode>3"
614 [(set (match_operand:VHB 0 "register_operand" "=f")
615 (ss_minus:VHB (match_operand:VHB 1 "register_operand" "f")
616 (match_operand:VHB 2 "register_operand" "f")))]
617 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
618 "psubs<V_suffix>\t%0,%1,%2"
619 [(set_attr "type" "fadd")])
621 ;; Subtraction, treating overflow by unsigned saturation.
622 (define_insn "ussub<mode>3"
623 [(set (match_operand:VHB 0 "register_operand" "=f")
624 (us_minus:VHB (match_operand:VHB 1 "register_operand" "f")
625 (match_operand:VHB 2 "register_operand" "f")))]
626 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
627 "psubus<V_suffix>\t%0,%1,%2"
628 [(set_attr "type" "fadd")])
630 ;; Unpack high data. Recall that Loongson only runs in little-endian.
631 (define_insn "loongson_punpckhbh"
632 [(set (match_operand:V8QI 0 "register_operand" "=f")
635 (match_operand:V8QI 1 "register_operand" "f")
636 (match_operand:V8QI 2 "register_operand" "f"))
637 (parallel [(const_int 4) (const_int 12)
638 (const_int 5) (const_int 13)
639 (const_int 6) (const_int 14)
640 (const_int 7) (const_int 15)])))]
641 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
642 "punpckhbh\t%0,%1,%2"
643 [(set_attr "type" "fdiv")])
645 (define_insn "loongson_punpckhhw"
646 [(set (match_operand:V4HI 0 "register_operand" "=f")
649 (match_operand:V4HI 1 "register_operand" "f")
650 (match_operand:V4HI 2 "register_operand" "f"))
651 (parallel [(const_int 2) (const_int 6)
652 (const_int 3) (const_int 7)])))]
653 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
654 "punpckhhw\t%0,%1,%2"
655 [(set_attr "type" "fdiv")])
657 (define_insn "loongson_punpckhhw_qi"
658 [(set (match_operand:V8QI 0 "register_operand" "=f")
661 (match_operand:V8QI 1 "register_operand" "f")
662 (match_operand:V8QI 2 "register_operand" "f"))
663 (parallel [(const_int 4) (const_int 5)
664 (const_int 12) (const_int 13)
665 (const_int 6) (const_int 7)
666 (const_int 14) (const_int 15)])))]
667 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
668 "punpckhhw\t%0,%1,%2"
669 [(set_attr "type" "fdiv")])
671 (define_insn "loongson_punpckhwd"
672 [(set (match_operand:V2SI 0 "register_operand" "=f")
675 (match_operand:V2SI 1 "register_operand" "f")
676 (match_operand:V2SI 2 "register_operand" "f"))
677 (parallel [(const_int 1) (const_int 3)])))]
678 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
679 "punpckhwd\t%0,%1,%2"
680 [(set_attr "type" "fcvt")])
682 (define_insn "loongson_punpckhwd_qi"
683 [(set (match_operand:V8QI 0 "register_operand" "=f")
686 (match_operand:V8QI 1 "register_operand" "f")
687 (match_operand:V8QI 2 "register_operand" "f"))
688 (parallel [(const_int 4) (const_int 5)
689 (const_int 6) (const_int 7)
690 (const_int 12) (const_int 13)
691 (const_int 14) (const_int 15)])))]
692 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
693 "punpckhwd\t%0,%1,%2"
694 [(set_attr "type" "fcvt")])
696 (define_insn "loongson_punpckhwd_hi"
697 [(set (match_operand:V4HI 0 "register_operand" "=f")
700 (match_operand:V4HI 1 "register_operand" "f")
701 (match_operand:V4HI 2 "register_operand" "f"))
702 (parallel [(const_int 2) (const_int 3)
703 (const_int 6) (const_int 7)])))]
704 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
705 "punpckhwd\t%0,%1,%2"
706 [(set_attr "type" "fcvt")])
709 (define_insn "loongson_punpcklbh"
710 [(set (match_operand:V8QI 0 "register_operand" "=f")
713 (match_operand:V8QI 1 "register_operand" "f")
714 (match_operand:V8QI 2 "register_operand" "f"))
715 (parallel [(const_int 0) (const_int 8)
716 (const_int 1) (const_int 9)
717 (const_int 2) (const_int 10)
718 (const_int 3) (const_int 11)])))]
719 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
720 "punpcklbh\t%0,%1,%2"
721 [(set_attr "type" "fdiv")])
723 (define_insn "loongson_punpcklhw"
724 [(set (match_operand:V4HI 0 "register_operand" "=f")
727 (match_operand:V4HI 1 "register_operand" "f")
728 (match_operand:V4HI 2 "register_operand" "f"))
729 (parallel [(const_int 0) (const_int 4)
730 (const_int 1) (const_int 5)])))]
731 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
732 "punpcklhw\t%0,%1,%2"
733 [(set_attr "type" "fdiv")])
735 (define_insn "*loongson_punpcklhw_qi"
736 [(set (match_operand:V8QI 0 "register_operand" "=f")
739 (match_operand:V8QI 1 "register_operand" "f")
740 (match_operand:V8QI 2 "register_operand" "f"))
741 (parallel [(const_int 0) (const_int 1)
742 (const_int 8) (const_int 9)
743 (const_int 2) (const_int 3)
744 (const_int 10) (const_int 11)])))]
745 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
746 "punpcklhw\t%0,%1,%2"
747 [(set_attr "type" "fdiv")])
749 (define_insn "loongson_punpcklwd"
750 [(set (match_operand:V2SI 0 "register_operand" "=f")
753 (match_operand:V2SI 1 "register_operand" "f")
754 (match_operand:V2SI 2 "register_operand" "f"))
755 (parallel [(const_int 0) (const_int 2)])))]
756 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
757 "punpcklwd\t%0,%1,%2"
758 [(set_attr "type" "fcvt")])
760 (define_insn "*loongson_punpcklwd_qi"
761 [(set (match_operand:V8QI 0 "register_operand" "=f")
764 (match_operand:V8QI 1 "register_operand" "f")
765 (match_operand:V8QI 2 "register_operand" "f"))
766 (parallel [(const_int 0) (const_int 1)
767 (const_int 2) (const_int 3)
768 (const_int 8) (const_int 9)
769 (const_int 10) (const_int 11)])))]
770 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
771 "punpcklwd\t%0,%1,%2"
772 [(set_attr "type" "fcvt")])
774 (define_insn "*loongson_punpcklwd_hi"
775 [(set (match_operand:V4HI 0 "register_operand" "=f")
778 (match_operand:V4HI 1 "register_operand" "f")
779 (match_operand:V4HI 2 "register_operand" "f"))
780 (parallel [(const_int 0) (const_int 1)
781 (const_int 4) (const_int 5)])))]
782 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
783 "punpcklwd\t%0,%1,%2"
784 [(set_attr "type" "fcvt")])
786 (define_expand "vec_unpacks_lo_<mode>"
787 [(match_operand:<V_stretch_half> 0 "register_operand" "")
788 (match_operand:VHB 1 "register_operand" "")]
789 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
791 mips_expand_vec_unpack (operands, false, false);
795 (define_expand "vec_unpacks_hi_<mode>"
796 [(match_operand:<V_stretch_half> 0 "register_operand" "")
797 (match_operand:VHB 1 "register_operand" "")]
798 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
800 mips_expand_vec_unpack (operands, false, true);
804 (define_expand "vec_unpacku_lo_<mode>"
805 [(match_operand:<V_stretch_half> 0 "register_operand" "")
806 (match_operand:VHB 1 "register_operand" "")]
807 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
809 mips_expand_vec_unpack (operands, true, false);
813 (define_expand "vec_unpacku_hi_<mode>"
814 [(match_operand:<V_stretch_half> 0 "register_operand" "")
815 (match_operand:VHB 1 "register_operand" "")]
816 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
818 mips_expand_vec_unpack (operands, true, true);
822 ;; Whole vector shifts, used for reduction epilogues.
823 (define_insn "vec_shl_<mode>"
824 [(set (match_operand:VWHBDI 0 "register_operand" "=f")
825 (unspec:VWHBDI [(match_operand:VWHBDI 1 "register_operand" "f")
826 (match_operand:SI 2 "register_operand" "f")]
827 UNSPEC_LOONGSON_DSLL))]
828 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
830 [(set_attr "type" "fcvt")])
832 (define_insn "vec_shr_<mode>"
833 [(set (match_operand:VWHBDI 0 "register_operand" "=f")
834 (unspec:VWHBDI [(match_operand:VWHBDI 1 "register_operand" "f")
835 (match_operand:SI 2 "register_operand" "f")]
836 UNSPEC_LOONGSON_DSRL))]
837 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
839 [(set_attr "type" "fcvt")])
841 (define_insn "vec_loongson_extract_lo_<mode>"
842 [(set (match_operand:<V_inner> 0 "register_operand" "=r")
843 (vec_select:<V_inner>
844 (match_operand:VWHB 1 "register_operand" "f")
845 (parallel [(const_int 0)])))]
846 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
848 [(set_attr "type" "mfc")])
850 (define_expand "reduc_plus_scal_<mode>"
851 [(match_operand:<V_inner> 0 "register_operand" "")
852 (match_operand:VWHB 1 "register_operand" "")]
853 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
855 rtx tmp = gen_reg_rtx (GET_MODE (operands[1]));
856 mips_expand_vec_reduc (tmp, operands[1], gen_add<mode>3);
857 emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp));
861 (define_expand "reduc_smax_scal_<mode>"
862 [(match_operand:<V_inner> 0 "register_operand" "")
863 (match_operand:VWHB 1 "register_operand" "")]
864 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
866 rtx tmp = gen_reg_rtx (GET_MODE (operands[1]));
867 mips_expand_vec_reduc (tmp, operands[1], gen_smax<mode>3);
868 emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp));
872 (define_expand "reduc_smin_scal_<mode>"
873 [(match_operand:<V_inner> 0 "register_operand" "")
874 (match_operand:VWHB 1 "register_operand" "")]
875 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
877 rtx tmp = gen_reg_rtx (GET_MODE (operands[1]));
878 mips_expand_vec_reduc (tmp, operands[1], gen_smin<mode>3);
879 emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp));
883 (define_expand "reduc_umax_scal_<mode>"
884 [(match_operand:<V_inner> 0 "register_operand" "")
885 (match_operand:VB 1 "register_operand" "")]
886 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
888 rtx tmp = gen_reg_rtx (GET_MODE (operands[1]));
889 mips_expand_vec_reduc (tmp, operands[1], gen_umax<mode>3);
890 emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp));
894 (define_expand "reduc_umin_scal_<mode>"
895 [(match_operand:<V_inner> 0 "register_operand" "")
896 (match_operand:VB 1 "register_operand" "")]
897 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
899 rtx tmp = gen_reg_rtx (GET_MODE (operands[1]));
900 mips_expand_vec_reduc (tmp, operands[1], gen_umin<mode>3);
901 emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp));