Daily bump.
[gcc.git] / gcc / config / mips / loongson-mmi.md
1 ;; Machine description for Loongson MultiMedia extensions Instructions (MMI).
2 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
3 ;; Contributed by CodeSourcery.
4 ;;
5 ;; This file is part of GCC.
6 ;;
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)
10 ;; any later version.
11
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.
16
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/>.
20
21 (define_c_enum "unspec" [
22 UNSPEC_LOONGSON_PAVG
23 UNSPEC_LOONGSON_PCMPEQ
24 UNSPEC_LOONGSON_PCMPGT
25 UNSPEC_LOONGSON_PEXTR
26 UNSPEC_LOONGSON_PINSRH
27 UNSPEC_LOONGSON_VINIT
28 UNSPEC_LOONGSON_PMADD
29 UNSPEC_LOONGSON_PMOVMSK
30 UNSPEC_LOONGSON_PMULHU
31 UNSPEC_LOONGSON_PMULH
32 UNSPEC_LOONGSON_PMULU
33 UNSPEC_LOONGSON_PASUBUB
34 UNSPEC_LOONGSON_BIADD
35 UNSPEC_LOONGSON_PSADBH
36 UNSPEC_LOONGSON_PSHUFH
37 UNSPEC_LOONGSON_PUNPCKH
38 UNSPEC_LOONGSON_PUNPCKL
39 UNSPEC_LOONGSON_PADDD
40 UNSPEC_LOONGSON_PSUBD
41 UNSPEC_LOONGSON_DSLL
42 UNSPEC_LOONGSON_DSRL
43 ])
44
45 ;; Mode iterators and attributes.
46
47 ;; 64-bit vectors of bytes.
48 (define_mode_iterator VB [V8QI])
49
50 ;; 64-bit vectors of halfwords.
51 (define_mode_iterator VH [V4HI])
52
53 ;; 64-bit vectors of words.
54 (define_mode_iterator VW [V2SI])
55
56 ;; 64-bit vectors of halfwords and bytes.
57 (define_mode_iterator VHB [V4HI V8QI])
58
59 ;; 64-bit vectors of words and halfwords.
60 (define_mode_iterator VWH [V2SI V4HI])
61
62 ;; 64-bit vectors of words and bytes
63 (define_mode_iterator VWB [V2SI V8QI])
64
65 ;; 64-bit vectors of words, halfwords and bytes.
66 (define_mode_iterator VWHB [V2SI V4HI V8QI])
67
68 ;; 64-bit vectors of words, halfwords and bytes; and DImode.
69 (define_mode_iterator VWHBDI [V2SI V4HI V8QI DI])
70
71 ;; The Loongson instruction suffixes corresponding to the modes in the
72 ;; VWHBDI iterator.
73 (define_mode_attr V_suffix [(V2SI "w") (V4HI "h") (V8QI "b") (DI "d")])
74
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")])
78
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")])
82
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")])
86
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")])
90
91 ;; Given a vector type T, the inner mode.
92 (define_mode_attr V_inner [(V8QI "QI") (V4HI "HI") (V2SI "SI")])
93
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")])
97
98 ;; Move patterns.
99
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"
105 {
106 if (mips_legitimize_move (<MODE>mode, operands[0], operands[1]))
107 DONE;
108 })
109
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")])
118
119 ;; Initialization of a vector.
120
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"
125 {
126 mips_expand_vector_init (operands[0], operands[1]);
127 DONE;
128 })
129
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"
138 "dmtc1\t%z1,%0"
139 [(set_attr "move_type" "mtc")
140 (set_attr "mode" "DI")])
141
142 ;; Helper for vec_initv2si.
143 (define_insn "*vec_concatv2si"
144 [(set (match_operand:V2SI 0 "register_operand" "=f")
145 (vec_concat:V2SI
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")])
151
152 ;; Instruction patterns for SIMD instructions.
153
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")])
165
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")])
177
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")])
186
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"
199 "paddd\t%0,%1,%2"
200 [(set_attr "type" "fadd")])
201
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")])
210
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")])
219
220 ;; Logical AND NOT.
221 (define_insn "loongson_pandn_<V_suffix>"
222 [(set (match_operand:VWHBDI 0 "register_operand" "=f")
223 (and:VWHBDI
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"
227 "pandn\t%0,%1,%2"
228 [(set_attr "type" "fmul")])
229
230 ;; Logical AND.
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"
236 "and\t%0,%1,%2"
237 [(set_attr "type" "fmul")])
238
239 ;; Logical OR.
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"
245 "or\t%0,%1,%2"
246 [(set_attr "type" "fcvt")])
247
248 ;; Logical XOR.
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"
254 "xor\t%0,%1,%2"
255 [(set_attr "type" "fmul")])
256
257 ;; Logical NOR.
258 (define_insn "*loongson_nor"
259 [(set (match_operand:VWHB 0 "register_operand" "=f")
260 (and:VWHB
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"
264 "nor\t%0,%1,%2"
265 [(set_attr "type" "fmul")])
266
267 ;; Logical NOT.
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"
272 "nor\t%0,%1,%1"
273 [(set_attr "type" "fmul")])
274
275 ;; Average.
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")])
284
285 ;; Equality test.
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")])
294
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")])
304
305 ;; Extract halfword.
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"
312 "pextrh\t%0,%1,%2"
313 [(set_attr "type" "fcvt")])
314
315 ;; Insert halfword.
316 (define_insn "loongson_pinsrh_0"
317 [(set (match_operand:V4HI 0 "register_operand" "=f")
318 (vec_select:V4HI
319 (vec_concat:V8HI
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"
325 "pinsrh_0\t%0,%1,%2"
326 [(set_attr "type" "fdiv")])
327
328 (define_insn "loongson_pinsrh_1"
329 [(set (match_operand:V4HI 0 "register_operand" "=f")
330 (vec_select:V4HI
331 (vec_concat:V8HI
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"
337 "pinsrh_1\t%0,%1,%2"
338 [(set_attr "type" "fdiv")])
339
340 (define_insn "loongson_pinsrh_2"
341 [(set (match_operand:V4HI 0 "register_operand" "=f")
342 (vec_select:V4HI
343 (vec_concat:V8HI
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"
349 "pinsrh_2\t%0,%1,%2"
350 [(set_attr "type" "fdiv")])
351
352 (define_insn "loongson_pinsrh_3"
353 [(set (match_operand:V4HI 0 "register_operand" "=f")
354 (vec_select:V4HI
355 (vec_concat:V8HI
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"
361 "pinsrh_3\t%0,%1,%2"
362 [(set_attr "type" "fdiv")])
363
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")])
373
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"
381 {
382 rtx ext = gen_reg_rtx (SImode);
383 emit_move_insn (ext, gen_lowpart (SImode, operands[2]));
384 operands[2] = ext;
385 })
386
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"
394 "pmaddhw\t%0,%1,%2"
395 [(set_attr "type" "fmul")])
396
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"
403 {
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]));
407 DONE;
408 })
409
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"
416 "pmaxsh\t%0,%1,%2"
417 [(set_attr "type" "fadd")])
418
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"
424 {
425 mips_expand_vec_minmax (operands[0], operands[1], operands[2],
426 gen_loongson_pcmpgt<V_suffix>, false);
427 DONE;
428 })
429
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"
436 "pmaxub\t%0,%1,%2"
437 [(set_attr "type" "fadd")])
438
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"
445 "pminsh\t%0,%1,%2"
446 [(set_attr "type" "fadd")])
447
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"
453 {
454 mips_expand_vec_minmax (operands[0], operands[1], operands[2],
455 gen_loongson_pcmpgt<V_suffix>, true);
456 DONE;
457 })
458
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"
465 "pminub\t%0,%1,%2"
466 [(set_attr "type" "fadd")])
467
468 ;; Move byte mask.
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")])
476
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")])
486
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")])
496
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")])
505
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")])
515
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"
523 "pasubub\t%0,%1,%2"
524 [(set_attr "type" "fadd")])
525
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"
532 "biadd\t%0,%1"
533 [(set_attr "type" "fabs")])
534
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"
540 "biadd\t%0,%1"
541 [(set_attr "type" "fabs")])
542
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")])
552
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"
560 "pshufh\t%0,%1,%2"
561 [(set_attr "type" "fmul")])
562
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")])
571
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")])
580
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")])
589
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")])
598
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
602 ;; 'minus' here.
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"
609 "psubd\t%0,%1,%2"
610 [(set_attr "type" "fadd")])
611
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")])
620
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")])
629
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")
633 (vec_select:V8QI
634 (vec_concat:V16QI
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")])
644
645 (define_insn "loongson_punpckhhw"
646 [(set (match_operand:V4HI 0 "register_operand" "=f")
647 (vec_select:V4HI
648 (vec_concat:V8HI
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")])
656
657 (define_insn "loongson_punpckhhw_qi"
658 [(set (match_operand:V8QI 0 "register_operand" "=f")
659 (vec_select:V8QI
660 (vec_concat:V16QI
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")])
670
671 (define_insn "loongson_punpckhwd"
672 [(set (match_operand:V2SI 0 "register_operand" "=f")
673 (vec_select:V2SI
674 (vec_concat:V4SI
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")])
681
682 (define_insn "loongson_punpckhwd_qi"
683 [(set (match_operand:V8QI 0 "register_operand" "=f")
684 (vec_select:V8QI
685 (vec_concat:V16QI
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")])
695
696 (define_insn "loongson_punpckhwd_hi"
697 [(set (match_operand:V4HI 0 "register_operand" "=f")
698 (vec_select:V4HI
699 (vec_concat:V8HI
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")])
707
708 ;; Unpack low data.
709 (define_insn "loongson_punpcklbh"
710 [(set (match_operand:V8QI 0 "register_operand" "=f")
711 (vec_select:V8QI
712 (vec_concat:V16QI
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")])
722
723 (define_insn "loongson_punpcklhw"
724 [(set (match_operand:V4HI 0 "register_operand" "=f")
725 (vec_select:V4HI
726 (vec_concat:V8HI
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")])
734
735 (define_insn "*loongson_punpcklhw_qi"
736 [(set (match_operand:V8QI 0 "register_operand" "=f")
737 (vec_select:V8QI
738 (vec_concat:V16QI
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")])
748
749 (define_insn "loongson_punpcklwd"
750 [(set (match_operand:V2SI 0 "register_operand" "=f")
751 (vec_select:V2SI
752 (vec_concat:V4SI
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")])
759
760 (define_insn "*loongson_punpcklwd_qi"
761 [(set (match_operand:V8QI 0 "register_operand" "=f")
762 (vec_select:V8QI
763 (vec_concat:V16QI
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")])
773
774 (define_insn "*loongson_punpcklwd_hi"
775 [(set (match_operand:V4HI 0 "register_operand" "=f")
776 (vec_select:V4HI
777 (vec_concat:V8HI
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")])
785
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"
790 {
791 mips_expand_vec_unpack (operands, false, false);
792 DONE;
793 })
794
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"
799 {
800 mips_expand_vec_unpack (operands, false, true);
801 DONE;
802 })
803
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"
808 {
809 mips_expand_vec_unpack (operands, true, false);
810 DONE;
811 })
812
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"
817 {
818 mips_expand_vec_unpack (operands, true, true);
819 DONE;
820 })
821
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"
829 "dsll\t%0,%1,%2"
830 [(set_attr "type" "fcvt")])
831
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"
838 "dsrl\t%0,%1,%2"
839 [(set_attr "type" "fcvt")])
840
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"
847 "mfc1\t%0,%1"
848 [(set_attr "type" "mfc")])
849
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"
854 {
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));
858 DONE;
859 })
860
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"
865 {
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));
869 DONE;
870 })
871
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"
876 {
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));
880 DONE;
881 })
882
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"
887 {
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));
891 DONE;
892 })
893
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"
898 {
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));
902 DONE;
903 })