]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/avr/avr-dimode.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / avr / avr-dimode.md
CommitLineData
8c57e547
GJL
1;; Machine description for GNU compiler,
2;; for Atmel AVR micro controllers.
aeee4812 3;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
8c57e547
GJL
4;; Contributed by Georg Lay (avr@gjlay.de)
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.
12;;
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.
17;;
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/>.
21
22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23
24;; The purpose of this file is to provide a light-weight DImode
25;; implementation for AVR. The trouble with DImode is that tree -> RTL
26;; lowering leads to really unpleasant code for operations that don't
27;; work byte-wise like NEG, PLUS, MINUS, etc. Defining optabs entries for
28;; them won't help because the optab machinery assumes these operations
29;; are cheap and does not check if a libgcc implementation is available.
30;;
31;; The DImode insns are all straight forward -- except movdi. The approach
32;; of this implementation is to provide DImode insns without the burden of
33;; introducing movdi.
00892272 34;;
8c57e547
GJL
35;; The caveat is that if there are insns for some mode, there must also be a
36;; respective move insn that describes reloads. Therefore, this
37;; implementation uses an accumulator-based model with two hard-coded,
38;; accumulator-like registers
39;;
40;; A[] = reg:DI 18
41;; B[] = reg:DI 10
42;;
43;; so that no DImode insn contains pseudos or needs reloading.
44
45(define_constants
46 [(ACC_A 18)
47 (ACC_B 10)])
48
e55e4056 49;; Supported modes that are 8 bytes wide
51526856
GJL
50(define_mode_iterator ALL8 [DI DQ UDQ DA UDA TA UTA])
51
52(define_mode_iterator ALL8U [UDQ UDA UTA])
53(define_mode_iterator ALL8S [ DQ DA TA])
e55e4056 54
8c57e547
GJL
55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
56;; Addition
57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
58
e55e4056
GJL
59;; "adddi3"
60;; "adddq3" "addudq3"
61;; "addda3" "adduda3"
62;; "addta3" "adduta3"
63(define_expand "add<mode>3"
64 [(parallel [(match_operand:ALL8 0 "general_operand" "")
65 (match_operand:ALL8 1 "general_operand" "")
66 (match_operand:ALL8 2 "general_operand" "")])]
8c57e547
GJL
67 "avr_have_dimode"
68 {
e55e4056 69 rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A);
8c57e547 70
00e641f1 71 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, ACC_A));
8c57e547
GJL
72 emit_move_insn (acc_a, operands[1]);
73
e55e4056
GJL
74 if (DImode == <MODE>mode
75 && s8_operand (operands[2], VOIDmode))
8c57e547
GJL
76 {
77 emit_move_insn (gen_rtx_REG (QImode, REG_X), operands[2]);
78 emit_insn (gen_adddi3_const8_insn ());
00892272 79 }
e55e4056 80 else if (const_operand (operands[2], GET_MODE (operands[2])))
8c57e547 81 {
e55e4056 82 emit_insn (gen_add<mode>3_const_insn (operands[2]));
8c57e547
GJL
83 }
84 else
85 {
e55e4056
GJL
86 emit_move_insn (gen_rtx_REG (<MODE>mode, ACC_B), operands[2]);
87 emit_insn (gen_add<mode>3_insn ());
8c57e547
GJL
88 }
89
90 emit_move_insn (operands[0], acc_a);
91 DONE;
92 })
93
e55e4056
GJL
94;; "adddi3_insn"
95;; "adddq3_insn" "addudq3_insn"
96;; "addda3_insn" "adduda3_insn"
97;; "addta3_insn" "adduta3_insn"
3ba781d3 98(define_insn_and_split "add<mode>3_insn"
e55e4056
GJL
99 [(set (reg:ALL8 ACC_A)
100 (plus:ALL8 (reg:ALL8 ACC_A)
101 (reg:ALL8 ACC_B)))]
8c57e547 102 "avr_have_dimode"
3ba781d3
SKS
103 "#"
104 "&& reload_completed"
105 [(parallel [(set (reg:ALL8 ACC_A)
106 (plus:ALL8 (reg:ALL8 ACC_A)
107 (reg:ALL8 ACC_B)))
108 (clobber (reg:CC REG_CC))])])
109
110(define_insn "*add<mode>3_insn"
111 [(set (reg:ALL8 ACC_A)
112 (plus:ALL8 (reg:ALL8 ACC_A)
113 (reg:ALL8 ACC_B)))
114 (clobber (reg:CC REG_CC))]
115 "avr_have_dimode && reload_completed"
8c57e547 116 "%~call __adddi3"
3ba781d3 117 [(set_attr "adjust_len" "call")])
8c57e547 118
3ba781d3 119(define_insn_and_split "adddi3_const8_insn"
8c57e547
GJL
120 [(set (reg:DI ACC_A)
121 (plus:DI (reg:DI ACC_A)
122 (sign_extend:DI (reg:QI REG_X))))]
123 "avr_have_dimode"
3ba781d3
SKS
124 "#"
125 "&& reload_completed"
126 [(parallel [(set (reg:DI ACC_A)
127 (plus:DI (reg:DI ACC_A)
128 (sign_extend:DI (reg:QI REG_X))))
129 (clobber (reg:CC REG_CC))])])
130
131(define_insn "*adddi3_const8_insn"
132 [(set (reg:DI ACC_A)
133 (plus:DI (reg:DI ACC_A)
134 (sign_extend:DI (reg:QI REG_X))))
135 (clobber (reg:CC REG_CC))]
136 "avr_have_dimode && reload_completed"
8c57e547 137 "%~call __adddi3_s8"
3ba781d3 138 [(set_attr "adjust_len" "call")])
8c57e547 139
e55e4056
GJL
140;; "adddi3_const_insn"
141;; "adddq3_const_insn" "addudq3_const_insn"
142;; "addda3_const_insn" "adduda3_const_insn"
143;; "addta3_const_insn" "adduta3_const_insn"
3ba781d3 144(define_insn_and_split "add<mode>3_const_insn"
e55e4056
GJL
145 [(set (reg:ALL8 ACC_A)
146 (plus:ALL8 (reg:ALL8 ACC_A)
147 (match_operand:ALL8 0 "const_operand" "n Ynn")))]
8c57e547
GJL
148 "avr_have_dimode
149 && !s8_operand (operands[0], VOIDmode)"
3ba781d3
SKS
150 "#"
151 "&& reload_completed"
152 [(parallel [(set (reg:ALL8 ACC_A)
153 (plus:ALL8 (reg:ALL8 ACC_A)
154 (match_dup 0)))
155 (clobber (reg:CC REG_CC))])])
156
157(define_insn "*add<mode>3_const_insn"
158 [(set (reg:ALL8 ACC_A)
159 (plus:ALL8 (reg:ALL8 ACC_A)
160 (match_operand:ALL8 0 "const_operand" "n Ynn")))
161 (clobber (reg:CC REG_CC))]
162 "avr_have_dimode
163 && !s8_operand (operands[0], VOIDmode)
164 && reload_completed"
8c57e547 165 {
51526856 166 return avr_out_plus (insn, operands);
8c57e547 167 }
3ba781d3 168 [(set_attr "adjust_len" "plus")])
8c57e547
GJL
169
170
171;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
172;; Subtraction
173;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
174
e55e4056
GJL
175;; "subdi3"
176;; "subdq3" "subudq3"
177;; "subda3" "subuda3"
178;; "subta3" "subuta3"
179(define_expand "sub<mode>3"
180 [(parallel [(match_operand:ALL8 0 "general_operand" "")
181 (match_operand:ALL8 1 "general_operand" "")
182 (match_operand:ALL8 2 "general_operand" "")])]
8c57e547
GJL
183 "avr_have_dimode"
184 {
e55e4056 185 rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A);
8c57e547 186
00e641f1 187 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, ACC_A));
8c57e547 188 emit_move_insn (acc_a, operands[1]);
e55e4056
GJL
189
190 if (const_operand (operands[2], GET_MODE (operands[2])))
191 {
192 emit_insn (gen_sub<mode>3_const_insn (operands[2]));
193 }
194 else
195 {
196 emit_move_insn (gen_rtx_REG (<MODE>mode, ACC_B), operands[2]);
197 emit_insn (gen_sub<mode>3_insn ());
198 }
199
8c57e547
GJL
200 emit_move_insn (operands[0], acc_a);
201 DONE;
202 })
203
e55e4056
GJL
204;; "subdi3_insn"
205;; "subdq3_insn" "subudq3_insn"
206;; "subda3_insn" "subuda3_insn"
207;; "subta3_insn" "subuta3_insn"
3ba781d3 208(define_insn_and_split "sub<mode>3_insn"
e55e4056
GJL
209 [(set (reg:ALL8 ACC_A)
210 (minus:ALL8 (reg:ALL8 ACC_A)
211 (reg:ALL8 ACC_B)))]
8c57e547 212 "avr_have_dimode"
3ba781d3
SKS
213 "#"
214 "&& reload_completed"
215 [(parallel [(set (reg:ALL8 ACC_A)
216 (minus:ALL8 (reg:ALL8 ACC_A)
217 (reg:ALL8 ACC_B)))
218 (clobber (reg:CC REG_CC))])])
219
220(define_insn "*sub<mode>3_insn"
221 [(set (reg:ALL8 ACC_A)
222 (minus:ALL8 (reg:ALL8 ACC_A)
223 (reg:ALL8 ACC_B)))
224 (clobber (reg:CC REG_CC))]
225 "avr_have_dimode && reload_completed"
8c57e547 226 "%~call __subdi3"
3ba781d3 227 [(set_attr "adjust_len" "call")])
8c57e547 228
e55e4056
GJL
229;; "subdi3_const_insn"
230;; "subdq3_const_insn" "subudq3_const_insn"
231;; "subda3_const_insn" "subuda3_const_insn"
232;; "subta3_const_insn" "subuta3_const_insn"
3ba781d3 233(define_insn_and_split "sub<mode>3_const_insn"
e55e4056
GJL
234 [(set (reg:ALL8 ACC_A)
235 (minus:ALL8 (reg:ALL8 ACC_A)
236 (match_operand:ALL8 0 "const_operand" "n Ynn")))]
237 "avr_have_dimode"
3ba781d3
SKS
238 "#"
239 "&& reload_completed"
240 [(parallel [(set (reg:ALL8 ACC_A)
241 (minus:ALL8 (reg:ALL8 ACC_A)
242 (match_dup 0)))
243 (clobber (reg:CC REG_CC))])])
244
245(define_insn "*sub<mode>3_const_insn"
246 [(set (reg:ALL8 ACC_A)
247 (minus:ALL8 (reg:ALL8 ACC_A)
248 (match_operand:ALL8 0 "const_operand" "n Ynn")))
249 (clobber (reg:CC REG_CC))]
250 "avr_have_dimode && reload_completed"
e55e4056 251 {
51526856
GJL
252 return avr_out_plus (insn, operands);
253 }
3ba781d3 254 [(set_attr "adjust_len" "plus")])
51526856
GJL
255
256;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
257;; Signed Saturating Addition and Subtraction
258;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
259
260(define_expand "<code_stdname><mode>3"
261 [(set (match_operand:ALL8S 0 "general_operand" "")
262 (ss_addsub:ALL8S (match_operand:ALL8S 1 "general_operand" "")
263 (match_operand:ALL8S 2 "general_operand" "")))]
264 "avr_have_dimode"
265 {
266 rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A);
267
00e641f1 268 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, ACC_A));
51526856
GJL
269 emit_move_insn (acc_a, operands[1]);
270
271 if (const_operand (operands[2], GET_MODE (operands[2])))
272 {
273 emit_insn (gen_<code_stdname><mode>3_const_insn (operands[2]));
274 }
275 else
276 {
277 emit_move_insn (gen_rtx_REG (<MODE>mode, ACC_B), operands[2]);
278 emit_insn (gen_<code_stdname><mode>3_insn ());
279 }
280
281 emit_move_insn (operands[0], acc_a);
282 DONE;
283 })
284
3ba781d3 285(define_insn_and_split "<code_stdname><mode>3_insn"
51526856
GJL
286 [(set (reg:ALL8S ACC_A)
287 (ss_addsub:ALL8S (reg:ALL8S ACC_A)
288 (reg:ALL8S ACC_B)))]
289 "avr_have_dimode"
3ba781d3
SKS
290 "#"
291 "&& reload_completed"
292 [(parallel [(set (reg:ALL8S ACC_A)
293 (ss_addsub:ALL8S (reg:ALL8S ACC_A)
294 (reg:ALL8S ACC_B)))
295 (clobber (reg:CC REG_CC))])])
296
297(define_insn "*<code_stdname><mode>3_insn"
298 [(set (reg:ALL8S ACC_A)
299 (ss_addsub:ALL8S (reg:ALL8S ACC_A)
300 (reg:ALL8S ACC_B)))
301 (clobber (reg:CC REG_CC))]
302 "avr_have_dimode && reload_completed"
51526856 303 "%~call __<code_stdname><mode>3"
3ba781d3 304 [(set_attr "adjust_len" "call")])
51526856 305
3ba781d3 306(define_insn_and_split "<code_stdname><mode>3_const_insn"
51526856
GJL
307 [(set (reg:ALL8S ACC_A)
308 (ss_addsub:ALL8S (reg:ALL8S ACC_A)
309 (match_operand:ALL8S 0 "const_operand" "n Ynn")))]
310 "avr_have_dimode"
3ba781d3
SKS
311 "#"
312 "&& reload_completed"
313 [(parallel [(set (reg:ALL8S ACC_A)
314 (ss_addsub:ALL8S (reg:ALL8S ACC_A)
315 (match_dup 0)))
316 (clobber (reg:CC REG_CC))])])
317
318(define_insn "*<code_stdname><mode>3_const_insn"
319 [(set (reg:ALL8S ACC_A)
320 (ss_addsub:ALL8S (reg:ALL8S ACC_A)
321 (match_operand:ALL8S 0 "const_operand" "n Ynn")))
322 (clobber (reg:CC REG_CC))]
323 "avr_have_dimode && reload_completed"
51526856
GJL
324 {
325 return avr_out_plus (insn, operands);
e55e4056 326 }
3ba781d3 327 [(set_attr "adjust_len" "plus")])
51526856
GJL
328
329;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
330;; Unsigned Saturating Addition and Subtraction
331;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
332
333(define_expand "<code_stdname><mode>3"
334 [(set (match_operand:ALL8U 0 "general_operand" "")
335 (us_addsub:ALL8U (match_operand:ALL8U 1 "general_operand" "")
336 (match_operand:ALL8U 2 "general_operand" "")))]
337 "avr_have_dimode"
338 {
339 rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A);
340
00e641f1 341 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, ACC_A));
51526856
GJL
342 emit_move_insn (acc_a, operands[1]);
343
344 if (const_operand (operands[2], GET_MODE (operands[2])))
345 {
346 emit_insn (gen_<code_stdname><mode>3_const_insn (operands[2]));
347 }
348 else
349 {
350 emit_move_insn (gen_rtx_REG (<MODE>mode, ACC_B), operands[2]);
351 emit_insn (gen_<code_stdname><mode>3_insn ());
352 }
353
354 emit_move_insn (operands[0], acc_a);
355 DONE;
356 })
357
3ba781d3 358(define_insn_and_split "<code_stdname><mode>3_insn"
51526856
GJL
359 [(set (reg:ALL8U ACC_A)
360 (us_addsub:ALL8U (reg:ALL8U ACC_A)
361 (reg:ALL8U ACC_B)))]
362 "avr_have_dimode"
3ba781d3
SKS
363 "#"
364 "&& reload_completed"
365 [(parallel [(set (reg:ALL8U ACC_A)
366 (us_addsub:ALL8U (reg:ALL8U ACC_A)
367 (reg:ALL8U ACC_B)))
368 (clobber (reg:CC REG_CC))])])
369
370(define_insn "*<code_stdname><mode>3_insn"
371 [(set (reg:ALL8U ACC_A)
372 (us_addsub:ALL8U (reg:ALL8U ACC_A)
373 (reg:ALL8U ACC_B)))
374 (clobber (reg:CC REG_CC))]
375 "avr_have_dimode && reload_completed"
51526856 376 "%~call __<code_stdname><mode>3"
3ba781d3 377 [(set_attr "adjust_len" "call")])
e55e4056 378
3ba781d3 379(define_insn_and_split "<code_stdname><mode>3_const_insn"
51526856
GJL
380 [(set (reg:ALL8U ACC_A)
381 (us_addsub:ALL8U (reg:ALL8U ACC_A)
382 (match_operand:ALL8U 0 "const_operand" "n Ynn")))]
383 "avr_have_dimode"
3ba781d3
SKS
384 "#"
385 "&& reload_completed"
386 [(parallel [(set (reg:ALL8U ACC_A)
387 (us_addsub:ALL8U (reg:ALL8U ACC_A)
388 (match_operand:ALL8U 0 "const_operand" "n Ynn")))
389 (clobber (reg:CC REG_CC))])])
390
391(define_insn "*<code_stdname><mode>3_const_insn"
392 [(set (reg:ALL8U ACC_A)
393 (us_addsub:ALL8U (reg:ALL8U ACC_A)
394 (match_operand:ALL8U 0 "const_operand" "n Ynn")))
395 (clobber (reg:CC REG_CC))]
396 "avr_have_dimode && reload_completed"
51526856
GJL
397 {
398 return avr_out_plus (insn, operands);
399 }
3ba781d3 400 [(set_attr "adjust_len" "plus")])
8c57e547
GJL
401
402;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
403;; Negation
404;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
405
406(define_expand "negdi2"
407 [(parallel [(match_operand:DI 0 "general_operand" "")
408 (match_operand:DI 1 "general_operand" "")])]
409 "avr_have_dimode"
410 {
411 rtx acc_a = gen_rtx_REG (DImode, ACC_A);
412
413 emit_move_insn (acc_a, operands[1]);
414 emit_insn (gen_negdi2_insn ());
415 emit_move_insn (operands[0], acc_a);
416 DONE;
417 })
418
3ba781d3 419(define_insn_and_split "negdi2_insn"
8c57e547
GJL
420 [(set (reg:DI ACC_A)
421 (neg:DI (reg:DI ACC_A)))]
422 "avr_have_dimode"
3ba781d3
SKS
423 "#"
424 "&& reload_completed"
425 [(parallel [(set (reg:DI ACC_A)
426 (neg:DI (reg:DI ACC_A)))
427 (clobber (reg:CC REG_CC))])])
428
429(define_insn "*negdi2_insn"
430 [(set (reg:DI ACC_A)
431 (neg:DI (reg:DI ACC_A)))
432 (clobber (reg:CC REG_CC))]
433 "avr_have_dimode && reload_completed"
8c57e547 434 "%~call __negdi2"
3ba781d3 435 [(set_attr "adjust_len" "call")])
8c57e547
GJL
436
437
438;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
439;; Comparison
440;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
441
442(define_expand "conditional_jump"
443 [(set (pc)
444 (if_then_else
3ba781d3 445 (match_operator 0 "ordered_comparison_operator" [(reg:CC REG_CC)
8c57e547
GJL
446 (const_int 0)])
447 (label_ref (match_operand 1 "" ""))
448 (pc)))]
449 "avr_have_dimode")
450
e55e4056
GJL
451;; "cbranchdi4"
452;; "cbranchdq4" "cbranchudq4"
453;; "cbranchda4" "cbranchuda4"
454;; "cbranchta4" "cbranchuta4"
455(define_expand "cbranch<mode>4"
3ba781d3
SKS
456 [(set (pc)
457 (if_then_else (match_operator 0 "ordered_comparison_operator"
458 [(match_operand:ALL8 1 "register_operand" "")
459 (match_operand:ALL8 2 "nonmemory_operand" "")])
460 (label_ref (match_operand 3 "" ""))
461 (pc)))]
8c57e547 462 "avr_have_dimode"
3ba781d3 463 {
e55e4056 464 rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A);
8c57e547 465
00e641f1 466 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, ACC_A));
8c57e547
GJL
467 emit_move_insn (acc_a, operands[1]);
468
469 if (s8_operand (operands[2], VOIDmode))
470 {
471 emit_move_insn (gen_rtx_REG (QImode, REG_X), operands[2]);
3ba781d3 472 emit_jump_insn (gen_cbranch_const8_di2_split (operands[0], operands[3]));
00892272 473 }
e55e4056 474 else if (const_operand (operands[2], GET_MODE (operands[2])))
8c57e547 475 {
3ba781d3
SKS
476 emit_jump_insn (gen_cbranch_const_<mode>2_split (operands[0],
477 operands[2],
478 operands[3]));
8c57e547
GJL
479 }
480 else
481 {
e55e4056 482 emit_move_insn (gen_rtx_REG (<MODE>mode, ACC_B), operands[2]);
3ba781d3 483 emit_jump_insn (gen_cbranch_<mode>2_split (operands[0], operands[3]));
8c57e547 484 }
3ba781d3
SKS
485 DONE;
486 })
8c57e547 487
3ba781d3
SKS
488(define_insn_and_split "cbranch_<mode>2_split"
489 [(set (pc)
490 (if_then_else (match_operator 0 "ordered_comparison_operator"
491 [(reg:ALL8 ACC_A)
492 (reg:ALL8 ACC_B)])
493 (label_ref (match_operand 1 "" ""))
494 (pc)))]
495 "avr_have_dimode"
496 "#"
497 "&& reload_completed"
498 [(const_int 0)]
499 {
500 emit_insn (gen_compare_<mode>2 ());
501 emit_jump_insn (gen_conditional_jump (operands[0], operands[1]));
8c57e547
GJL
502 DONE;
503 })
504
e55e4056
GJL
505;; "compare_di2"
506;; "compare_dq2" "compare_udq2"
507;; "compare_da2" "compare_uda2"
508;; "compare_ta2" "compare_uta2"
509(define_insn "compare_<mode>2"
3ba781d3
SKS
510 [(set (reg:CC REG_CC)
511 (compare:CC (reg:ALL8 ACC_A)
512 (reg:ALL8 ACC_B)))]
513 "reload_completed && avr_have_dimode"
8c57e547 514 "%~call __cmpdi2"
3ba781d3 515 [(set_attr "adjust_len" "call")])
8c57e547 516
3ba781d3
SKS
517(define_insn_and_split "cbranch_const8_di2_split"
518 [(set (pc)
519 (if_then_else (match_operator 0 "ordered_comparison_operator"
520 [(reg:DI ACC_A)
521 (sign_extend:DI (reg:QI REG_X))])
522 (label_ref (match_operand 1 "" ""))
523 (pc)))]
8c57e547 524 "avr_have_dimode"
3ba781d3
SKS
525 "#"
526 "&& reload_completed"
527 [(const_int 0)]
528 {
529 emit_insn (gen_compare_const8_di2 ());
530 emit_jump_insn (gen_conditional_jump (operands[0], operands[1]));
531 DONE;
532 })
533
534(define_insn "compare_const8_di2"
535 [(set (reg:CC REG_CC)
536 (compare:CC (reg:DI ACC_A)
537 (sign_extend:DI (reg:QI REG_X))))]
538 "reload_completed && avr_have_dimode"
8c57e547 539 "%~call __cmpdi2_s8"
3ba781d3
SKS
540 [(set_attr "adjust_len" "call")])
541
542(define_insn_and_split "cbranch_const_<mode>2_split"
543 [(set (pc)
544 (if_then_else (match_operator 0 "ordered_comparison_operator"
545 [(reg:ALL8 ACC_A)
546 (match_operand:ALL8 1 "const_operand" "n Ynn")])
547 (label_ref (match_operand 2 "" ""))
548 (pc)))
549 (clobber (match_scratch:QI 3 "=&d"))]
550 "avr_have_dimode
551 && !s8_operand (operands[1], VOIDmode)"
552 "#"
553 "&& reload_completed"
554 [(const_int 0)]
555 {
556 emit_insn (gen_compare_const_<mode>2 (operands[1], operands[3]));
557 emit_jump_insn (gen_conditional_jump (operands[0], operands[2]));
558 DONE;
559 })
560
8c57e547 561
e55e4056
GJL
562;; "compare_const_di2"
563;; "compare_const_dq2" "compare_const_udq2"
564;; "compare_const_da2" "compare_const_uda2"
565;; "compare_const_ta2" "compare_const_uta2"
566(define_insn "compare_const_<mode>2"
3ba781d3
SKS
567 [(set (reg:CC REG_CC)
568 (compare:CC (reg:ALL8 ACC_A)
569 (match_operand:ALL8 0 "const_operand" "n Ynn")))
570 (clobber (match_operand:QI 1 "register_operand" "=&d"))]
571 "reload_completed
572 && avr_have_dimode
8c57e547
GJL
573 && !s8_operand (operands[0], VOIDmode)"
574 {
575 return avr_out_compare64 (insn, operands, NULL);
576 }
3ba781d3 577 [(set_attr "adjust_len" "compare64")])
8c57e547
GJL
578
579
580;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
581;; Shifts and Rotate
582;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
583
584(define_code_iterator di_shifts
585 [ashift ashiftrt lshiftrt rotate])
586
587;; Shift functions from libgcc are called without defining these insns,
588;; but with them we can describe their reduced register footprint.
589
e55e4056
GJL
590;; "ashldi3" "ashrdi3" "lshrdi3" "rotldi3"
591;; "ashldq3" "ashrdq3" "lshrdq3" "rotldq3"
592;; "ashlda3" "ashrda3" "lshrda3" "rotlda3"
593;; "ashlta3" "ashrta3" "lshrta3" "rotlta3"
594;; "ashludq3" "ashrudq3" "lshrudq3" "rotludq3"
595;; "ashluda3" "ashruda3" "lshruda3" "rotluda3"
596;; "ashluta3" "ashruta3" "lshruta3" "rotluta3"
597(define_expand "<code_stdname><mode>3"
598 [(parallel [(match_operand:ALL8 0 "general_operand" "")
599 (di_shifts:ALL8 (match_operand:ALL8 1 "general_operand" "")
600 (match_operand:QI 2 "general_operand" ""))])]
8c57e547
GJL
601 "avr_have_dimode"
602 {
e55e4056 603 rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A);
8c57e547 604
00e641f1 605 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, ACC_A));
8c57e547
GJL
606 emit_move_insn (acc_a, operands[1]);
607 emit_move_insn (gen_rtx_REG (QImode, 16), operands[2]);
e55e4056 608 emit_insn (gen_<code_stdname><mode>3_insn ());
8c57e547
GJL
609 emit_move_insn (operands[0], acc_a);
610 DONE;
611 })
612
e55e4056
GJL
613;; "ashldi3_insn" "ashrdi3_insn" "lshrdi3_insn" "rotldi3_insn"
614;; "ashldq3_insn" "ashrdq3_insn" "lshrdq3_insn" "rotldq3_insn"
615;; "ashlda3_insn" "ashrda3_insn" "lshrda3_insn" "rotlda3_insn"
616;; "ashlta3_insn" "ashrta3_insn" "lshrta3_insn" "rotlta3_insn"
617;; "ashludq3_insn" "ashrudq3_insn" "lshrudq3_insn" "rotludq3_insn"
618;; "ashluda3_insn" "ashruda3_insn" "lshruda3_insn" "rotluda3_insn"
619;; "ashluta3_insn" "ashruta3_insn" "lshruta3_insn" "rotluta3_insn"
3ba781d3 620(define_insn_and_split "<code_stdname><mode>3_insn"
e55e4056
GJL
621 [(set (reg:ALL8 ACC_A)
622 (di_shifts:ALL8 (reg:ALL8 ACC_A)
623 (reg:QI 16)))]
8c57e547 624 "avr_have_dimode"
3ba781d3
SKS
625 "#"
626 "&& reload_completed"
627 [(parallel [(set (reg:ALL8 ACC_A)
628 (di_shifts:ALL8 (reg:ALL8 ACC_A)
629 (reg:QI 16)))
630 (clobber (reg:CC REG_CC))])])
631
632(define_insn "*<code_stdname><mode>3_insn"
633 [(set (reg:ALL8 ACC_A)
634 (di_shifts:ALL8 (reg:ALL8 ACC_A)
635 (reg:QI 16)))
636 (clobber (reg:CC REG_CC))]
637 "avr_have_dimode && reload_completed"
8c57e547 638 "%~call __<code_stdname>di3"
3ba781d3 639 [(set_attr "adjust_len" "call")])
e68a4ef6
GJL
640
641;; "umulsidi3"
642;; "mulsidi3"
643(define_expand "<extend_u>mulsidi3"
644 [(parallel [(match_operand:DI 0 "register_operand" "")
645 (match_operand:SI 1 "general_operand" "")
646 (match_operand:SI 2 "general_operand" "")
647 ;; Just to mention the iterator
648 (clobber (any_extend:SI (match_dup 1)))])]
1f82f124
GJL
649 "avr_have_dimode
650 && AVR_HAVE_MUL"
e68a4ef6 651 {
00e641f1 652 avr_fix_inputs (operands, 1 << 2, regmask (SImode, 22));
e68a4ef6
GJL
653 emit_move_insn (gen_rtx_REG (SImode, 22), operands[1]);
654 emit_move_insn (gen_rtx_REG (SImode, 18), operands[2]);
655 emit_insn (gen_<extend_u>mulsidi3_insn());
656 // Use emit_move_insn and not open-coded expand because of missing movdi
657 emit_move_insn (operands[0], gen_rtx_REG (DImode, ACC_A));
658 DONE;
659 })
660
661;; "umulsidi3_insn"
662;; "mulsidi3_insn"
3ba781d3
SKS
663
664(define_insn_and_split "<extend_u>mulsidi3_insn"
e68a4ef6
GJL
665 [(set (reg:DI ACC_A)
666 (mult:DI (any_extend:DI (reg:SI 18))
667 (any_extend:DI (reg:SI 22))))
668 (clobber (reg:HI REG_X))
669 (clobber (reg:HI REG_Z))]
1f82f124
GJL
670 "avr_have_dimode
671 && AVR_HAVE_MUL"
3ba781d3
SKS
672 "#"
673 "&& reload_completed"
674 [(parallel [(set (reg:DI ACC_A)
675 (mult:DI (any_extend:DI (reg:SI 18))
676 (any_extend:DI (reg:SI 22))))
677 (clobber (reg:HI REG_X))
678 (clobber (reg:HI REG_Z))
679 (clobber (reg:CC REG_CC))])])
680
681(define_insn "*<extend_u>mulsidi3_insn"
682 [(set (reg:DI ACC_A)
683 (mult:DI (any_extend:DI (reg:SI 18))
684 (any_extend:DI (reg:SI 22))))
685 (clobber (reg:HI REG_X))
686 (clobber (reg:HI REG_Z))
687 (clobber (reg:CC REG_CC))]
688 "avr_have_dimode
689 && AVR_HAVE_MUL
690 && reload_completed"
e68a4ef6 691 "%~call __<extend_u>mulsidi3"
3ba781d3 692 [(set_attr "adjust_len" "call")])