]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/avr/avr-fixed.md
Change references of .c files to .cc files
[thirdparty/gcc.git] / gcc / config / avr / avr-fixed.md
CommitLineData
e55e4056
GJL
1;; This file contains instructions that support fixed-point operations
2;; for Atmel AVR micro controllers.
7adcbafe 3;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
e55e4056
GJL
4;;
5;; Contributed by Sean D'Epagnier (sean@depagnier.com)
6;; Georg-Johann Lay (avr@gjlay.de)
7
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.
14;;
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.
19;;
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/>.
23
487e359c
GJL
24(define_mode_iterator ALL1Q [QQ UQQ])
25(define_mode_iterator ALL2Q [HQ UHQ])
26(define_mode_iterator ALL2A [HA UHA])
487e359c 27(define_mode_iterator ALL4A [SA USA])
85d768f3
GJL
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])
e55e4056 32
51526856
GJL
33(define_mode_iterator ALL2S [HQ HA])
34(define_mode_iterator ALL4S [SA SQ])
85d768f3
GJL
35(define_mode_iterator ALL24S [ HQ HA SA SQ])
36(define_mode_iterator ALL124S [ QQ HQ HA SA SQ])
51526856
GJL
37(define_mode_iterator ALL124U [UQQ UHQ UHA USA USQ])
38
e55e4056
GJL
39;;; Conversions
40
41(define_mode_iterator FIXED_A
487e359c
GJL
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])
e55e4056
GJL
48
49;; Same so that be can build cross products
50
51(define_mode_iterator FIXED_B
487e359c
GJL
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])
e55e4056 58
3ba781d3 59(define_insn_and_split "fract<FIXED_B:mode><FIXED_A:mode>2"
e55e4056
GJL
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"
3ba781d3
SKS
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))])])
70
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"
e55e4056
GJL
78 {
79 return avr_out_fract (insn, operands, true, NULL);
80 }
3ba781d3 81 [(set_attr "adjust_len" "sfract")])
e55e4056 82
3ba781d3 83(define_insn_and_split "fractuns<FIXED_B:mode><FIXED_A:mode>2"
e55e4056
GJL
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"
3ba781d3
SKS
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))])])
94
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"
e55e4056
GJL
102 {
103 return avr_out_fract (insn, operands, false, NULL);
104 }
3ba781d3 105 [(set_attr "adjust_len" "ufract")])
e55e4056 106
51526856
GJL
107;******************************************************************************
108;** Saturated Addition and Subtraction
109;******************************************************************************
110
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.
118
119;; "ssaddqq3" "ssaddhq3" "ssaddha3" "ssaddsq3" "ssaddsa3"
120;; "sssubqq3" "sssubhq3" "sssubha3" "sssubsq3" "sssubsa3"
3ba781d3 121(define_insn_and_split "<code_stdname><mode>3"
51526856
GJL
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 ""
3ba781d3
SKS
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))])])
132
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"
51526856
GJL
139 {
140 return avr_out_plus (insn, operands);
141 }
3ba781d3 142 [(set_attr "adjust_len" "plus")])
51526856
GJL
143
144;; "usadduqq3" "usadduhq3" "usadduha3" "usaddusq3" "usaddusa3"
145;; "ussubuqq3" "ussubuhq3" "ussubuha3" "ussubusq3" "ussubusa3"
3ba781d3 146(define_insn_and_split "<code_stdname><mode>3"
51526856
GJL
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 ""
3ba781d3
SKS
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))])])
157
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"
51526856
GJL
164 {
165 return avr_out_plus (insn, operands);
166 }
3ba781d3 167 [(set_attr "adjust_len" "plus")])
51526856
GJL
168
169;******************************************************************************
170;** Saturated Negation and Absolute Value
171;******************************************************************************
172
e53b6e56 173;; Fixme: This will always result in 0. Dunno why simplify-rtx.cc says
51526856
GJL
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 */
177
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 })
186
3ba781d3 187(define_insn_and_split "ssnegqq2"
51526856
GJL
188 [(set (match_operand:QQ 0 "register_operand" "=r")
189 (ss_neg:QQ (match_operand:QQ 1 "register_operand" "0")))]
190 ""
3ba781d3
SKS
191 "#"
192 "&& reload_completed"
193 [(parallel [(set (match_dup 0)
194 (ss_neg:QQ (match_dup 1)))
195 (clobber (reg:CC REG_CC))])])
196
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"
51526856 202 "neg %0\;brvc 0f\;dec %0\;0:"
3ba781d3 203 [(set_attr "length" "3")])
51526856 204
3ba781d3 205(define_insn_and_split "ssabsqq2"
51526856
GJL
206 [(set (match_operand:QQ 0 "register_operand" "=r")
207 (ss_abs:QQ (match_operand:QQ 1 "register_operand" "0")))]
208 ""
3ba781d3
SKS
209 "#"
210 "&& reload_completed"
211 [(parallel [(set (match_dup 0)
212 (ss_abs:QQ (match_dup 1)))
213 (clobber (reg:CC REG_CC))])])
214
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"
51526856 220 "sbrc %0,7\;neg %0\;sbrc %0,7\;dec %0"
3ba781d3 221 [(set_attr "length" "4")])
51526856
GJL
222
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 })
236
237;; "*ssneghq2" "*ssnegha2"
238;; "*ssabshq2" "*ssabsha2"
3ba781d3 239(define_insn_and_split "*<code_stdname><mode>2_split"
51526856
GJL
240 [(set (reg:ALL2S 24)
241 (ss_abs_neg:ALL2S (reg:ALL2S 24)))]
242 ""
3ba781d3
SKS
243 "#"
244 "&& reload_completed"
245 [(parallel [(set (reg:ALL2S 24)
246 (ss_abs_neg:ALL2S (reg:ALL2S 24)))
247 (clobber (reg:CC REG_CC))])])
248
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"
51526856 254 "%~call __<code_stdname>_2"
3ba781d3 255 [(set_attr "type" "xcall")])
51526856
GJL
256
257;; "*ssnegsq2" "*ssnegsa2"
258;; "*ssabssq2" "*ssabssa2"
3ba781d3 259(define_insn_and_split "*<code_stdname><mode>2_split"
51526856
GJL
260 [(set (reg:ALL4S 22)
261 (ss_abs_neg:ALL4S (reg:ALL4S 22)))]
262 ""
3ba781d3
SKS
263 "#"
264 "&& reload_completed"
265 [(parallel [(set (reg:ALL4S 22)
266 (ss_abs_neg:ALL4S (reg:ALL4S 22)))
267 (clobber (reg:CC REG_CC))])])
268
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"
51526856 274 "%~call __<code_stdname>_4"
3ba781d3 275 [(set_attr "type" "xcall")])
51526856 276
e55e4056
GJL
277;******************************************************************************
278; mul
279
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 })
292
3ba781d3 293(define_insn_and_split "mulqq3_enh"
e55e4056
GJL
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"
3ba781d3
SKS
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))])])
304
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"
e55e4056 311 "fmuls %1,%2\;dec r1\;brvs 0f\;inc r1\;0:\;mov %0,r1\;clr __zero_reg__"
3ba781d3 312 [(set_attr "length" "6")])
e55e4056 313
3ba781d3 314(define_insn_and_split "muluqq3_enh"
e55e4056
GJL
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"
3ba781d3
SKS
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))])])
325
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"
e55e4056 332 "mul %1,%2\;mov %0,r1\;clr __zero_reg__"
3ba781d3 333 [(set_attr "length" "3")])
e55e4056
GJL
334
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))]
00e641f1
GJL
348 "!AVR_HAVE_MUL"
349 {
350 avr_fix_inputs (operands, 1 << 2, regmask (QQmode, 24));
351 })
352
e55e4056
GJL
353
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))]
00e641f1
GJL
367 "!AVR_HAVE_MUL"
368 {
369 avr_fix_inputs (operands, 1 << 2, regmask (UQQmode, 22));
370 })
e55e4056 371
3ba781d3 372(define_insn_and_split "*mulqq3.call_split"
e55e4056
GJL
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"
3ba781d3
SKS
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))])])
387
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"
e55e4056 396 "%~call __mulqq3"
3ba781d3 397 [(set_attr "type" "xcall")])
e55e4056
GJL
398
399
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))]
00e641f1
GJL
414 "AVR_HAVE_MUL"
415 {
416 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 18));
417 })
e55e4056
GJL
418
419;; "*mulhq3.call" "*muluhq3.call"
420;; "*mulha3.call" "*muluha3.call"
3ba781d3 421(define_insn_and_split "*mul<mode>3.call_split"
e55e4056
GJL
422 [(set (reg:ALL2QA 24)
423 (mult:ALL2QA (reg:ALL2QA 18)
424 (reg:ALL2QA 26)))
425 (clobber (reg:HI 22))]
426 "AVR_HAVE_MUL"
3ba781d3
SKS
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))])])
434
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"
e55e4056 442 "%~call __mul<mode>3"
3ba781d3 443 [(set_attr "type" "xcall")])
e55e4056
GJL
444
445
446;; On the enhanced core, don't clobber either input and use a separate output
447
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))]
00e641f1
GJL
459 "AVR_HAVE_MUL"
460 {
461 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 16));
462 })
e55e4056
GJL
463
464;; "*mulsa3.call" "*mulusa3.call"
3ba781d3 465(define_insn_and_split "*mul<mode>3.call_split"
e55e4056
GJL
466 [(set (reg:ALL4A 24)
467 (mult:ALL4A (reg:ALL4A 16)
468 (reg:ALL4A 20)))]
469 "AVR_HAVE_MUL"
3ba781d3
SKS
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))])])
476
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"
e55e4056 483 "%~call __mul<mode>3"
3ba781d3 484 [(set_attr "type" "xcall")])
e55e4056
GJL
485
486; / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
487; div
488
489(define_code_iterator usdiv [udiv div])
490
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" "")
00e641f1
GJL
502 (reg:ALL1Q 24))]
503 ""
504 {
505 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 25));
506 })
507
e55e4056
GJL
508
509;; "*divqq3.call" "*udivuqq3.call"
3ba781d3 510(define_insn_and_split "*<code><mode>3.call_split"
e55e4056
GJL
511 [(set (reg:ALL1Q 24)
512 (usdiv:ALL1Q (reg:ALL1Q 25)
513 (reg:ALL1Q 22)))
514 (clobber (reg:QI 25))]
515 ""
3ba781d3
SKS
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))])])
523
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"
e55e4056 531 "%~call __<code><mode>3"
3ba781d3 532 [(set_attr "type" "xcall")])
e55e4056
GJL
533
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" "")
00e641f1
GJL
547 (reg:ALL2QA 24))]
548 ""
549 {
550 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 26));
551 })
e55e4056
GJL
552
553;; "*divhq3.call" "*udivuhq3.call"
554;; "*divha3.call" "*udivuha3.call"
3ba781d3 555(define_insn_and_split "*<code><mode>3.call_split"
e55e4056
GJL
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 ""
3ba781d3
SKS
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))])])
570
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"
e55e4056 579 "%~call __<code><mode>3"
3ba781d3 580 [(set_attr "type" "xcall")])
e55e4056
GJL
581
582;; Note the first parameter gets passed in already offset by 2 bytes
583
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" "")
00e641f1
GJL
596 (reg:ALL4A 22))]
597 ""
598 {
599 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 24));
600 })
e55e4056
GJL
601
602;; "*divsa3.call" "*udivusa3.call"
3ba781d3 603(define_insn_and_split "*<code><mode>3.call_split"
e55e4056
GJL
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 ""
3ba781d3
SKS
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))])])
618
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"
e55e4056 627 "%~call __<code><mode>3"
3ba781d3 628 [(set_attr "type" "xcall")])
85d768f3
GJL
629
630
631;******************************************************************************
632;** Rounding
633;******************************************************************************
634
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 }
659
660 // Input and output of the libgcc function
c204f1b5
GJL
661 const unsigned int regno_in[] = { -1U, 22, 22, -1U, 18 };
662 const unsigned int regno_out[] = { -1U, 24, 24, -1U, 22 };
85d768f3
GJL
663
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)]);
00e641f1 666 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, REGNO (operands[4])));
85d768f3
GJL
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 })
671
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.
675
676;; "roundqq3_const" "rounduqq3_const"
677;; "roundhq3_const" "rounduhq3_const" "roundha3_const" "rounduha3_const"
678;; "roundsq3_const" "roundusq3_const" "roundsa3_const" "roundusa3_const"
3ba781d3 679(define_insn_and_split "round<mode>3_const"
02371798
GJL
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))]
85d768f3 685 ""
3ba781d3
SKS
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))])])
694
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"
85d768f3 703 {
02371798
GJL
704 return avr_out_round (insn, operands);
705 }
3ba781d3 706 [(set_attr "adjust_len" "round")])
85d768f3
GJL
707
708
709;; "*roundqq3.libgcc" "*rounduqq3.libgcc"
3ba781d3 710(define_insn_and_split "*round<mode>3.libgcc_split"
85d768f3
GJL
711 [(set (reg:ALL1Q 24)
712 (unspec:ALL1Q [(reg:ALL1Q 22)
713 (reg:QI 24)] UNSPEC_ROUND))
714 (clobber (reg:ALL1Q 22))]
715 ""
3ba781d3
SKS
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))])])
723
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"
85d768f3 731 "%~call __round<mode>3"
3ba781d3 732 [(set_attr "type" "xcall")])
85d768f3
GJL
733
734;; "*roundhq3.libgcc" "*rounduhq3.libgcc"
735;; "*roundha3.libgcc" "*rounduha3.libgcc"
3ba781d3 736(define_insn_and_split "*round<mode>3.libgcc_split"
85d768f3
GJL
737 [(set (reg:ALL2QA 24)
738 (unspec:ALL2QA [(reg:ALL2QA 22)
739 (reg:QI 24)] UNSPEC_ROUND))
740 (clobber (reg:ALL2QA 22))]
741 ""
3ba781d3
SKS
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))])])
749
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"
85d768f3 757 "%~call __round<mode>3"
3ba781d3 758 [(set_attr "type" "xcall")])
85d768f3
GJL
759
760;; "*roundsq3.libgcc" "*roundusq3.libgcc"
761;; "*roundsa3.libgcc" "*roundusa3.libgcc"
3ba781d3 762(define_insn_and_split "*round<mode>3.libgcc_split"
85d768f3
GJL
763 [(set (reg:ALL4QA 22)
764 (unspec:ALL4QA [(reg:ALL4QA 18)
765 (reg:QI 24)] UNSPEC_ROUND))
766 (clobber (reg:ALL4QA 18))]
767 ""
3ba781d3
SKS
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))])])
775
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"
85d768f3 783 "%~call __round<mode>3"
3ba781d3 784 [(set_attr "type" "xcall")])