MIPS32R6 and MIPS64R6 support
[official-gcc.git] / gcc / config / mips / loongson.md
blob08691313c69dd3af73cc261e4bad379060f1f9f2
1 ;; Machine description for Loongson-specific patterns, such as
2 ;; ST Microelectronics Loongson-2E/2F etc.
3 ;; Copyright (C) 2008-2014 Free Software Foundation, Inc.
4 ;; Contributed by CodeSourcery.
5 ;;
6 ;; This file is part of GCC.
7 ;;
8 ;; GCC is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 3, or (at your option)
11 ;; any later version.
13 ;; GCC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3.  If not see
20 ;; <http://www.gnu.org/licenses/>.
22 (define_c_enum "unspec" [
23   UNSPEC_LOONGSON_PAVG
24   UNSPEC_LOONGSON_PCMPEQ
25   UNSPEC_LOONGSON_PCMPGT
26   UNSPEC_LOONGSON_PEXTR
27   UNSPEC_LOONGSON_PINSRH
28   UNSPEC_LOONGSON_VINIT
29   UNSPEC_LOONGSON_PMADD
30   UNSPEC_LOONGSON_PMOVMSK
31   UNSPEC_LOONGSON_PMULHU
32   UNSPEC_LOONGSON_PMULH
33   UNSPEC_LOONGSON_PMULU
34   UNSPEC_LOONGSON_PASUBUB
35   UNSPEC_LOONGSON_BIADD
36   UNSPEC_LOONGSON_PSADBH
37   UNSPEC_LOONGSON_PSHUFH
38   UNSPEC_LOONGSON_PUNPCKH
39   UNSPEC_LOONGSON_PUNPCKL
40   UNSPEC_LOONGSON_PADDD
41   UNSPEC_LOONGSON_PSUBD
42   UNSPEC_LOONGSON_DSLL
43   UNSPEC_LOONGSON_DSRL
46 ;; Mode iterators and attributes.
48 ;; 64-bit vectors of bytes.
49 (define_mode_iterator VB [V8QI])
51 ;; 64-bit vectors of halfwords.
52 (define_mode_iterator VH [V4HI])
54 ;; 64-bit vectors of words.
55 (define_mode_iterator VW [V2SI])
57 ;; 64-bit vectors of halfwords and bytes.
58 (define_mode_iterator VHB [V4HI V8QI])
60 ;; 64-bit vectors of words and halfwords.
61 (define_mode_iterator VWH [V2SI V4HI])
63 ;; 64-bit vectors of words and bytes
64 (define_mode_iterator VWB [V2SI V8QI])
66 ;; 64-bit vectors of words, halfwords and bytes.
67 (define_mode_iterator VWHB [V2SI V4HI V8QI])
69 ;; 64-bit vectors of words, halfwords and bytes; and DImode.
70 (define_mode_iterator VWHBDI [V2SI V4HI V8QI DI])
72 ;; The Loongson instruction suffixes corresponding to the modes in the
73 ;; VWHBDI iterator.
74 (define_mode_attr V_suffix [(V2SI "w") (V4HI "h") (V8QI "b") (DI "d")])
76 ;; Given a vector type T, the mode of a vector half the size of T
77 ;; and with the same number of elements.
78 (define_mode_attr V_squash [(V2SI "V2HI") (V4HI "V4QI")])
80 ;; Given a vector type T, the mode of a vector the same size as T
81 ;; but with half as many elements.
82 (define_mode_attr V_stretch_half [(V2SI "DI") (V4HI "V2SI") (V8QI "V4HI")])
84 ;; The Loongson instruction suffixes corresponding to the transformation
85 ;; expressed by V_stretch_half.
86 (define_mode_attr V_stretch_half_suffix [(V2SI "wd") (V4HI "hw") (V8QI "bh")])
88 ;; Given a vector type T, the mode of a vector the same size as T
89 ;; but with twice as many elements.
90 (define_mode_attr V_squash_double [(V2SI "V4HI") (V4HI "V8QI")])
92 ;; Given a vector type T, the inner mode.
93 (define_mode_attr V_inner [(V8QI "QI") (V4HI "HI") (V2SI "SI")])
95 ;; The Loongson instruction suffixes corresponding to the conversions
96 ;; specified by V_half_width.
97 (define_mode_attr V_squash_double_suffix [(V2SI "wh") (V4HI "hb")])
99 ;; Move patterns.
101 ;; Expander to legitimize moves involving values of vector modes.
102 (define_expand "mov<mode>"
103   [(set (match_operand:VWHB 0)
104         (match_operand:VWHB 1))]
105   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
107   if (mips_legitimize_move (<MODE>mode, operands[0], operands[1]))
108     DONE;
111 ;; Handle legitimized moves between values of vector modes.
112 (define_insn "mov<mode>_internal"
113   [(set (match_operand:VWHB 0 "nonimmediate_operand" "=m,f,d,f,  d,  m,  d")
114         (match_operand:VWHB 1 "move_operand"          "f,m,f,dYG,dYG,dYG,m"))]
115   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
116   { return mips_output_move (operands[0], operands[1]); }
117   [(set_attr "move_type" "fpstore,fpload,mfc,mtc,move,store,load")
118    (set_attr "mode" "DI")])
120 ;; Initialization of a vector.
122 (define_expand "vec_init<mode>"
123   [(set (match_operand:VWHB 0 "register_operand")
124         (match_operand 1 ""))]
125   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
127   mips_expand_vector_init (operands[0], operands[1]);
128   DONE;
131 ;; Helper for vec_init.  Initialize element 0 of the output from the input.
132 ;; All other elements are undefined.
133 (define_insn "loongson_vec_init1_<mode>"
134   [(set (match_operand:VHB 0 "register_operand" "=f")
135         (unspec:VHB [(truncate:<V_inner>
136                        (match_operand:DI 1 "reg_or_0_operand" "Jd"))]
137                     UNSPEC_LOONGSON_VINIT))]
138   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
139   "dmtc1\t%z1,%0"
140   [(set_attr "move_type" "mtc")
141    (set_attr "mode" "DI")])
143 ;; Helper for vec_initv2si.
144 (define_insn "*vec_concatv2si"
145   [(set (match_operand:V2SI 0 "register_operand" "=f")
146         (vec_concat:V2SI
147           (match_operand:SI 1 "register_operand" "f")
148           (match_operand:SI 2 "register_operand" "f")))]
149   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
150   "punpcklwd\t%0,%1,%2"
151   [(set_attr "type" "fcvt")])
153 ;; Instruction patterns for SIMD instructions.
155 ;; Pack with signed saturation.
156 (define_insn "vec_pack_ssat_<mode>"
157   [(set (match_operand:<V_squash_double> 0 "register_operand" "=f")
158         (vec_concat:<V_squash_double>
159          (ss_truncate:<V_squash>
160           (match_operand:VWH 1 "register_operand" "f"))
161          (ss_truncate:<V_squash>
162           (match_operand:VWH 2 "register_operand" "f"))))]
163   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
164   "packss<V_squash_double_suffix>\t%0,%1,%2"
165   [(set_attr "type" "fmul")])
167 ;; Pack with unsigned saturation.
168 (define_insn "vec_pack_usat_<mode>"
169   [(set (match_operand:<V_squash_double> 0 "register_operand" "=f")
170         (vec_concat:<V_squash_double>
171          (us_truncate:<V_squash>
172           (match_operand:VH 1 "register_operand" "f"))
173          (us_truncate:<V_squash>
174           (match_operand:VH 2 "register_operand" "f"))))]
175   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
176   "packus<V_squash_double_suffix>\t%0,%1,%2"
177   [(set_attr "type" "fmul")])
179 ;; Addition, treating overflow by wraparound.
180 (define_insn "add<mode>3"
181   [(set (match_operand:VWHB 0 "register_operand" "=f")
182         (plus:VWHB (match_operand:VWHB 1 "register_operand" "f")
183                    (match_operand:VWHB 2 "register_operand" "f")))]
184   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
185   "padd<V_suffix>\t%0,%1,%2"
186   [(set_attr "type" "fadd")])
188 ;; Addition of doubleword integers stored in FP registers.
189 ;; Overflow is treated by wraparound.
190 ;; We use 'unspec' instead of 'plus' here to avoid clash with
191 ;; mips.md::add<mode>3.  If 'plus' was used, then such instruction
192 ;; would be recognized as adddi3 and reload would make it use
193 ;; GPRs instead of FPRs.
194 (define_insn "loongson_paddd"
195   [(set (match_operand:DI 0 "register_operand" "=f")
196         (unspec:DI [(match_operand:DI 1 "register_operand" "f")
197                     (match_operand:DI 2 "register_operand" "f")]
198                    UNSPEC_LOONGSON_PADDD))]
199   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
200   "paddd\t%0,%1,%2"
201   [(set_attr "type" "fadd")])
203 ;; Addition, treating overflow by signed saturation.
204 (define_insn "ssadd<mode>3"
205   [(set (match_operand:VHB 0 "register_operand" "=f")
206         (ss_plus:VHB (match_operand:VHB 1 "register_operand" "f")
207                      (match_operand:VHB 2 "register_operand" "f")))]
208   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
209   "padds<V_suffix>\t%0,%1,%2"
210   [(set_attr "type" "fadd")])
212 ;; Addition, treating overflow by unsigned saturation.
213 (define_insn "usadd<mode>3"
214   [(set (match_operand:VHB 0 "register_operand" "=f")
215         (us_plus:VHB (match_operand:VHB 1 "register_operand" "f")
216                      (match_operand:VHB 2 "register_operand" "f")))]
217   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
218   "paddus<V_suffix>\t%0,%1,%2"
219   [(set_attr "type" "fadd")])
221 ;; Logical AND NOT.
222 (define_insn "loongson_pandn_<V_suffix>"
223   [(set (match_operand:VWHBDI 0 "register_operand" "=f")
224         (and:VWHBDI
225          (not:VWHBDI (match_operand:VWHBDI 1 "register_operand" "f"))
226          (match_operand:VWHBDI 2 "register_operand" "f")))]
227   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
228   "pandn\t%0,%1,%2"
229   [(set_attr "type" "fmul")])
231 ;; Logical AND.
232 (define_insn "and<mode>3"
233   [(set (match_operand:VWHB 0 "register_operand" "=f")
234         (and:VWHB (match_operand:VWHB 1 "register_operand" "f")
235                   (match_operand:VWHB 2 "register_operand" "f")))]
236   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
237   "and\t%0,%1,%2"
238   [(set_attr "type" "fmul")])
240 ;; Logical OR.
241 (define_insn "ior<mode>3"
242   [(set (match_operand:VWHB 0 "register_operand" "=f")
243         (ior:VWHB (match_operand:VWHB 1 "register_operand" "f")
244                   (match_operand:VWHB 2 "register_operand" "f")))]
245   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
246   "or\t%0,%1,%2"
247   [(set_attr "type" "fcvt")])
249 ;; Logical XOR.
250 (define_insn "xor<mode>3"
251   [(set (match_operand:VWHB 0 "register_operand" "=f")
252         (xor:VWHB (match_operand:VWHB 1 "register_operand" "f")
253                   (match_operand:VWHB 2 "register_operand" "f")))]
254   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
255   "xor\t%0,%1,%2"
256   [(set_attr "type" "fmul")])
258 ;; Logical NOR.
259 (define_insn "*loongson_nor"
260   [(set (match_operand:VWHB 0 "register_operand" "=f")
261         (and:VWHB
262           (not:VWHB (match_operand:VWHB 1 "register_operand" "f"))
263           (not:VWHB (match_operand:VWHB 2 "register_operand" "f"))))]
264   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
265   "nor\t%0,%1,%2"
266   [(set_attr "type" "fmul")])
268 ;; Logical NOT.
269 (define_insn "one_cmpl<mode>2"
270   [(set (match_operand:VWHB 0 "register_operand" "=f")
271         (not:VWHB (match_operand:VWHB 1 "register_operand" "f")))]
272   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
273   "nor\t%0,%1,%1"
274   [(set_attr "type" "fmul")])
276 ;; Average.
277 (define_insn "loongson_pavg<V_suffix>"
278   [(set (match_operand:VHB 0 "register_operand" "=f")
279         (unspec:VHB [(match_operand:VHB 1 "register_operand" "f")
280                      (match_operand:VHB 2 "register_operand" "f")]
281                     UNSPEC_LOONGSON_PAVG))]
282   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
283   "pavg<V_suffix>\t%0,%1,%2"
284   [(set_attr "type" "fadd")])
286 ;; Equality test.
287 (define_insn "loongson_pcmpeq<V_suffix>"
288   [(set (match_operand:VWHB 0 "register_operand" "=f")
289         (unspec:VWHB [(match_operand:VWHB 1 "register_operand" "f")
290                       (match_operand:VWHB 2 "register_operand" "f")]
291                      UNSPEC_LOONGSON_PCMPEQ))]
292   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
293   "pcmpeq<V_suffix>\t%0,%1,%2"
294   [(set_attr "type" "fadd")])
296 ;; Greater-than test.
297 (define_insn "loongson_pcmpgt<V_suffix>"
298   [(set (match_operand:VWHB 0 "register_operand" "=f")
299         (unspec:VWHB [(match_operand:VWHB 1 "register_operand" "f")
300                       (match_operand:VWHB 2 "register_operand" "f")]
301                      UNSPEC_LOONGSON_PCMPGT))]
302   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
303   "pcmpgt<V_suffix>\t%0,%1,%2"
304   [(set_attr "type" "fadd")])
306 ;; Extract halfword.
307 (define_insn "loongson_pextrh"
308   [(set (match_operand:V4HI 0 "register_operand" "=f")
309         (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "f")
310                       (match_operand:SI 2 "register_operand" "f")]
311                    UNSPEC_LOONGSON_PEXTR))]
312   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
313   "pextrh\t%0,%1,%2"
314   [(set_attr "type" "fcvt")])
316 ;; Insert halfword.
317 (define_insn "loongson_pinsrh_0"
318   [(set (match_operand:V4HI 0 "register_operand" "=f")
319         (vec_select:V4HI
320           (vec_concat:V8HI
321             (match_operand:V4HI 1 "register_operand" "f")
322             (match_operand:V4HI 2 "register_operand" "f"))
323           (parallel [(const_int 4) (const_int 1)
324                      (const_int 2) (const_int 3)])))]
325   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
326   "pinsrh_0\t%0,%1,%2"
327   [(set_attr "type" "fdiv")])
329 (define_insn "loongson_pinsrh_1"
330   [(set (match_operand:V4HI 0 "register_operand" "=f")
331         (vec_select:V4HI
332           (vec_concat:V8HI
333             (match_operand:V4HI 1 "register_operand" "f")
334             (match_operand:V4HI 2 "register_operand" "f"))
335           (parallel [(const_int 0) (const_int 4)
336                      (const_int 2) (const_int 3)])))]
337   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
338   "pinsrh_1\t%0,%1,%2"
339   [(set_attr "type" "fdiv")])
341 (define_insn "loongson_pinsrh_2"
342   [(set (match_operand:V4HI 0 "register_operand" "=f")
343         (vec_select:V4HI
344           (vec_concat:V8HI
345             (match_operand:V4HI 1 "register_operand" "f")
346             (match_operand:V4HI 2 "register_operand" "f"))
347           (parallel [(const_int 0) (const_int 1)
348                      (const_int 4) (const_int 3)])))]
349   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
350   "pinsrh_2\t%0,%1,%2"
351   [(set_attr "type" "fdiv")])
353 (define_insn "loongson_pinsrh_3"
354   [(set (match_operand:V4HI 0 "register_operand" "=f")
355         (vec_select:V4HI
356           (vec_concat:V8HI
357             (match_operand:V4HI 1 "register_operand" "f")
358             (match_operand:V4HI 2 "register_operand" "f"))
359           (parallel [(const_int 0) (const_int 1)
360                      (const_int 2) (const_int 4)])))]
361   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
362   "pinsrh_3\t%0,%1,%2"
363   [(set_attr "type" "fdiv")])
365 (define_insn "*vec_setv4hi"
366   [(set (match_operand:V4HI 0 "register_operand" "=f")
367         (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "f")
368                       (match_operand:SI 2 "register_operand" "f")
369                       (match_operand:SI 3 "const_0_to_3_operand" "")]
370                      UNSPEC_LOONGSON_PINSRH))]
371   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
372   "pinsrh_%3\t%0,%1,%2"
373   [(set_attr "type" "fdiv")])
375 (define_expand "vec_setv4hi"
376   [(set (match_operand:V4HI 0 "register_operand" "=f")
377         (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "f")
378                       (match_operand:HI 2 "register_operand" "f")
379                       (match_operand:SI 3 "const_0_to_3_operand" "")]
380                      UNSPEC_LOONGSON_PINSRH))]
381   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
383   rtx ext = gen_reg_rtx (SImode);
384   emit_move_insn (ext, gen_lowpart (SImode, operands[1]));
385   operands[1] = ext;
388 ;; Multiply and add packed integers.
389 (define_insn "loongson_pmaddhw"
390   [(set (match_operand:V2SI 0 "register_operand" "=f")
391         (unspec:V2SI [(match_operand:V4HI 1 "register_operand" "f")
392                       (match_operand:V4HI 2 "register_operand" "f")]
393                      UNSPEC_LOONGSON_PMADD))]
394   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
395   "pmaddhw\t%0,%1,%2"
396   [(set_attr "type" "fmul")])
398 (define_expand "sdot_prodv4hi"
399   [(match_operand:V2SI 0 "register_operand" "")
400    (match_operand:V4HI 1 "register_operand" "")
401    (match_operand:V4HI 2 "register_operand" "")
402    (match_operand:V2SI 3 "register_operand" "")]
403   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
405   rtx t = gen_reg_rtx (V2SImode);
406   emit_insn (gen_loongson_pmaddhw (t, operands[1], operands[2]));
407   emit_insn (gen_addv2si3 (operands[0], t, operands[3]));
408   DONE;
411 ;; Maximum of signed halfwords.
412 (define_insn "smaxv4hi3"
413   [(set (match_operand:V4HI 0 "register_operand" "=f")
414         (smax:V4HI (match_operand:V4HI 1 "register_operand" "f")
415                    (match_operand:V4HI 2 "register_operand" "f")))]
416   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
417   "pmaxsh\t%0,%1,%2"
418   [(set_attr "type" "fadd")])
420 (define_expand "smax<mode>3"
421   [(match_operand:VWB 0 "register_operand" "")
422    (match_operand:VWB 1 "register_operand" "")
423    (match_operand:VWB 2 "register_operand" "")]
424   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
426   mips_expand_vec_minmax (operands[0], operands[1], operands[2],
427                           gen_loongson_pcmpgt<V_suffix>, false);
428   DONE;
431 ;; Maximum of unsigned bytes.
432 (define_insn "umaxv8qi3"
433   [(set (match_operand:V8QI 0 "register_operand" "=f")
434         (umax:V8QI (match_operand:V8QI 1 "register_operand" "f")
435                    (match_operand:V8QI 2 "register_operand" "f")))]
436   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
437   "pmaxub\t%0,%1,%2"
438   [(set_attr "type" "fadd")])
440 ;; Minimum of signed halfwords.
441 (define_insn "sminv4hi3"
442   [(set (match_operand:V4HI 0 "register_operand" "=f")
443         (smin:V4HI (match_operand:V4HI 1 "register_operand" "f")
444                    (match_operand:V4HI 2 "register_operand" "f")))]
445   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
446   "pminsh\t%0,%1,%2"
447   [(set_attr "type" "fadd")])
449 (define_expand "smin<mode>3"
450   [(match_operand:VWB 0 "register_operand" "")
451    (match_operand:VWB 1 "register_operand" "")
452    (match_operand:VWB 2 "register_operand" "")]
453   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
455   mips_expand_vec_minmax (operands[0], operands[1], operands[2],
456                           gen_loongson_pcmpgt<V_suffix>, true);
457   DONE;
460 ;; Minimum of unsigned bytes.
461 (define_insn "uminv8qi3"
462   [(set (match_operand:V8QI 0 "register_operand" "=f")
463         (umin:V8QI (match_operand:V8QI 1 "register_operand" "f")
464                    (match_operand:V8QI 2 "register_operand" "f")))]
465   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
466   "pminub\t%0,%1,%2"
467   [(set_attr "type" "fadd")])
469 ;; Move byte mask.
470 (define_insn "loongson_pmovmsk<V_suffix>"
471   [(set (match_operand:VB 0 "register_operand" "=f")
472         (unspec:VB [(match_operand:VB 1 "register_operand" "f")]
473                    UNSPEC_LOONGSON_PMOVMSK))]
474   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
475   "pmovmsk<V_suffix>\t%0,%1"
476   [(set_attr "type" "fabs")])
478 ;; Multiply unsigned integers and store high result.
479 (define_insn "umul<mode>3_highpart"
480   [(set (match_operand:VH 0 "register_operand" "=f")
481         (unspec:VH [(match_operand:VH 1 "register_operand" "f")
482                     (match_operand:VH 2 "register_operand" "f")]
483                    UNSPEC_LOONGSON_PMULHU))]
484   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
485   "pmulhu<V_suffix>\t%0,%1,%2"
486   [(set_attr "type" "fmul")])
488 ;; Multiply signed integers and store high result.
489 (define_insn "smul<mode>3_highpart"
490   [(set (match_operand:VH 0 "register_operand" "=f")
491         (unspec:VH [(match_operand:VH 1 "register_operand" "f")
492                     (match_operand:VH 2 "register_operand" "f")]
493                    UNSPEC_LOONGSON_PMULH))]
494   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
495   "pmulh<V_suffix>\t%0,%1,%2"
496   [(set_attr "type" "fmul")])
498 ;; Multiply signed integers and store low result.
499 (define_insn "mul<mode>3"
500   [(set (match_operand:VH 0 "register_operand" "=f")
501         (mult:VH (match_operand:VH 1 "register_operand" "f")
502                  (match_operand:VH 2 "register_operand" "f")))]
503   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
504   "pmull<V_suffix>\t%0,%1,%2"
505   [(set_attr "type" "fmul")])
507 ;; Multiply unsigned word integers.
508 (define_insn "loongson_pmulu<V_suffix>"
509   [(set (match_operand:DI 0 "register_operand" "=f")
510         (unspec:DI [(match_operand:VW 1 "register_operand" "f")
511                     (match_operand:VW 2 "register_operand" "f")]
512                    UNSPEC_LOONGSON_PMULU))]
513   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
514   "pmulu<V_suffix>\t%0,%1,%2"
515   [(set_attr "type" "fmul")])
517 ;; Absolute difference.
518 (define_insn "loongson_pasubub"
519   [(set (match_operand:VB 0 "register_operand" "=f")
520         (unspec:VB [(match_operand:VB 1 "register_operand" "f")
521                     (match_operand:VB 2 "register_operand" "f")]
522                    UNSPEC_LOONGSON_PASUBUB))]
523   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
524   "pasubub\t%0,%1,%2"
525   [(set_attr "type" "fadd")])
527 ;; Sum of unsigned byte integers.
528 (define_insn "loongson_biadd"
529   [(set (match_operand:<V_stretch_half> 0 "register_operand" "=f")
530         (unspec:<V_stretch_half> [(match_operand:VB 1 "register_operand" "f")]
531                                  UNSPEC_LOONGSON_BIADD))]
532   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
533   "biadd\t%0,%1"
534   [(set_attr "type" "fabs")])
536 (define_insn "reduc_uplus_v8qi"
537   [(set (match_operand:V8QI 0 "register_operand" "=f")
538         (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "f")]
539                      UNSPEC_LOONGSON_BIADD))]
540   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
541   "biadd\t%0,%1"
542   [(set_attr "type" "fabs")])
544 ;; Sum of absolute differences.
545 (define_insn "loongson_psadbh"
546   [(set (match_operand:<V_stretch_half> 0 "register_operand" "=f")
547         (unspec:<V_stretch_half> [(match_operand:VB 1 "register_operand" "f")
548                                   (match_operand:VB 2 "register_operand" "f")]
549                                  UNSPEC_LOONGSON_PSADBH))]
550   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
551   "pasubub\t%0,%1,%2;biadd\t%0,%0"
552   [(set_attr "type" "fadd")])
554 ;; Shuffle halfwords.
555 (define_insn "loongson_pshufh"
556   [(set (match_operand:VH 0 "register_operand" "=f")
557         (unspec:VH [(match_operand:VH 1 "register_operand" "f")
558                     (match_operand:SI 2 "register_operand" "f")]
559                    UNSPEC_LOONGSON_PSHUFH))]
560   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
561   "pshufh\t%0,%1,%2"
562   [(set_attr "type" "fmul")])
564 ;; Shift left logical.
565 (define_insn "ashl<mode>3"
566   [(set (match_operand:VWH 0 "register_operand" "=f")
567         (ashift:VWH (match_operand:VWH 1 "register_operand" "f")
568                     (match_operand:SI 2 "register_operand" "f")))]
569   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
570   "psll<V_suffix>\t%0,%1,%2"
571   [(set_attr "type" "fcvt")])
573 ;; Shift right arithmetic.
574 (define_insn "ashr<mode>3"
575   [(set (match_operand:VWH 0 "register_operand" "=f")
576         (ashiftrt:VWH (match_operand:VWH 1 "register_operand" "f")
577                       (match_operand:SI 2 "register_operand" "f")))]
578   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
579   "psra<V_suffix>\t%0,%1,%2"
580   [(set_attr "type" "fcvt")])
582 ;; Shift right logical.
583 (define_insn "lshr<mode>3"
584   [(set (match_operand:VWH 0 "register_operand" "=f")
585         (lshiftrt:VWH (match_operand:VWH 1 "register_operand" "f")
586                       (match_operand:SI 2 "register_operand" "f")))]
587   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
588   "psrl<V_suffix>\t%0,%1,%2"
589   [(set_attr "type" "fcvt")])
591 ;; Subtraction, treating overflow by wraparound.
592 (define_insn "sub<mode>3"
593   [(set (match_operand:VWHB 0 "register_operand" "=f")
594         (minus:VWHB (match_operand:VWHB 1 "register_operand" "f")
595                     (match_operand:VWHB 2 "register_operand" "f")))]
596   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
597   "psub<V_suffix>\t%0,%1,%2"
598   [(set_attr "type" "fadd")])
600 ;; Subtraction of doubleword integers stored in FP registers.
601 ;; Overflow is treated by wraparound.
602 ;; See loongson_paddd for the reason we use 'unspec' rather than
603 ;; 'minus' here.
604 (define_insn "loongson_psubd"
605   [(set (match_operand:DI 0 "register_operand" "=f")
606         (unspec:DI [(match_operand:DI 1 "register_operand" "f")
607                     (match_operand:DI 2 "register_operand" "f")]
608                    UNSPEC_LOONGSON_PSUBD))]
609   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
610   "psubd\t%0,%1,%2"
611   [(set_attr "type" "fadd")])
613 ;; Subtraction, treating overflow by signed saturation.
614 (define_insn "sssub<mode>3"
615   [(set (match_operand:VHB 0 "register_operand" "=f")
616         (ss_minus:VHB (match_operand:VHB 1 "register_operand" "f")
617                       (match_operand:VHB 2 "register_operand" "f")))]
618   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
619   "psubs<V_suffix>\t%0,%1,%2"
620   [(set_attr "type" "fadd")])
622 ;; Subtraction, treating overflow by unsigned saturation.
623 (define_insn "ussub<mode>3"
624   [(set (match_operand:VHB 0 "register_operand" "=f")
625         (us_minus:VHB (match_operand:VHB 1 "register_operand" "f")
626                       (match_operand:VHB 2 "register_operand" "f")))]
627   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
628   "psubus<V_suffix>\t%0,%1,%2"
629   [(set_attr "type" "fadd")])
631 ;; Unpack high data.  Recall that Loongson only runs in little-endian.
632 (define_insn "loongson_punpckhbh"
633   [(set (match_operand:V8QI 0 "register_operand" "=f")
634         (vec_select:V8QI
635           (vec_concat:V16QI
636             (match_operand:V8QI 1 "register_operand" "f")
637             (match_operand:V8QI 2 "register_operand" "f"))
638           (parallel [(const_int 4) (const_int 12)
639                      (const_int 5) (const_int 13)
640                      (const_int 6) (const_int 14)
641                      (const_int 7) (const_int 15)])))]
642   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
643   "punpckhbh\t%0,%1,%2"
644   [(set_attr "type" "fdiv")])
646 (define_insn "loongson_punpckhhw"
647   [(set (match_operand:V4HI 0 "register_operand" "=f")
648         (vec_select:V4HI
649           (vec_concat:V8HI
650             (match_operand:V4HI 1 "register_operand" "f")
651             (match_operand:V4HI 2 "register_operand" "f"))
652           (parallel [(const_int 2) (const_int 6)
653                      (const_int 3) (const_int 7)])))]
654   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
655   "punpckhhw\t%0,%1,%2"
656   [(set_attr "type" "fdiv")])
658 (define_insn "loongson_punpckhhw_qi"
659   [(set (match_operand:V8QI 0 "register_operand" "=f")
660         (vec_select:V8QI
661           (vec_concat:V16QI
662             (match_operand:V8QI 1 "register_operand" "f")
663             (match_operand:V8QI 2 "register_operand" "f"))
664           (parallel [(const_int 4)  (const_int 5)
665                      (const_int 12) (const_int 13)
666                      (const_int 6)  (const_int 7)
667                      (const_int 14) (const_int 15)])))]
668   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
669   "punpckhhw\t%0,%1,%2"
670   [(set_attr "type" "fdiv")])
672 (define_insn "loongson_punpckhwd"
673   [(set (match_operand:V2SI 0 "register_operand" "=f")
674         (vec_select:V2SI
675           (vec_concat:V4SI
676             (match_operand:V2SI 1 "register_operand" "f")
677             (match_operand:V2SI 2 "register_operand" "f"))
678           (parallel [(const_int 1) (const_int 3)])))]
679   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
680   "punpckhwd\t%0,%1,%2"
681   [(set_attr "type" "fcvt")])
683 (define_insn "loongson_punpckhwd_qi"
684   [(set (match_operand:V8QI 0 "register_operand" "=f")
685         (vec_select:V8QI
686           (vec_concat:V16QI
687             (match_operand:V8QI 1 "register_operand" "f")
688             (match_operand:V8QI 2 "register_operand" "f"))
689           (parallel [(const_int 4) (const_int 5)
690                      (const_int 6) (const_int 7)
691                      (const_int 12) (const_int 13)
692                      (const_int 14) (const_int 15)])))]
693   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
694   "punpckhwd\t%0,%1,%2"
695   [(set_attr "type" "fcvt")])
697 (define_insn "loongson_punpckhwd_hi"
698   [(set (match_operand:V4HI 0 "register_operand" "=f")
699         (vec_select:V4HI
700           (vec_concat:V8HI
701             (match_operand:V4HI 1 "register_operand" "f")
702             (match_operand:V4HI 2 "register_operand" "f"))
703           (parallel [(const_int 2) (const_int 3)
704                      (const_int 6) (const_int 7)])))]
705   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
706   "punpckhwd\t%0,%1,%2"
707   [(set_attr "type" "fcvt")])
709 ;; Unpack low data.
710 (define_insn "loongson_punpcklbh"
711   [(set (match_operand:V8QI 0 "register_operand" "=f")
712         (vec_select:V8QI
713           (vec_concat:V16QI
714             (match_operand:V8QI 1 "register_operand" "f")
715             (match_operand:V8QI 2 "register_operand" "f"))
716           (parallel [(const_int 0) (const_int 8)
717                      (const_int 1) (const_int 9)
718                      (const_int 2) (const_int 10)
719                      (const_int 3) (const_int 11)])))]
720   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
721   "punpcklbh\t%0,%1,%2"
722   [(set_attr "type" "fdiv")])
724 (define_insn "loongson_punpcklhw"
725   [(set (match_operand:V4HI 0 "register_operand" "=f")
726         (vec_select:V4HI
727           (vec_concat:V8HI
728             (match_operand:V4HI 1 "register_operand" "f")
729             (match_operand:V4HI 2 "register_operand" "f"))
730           (parallel [(const_int 0) (const_int 4)
731                      (const_int 1) (const_int 5)])))]
732   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
733   "punpcklhw\t%0,%1,%2"
734   [(set_attr "type" "fdiv")])
736 (define_insn "*loongson_punpcklhw_qi"
737   [(set (match_operand:V8QI 0 "register_operand" "=f")
738         (vec_select:V8QI
739           (vec_concat:V16QI
740             (match_operand:V8QI 1 "register_operand" "f")
741             (match_operand:V8QI 2 "register_operand" "f"))
742           (parallel [(const_int 0)  (const_int 1)
743                      (const_int 8)  (const_int 9)
744                      (const_int 2)  (const_int 3)
745                      (const_int 10) (const_int 11)])))]
746   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
747   "punpcklhw\t%0,%1,%2"
748   [(set_attr "type" "fdiv")])
750 (define_insn "loongson_punpcklwd"
751   [(set (match_operand:V2SI 0 "register_operand" "=f")
752         (vec_select:V2SI
753           (vec_concat:V4SI
754             (match_operand:V2SI 1 "register_operand" "f")
755             (match_operand:V2SI 2 "register_operand" "f"))
756           (parallel [(const_int 0) (const_int 2)])))]
757   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
758   "punpcklwd\t%0,%1,%2"
759   [(set_attr "type" "fcvt")])
761 (define_insn "*loongson_punpcklwd_qi"
762   [(set (match_operand:V8QI 0 "register_operand" "=f")
763         (vec_select:V8QI
764           (vec_concat:V16QI
765             (match_operand:V8QI 1 "register_operand" "f")
766             (match_operand:V8QI 2 "register_operand" "f"))
767           (parallel [(const_int 0) (const_int 1)
768                      (const_int 2) (const_int 3)
769                      (const_int 8) (const_int 9)
770                      (const_int 10) (const_int 11)])))]
771   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
772   "punpcklwd\t%0,%1,%2"
773   [(set_attr "type" "fcvt")])
775 (define_insn "*loongson_punpcklwd_hi"
776   [(set (match_operand:V4HI 0 "register_operand" "=f")
777         (vec_select:V4HI
778           (vec_concat:V8HI
779             (match_operand:V4HI 1 "register_operand" "f")
780             (match_operand:V4HI 2 "register_operand" "f"))
781           (parallel [(const_int 0) (const_int 1)
782                      (const_int 4) (const_int 5)])))]
783   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
784   "punpcklwd\t%0,%1,%2"
785   [(set_attr "type" "fcvt")])
787 (define_expand "vec_perm_const<mode>"
788   [(match_operand:VWHB 0 "register_operand" "")
789    (match_operand:VWHB 1 "register_operand" "")
790    (match_operand:VWHB 2 "register_operand" "")
791    (match_operand:VWHB 3 "" "")]
792   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
794   if (mips_expand_vec_perm_const (operands))
795     DONE;
796   else
797     FAIL;
800 (define_expand "vec_unpacks_lo_<mode>"
801   [(match_operand:<V_stretch_half> 0 "register_operand" "")
802    (match_operand:VHB 1 "register_operand" "")]
803   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
805   mips_expand_vec_unpack (operands, false, false);
806   DONE;
809 (define_expand "vec_unpacks_hi_<mode>"
810   [(match_operand:<V_stretch_half> 0 "register_operand" "")
811    (match_operand:VHB 1 "register_operand" "")]
812   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
814   mips_expand_vec_unpack (operands, false, true);
815   DONE;
818 (define_expand "vec_unpacku_lo_<mode>"
819   [(match_operand:<V_stretch_half> 0 "register_operand" "")
820    (match_operand:VHB 1 "register_operand" "")]
821   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
823   mips_expand_vec_unpack (operands, true, false);
824   DONE;
827 (define_expand "vec_unpacku_hi_<mode>"
828   [(match_operand:<V_stretch_half> 0 "register_operand" "")
829    (match_operand:VHB 1 "register_operand" "")]
830   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
832   mips_expand_vec_unpack (operands, true, true);
833   DONE;
836 ;; Whole vector shifts, used for reduction epilogues.
837 (define_insn "vec_shl_<mode>"
838   [(set (match_operand:VWHBDI 0 "register_operand" "=f")
839         (unspec:VWHBDI [(match_operand:VWHBDI 1 "register_operand" "f")
840                         (match_operand:SI 2 "register_operand" "f")]
841                        UNSPEC_LOONGSON_DSLL))]
842   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
843   "dsll\t%0,%1,%2"
844   [(set_attr "type" "fcvt")])
846 (define_insn "vec_shr_<mode>"
847   [(set (match_operand:VWHBDI 0 "register_operand" "=f")
848         (unspec:VWHBDI [(match_operand:VWHBDI 1 "register_operand" "f")
849                         (match_operand:SI 2 "register_operand" "f")]
850                        UNSPEC_LOONGSON_DSRL))]
851   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
852   "dsrl\t%0,%1,%2"
853   [(set_attr "type" "fcvt")])
855 (define_expand "reduc_uplus_<mode>"
856   [(match_operand:VWH 0 "register_operand" "")
857    (match_operand:VWH 1 "register_operand" "")]
858   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
860   mips_expand_vec_reduc (operands[0], operands[1], gen_add<mode>3);
861   DONE;
864 ; ??? Given that we're not describing a widening reduction, we should
865 ; not have separate optabs for signed and unsigned.
866 (define_expand "reduc_splus_<mode>"
867   [(match_operand:VWHB 0 "register_operand" "")
868    (match_operand:VWHB 1 "register_operand" "")]
869   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
871   emit_insn (gen_reduc_uplus_<mode>(operands[0], operands[1]));
872   DONE;
875 (define_expand "reduc_smax_<mode>"
876   [(match_operand:VWHB 0 "register_operand" "")
877    (match_operand:VWHB 1 "register_operand" "")]
878   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
880   mips_expand_vec_reduc (operands[0], operands[1], gen_smax<mode>3);
881   DONE;
884 (define_expand "reduc_smin_<mode>"
885   [(match_operand:VWHB 0 "register_operand" "")
886    (match_operand:VWHB 1 "register_operand" "")]
887   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
889   mips_expand_vec_reduc (operands[0], operands[1], gen_smin<mode>3);
890   DONE;
893 (define_expand "reduc_umax_<mode>"
894   [(match_operand:VB 0 "register_operand" "")
895    (match_operand:VB 1 "register_operand" "")]
896   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
898   mips_expand_vec_reduc (operands[0], operands[1], gen_umax<mode>3);
899   DONE;
902 (define_expand "reduc_umin_<mode>"
903   [(match_operand:VB 0 "register_operand" "")
904    (match_operand:VB 1 "register_operand" "")]
905   "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
907   mips_expand_vec_reduc (operands[0], operands[1], gen_umin<mode>3);
908   DONE;