PR96463: Optimise svld1rq from vectors for little endian AArch64 targets.
[official-gcc.git] / gcc / config / avr / avr-fixed.md
blob542d92e1c136400183f81a286c4cf6a8792ed985
1 ;;   This file contains instructions that support fixed-point operations
2 ;;   for Atmel AVR micro controllers.
3 ;;   Copyright (C) 2012-2022 Free Software Foundation, Inc.
4 ;;
5 ;;   Contributed by Sean D'Epagnier  (sean@depagnier.com)
6 ;;                  Georg-Johann Lay (avr@gjlay.de)
8 ;; This file is part of GCC.
9 ;;
10 ;; GCC is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 3, or (at your option)
13 ;; any later version.
15 ;; GCC is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING3.  If not see
22 ;; <http://www.gnu.org/licenses/>.
24 (define_mode_iterator ALL1Q  [QQ UQQ])
25 (define_mode_iterator ALL2Q  [HQ UHQ])
26 (define_mode_iterator ALL2A  [HA UHA])
27 (define_mode_iterator ALL4A  [SA USA])
28 (define_mode_iterator ALL2QA [HQ UHQ HA UHA])
29 (define_mode_iterator ALL4QA [SQ USQ SA USA])
30 (define_mode_iterator ALL124QA [ QQ   HQ  HA  SA  SQ
31                                 UQQ  UHQ UHA USA USQ])
33 (define_mode_iterator ALL2S [HQ HA])
34 (define_mode_iterator ALL4S [SA SQ])
35 (define_mode_iterator ALL24S  [     HQ  HA  SA  SQ])
36 (define_mode_iterator ALL124S [ QQ  HQ  HA  SA  SQ])
37 (define_mode_iterator ALL124U [UQQ UHQ UHA USA USQ])
39 ;;; Conversions
41 (define_mode_iterator FIXED_A
42   [QQ UQQ
43    HQ UHQ HA UHA
44    SQ USQ SA USA
45    DQ UDQ DA UDA
46    TA UTA
47    QI HI SI DI])
49 ;; Same so that be can build cross products
51 (define_mode_iterator FIXED_B
52   [QQ UQQ
53    HQ UHQ HA UHA
54    SQ USQ SA USA
55    DQ UDQ DA UDA
56    TA UTA
57    QI HI SI DI])
59 (define_insn_and_split "fract<FIXED_B:mode><FIXED_A:mode>2"
60   [(set (match_operand:FIXED_A 0 "register_operand" "=r")
61         (fract_convert:FIXED_A
62          (match_operand:FIXED_B 1 "register_operand" "r")))]
63   "<FIXED_B:MODE>mode != <FIXED_A:MODE>mode"
64   "#"
65   "&& reload_completed"
66   [(parallel [(set (match_dup 0)
67                    (fract_convert:FIXED_A
68                     (match_dup 1)))
69               (clobber (reg:CC REG_CC))])])
71 (define_insn "*fract<FIXED_B:mode><FIXED_A:mode>2"
72   [(set (match_operand:FIXED_A 0 "register_operand" "=r")
73         (fract_convert:FIXED_A
74          (match_operand:FIXED_B 1 "register_operand" "r")))
75    (clobber (reg:CC REG_CC))]
76   "<FIXED_B:MODE>mode != <FIXED_A:MODE>mode
77    && reload_completed"
78   {
79     return avr_out_fract (insn, operands, true, NULL);
80   }
81   [(set_attr "adjust_len" "sfract")])
83 (define_insn_and_split "fractuns<FIXED_B:mode><FIXED_A:mode>2"
84   [(set (match_operand:FIXED_A 0 "register_operand" "=r")
85         (unsigned_fract_convert:FIXED_A
86          (match_operand:FIXED_B 1 "register_operand" "r")))]
87   "<FIXED_B:MODE>mode != <FIXED_A:MODE>mode"
88   "#"
89   "&& reload_completed"
90   [(parallel [(set (match_dup 0)
91                    (unsigned_fract_convert:FIXED_A
92                     (match_dup 1)))
93               (clobber (reg:CC REG_CC))])])
95 (define_insn "*fractuns<FIXED_B:mode><FIXED_A:mode>2"
96   [(set (match_operand:FIXED_A 0 "register_operand" "=r")
97         (unsigned_fract_convert:FIXED_A
98          (match_operand:FIXED_B 1 "register_operand" "r")))
99    (clobber (reg:CC REG_CC))]
100   "<FIXED_B:MODE>mode != <FIXED_A:MODE>mode
101    && reload_completed"
102   {
103     return avr_out_fract (insn, operands, false, NULL);
104   }
105   [(set_attr "adjust_len" "ufract")])
107 ;******************************************************************************
108 ;** Saturated Addition and Subtraction
109 ;******************************************************************************
111 ;; Fixme:  It would be nice if we could expand the 32-bit versions to a
112 ;;    transparent libgcc call if $2 is a REG.  Problem is that it is
113 ;;    not possible to describe that addition is commutative.
114 ;;    And defining register classes/constraintrs for the involved hard
115 ;;    registers and let IRA do the work, yields inacceptable bloated code.
116 ;;    Thus, we have to live with the up to 11 instructions that are output
117 ;;    for these 32-bit saturated operations.
119 ;; "ssaddqq3"  "ssaddhq3"  "ssaddha3"  "ssaddsq3"  "ssaddsa3"
120 ;; "sssubqq3"  "sssubhq3"  "sssubha3"  "sssubsq3"  "sssubsa3"
121 (define_insn_and_split "<code_stdname><mode>3"
122   [(set (match_operand:ALL124S 0 "register_operand"                          "=??d,d")
123         (ss_addsub:ALL124S (match_operand:ALL124S 1 "register_operand" "<abelian>0,0")
124                            (match_operand:ALL124S 2 "nonmemory_operand"         "r,Ynn")))]
125   ""
126   "#"
127   "&& reload_completed"
128   [(parallel [(set (match_dup 0)
129                    (ss_addsub:ALL124S (match_dup 1)
130                                       (match_dup 2)))
131               (clobber (reg:CC REG_CC))])])
133 (define_insn "*<code_stdname><mode>3"
134   [(set (match_operand:ALL124S 0 "register_operand"                          "=??d,d")
135         (ss_addsub:ALL124S (match_operand:ALL124S 1 "register_operand" "<abelian>0,0")
136                            (match_operand:ALL124S 2 "nonmemory_operand"         "r,Ynn")))
137    (clobber (reg:CC REG_CC))]
138   "reload_completed"
139   {
140     return avr_out_plus (insn, operands);
141   }
142   [(set_attr "adjust_len" "plus")])
144 ;; "usadduqq3"  "usadduhq3"  "usadduha3" "usaddusq3"  "usaddusa3"
145 ;; "ussubuqq3"  "ussubuhq3"  "ussubuha3" "ussubusq3"  "ussubusa3"
146 (define_insn_and_split "<code_stdname><mode>3"
147   [(set (match_operand:ALL124U 0 "register_operand"                          "=??r,d")
148         (us_addsub:ALL124U (match_operand:ALL124U 1 "register_operand" "<abelian>0,0")
149                            (match_operand:ALL124U 2 "nonmemory_operand"         "r,Ynn")))]
150   ""
151   "#"
152   "&& reload_completed"
153   [(parallel [(set (match_dup 0)
154                    (us_addsub:ALL124U (match_dup 1)
155                                       (match_dup 2)))
156               (clobber (reg:CC REG_CC))])])
158 (define_insn "*<code_stdname><mode>3"
159   [(set (match_operand:ALL124U 0 "register_operand"                          "=??r,d")
160         (us_addsub:ALL124U (match_operand:ALL124U 1 "register_operand" "<abelian>0,0")
161                            (match_operand:ALL124U 2 "nonmemory_operand"         "r,Ynn")))
162    (clobber (reg:CC REG_CC))]
163   "reload_completed"
164   {
165     return avr_out_plus (insn, operands);
166   }
167   [(set_attr "adjust_len" "plus")])
169 ;******************************************************************************
170 ;** Saturated Negation and Absolute Value
171 ;******************************************************************************
173 ;; Fixme: This will always result in 0.  Dunno why simplify-rtx.cc says
174 ;;   "unknown" on how to optimize this.  libgcc call would be in order,
175 ;;   but the performance is *PLAIN* *HORROR* because the optimizers don't
176 ;;   manage to optimize out MEMCPY that's sprincled all over fixed-bit.c  */
178 (define_expand "usneg<mode>2"
179   [(parallel [(match_operand:ALL124U 0 "register_operand" "")
180               (match_operand:ALL124U 1 "nonmemory_operand" "")])]
181   ""
182   {
183     emit_move_insn (operands[0], CONST0_RTX (<MODE>mode));
184     DONE;
185   })
187 (define_insn_and_split "ssnegqq2"
188   [(set (match_operand:QQ 0 "register_operand"            "=r")
189         (ss_neg:QQ (match_operand:QQ 1 "register_operand"  "0")))]
190   ""
191   "#"
192   "&& reload_completed"
193   [(parallel [(set (match_dup 0)
194                    (ss_neg:QQ (match_dup 1)))
195               (clobber (reg:CC REG_CC))])])
197 (define_insn "*ssnegqq2"
198   [(set (match_operand:QQ 0 "register_operand"            "=r")
199         (ss_neg:QQ (match_operand:QQ 1 "register_operand"  "0")))
200    (clobber (reg:CC REG_CC))]
201   "reload_completed"
202   "neg %0\;brvc 0f\;dec %0\;0:"
203   [(set_attr "length" "3")])
205 (define_insn_and_split "ssabsqq2"
206   [(set (match_operand:QQ 0 "register_operand"            "=r")
207         (ss_abs:QQ (match_operand:QQ 1 "register_operand"  "0")))]
208   ""
209   "#"
210   "&& reload_completed"
211   [(parallel [(set (match_dup 0)
212                    (ss_abs:QQ (match_dup 1)))
213               (clobber (reg:CC REG_CC))])])
215 (define_insn "*ssabsqq2"
216   [(set (match_operand:QQ 0 "register_operand"            "=r")
217         (ss_abs:QQ (match_operand:QQ 1 "register_operand"  "0")))
218    (clobber (reg:CC REG_CC))]
219   "reload_completed"
220   "sbrc %0,7\;neg %0\;sbrc %0,7\;dec %0"
221   [(set_attr "length" "4")])
223 ;; "ssneghq2"  "ssnegha2"  "ssnegsq2"  "ssnegsa2"
224 ;; "ssabshq2"  "ssabsha2"  "ssabssq2"  "ssabssa2"
225 (define_expand "<code_stdname><mode>2"
226   [(set (match_dup 2)
227         (match_operand:ALL24S 1 "register_operand" ""))
228    (set (match_dup 2)
229         (ss_abs_neg:ALL24S (match_dup 2)))
230    (set (match_operand:ALL24S 0 "register_operand" "")
231         (match_dup 2))]
232   ""
233   {
234     operands[2] = gen_rtx_REG (<MODE>mode, 26 - GET_MODE_SIZE (<MODE>mode));
235   })
237 ;; "*ssneghq2"  "*ssnegha2"
238 ;; "*ssabshq2"  "*ssabsha2"
239 (define_insn_and_split "*<code_stdname><mode>2_split"
240   [(set (reg:ALL2S 24)
241         (ss_abs_neg:ALL2S (reg:ALL2S 24)))]
242   ""
243   "#"
244   "&& reload_completed"
245   [(parallel [(set (reg:ALL2S 24)
246                    (ss_abs_neg:ALL2S (reg:ALL2S 24)))
247               (clobber (reg:CC REG_CC))])])
249 (define_insn "*<code_stdname><mode>2"
250   [(set (reg:ALL2S 24)
251         (ss_abs_neg:ALL2S (reg:ALL2S 24)))
252    (clobber (reg:CC REG_CC))]
253   "reload_completed"
254   "%~call __<code_stdname>_2"
255   [(set_attr "type" "xcall")])
257 ;; "*ssnegsq2"  "*ssnegsa2"
258 ;; "*ssabssq2"  "*ssabssa2"
259 (define_insn_and_split "*<code_stdname><mode>2_split"
260   [(set (reg:ALL4S 22)
261         (ss_abs_neg:ALL4S (reg:ALL4S 22)))]
262   ""
263   "#"
264   "&& reload_completed"
265   [(parallel [(set (reg:ALL4S 22)
266                    (ss_abs_neg:ALL4S (reg:ALL4S 22)))
267               (clobber (reg:CC REG_CC))])])
269 (define_insn "*<code_stdname><mode>2"
270   [(set (reg:ALL4S 22)
271         (ss_abs_neg:ALL4S (reg:ALL4S 22)))
272    (clobber (reg:CC REG_CC))]
273   "reload_completed"
274   "%~call __<code_stdname>_4"
275   [(set_attr "type" "xcall")])
277 ;******************************************************************************
278 ; mul
280 ;; "mulqq3" "muluqq3"
281 (define_expand "mul<mode>3"
282   [(parallel [(match_operand:ALL1Q 0 "register_operand" "")
283               (match_operand:ALL1Q 1 "register_operand" "")
284               (match_operand:ALL1Q 2 "register_operand" "")])]
285   ""
286   {
287     emit_insn (AVR_HAVE_MUL
288       ? gen_mul<mode>3_enh (operands[0], operands[1], operands[2])
289       : gen_mul<mode>3_nomul (operands[0], operands[1], operands[2]));
290     DONE;
291   })
293 (define_insn_and_split "mulqq3_enh"
294   [(set (match_operand:QQ 0 "register_operand"         "=r")
295         (mult:QQ (match_operand:QQ 1 "register_operand" "a")
296                  (match_operand:QQ 2 "register_operand" "a")))]
297   "AVR_HAVE_MUL"
298   "#"
299   "&& reload_completed"
300   [(parallel [(set (match_dup 0)
301                    (mult:QQ (match_dup 1)
302                             (match_dup 2)))
303               (clobber (reg:CC REG_CC))])])
305 (define_insn "*mulqq3_enh"
306   [(set (match_operand:QQ 0 "register_operand"         "=r")
307         (mult:QQ (match_operand:QQ 1 "register_operand" "a")
308                  (match_operand:QQ 2 "register_operand" "a")))
309    (clobber (reg:CC REG_CC))]
310   "AVR_HAVE_MUL && reload_completed"
311   "fmuls %1,%2\;dec r1\;brvs 0f\;inc r1\;0:\;mov %0,r1\;clr __zero_reg__"
312   [(set_attr "length" "6")])
314 (define_insn_and_split "muluqq3_enh"
315   [(set (match_operand:UQQ 0 "register_operand"          "=r")
316         (mult:UQQ (match_operand:UQQ 1 "register_operand" "r")
317                   (match_operand:UQQ 2 "register_operand" "r")))]
318   "AVR_HAVE_MUL"
319   "#"
320   "&& reload_completed"
321   [(parallel [(set (match_dup 0)
322                    (mult:UQQ (match_dup 1)
323                              (match_dup 2)))
324               (clobber (reg:CC REG_CC))])])
326 (define_insn "*muluqq3_enh"
327   [(set (match_operand:UQQ 0 "register_operand"          "=r")
328         (mult:UQQ (match_operand:UQQ 1 "register_operand" "r")
329                   (match_operand:UQQ 2 "register_operand" "r")))
330    (clobber (reg:CC REG_CC))]
331   "AVR_HAVE_MUL && reload_completed"
332   "mul %1,%2\;mov %0,r1\;clr __zero_reg__"
333   [(set_attr "length" "3")])
335 (define_expand "mulqq3_nomul"
336   [(set (reg:QQ 24)
337         (match_operand:QQ 1 "register_operand" ""))
338    (set (reg:QQ 25)
339         (match_operand:QQ 2 "register_operand" ""))
340    ;; "*mulqq3.call"
341    (parallel [(set (reg:QQ 23)
342                    (mult:QQ (reg:QQ 24)
343                             (reg:QQ 25)))
344               (clobber (reg:QI 22))
345               (clobber (reg:HI 24))])
346    (set (match_operand:QQ 0 "register_operand" "")
347         (reg:QQ 23))]
348   "!AVR_HAVE_MUL"
349   {
350     avr_fix_inputs (operands, 1 << 2, regmask (QQmode, 24));
351   })
354 (define_expand "muluqq3_nomul"
355   [(set (reg:UQQ 22)
356         (match_operand:UQQ 1 "register_operand" ""))
357    (set (reg:UQQ 24)
358         (match_operand:UQQ 2 "register_operand" ""))
359    ;; "*umulqihi3.call"
360    (parallel [(set (reg:HI 24)
361                    (mult:HI (zero_extend:HI (reg:QI 22))
362                             (zero_extend:HI (reg:QI 24))))
363               (clobber (reg:QI 21))
364               (clobber (reg:HI 22))])
365    (set (match_operand:UQQ 0 "register_operand" "")
366         (reg:UQQ 25))]
367   "!AVR_HAVE_MUL"
368   {
369     avr_fix_inputs (operands, 1 << 2, regmask (UQQmode, 22));
370   })
372 (define_insn_and_split "*mulqq3.call_split"
373   [(set (reg:QQ 23)
374         (mult:QQ (reg:QQ 24)
375                  (reg:QQ 25)))
376    (clobber (reg:QI 22))
377    (clobber (reg:HI 24))]
378   "!AVR_HAVE_MUL"
379   "#"
380   "&& reload_completed"
381   [(parallel [(set (reg:QQ 23)
382                    (mult:QQ (reg:QQ 24)
383                             (reg:QQ 25)))
384               (clobber (reg:QI 22))
385               (clobber (reg:HI 24))
386               (clobber (reg:CC REG_CC))])])
388 (define_insn "*mulqq3.call"
389   [(set (reg:QQ 23)
390         (mult:QQ (reg:QQ 24)
391                  (reg:QQ 25)))
392    (clobber (reg:QI 22))
393    (clobber (reg:HI 24))
394    (clobber (reg:CC REG_CC))]
395   "!AVR_HAVE_MUL && reload_completed"
396   "%~call __mulqq3"
397   [(set_attr "type" "xcall")])
400 ;; "mulhq3" "muluhq3"
401 ;; "mulha3" "muluha3"
402 (define_expand "mul<mode>3"
403   [(set (reg:ALL2QA 18)
404         (match_operand:ALL2QA 1 "register_operand" ""))
405    (set (reg:ALL2QA 26)
406         (match_operand:ALL2QA 2 "register_operand" ""))
407    ;; "*mulhq3.call.enh"
408    (parallel [(set (reg:ALL2QA 24)
409                    (mult:ALL2QA (reg:ALL2QA 18)
410                                 (reg:ALL2QA 26)))
411               (clobber (reg:HI 22))])
412    (set (match_operand:ALL2QA 0 "register_operand" "")
413         (reg:ALL2QA 24))]
414   "AVR_HAVE_MUL"
415   {
416     avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 18));
417   })
419 ;; "*mulhq3.call"  "*muluhq3.call"
420 ;; "*mulha3.call"  "*muluha3.call"
421 (define_insn_and_split "*mul<mode>3.call_split"
422   [(set (reg:ALL2QA 24)
423         (mult:ALL2QA (reg:ALL2QA 18)
424                      (reg:ALL2QA 26)))
425    (clobber (reg:HI 22))]
426   "AVR_HAVE_MUL"
427   "#"
428   "&& reload_completed"
429   [(parallel [(set (reg:ALL2QA 24)
430                    (mult:ALL2QA (reg:ALL2QA 18)
431                                 (reg:ALL2QA 26)))
432               (clobber (reg:HI 22))
433               (clobber (reg:CC REG_CC))])])
435 (define_insn "*mul<mode>3.call"
436   [(set (reg:ALL2QA 24)
437         (mult:ALL2QA (reg:ALL2QA 18)
438                      (reg:ALL2QA 26)))
439    (clobber (reg:HI 22))
440    (clobber (reg:CC REG_CC))]
441   "AVR_HAVE_MUL && reload_completed"
442   "%~call __mul<mode>3"
443   [(set_attr "type" "xcall")])
446 ;; On the enhanced core, don't clobber either input and use a separate output
448 ;; "mulsa3" "mulusa3"
449 (define_expand "mul<mode>3"
450   [(set (reg:ALL4A 16)
451         (match_operand:ALL4A 1 "register_operand" ""))
452    (set (reg:ALL4A 20)
453         (match_operand:ALL4A 2 "register_operand" ""))
454    (set (reg:ALL4A 24)
455         (mult:ALL4A (reg:ALL4A 16)
456                     (reg:ALL4A 20)))
457    (set (match_operand:ALL4A 0 "register_operand" "")
458         (reg:ALL4A 24))]
459   "AVR_HAVE_MUL"
460   {
461     avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 16));
462   })
464 ;; "*mulsa3.call" "*mulusa3.call"
465 (define_insn_and_split "*mul<mode>3.call_split"
466   [(set (reg:ALL4A 24)
467         (mult:ALL4A (reg:ALL4A 16)
468                     (reg:ALL4A 20)))]
469   "AVR_HAVE_MUL"
470   "#"
471   "&& reload_completed"
472   [(parallel [(set (reg:ALL4A 24)
473                    (mult:ALL4A (reg:ALL4A 16)
474                                (reg:ALL4A 20)))
475               (clobber (reg:CC REG_CC))])])
477 (define_insn "*mul<mode>3.call"
478   [(set (reg:ALL4A 24)
479         (mult:ALL4A (reg:ALL4A 16)
480                     (reg:ALL4A 20)))
481    (clobber (reg:CC REG_CC))]
482   "AVR_HAVE_MUL && reload_completed"
483   "%~call __mul<mode>3"
484   [(set_attr "type" "xcall")])
486 ; / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
487 ; div
489 (define_code_iterator usdiv [udiv div])
491 ;; "divqq3" "udivuqq3"
492 (define_expand "<code><mode>3"
493   [(set (reg:ALL1Q 25)
494         (match_operand:ALL1Q 1 "register_operand" ""))
495    (set (reg:ALL1Q 22)
496         (match_operand:ALL1Q 2 "register_operand" ""))
497    (parallel [(set (reg:ALL1Q 24)
498                    (usdiv:ALL1Q (reg:ALL1Q 25)
499                                 (reg:ALL1Q 22)))
500               (clobber (reg:QI 25))])
501    (set (match_operand:ALL1Q 0 "register_operand" "")
502         (reg:ALL1Q 24))]
503   ""
504   {
505     avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 25));
506   })
509 ;; "*divqq3.call" "*udivuqq3.call"
510 (define_insn_and_split "*<code><mode>3.call_split"
511   [(set (reg:ALL1Q 24)
512         (usdiv:ALL1Q (reg:ALL1Q 25)
513                      (reg:ALL1Q 22)))
514    (clobber (reg:QI 25))]
515   ""
516   "#"
517   "&& reload_completed"
518   [(parallel [(set (reg:ALL1Q 24)
519                    (usdiv:ALL1Q (reg:ALL1Q 25)
520                                 (reg:ALL1Q 22)))
521               (clobber (reg:QI 25))
522               (clobber (reg:CC REG_CC))])])
524 (define_insn "*<code><mode>3.call"
525   [(set (reg:ALL1Q 24)
526         (usdiv:ALL1Q (reg:ALL1Q 25)
527                      (reg:ALL1Q 22)))
528    (clobber (reg:QI 25))
529    (clobber (reg:CC REG_CC))]
530   "reload_completed"
531   "%~call __<code><mode>3"
532   [(set_attr "type" "xcall")])
534 ;; "divhq3" "udivuhq3"
535 ;; "divha3" "udivuha3"
536 (define_expand "<code><mode>3"
537   [(set (reg:ALL2QA 26)
538         (match_operand:ALL2QA 1 "register_operand" ""))
539    (set (reg:ALL2QA 22)
540         (match_operand:ALL2QA 2 "register_operand" ""))
541    (parallel [(set (reg:ALL2QA 24)
542                    (usdiv:ALL2QA (reg:ALL2QA 26)
543                                  (reg:ALL2QA 22)))
544               (clobber (reg:HI 26))
545               (clobber (reg:QI 21))])
546    (set (match_operand:ALL2QA 0 "register_operand" "")
547         (reg:ALL2QA 24))]
548   ""
549   {
550     avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 26));
551   })
553 ;; "*divhq3.call" "*udivuhq3.call"
554 ;; "*divha3.call" "*udivuha3.call"
555 (define_insn_and_split "*<code><mode>3.call_split"
556   [(set (reg:ALL2QA 24)
557         (usdiv:ALL2QA (reg:ALL2QA 26)
558                       (reg:ALL2QA 22)))
559    (clobber (reg:HI 26))
560    (clobber (reg:QI 21))]
561   ""
562   "#"
563   "&& reload_completed"
564   [(parallel [(set (reg:ALL2QA 24)
565                    (usdiv:ALL2QA (reg:ALL2QA 26)
566                                  (reg:ALL2QA 22)))
567               (clobber (reg:HI 26))
568               (clobber (reg:QI 21))
569               (clobber (reg:CC REG_CC))])])
571 (define_insn "*<code><mode>3.call"
572   [(set (reg:ALL2QA 24)
573         (usdiv:ALL2QA (reg:ALL2QA 26)
574                       (reg:ALL2QA 22)))
575    (clobber (reg:HI 26))
576    (clobber (reg:QI 21))
577    (clobber (reg:CC REG_CC))]
578   "reload_completed"
579   "%~call __<code><mode>3"
580   [(set_attr "type" "xcall")])
582 ;; Note the first parameter gets passed in already offset by 2 bytes
584 ;; "divsa3" "udivusa3"
585 (define_expand "<code><mode>3"
586   [(set (reg:ALL4A 24)
587         (match_operand:ALL4A 1 "register_operand" ""))
588    (set (reg:ALL4A 18)
589         (match_operand:ALL4A 2 "register_operand" ""))
590    (parallel [(set (reg:ALL4A 22)
591                    (usdiv:ALL4A (reg:ALL4A 24)
592                                 (reg:ALL4A 18)))
593               (clobber (reg:HI 26))
594               (clobber (reg:HI 30))])
595    (set (match_operand:ALL4A 0 "register_operand" "")
596         (reg:ALL4A 22))]
597   ""
598   {
599     avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 24));
600   })
602 ;; "*divsa3.call" "*udivusa3.call"
603 (define_insn_and_split "*<code><mode>3.call_split"
604   [(set (reg:ALL4A 22)
605         (usdiv:ALL4A (reg:ALL4A 24)
606                      (reg:ALL4A 18)))
607    (clobber (reg:HI 26))
608    (clobber (reg:HI 30))]
609   ""
610   "#"
611   "&& reload_completed"
612   [(parallel [(set (reg:ALL4A 22)
613                    (usdiv:ALL4A (reg:ALL4A 24)
614                                 (reg:ALL4A 18)))
615               (clobber (reg:HI 26))
616               (clobber (reg:HI 30))
617               (clobber (reg:CC REG_CC))])])
619 (define_insn "*<code><mode>3.call"
620   [(set (reg:ALL4A 22)
621         (usdiv:ALL4A (reg:ALL4A 24)
622                      (reg:ALL4A 18)))
623    (clobber (reg:HI 26))
624    (clobber (reg:HI 30))
625    (clobber (reg:CC REG_CC))]
626   "reload_completed"
627   "%~call __<code><mode>3"
628   [(set_attr "type" "xcall")])
631 ;******************************************************************************
632 ;** Rounding
633 ;******************************************************************************
635 ;; "roundqq3"  "rounduqq3"
636 ;; "roundhq3"  "rounduhq3"  "roundha3"  "rounduha3"
637 ;; "roundsq3"  "roundusq3"  "roundsa3"  "roundusa3"
638 (define_expand "round<mode>3"
639   [(set (match_dup 4)
640         (match_operand:ALL124QA 1 "register_operand" ""))
641    (set (reg:QI 24)
642         (match_dup 5))
643    (parallel [(set (match_dup 3)
644                    (unspec:ALL124QA [(match_dup 4)
645                                      (reg:QI 24)] UNSPEC_ROUND))
646               (clobber (match_dup 4))])
647    (set (match_operand:ALL124QA 0 "register_operand" "")
648         (match_dup 3))
649    (use (match_operand:HI 2 "nonmemory_operand" ""))]
650   ""
651   {
652     if (CONST_INT_P (operands[2])
653         && !(optimize_size
654              && 4 == GET_MODE_SIZE (<MODE>mode)))
655       {
656         emit_insn (gen_round<mode>3_const (operands[0], operands[1], operands[2]));
657         DONE;
658       }
660     // Input and output of the libgcc function
661     const unsigned int regno_in[]  = { -1U, 22, 22, -1U, 18 };
662     const unsigned int regno_out[] = { -1U, 24, 24, -1U, 22 };
664     operands[3] = gen_rtx_REG (<MODE>mode, regno_out[(size_t) GET_MODE_SIZE (<MODE>mode)]);
665     operands[4] = gen_rtx_REG (<MODE>mode,  regno_in[(size_t) GET_MODE_SIZE (<MODE>mode)]);
666     avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, REGNO (operands[4])));
667     operands[5] = simplify_gen_subreg (QImode, force_reg (HImode, operands[2]), HImode, 0);
668     // $2 is no more needed, but is referenced for expand.
669     operands[2] = const0_rtx;
670   })
672 ;; Expand rounding with known rounding points inline so that the addend / mask
673 ;; will be consumed by operation with immediate operands and there is no
674 ;; need for a shift with variable offset.
676 ;; "roundqq3_const"  "rounduqq3_const"
677 ;; "roundhq3_const"  "rounduhq3_const"  "roundha3_const"  "rounduha3_const"
678 ;; "roundsq3_const"  "roundusq3_const"  "roundsa3_const"  "roundusa3_const"
679 (define_insn_and_split "round<mode>3_const"
680   [(set (match_operand:ALL124QA 0 "register_operand"                  "=d")
681         (unspec:ALL124QA [(match_operand:ALL124QA 1 "register_operand" "0")
682                           (match_operand:HI 2 "const_int_operand"      "n")
683                           (const_int 0)]
684                          UNSPEC_ROUND))]
685   ""
686   "#"
687   "&& reload_completed"
688   [(parallel [(set (match_dup 0)
689                    (unspec:ALL124QA [(match_dup 1)
690                                      (match_dup 2)
691                                      (const_int 0)]
692                                     UNSPEC_ROUND))
693               (clobber (reg:CC REG_CC))])])
695 (define_insn "*round<mode>3_const"
696   [(set (match_operand:ALL124QA 0 "register_operand"                  "=d")
697         (unspec:ALL124QA [(match_operand:ALL124QA 1 "register_operand" "0")
698                           (match_operand:HI 2 "const_int_operand"      "n")
699                           (const_int 0)]
700                          UNSPEC_ROUND))
701    (clobber (reg:CC REG_CC))]
702   "reload_completed"
703   {
704     return avr_out_round (insn, operands);
705   }
706   [(set_attr "adjust_len" "round")])
709 ;; "*roundqq3.libgcc"  "*rounduqq3.libgcc"
710 (define_insn_and_split "*round<mode>3.libgcc_split"
711   [(set (reg:ALL1Q 24)
712         (unspec:ALL1Q [(reg:ALL1Q 22)
713                        (reg:QI 24)] UNSPEC_ROUND))
714    (clobber (reg:ALL1Q 22))]
715   ""
716   "#"
717   "&& reload_completed"
718   [(parallel [(set (reg:ALL1Q 24)
719                    (unspec:ALL1Q [(reg:ALL1Q 22)
720                                   (reg:QI 24)] UNSPEC_ROUND))
721               (clobber (reg:ALL1Q 22))
722               (clobber (reg:CC REG_CC))])])
724 (define_insn "*round<mode>3.libgcc"
725   [(set (reg:ALL1Q 24)
726         (unspec:ALL1Q [(reg:ALL1Q 22)
727                        (reg:QI 24)] UNSPEC_ROUND))
728    (clobber (reg:ALL1Q 22))
729    (clobber (reg:CC REG_CC))]
730   "reload_completed"
731   "%~call __round<mode>3"
732   [(set_attr "type" "xcall")])
734 ;; "*roundhq3.libgcc"  "*rounduhq3.libgcc"
735 ;; "*roundha3.libgcc"  "*rounduha3.libgcc"
736 (define_insn_and_split "*round<mode>3.libgcc_split"
737   [(set (reg:ALL2QA 24)
738         (unspec:ALL2QA [(reg:ALL2QA 22)
739                         (reg:QI 24)] UNSPEC_ROUND))
740    (clobber (reg:ALL2QA 22))]
741   ""
742   "#"
743   "&& reload_completed"
744   [(parallel [(set (reg:ALL2QA 24)
745                    (unspec:ALL2QA [(reg:ALL2QA 22)
746                                    (reg:QI 24)] UNSPEC_ROUND))
747               (clobber (reg:ALL2QA 22))
748               (clobber (reg:CC REG_CC))])])
750 (define_insn "*round<mode>3.libgcc"
751   [(set (reg:ALL2QA 24)
752         (unspec:ALL2QA [(reg:ALL2QA 22)
753                         (reg:QI 24)] UNSPEC_ROUND))
754    (clobber (reg:ALL2QA 22))
755    (clobber (reg:CC REG_CC))]
756   "reload_completed"
757   "%~call __round<mode>3"
758   [(set_attr "type" "xcall")])
760 ;; "*roundsq3.libgcc"  "*roundusq3.libgcc"
761 ;; "*roundsa3.libgcc"  "*roundusa3.libgcc"
762 (define_insn_and_split "*round<mode>3.libgcc_split"
763   [(set (reg:ALL4QA 22)
764         (unspec:ALL4QA [(reg:ALL4QA 18)
765                         (reg:QI 24)] UNSPEC_ROUND))
766    (clobber (reg:ALL4QA 18))]
767   ""
768   "#"
769   "&& reload_completed"
770   [(parallel [(set (reg:ALL4QA 22)
771                    (unspec:ALL4QA [(reg:ALL4QA 18)
772                                    (reg:QI 24)] UNSPEC_ROUND))
773               (clobber (reg:ALL4QA 18))
774               (clobber (reg:CC REG_CC))])])
776 (define_insn "*round<mode>3.libgcc"
777   [(set (reg:ALL4QA 22)
778         (unspec:ALL4QA [(reg:ALL4QA 18)
779                         (reg:QI 24)] UNSPEC_ROUND))
780    (clobber (reg:ALL4QA 18))
781    (clobber (reg:CC REG_CC))]
782   "reload_completed"
783   "%~call __round<mode>3"
784   [(set_attr "type" "xcall")])