]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/avr/avr.md
Update Copyright years for files modified in 2011 and/or 2012.
[thirdparty/gcc.git] / gcc / config / avr / avr.md
1 ;; Machine description for GNU compiler,
2 ;; for ATMEL AVR micro controllers.
3 ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008,
4 ;; 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
5 ;; Contributed by Denis Chertykov (chertykov@gmail.com)
6
7 ;; This file is part of GCC.
8
9 ;; GCC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 3, or (at your option)
12 ;; any later version.
13
14 ;; GCC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GCC; see the file COPYING3. If not see
21 ;; <http://www.gnu.org/licenses/>.
22
23 ;; Special characters after '%':
24 ;; A No effect (add 0).
25 ;; B Add 1 to REG number, MEM address or CONST_INT.
26 ;; C Add 2.
27 ;; D Add 3.
28 ;; j Branch condition.
29 ;; k Reverse branch condition.
30 ;;..m..Constant Direct Data memory address.
31 ;; i Print the SFR address quivalent of a CONST_INT or a CONST_INT
32 ;; RAM address. The resulting address is suitable to be used in IN/OUT.
33 ;; o Displacement for (mem (plus (reg) (const_int))) operands.
34 ;; p POST_INC or PRE_DEC address as a pointer (X, Y, Z)
35 ;; r POST_INC or PRE_DEC address as a register (r26, r28, r30)
36 ;; T/T Print operand suitable for BLD/BST instruction, i.e. register and
37 ;; bit number. This gets 2 operands: The first %T gets a REG_P and
38 ;; just cashes the operand for the next %T. The second %T gets
39 ;; a CONST_INT that represents a bit position.
40 ;; Example: With %0 = (reg:HI 18) and %1 = (const_int 13)
41 ;; "%T0%T1" it will print "r19,5".
42 ;; Notice that you must not write a comma between %T0 and %T1.
43 ;; T/t Similar to above, but don't print the comma and the bit number.
44 ;; Example: With %0 = (reg:HI 18) and %1 = (const_int 13)
45 ;; "%T0%t1" it will print "r19".
46 ;;..x..Constant Direct Program memory address.
47 ;; ~ Output 'r' if not AVR_HAVE_JMP_CALL.
48 ;; ! Output 'e' if AVR_HAVE_EIJMP_EICALL.
49
50
51 (define_constants
52 [(REG_X 26)
53 (REG_Y 28)
54 (REG_Z 30)
55 (REG_W 24)
56 (REG_SP 32)
57 (LPM_REGNO 0) ; implicit target register of LPM
58 (TMP_REGNO 0) ; temporary register r0
59 (ZERO_REGNO 1) ; zero register r1
60 ])
61
62 (define_c_enum "unspec"
63 [UNSPEC_STRLEN
64 UNSPEC_MOVMEM
65 UNSPEC_INDEX_JMP
66 UNSPEC_FMUL
67 UNSPEC_FMULS
68 UNSPEC_FMULSU
69 UNSPEC_COPYSIGN
70 UNSPEC_IDENTITY
71 UNSPEC_INSERT_BITS
72 ])
73
74 (define_c_enum "unspecv"
75 [UNSPECV_PROLOGUE_SAVES
76 UNSPECV_EPILOGUE_RESTORES
77 UNSPECV_WRITE_SP
78 UNSPECV_GOTO_RECEIVER
79 UNSPECV_ENABLE_IRQS
80 UNSPECV_MEMORY_BARRIER
81 UNSPECV_NOP
82 UNSPECV_SLEEP
83 UNSPECV_WDR
84 UNSPECV_DELAY_CYCLES
85 ])
86
87
88 (include "predicates.md")
89 (include "constraints.md")
90
91 ;; Condition code settings.
92 (define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber,
93 plus,ldi"
94 (const_string "none"))
95
96 (define_attr "type" "branch,branch1,arith,xcall"
97 (const_string "arith"))
98
99 ;; The size of instructions in bytes.
100 ;; XXX may depend from "cc"
101
102 (define_attr "length" ""
103 (cond [(eq_attr "type" "branch")
104 (if_then_else (and (ge (minus (pc) (match_dup 0))
105 (const_int -63))
106 (le (minus (pc) (match_dup 0))
107 (const_int 62)))
108 (const_int 1)
109 (if_then_else (and (ge (minus (pc) (match_dup 0))
110 (const_int -2045))
111 (le (minus (pc) (match_dup 0))
112 (const_int 2045)))
113 (const_int 2)
114 (const_int 3)))
115 (eq_attr "type" "branch1")
116 (if_then_else (and (ge (minus (pc) (match_dup 0))
117 (const_int -62))
118 (le (minus (pc) (match_dup 0))
119 (const_int 61)))
120 (const_int 2)
121 (if_then_else (and (ge (minus (pc) (match_dup 0))
122 (const_int -2044))
123 (le (minus (pc) (match_dup 0))
124 (const_int 2043)))
125 (const_int 3)
126 (const_int 4)))
127 (eq_attr "type" "xcall")
128 (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
129 (const_int 1)
130 (const_int 2))]
131 (const_int 2)))
132
133 ;; Lengths of several insns are adjusted in avr.c:adjust_insn_length().
134 ;; Following insn attribute tells if and how the adjustment has to be
135 ;; done:
136 ;; no No adjustment needed; attribute "length" is fine.
137 ;; Otherwise do special processing depending on the attribute.
138
139 (define_attr "adjust_len"
140 "out_bitop, plus, addto_sp,
141 tsthi, tstpsi, tstsi, compare, compare64, call,
142 mov8, mov16, mov24, mov32, reload_in16, reload_in24, reload_in32,
143 ufract, sfract,
144 xload, lpm, movmem,
145 ashlqi, ashrqi, lshrqi,
146 ashlhi, ashrhi, lshrhi,
147 ashlsi, ashrsi, lshrsi,
148 ashlpsi, ashrpsi, lshrpsi,
149 insert_bits,
150 no"
151 (const_string "no"))
152
153 ;; Flavours of instruction set architecture (ISA), used in enabled attribute
154
155 ;; mov : ISA has no MOVW movw : ISA has MOVW
156 ;; rjmp : ISA has no CALL/JMP jmp : ISA has CALL/JMP
157 ;; ijmp : ISA has no EICALL/EIJMP eijmp : ISA has EICALL/EIJMP
158 ;; lpm : ISA has no LPMX lpmx : ISA has LPMX
159 ;; elpm : ISA has ELPM but no ELPMX elpmx : ISA has ELPMX
160 ;; no_xmega: non-XMEGA core xmega : XMEGA core
161
162 (define_attr "isa"
163 "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx, no_xmega,xmega,
164 standard"
165 (const_string "standard"))
166
167 (define_attr "enabled" ""
168 (cond [(eq_attr "isa" "standard")
169 (const_int 1)
170
171 (and (eq_attr "isa" "mov")
172 (match_test "!AVR_HAVE_MOVW"))
173 (const_int 1)
174
175 (and (eq_attr "isa" "movw")
176 (match_test "AVR_HAVE_MOVW"))
177 (const_int 1)
178
179 (and (eq_attr "isa" "rjmp")
180 (match_test "!AVR_HAVE_JMP_CALL"))
181 (const_int 1)
182
183 (and (eq_attr "isa" "jmp")
184 (match_test "AVR_HAVE_JMP_CALL"))
185 (const_int 1)
186
187 (and (eq_attr "isa" "ijmp")
188 (match_test "!AVR_HAVE_EIJMP_EICALL"))
189 (const_int 1)
190
191 (and (eq_attr "isa" "eijmp")
192 (match_test "AVR_HAVE_EIJMP_EICALL"))
193 (const_int 1)
194
195 (and (eq_attr "isa" "lpm")
196 (match_test "!AVR_HAVE_LPMX"))
197 (const_int 1)
198
199 (and (eq_attr "isa" "lpmx")
200 (match_test "AVR_HAVE_LPMX"))
201 (const_int 1)
202
203 (and (eq_attr "isa" "elpm")
204 (match_test "AVR_HAVE_ELPM && !AVR_HAVE_ELPMX"))
205 (const_int 1)
206
207 (and (eq_attr "isa" "elpmx")
208 (match_test "AVR_HAVE_ELPMX"))
209 (const_int 1)
210
211 (and (eq_attr "isa" "xmega")
212 (match_test "AVR_XMEGA"))
213 (const_int 1)
214
215 (and (eq_attr "isa" "no_xmega")
216 (match_test "!AVR_XMEGA"))
217 (const_int 1)
218 ] (const_int 0)))
219
220
221 ;; Define mode iterators
222 (define_mode_iterator QIHI [QI HI])
223 (define_mode_iterator QIHI2 [QI HI])
224 (define_mode_iterator QISI [QI HI PSI SI])
225 (define_mode_iterator QIDI [QI HI PSI SI DI])
226 (define_mode_iterator HISI [HI PSI SI])
227
228 (define_mode_iterator ALL1 [QI QQ UQQ])
229 (define_mode_iterator ALL2 [HI HQ UHQ HA UHA])
230 (define_mode_iterator ALL4 [SI SQ USQ SA USA])
231
232 ;; All supported move-modes
233 (define_mode_iterator MOVMODE [QI QQ UQQ
234 HI HQ UHQ HA UHA
235 SI SQ USQ SA USA
236 SF PSI])
237
238 ;; Supported ordered modes that are 2, 3, 4 bytes wide
239 (define_mode_iterator ORDERED234 [HI SI PSI
240 HQ UHQ HA UHA
241 SQ USQ SA USA])
242
243 ;; Define code iterators
244 ;; Define two incarnations so that we can build the cross product.
245 (define_code_iterator any_extend [sign_extend zero_extend])
246 (define_code_iterator any_extend2 [sign_extend zero_extend])
247
248 (define_code_iterator xior [xor ior])
249 (define_code_iterator eqne [eq ne])
250
251 (define_code_iterator ss_addsub [ss_plus ss_minus])
252 (define_code_iterator us_addsub [us_plus us_minus])
253 (define_code_iterator ss_abs_neg [ss_abs ss_neg])
254
255 ;; Define code attributes
256 (define_code_attr extend_su
257 [(sign_extend "s")
258 (zero_extend "u")])
259
260 (define_code_attr extend_u
261 [(sign_extend "")
262 (zero_extend "u")])
263
264 (define_code_attr extend_s
265 [(sign_extend "s")
266 (zero_extend "")])
267
268 ;; Constrain input operand of widening multiply, i.e. MUL resp. MULS.
269 (define_code_attr mul_r_d
270 [(zero_extend "r")
271 (sign_extend "d")])
272
273 (define_code_attr abelian
274 [(ss_minus "") (us_minus "")
275 (ss_plus "%") (us_plus "%")])
276
277 ;; Map RTX code to its standard insn name
278 (define_code_attr code_stdname
279 [(ashift "ashl")
280 (ashiftrt "ashr")
281 (lshiftrt "lshr")
282 (ior "ior")
283 (xor "xor")
284 (rotate "rotl")
285 (ss_plus "ssadd") (ss_minus "sssub") (ss_neg "ssneg") (ss_abs "ssabs")
286 (us_plus "usadd") (us_minus "ussub") (us_neg "usneg")
287 ])
288
289 ;;========================================================================
290 ;; The following is used by nonlocal_goto and setjmp.
291 ;; The receiver pattern will create no instructions since internally
292 ;; virtual_stack_vars = hard_frame_pointer + 1 so the RTL become R28=R28
293 ;; This avoids creating add/sub offsets in frame_pointer save/resore.
294 ;; The 'null' receiver also avoids problems with optimisation
295 ;; not recognising incoming jmp and removing code that resets frame_pointer.
296 ;; The code derived from builtins.c.
297
298 (define_expand "nonlocal_goto_receiver"
299 [(set (reg:HI REG_Y)
300 (unspec_volatile:HI [(const_int 0)] UNSPECV_GOTO_RECEIVER))]
301 ""
302 {
303 emit_move_insn (virtual_stack_vars_rtx,
304 gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx,
305 gen_int_mode (STARTING_FRAME_OFFSET,
306 Pmode)));
307 /* ; This might change the hard frame pointer in ways that aren't
308 ; apparent to early optimization passes, so force a clobber. */
309 emit_clobber (hard_frame_pointer_rtx);
310 DONE;
311 })
312
313
314 ;; Defining nonlocal_goto_receiver means we must also define this.
315 ;; even though its function is identical to that in builtins.c
316
317 (define_expand "nonlocal_goto"
318 [(use (match_operand 0 "general_operand"))
319 (use (match_operand 1 "general_operand"))
320 (use (match_operand 2 "general_operand"))
321 (use (match_operand 3 "general_operand"))]
322 ""
323 {
324 rtx r_label = copy_to_reg (operands[1]);
325 rtx r_fp = operands[3];
326 rtx r_sp = operands[2];
327
328 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
329
330 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
331
332 emit_move_insn (hard_frame_pointer_rtx, r_fp);
333 emit_stack_restore (SAVE_NONLOCAL, r_sp);
334
335 emit_use (hard_frame_pointer_rtx);
336 emit_use (stack_pointer_rtx);
337
338 emit_indirect_jump (r_label);
339
340 DONE;
341 })
342
343 ;; "pushqi1"
344 ;; "pushqq1" "pushuqq1"
345 (define_insn "push<mode>1"
346 [(set (mem:ALL1 (post_dec:HI (reg:HI REG_SP)))
347 (match_operand:ALL1 0 "reg_or_0_operand" "r,Y00"))]
348 ""
349 "@
350 push %0
351 push __zero_reg__"
352 [(set_attr "length" "1,1")])
353
354 ;; All modes for a multi-byte push. We must include complex modes here too,
355 ;; lest emit_single_push_insn "helpfully" create the auto-inc itself.
356 (define_mode_iterator MPUSH
357 [CQI
358 HI CHI HA UHA HQ UHQ
359 SI CSI SA USA SQ USQ
360 DI CDI DA UDA DQ UDQ
361 TA UTA
362 SF SC
363 PSI])
364
365 (define_expand "push<mode>1"
366 [(match_operand:MPUSH 0 "" "")]
367 ""
368 {
369 int i;
370 for (i = GET_MODE_SIZE (<MODE>mode) - 1; i >= 0; --i)
371 {
372 rtx part = simplify_gen_subreg (QImode, operands[0], <MODE>mode, i);
373 if (part != const0_rtx)
374 part = force_reg (QImode, part);
375 emit_insn (gen_pushqi1 (part));
376 }
377 DONE;
378 })
379
380 ;; Notice a special-case when adding N to SP where N results in a
381 ;; zero REG_ARGS_SIZE. This is equivalent to a move from FP.
382 (define_split
383 [(set (reg:HI REG_SP)
384 (match_operand:HI 0 "register_operand" ""))]
385 "reload_completed
386 && frame_pointer_needed
387 && !cfun->calls_alloca
388 && find_reg_note (insn, REG_ARGS_SIZE, const0_rtx)"
389 [(set (reg:HI REG_SP)
390 (reg:HI REG_Y))])
391
392 ;;========================================================================
393 ;; Move stuff around
394
395 ;; Secondary input reload from non-generic 16-bit address spaces
396 (define_insn "reload_in<mode>"
397 [(set (match_operand:MOVMODE 0 "register_operand" "=r")
398 (match_operand:MOVMODE 1 "flash_operand" "m"))
399 (clobber (match_operand:QI 2 "d_register_operand" "=d"))]
400 ;; Fixme: The insn condition must not test the address space.
401 ;; Because the gen tools refuse to generate insns for address spaces
402 ;; and will generate insn-codes.h to look like:
403 ;; #define CODE_FOR_reload_inhi CODE_FOR_nothing
404 "reload_completed || reload_in_progress"
405 {
406 return avr_out_lpm (insn, operands, NULL);
407 }
408 [(set_attr "adjust_len" "lpm")
409 (set_attr "cc" "clobber")])
410
411
412 ;; "loadqi_libgcc"
413 ;; "loadhi_libgcc"
414 ;; "loadpsi_libgcc"
415 ;; "loadsi_libgcc"
416 ;; "loadsf_libgcc"
417 (define_expand "load<mode>_libgcc"
418 [(set (match_dup 3)
419 (match_dup 2))
420 (set (reg:MOVMODE 22)
421 (match_operand:MOVMODE 1 "memory_operand" ""))
422 (set (match_operand:MOVMODE 0 "register_operand" "")
423 (reg:MOVMODE 22))]
424 "avr_load_libgcc_p (operands[1])"
425 {
426 operands[3] = gen_rtx_REG (HImode, REG_Z);
427 operands[2] = force_operand (XEXP (operands[1], 0), NULL_RTX);
428 operands[1] = replace_equiv_address (operands[1], operands[3]);
429 set_mem_addr_space (operands[1], ADDR_SPACE_FLASH);
430 })
431
432 ;; "load_qi_libgcc"
433 ;; "load_hi_libgcc"
434 ;; "load_psi_libgcc"
435 ;; "load_si_libgcc"
436 ;; "load_sf_libgcc"
437 (define_insn "load_<mode>_libgcc"
438 [(set (reg:MOVMODE 22)
439 (match_operand:MOVMODE 0 "memory_operand" "m,m"))]
440 "avr_load_libgcc_p (operands[0])
441 && REG_P (XEXP (operands[0], 0))
442 && REG_Z == REGNO (XEXP (operands[0], 0))"
443 {
444 operands[0] = GEN_INT (GET_MODE_SIZE (<MODE>mode));
445 return "%~call __load_%0";
446 }
447 [(set_attr "length" "1,2")
448 (set_attr "isa" "rjmp,jmp")
449 (set_attr "cc" "clobber")])
450
451
452 ;; "xload8qi_A"
453 ;; "xload8qq_A" "xload8uqq_A"
454 (define_insn_and_split "xload8<mode>_A"
455 [(set (match_operand:ALL1 0 "register_operand" "=r")
456 (match_operand:ALL1 1 "memory_operand" "m"))
457 (clobber (reg:HI REG_Z))]
458 "can_create_pseudo_p()
459 && !avr_xload_libgcc_p (<MODE>mode)
460 && avr_mem_memx_p (operands[1])
461 && REG_P (XEXP (operands[1], 0))"
462 { gcc_unreachable(); }
463 "&& 1"
464 [(clobber (const_int 0))]
465 {
466 /* ; Split away the high part of the address. GCC's register allocator
467 ; in not able to allocate segment registers and reload the resulting
468 ; expressions. Notice that no address register can hold a PSImode. */
469
470 rtx insn, addr = XEXP (operands[1], 0);
471 rtx hi8 = gen_reg_rtx (QImode);
472 rtx reg_z = gen_rtx_REG (HImode, REG_Z);
473
474 emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0));
475 emit_move_insn (hi8, simplify_gen_subreg (QImode, addr, PSImode, 2));
476
477 insn = emit_insn (gen_xload<mode>_8 (operands[0], hi8));
478 set_mem_addr_space (SET_SRC (single_set (insn)),
479 MEM_ADDR_SPACE (operands[1]));
480 DONE;
481 })
482
483 ;; "xloadqi_A" "xloadqq_A" "xloaduqq_A"
484 ;; "xloadhi_A" "xloadhq_A" "xloaduhq_A" "xloadha_A" "xloaduha_A"
485 ;; "xloadsi_A" "xloadsq_A" "xloadusq_A" "xloadsa_A" "xloadusa_A"
486 ;; "xloadpsi_A"
487 ;; "xloadsf_A"
488 (define_insn_and_split "xload<mode>_A"
489 [(set (match_operand:MOVMODE 0 "register_operand" "=r")
490 (match_operand:MOVMODE 1 "memory_operand" "m"))
491 (clobber (reg:MOVMODE 22))
492 (clobber (reg:QI 21))
493 (clobber (reg:HI REG_Z))]
494 "can_create_pseudo_p()
495 && avr_mem_memx_p (operands[1])
496 && REG_P (XEXP (operands[1], 0))"
497 { gcc_unreachable(); }
498 "&& 1"
499 [(clobber (const_int 0))]
500 {
501 rtx addr = XEXP (operands[1], 0);
502 rtx reg_z = gen_rtx_REG (HImode, REG_Z);
503 rtx addr_hi8 = simplify_gen_subreg (QImode, addr, PSImode, 2);
504 addr_space_t as = MEM_ADDR_SPACE (operands[1]);
505 rtx insn;
506
507 /* Split the address to R21:Z */
508 emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0));
509 emit_move_insn (gen_rtx_REG (QImode, 21), addr_hi8);
510
511 /* Load with code from libgcc */
512 insn = emit_insn (gen_xload_<mode>_libgcc ());
513 set_mem_addr_space (SET_SRC (single_set (insn)), as);
514
515 /* Move to destination */
516 emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, 22));
517
518 DONE;
519 })
520
521 ;; Move value from address space memx to a register
522 ;; These insns must be prior to respective generic move insn.
523
524 ;; "xloadqi_8"
525 ;; "xloadqq_8" "xloaduqq_8"
526 (define_insn "xload<mode>_8"
527 [(set (match_operand:ALL1 0 "register_operand" "=&r,r")
528 (mem:ALL1 (lo_sum:PSI (match_operand:QI 1 "register_operand" "r,r")
529 (reg:HI REG_Z))))]
530 "!avr_xload_libgcc_p (<MODE>mode)"
531 {
532 return avr_out_xload (insn, operands, NULL);
533 }
534 [(set_attr "length" "4,4")
535 (set_attr "adjust_len" "*,xload")
536 (set_attr "isa" "lpmx,lpm")
537 (set_attr "cc" "none")])
538
539 ;; R21:Z : 24-bit source address
540 ;; R22 : 1-4 byte output
541
542 ;; "xload_qi_libgcc" "xload_qq_libgcc" "xload_uqq_libgcc"
543 ;; "xload_hi_libgcc" "xload_hq_libgcc" "xload_uhq_libgcc" "xload_ha_libgcc" "xload_uha_libgcc"
544 ;; "xload_si_libgcc" "xload_sq_libgcc" "xload_usq_libgcc" "xload_sa_libgcc" "xload_usa_libgcc"
545 ;; "xload_sf_libgcc"
546 ;; "xload_psi_libgcc"
547 (define_insn "xload_<mode>_libgcc"
548 [(set (reg:MOVMODE 22)
549 (mem:MOVMODE (lo_sum:PSI (reg:QI 21)
550 (reg:HI REG_Z))))
551 (clobber (reg:QI 21))
552 (clobber (reg:HI REG_Z))]
553 "avr_xload_libgcc_p (<MODE>mode)"
554 {
555 rtx x_bytes = GEN_INT (GET_MODE_SIZE (<MODE>mode));
556
557 output_asm_insn ("%~call __xload_%0", &x_bytes);
558 return "";
559 }
560 [(set_attr "type" "xcall")
561 (set_attr "cc" "clobber")])
562
563
564 ;; General move expanders
565
566 ;; "movqi" "movqq" "movuqq"
567 ;; "movhi" "movhq" "movuhq" "movha" "movuha"
568 ;; "movsi" "movsq" "movusq" "movsa" "movusa"
569 ;; "movsf"
570 ;; "movpsi"
571 (define_expand "mov<mode>"
572 [(set (match_operand:MOVMODE 0 "nonimmediate_operand" "")
573 (match_operand:MOVMODE 1 "general_operand" ""))]
574 ""
575 {
576 rtx dest = operands[0];
577 rtx src = operands[1];
578
579 if (avr_mem_flash_p (dest))
580 DONE;
581
582 /* One of the operands has to be in a register. */
583 if (!register_operand (dest, <MODE>mode)
584 && !reg_or_0_operand (src, <MODE>mode))
585 {
586 operands[1] = src = copy_to_mode_reg (<MODE>mode, src);
587 }
588
589 if (avr_mem_memx_p (src))
590 {
591 rtx addr = XEXP (src, 0);
592
593 if (!REG_P (addr))
594 src = replace_equiv_address (src, copy_to_mode_reg (PSImode, addr));
595
596 if (!avr_xload_libgcc_p (<MODE>mode))
597 /* ; No <mode> here because gen_xload8<mode>_A only iterates over ALL1.
598 ; insn-emit does not depend on the mode, it's all about operands. */
599 emit_insn (gen_xload8qi_A (dest, src));
600 else
601 emit_insn (gen_xload<mode>_A (dest, src));
602
603 DONE;
604 }
605
606 if (avr_load_libgcc_p (src))
607 {
608 /* For the small devices, do loads per libgcc call. */
609 emit_insn (gen_load<mode>_libgcc (dest, src));
610 DONE;
611 }
612 })
613
614 ;;========================================================================
615 ;; move byte
616 ;; The last alternative (any immediate constant to any register) is
617 ;; very expensive. It should be optimized by peephole2 if a scratch
618 ;; register is available, but then that register could just as well be
619 ;; allocated for the variable we are loading. But, most of NO_LD_REGS
620 ;; are call-saved registers, and most of LD_REGS are call-used registers,
621 ;; so this may still be a win for registers live across function calls.
622
623 ;; "movqi_insn"
624 ;; "movqq_insn" "movuqq_insn"
625 (define_insn "mov<mode>_insn"
626 [(set (match_operand:ALL1 0 "nonimmediate_operand" "=r ,d ,Qm ,r ,q,r,*r")
627 (match_operand:ALL1 1 "nox_general_operand" "r Y00,n Ynn,r Y00,Qm,r,q,i"))]
628 "register_operand (operands[0], <MODE>mode)
629 || reg_or_0_operand (operands[1], <MODE>mode)"
630 {
631 return output_movqi (insn, operands, NULL);
632 }
633 [(set_attr "length" "1,1,5,5,1,1,4")
634 (set_attr "adjust_len" "mov8")
635 (set_attr "cc" "ldi,none,clobber,clobber,none,none,clobber")])
636
637 ;; This is used in peephole2 to optimize loading immediate constants
638 ;; if a scratch register from LD_REGS happens to be available.
639
640 ;; "*reload_inqi"
641 ;; "*reload_inqq" "*reload_inuqq"
642 (define_insn "*reload_in<mode>"
643 [(set (match_operand:ALL1 0 "register_operand" "=l")
644 (match_operand:ALL1 1 "const_operand" "i"))
645 (clobber (match_operand:QI 2 "register_operand" "=&d"))]
646 "reload_completed"
647 "ldi %2,lo8(%1)
648 mov %0,%2"
649 [(set_attr "length" "2")
650 (set_attr "cc" "none")])
651
652 (define_peephole2
653 [(match_scratch:QI 2 "d")
654 (set (match_operand:ALL1 0 "l_register_operand" "")
655 (match_operand:ALL1 1 "const_operand" ""))]
656 ; No need for a clobber reg for 0x0, 0x01 or 0xff
657 "!satisfies_constraint_Y00 (operands[1])
658 && !satisfies_constraint_Y01 (operands[1])
659 && !satisfies_constraint_Ym1 (operands[1])"
660 [(parallel [(set (match_dup 0)
661 (match_dup 1))
662 (clobber (match_dup 2))])])
663
664 ;;============================================================================
665 ;; move word (16 bit)
666
667 ;; Move register $1 to the Stack Pointer register SP.
668 ;; This insn is emit during function prologue/epilogue generation.
669 ;; $2 = 0: We know that IRQs are off
670 ;; $2 = 1: We know that IRQs are on
671 ;; $2 = 2: SP has 8 bits only, IRQ state does not matter
672 ;; $2 = -1: We don't know anything about IRQ on/off
673 ;; Always write SP via unspec, see PR50063
674
675 (define_insn "movhi_sp_r"
676 [(set (match_operand:HI 0 "stack_register_operand" "=q,q,q,q,q")
677 (unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r,r,r,r,r")
678 (match_operand:HI 2 "const_int_operand" "L,P,N,K,LPN")]
679 UNSPECV_WRITE_SP))]
680 ""
681 "@
682 out %B0,%B1\;out %A0,%A1
683 cli\;out %B0,%B1\;sei\;out %A0,%A1
684 in __tmp_reg__,__SREG__\;cli\;out %B0,%B1\;out __SREG__,__tmp_reg__\;out %A0,%A1
685 out %A0,%A1
686 out %A0,%A1\;out %B0,%B1"
687 [(set_attr "length" "2,4,5,1,2")
688 (set_attr "isa" "no_xmega,no_xmega,no_xmega,*,xmega")
689 (set_attr "cc" "none")])
690
691 (define_peephole2
692 [(match_scratch:QI 2 "d")
693 (set (match_operand:ALL2 0 "l_register_operand" "")
694 (match_operand:ALL2 1 "const_or_immediate_operand" ""))]
695 "operands[1] != CONST0_RTX (<MODE>mode)"
696 [(parallel [(set (match_dup 0)
697 (match_dup 1))
698 (clobber (match_dup 2))])])
699
700 ;; '*' because it is not used in rtl generation, only in above peephole
701 ;; "*reload_inhi"
702 ;; "*reload_inhq" "*reload_inuhq"
703 ;; "*reload_inha" "*reload_inuha"
704 (define_insn "*reload_in<mode>"
705 [(set (match_operand:ALL2 0 "l_register_operand" "=l")
706 (match_operand:ALL2 1 "immediate_operand" "i"))
707 (clobber (match_operand:QI 2 "register_operand" "=&d"))]
708 "reload_completed"
709 {
710 return output_reload_inhi (operands, operands[2], NULL);
711 }
712 [(set_attr "length" "4")
713 (set_attr "adjust_len" "reload_in16")
714 (set_attr "cc" "clobber")])
715
716 ;; "*movhi"
717 ;; "*movhq" "*movuhq"
718 ;; "*movha" "*movuha"
719 (define_insn "*mov<mode>"
720 [(set (match_operand:ALL2 0 "nonimmediate_operand" "=r,r ,r,m ,d,*r,q,r")
721 (match_operand:ALL2 1 "nox_general_operand" "r,Y00,m,r Y00,i,i ,r,q"))]
722 "register_operand (operands[0], <MODE>mode)
723 || reg_or_0_operand (operands[1], <MODE>mode)"
724 {
725 return output_movhi (insn, operands, NULL);
726 }
727 [(set_attr "length" "2,2,6,7,2,6,5,2")
728 (set_attr "adjust_len" "mov16")
729 (set_attr "cc" "none,none,clobber,clobber,none,clobber,none,none")])
730
731 (define_peephole2 ; movw
732 [(set (match_operand:ALL1 0 "even_register_operand" "")
733 (match_operand:ALL1 1 "even_register_operand" ""))
734 (set (match_operand:ALL1 2 "odd_register_operand" "")
735 (match_operand:ALL1 3 "odd_register_operand" ""))]
736 "AVR_HAVE_MOVW
737 && REGNO (operands[0]) == REGNO (operands[2]) - 1
738 && REGNO (operands[1]) == REGNO (operands[3]) - 1"
739 [(set (match_dup 4)
740 (match_dup 5))]
741 {
742 operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
743 operands[5] = gen_rtx_REG (HImode, REGNO (operands[1]));
744 })
745
746 (define_peephole2 ; movw_r
747 [(set (match_operand:ALL1 0 "odd_register_operand" "")
748 (match_operand:ALL1 1 "odd_register_operand" ""))
749 (set (match_operand:ALL1 2 "even_register_operand" "")
750 (match_operand:ALL1 3 "even_register_operand" ""))]
751 "AVR_HAVE_MOVW
752 && REGNO (operands[2]) == REGNO (operands[0]) - 1
753 && REGNO (operands[3]) == REGNO (operands[1]) - 1"
754 [(set (match_dup 4)
755 (match_dup 5))]
756 {
757 operands[4] = gen_rtx_REG (HImode, REGNO (operands[2]));
758 operands[5] = gen_rtx_REG (HImode, REGNO (operands[3]));
759 })
760
761 ;; For LPM loads from AS1 we split
762 ;; R = *Z
763 ;; to
764 ;; R = *Z++
765 ;; Z = Z - sizeof (R)
766 ;;
767 ;; so that the second instruction can be optimized out.
768
769 (define_split ; "split-lpmx"
770 [(set (match_operand:HISI 0 "register_operand" "")
771 (match_operand:HISI 1 "memory_operand" ""))]
772 "reload_completed
773 && AVR_HAVE_LPMX"
774 [(set (match_dup 0)
775 (match_dup 2))
776 (set (match_dup 3)
777 (plus:HI (match_dup 3)
778 (match_dup 4)))]
779 {
780 rtx addr = XEXP (operands[1], 0);
781
782 if (!avr_mem_flash_p (operands[1])
783 || !REG_P (addr)
784 || reg_overlap_mentioned_p (addr, operands[0]))
785 {
786 FAIL;
787 }
788
789 operands[2] = replace_equiv_address (operands[1],
790 gen_rtx_POST_INC (Pmode, addr));
791 operands[3] = addr;
792 operands[4] = gen_int_mode (-GET_MODE_SIZE (<MODE>mode), HImode);
793 })
794
795 ;;==========================================================================
796 ;; xpointer move (24 bit)
797
798 (define_peephole2 ; *reload_inpsi
799 [(match_scratch:QI 2 "d")
800 (set (match_operand:PSI 0 "l_register_operand" "")
801 (match_operand:PSI 1 "immediate_operand" ""))
802 (match_dup 2)]
803 "operands[1] != const0_rtx
804 && operands[1] != constm1_rtx"
805 [(parallel [(set (match_dup 0)
806 (match_dup 1))
807 (clobber (match_dup 2))])])
808
809 ;; '*' because it is not used in rtl generation.
810 (define_insn "*reload_inpsi"
811 [(set (match_operand:PSI 0 "register_operand" "=r")
812 (match_operand:PSI 1 "immediate_operand" "i"))
813 (clobber (match_operand:QI 2 "register_operand" "=&d"))]
814 "reload_completed"
815 {
816 return avr_out_reload_inpsi (operands, operands[2], NULL);
817 }
818 [(set_attr "length" "6")
819 (set_attr "adjust_len" "reload_in24")
820 (set_attr "cc" "clobber")])
821
822 (define_insn "*movpsi"
823 [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
824 (match_operand:PSI 1 "nox_general_operand" "r,L,Qm,rL,i ,i"))]
825 "register_operand (operands[0], PSImode)
826 || register_operand (operands[1], PSImode)
827 || const0_rtx == operands[1]"
828 {
829 return avr_out_movpsi (insn, operands, NULL);
830 }
831 [(set_attr "length" "3,3,8,9,4,10")
832 (set_attr "adjust_len" "mov24")
833 (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
834
835 ;;==========================================================================
836 ;; move double word (32 bit)
837
838 (define_peephole2 ; *reload_insi
839 [(match_scratch:QI 2 "d")
840 (set (match_operand:ALL4 0 "l_register_operand" "")
841 (match_operand:ALL4 1 "immediate_operand" ""))
842 (match_dup 2)]
843 "operands[1] != CONST0_RTX (<MODE>mode)"
844 [(parallel [(set (match_dup 0)
845 (match_dup 1))
846 (clobber (match_dup 2))])])
847
848 ;; '*' because it is not used in rtl generation.
849 ;; "*reload_insi"
850 ;; "*reload_insq" "*reload_inusq"
851 ;; "*reload_insa" "*reload_inusa"
852 (define_insn "*reload_insi"
853 [(set (match_operand:ALL4 0 "register_operand" "=r")
854 (match_operand:ALL4 1 "immediate_operand" "n Ynn"))
855 (clobber (match_operand:QI 2 "register_operand" "=&d"))]
856 "reload_completed"
857 {
858 return output_reload_insisf (operands, operands[2], NULL);
859 }
860 [(set_attr "length" "8")
861 (set_attr "adjust_len" "reload_in32")
862 (set_attr "cc" "clobber")])
863
864
865 ;; "*movsi"
866 ;; "*movsq" "*movusq"
867 ;; "*movsa" "*movusa"
868 (define_insn "*mov<mode>"
869 [(set (match_operand:ALL4 0 "nonimmediate_operand" "=r,r ,r ,Qm ,!d,r")
870 (match_operand:ALL4 1 "nox_general_operand" "r,Y00,Qm,r Y00,i ,i"))]
871 "register_operand (operands[0], <MODE>mode)
872 || reg_or_0_operand (operands[1], <MODE>mode)"
873 {
874 return output_movsisf (insn, operands, NULL);
875 }
876 [(set_attr "length" "4,4,8,9,4,10")
877 (set_attr "adjust_len" "mov32")
878 (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
879
880 ;; fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
881 ;; move floating point numbers (32 bit)
882
883 (define_insn "*movsf"
884 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
885 (match_operand:SF 1 "nox_general_operand" "r,G,Qm,rG,F ,F"))]
886 "register_operand (operands[0], SFmode)
887 || reg_or_0_operand (operands[1], SFmode)"
888 {
889 return output_movsisf (insn, operands, NULL);
890 }
891 [(set_attr "length" "4,4,8,9,4,10")
892 (set_attr "adjust_len" "mov32")
893 (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
894
895 (define_peephole2 ; *reload_insf
896 [(match_scratch:QI 2 "d")
897 (set (match_operand:SF 0 "l_register_operand" "")
898 (match_operand:SF 1 "const_double_operand" ""))
899 (match_dup 2)]
900 "operands[1] != CONST0_RTX (SFmode)"
901 [(parallel [(set (match_dup 0)
902 (match_dup 1))
903 (clobber (match_dup 2))])])
904
905 ;; '*' because it is not used in rtl generation.
906 (define_insn "*reload_insf"
907 [(set (match_operand:SF 0 "register_operand" "=r")
908 (match_operand:SF 1 "const_double_operand" "F"))
909 (clobber (match_operand:QI 2 "register_operand" "=&d"))]
910 "reload_completed"
911 {
912 return output_reload_insisf (operands, operands[2], NULL);
913 }
914 [(set_attr "length" "8")
915 (set_attr "adjust_len" "reload_in32")
916 (set_attr "cc" "clobber")])
917
918 ;;=========================================================================
919 ;; move string (like memcpy)
920
921 (define_expand "movmemhi"
922 [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
923 (match_operand:BLK 1 "memory_operand" ""))
924 (use (match_operand:HI 2 "const_int_operand" ""))
925 (use (match_operand:HI 3 "const_int_operand" ""))])]
926 ""
927 {
928 if (avr_emit_movmemhi (operands))
929 DONE;
930
931 FAIL;
932 })
933
934 (define_mode_attr MOVMEM_r_d [(QI "r")
935 (HI "wd")])
936
937 ;; $0 : Address Space
938 ;; $1, $2 : Loop register
939 ;; R30 : source address
940 ;; R26 : destination address
941
942 ;; "movmem_qi"
943 ;; "movmem_hi"
944 (define_insn "movmem_<mode>"
945 [(set (mem:BLK (reg:HI REG_X))
946 (mem:BLK (reg:HI REG_Z)))
947 (unspec [(match_operand:QI 0 "const_int_operand" "n")]
948 UNSPEC_MOVMEM)
949 (use (match_operand:QIHI 1 "register_operand" "<MOVMEM_r_d>"))
950 (clobber (reg:HI REG_X))
951 (clobber (reg:HI REG_Z))
952 (clobber (reg:QI LPM_REGNO))
953 (clobber (match_operand:QIHI 2 "register_operand" "=1"))]
954 ""
955 {
956 return avr_out_movmem (insn, operands, NULL);
957 }
958 [(set_attr "adjust_len" "movmem")
959 (set_attr "cc" "clobber")])
960
961
962 ;; $0 : Address Space
963 ;; $1 : RAMPZ RAM address
964 ;; R24 : #bytes and loop register
965 ;; R23:Z : 24-bit source address
966 ;; R26 : 16-bit destination address
967
968 ;; "movmemx_qi"
969 ;; "movmemx_hi"
970 (define_insn "movmemx_<mode>"
971 [(set (mem:BLK (reg:HI REG_X))
972 (mem:BLK (lo_sum:PSI (reg:QI 23)
973 (reg:HI REG_Z))))
974 (unspec [(match_operand:QI 0 "const_int_operand" "n")]
975 UNSPEC_MOVMEM)
976 (use (reg:QIHI 24))
977 (clobber (reg:HI REG_X))
978 (clobber (reg:HI REG_Z))
979 (clobber (reg:QI LPM_REGNO))
980 (clobber (reg:HI 24))
981 (clobber (reg:QI 23))
982 (clobber (mem:QI (match_operand:QI 1 "io_address_operand" "n")))]
983 ""
984 "%~call __movmemx_<mode>"
985 [(set_attr "type" "xcall")
986 (set_attr "cc" "clobber")])
987
988
989 ;; =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2
990 ;; memset (%0, %2, %1)
991
992 (define_expand "setmemhi"
993 [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
994 (match_operand 2 "const_int_operand" ""))
995 (use (match_operand:HI 1 "const_int_operand" ""))
996 (use (match_operand:HI 3 "const_int_operand" ""))
997 (clobber (match_scratch:HI 4 ""))
998 (clobber (match_dup 5))])]
999 ""
1000 {
1001 rtx addr0;
1002 enum machine_mode mode;
1003
1004 /* If value to set is not zero, use the library routine. */
1005 if (operands[2] != const0_rtx)
1006 FAIL;
1007
1008 if (!CONST_INT_P (operands[1]))
1009 FAIL;
1010
1011 mode = u8_operand (operands[1], VOIDmode) ? QImode : HImode;
1012 operands[5] = gen_rtx_SCRATCH (mode);
1013 operands[1] = copy_to_mode_reg (mode,
1014 gen_int_mode (INTVAL (operands[1]), mode));
1015 addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
1016 operands[0] = gen_rtx_MEM (BLKmode, addr0);
1017 })
1018
1019
1020 (define_insn "*clrmemqi"
1021 [(set (mem:BLK (match_operand:HI 0 "register_operand" "e"))
1022 (const_int 0))
1023 (use (match_operand:QI 1 "register_operand" "r"))
1024 (use (match_operand:QI 2 "const_int_operand" "n"))
1025 (clobber (match_scratch:HI 3 "=0"))
1026 (clobber (match_scratch:QI 4 "=&1"))]
1027 ""
1028 "0:\;st %a0+,__zero_reg__\;dec %1\;brne 0b"
1029 [(set_attr "length" "3")
1030 (set_attr "cc" "clobber")])
1031
1032
1033 (define_insn "*clrmemhi"
1034 [(set (mem:BLK (match_operand:HI 0 "register_operand" "e,e"))
1035 (const_int 0))
1036 (use (match_operand:HI 1 "register_operand" "!w,d"))
1037 (use (match_operand:HI 2 "const_int_operand" "n,n"))
1038 (clobber (match_scratch:HI 3 "=0,0"))
1039 (clobber (match_scratch:HI 4 "=&1,&1"))]
1040 ""
1041 "@
1042 0:\;st %a0+,__zero_reg__\;sbiw %A1,1\;brne 0b
1043 0:\;st %a0+,__zero_reg__\;subi %A1,1\;sbci %B1,0\;brne 0b"
1044 [(set_attr "length" "3,4")
1045 (set_attr "cc" "clobber,clobber")])
1046
1047 (define_expand "strlenhi"
1048 [(set (match_dup 4)
1049 (unspec:HI [(match_operand:BLK 1 "memory_operand" "")
1050 (match_operand:QI 2 "const_int_operand" "")
1051 (match_operand:HI 3 "immediate_operand" "")]
1052 UNSPEC_STRLEN))
1053 (set (match_dup 4)
1054 (plus:HI (match_dup 4)
1055 (const_int -1)))
1056 (parallel [(set (match_operand:HI 0 "register_operand" "")
1057 (minus:HI (match_dup 4)
1058 (match_dup 5)))
1059 (clobber (scratch:QI))])]
1060 ""
1061 {
1062 rtx addr;
1063 if (operands[2] != const0_rtx)
1064 FAIL;
1065 addr = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
1066 operands[1] = gen_rtx_MEM (BLKmode, addr);
1067 operands[5] = addr;
1068 operands[4] = gen_reg_rtx (HImode);
1069 })
1070
1071 (define_insn "*strlenhi"
1072 [(set (match_operand:HI 0 "register_operand" "=e")
1073 (unspec:HI [(mem:BLK (match_operand:HI 1 "register_operand" "0"))
1074 (const_int 0)
1075 (match_operand:HI 2 "immediate_operand" "i")]
1076 UNSPEC_STRLEN))]
1077 ""
1078 "0:\;ld __tmp_reg__,%a0+\;tst __tmp_reg__\;brne 0b"
1079 [(set_attr "length" "3")
1080 (set_attr "cc" "clobber")])
1081
1082 ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1083 ; add bytes
1084
1085 ;; "addqi3"
1086 ;; "addqq3" "adduqq3"
1087 (define_insn "add<mode>3"
1088 [(set (match_operand:ALL1 0 "register_operand" "=r,d ,r ,r ,r ,r")
1089 (plus:ALL1 (match_operand:ALL1 1 "register_operand" "%0,0 ,0 ,0 ,0 ,0")
1090 (match_operand:ALL1 2 "nonmemory_operand" "r,n Ynn,Y01,Ym1,Y02,Ym2")))]
1091 ""
1092 "@
1093 add %0,%2
1094 subi %0,lo8(-(%2))
1095 inc %0
1096 dec %0
1097 inc %0\;inc %0
1098 dec %0\;dec %0"
1099 [(set_attr "length" "1,1,1,1,2,2")
1100 (set_attr "cc" "set_czn,set_czn,set_zn,set_zn,set_zn,set_zn")])
1101
1102 ;; "addhi3"
1103 ;; "addhq3" "adduhq3"
1104 ;; "addha3" "adduha3"
1105 (define_expand "add<mode>3"
1106 [(set (match_operand:ALL2 0 "register_operand" "")
1107 (plus:ALL2 (match_operand:ALL2 1 "register_operand" "")
1108 (match_operand:ALL2 2 "nonmemory_or_const_operand" "")))]
1109 ""
1110 {
1111 if (CONST_INT_P (operands[2]))
1112 {
1113 operands[2] = gen_int_mode (INTVAL (operands[2]), HImode);
1114
1115 if (can_create_pseudo_p()
1116 && !stack_register_operand (operands[0], HImode)
1117 && !stack_register_operand (operands[1], HImode)
1118 && !d_register_operand (operands[0], HImode)
1119 && !d_register_operand (operands[1], HImode))
1120 {
1121 emit_insn (gen_addhi3_clobber (operands[0], operands[1], operands[2]));
1122 DONE;
1123 }
1124 }
1125
1126 if (CONST_FIXED_P (operands[2]))
1127 {
1128 emit_insn (gen_add<mode>3_clobber (operands[0], operands[1], operands[2]));
1129 DONE;
1130 }
1131 })
1132
1133
1134 (define_insn "*addhi3_zero_extend"
1135 [(set (match_operand:HI 0 "register_operand" "=r")
1136 (plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1137 (match_operand:HI 2 "register_operand" "0")))]
1138 ""
1139 "add %A0,%1\;adc %B0,__zero_reg__"
1140 [(set_attr "length" "2")
1141 (set_attr "cc" "set_n")])
1142
1143 (define_insn "*addhi3_zero_extend1"
1144 [(set (match_operand:HI 0 "register_operand" "=r")
1145 (plus:HI (match_operand:HI 1 "register_operand" "0")
1146 (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1147 ""
1148 "add %A0,%2\;adc %B0,__zero_reg__"
1149 [(set_attr "length" "2")
1150 (set_attr "cc" "set_n")])
1151
1152 (define_insn "*addhi3.sign_extend1"
1153 [(set (match_operand:HI 0 "register_operand" "=r")
1154 (plus:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "r"))
1155 (match_operand:HI 2 "register_operand" "0")))]
1156 ""
1157 {
1158 return reg_overlap_mentioned_p (operands[0], operands[1])
1159 ? "mov __tmp_reg__,%1\;add %A0,%1\;adc %B0,__zero_reg__\;sbrc __tmp_reg__,7\;dec %B0"
1160 : "add %A0,%1\;adc %B0,__zero_reg__\;sbrc %1,7\;dec %B0";
1161 }
1162 [(set_attr "length" "5")
1163 (set_attr "cc" "clobber")])
1164
1165 (define_insn "*addhi3_sp"
1166 [(set (match_operand:HI 1 "stack_register_operand" "=q")
1167 (plus:HI (match_operand:HI 2 "stack_register_operand" "q")
1168 (match_operand:HI 0 "avr_sp_immediate_operand" "Csp")))]
1169 ""
1170 {
1171 return avr_out_addto_sp (operands, NULL);
1172 }
1173 [(set_attr "length" "6")
1174 (set_attr "adjust_len" "addto_sp")])
1175
1176 ;; "*addhi3"
1177 ;; "*addhq3" "*adduhq3"
1178 ;; "*addha3" "*adduha3"
1179 (define_insn "*add<mode>3"
1180 [(set (match_operand:ALL2 0 "register_operand" "=??r,d,!w ,d")
1181 (plus:ALL2 (match_operand:ALL2 1 "register_operand" "%0,0,0 ,0")
1182 (match_operand:ALL2 2 "nonmemory_or_const_operand" "r,s,IJ YIJ,n Ynn")))]
1183 ""
1184 {
1185 return avr_out_plus (insn, operands);
1186 }
1187 [(set_attr "length" "2")
1188 (set_attr "adjust_len" "plus")
1189 (set_attr "cc" "plus")])
1190
1191 ;; Adding a constant to NO_LD_REGS might have lead to a reload of
1192 ;; that constant to LD_REGS. We don't add a scratch to *addhi3
1193 ;; itself because that insn is special to reload.
1194
1195 (define_peephole2 ; addhi3_clobber
1196 [(set (match_operand:ALL2 0 "d_register_operand" "")
1197 (match_operand:ALL2 1 "const_operand" ""))
1198 (set (match_operand:ALL2 2 "l_register_operand" "")
1199 (plus:ALL2 (match_dup 2)
1200 (match_dup 0)))]
1201 "peep2_reg_dead_p (2, operands[0])"
1202 [(parallel [(set (match_dup 2)
1203 (plus:ALL2 (match_dup 2)
1204 (match_dup 1)))
1205 (clobber (match_dup 3))])]
1206 {
1207 operands[3] = simplify_gen_subreg (QImode, operands[0], <MODE>mode, 0);
1208 })
1209
1210 ;; Same, but with reload to NO_LD_REGS
1211 ;; Combine *reload_inhi with *addhi3
1212
1213 (define_peephole2 ; addhi3_clobber
1214 [(parallel [(set (match_operand:ALL2 0 "l_register_operand" "")
1215 (match_operand:ALL2 1 "const_operand" ""))
1216 (clobber (match_operand:QI 2 "d_register_operand" ""))])
1217 (set (match_operand:ALL2 3 "l_register_operand" "")
1218 (plus:ALL2 (match_dup 3)
1219 (match_dup 0)))]
1220 "peep2_reg_dead_p (2, operands[0])"
1221 [(parallel [(set (match_dup 3)
1222 (plus:ALL2 (match_dup 3)
1223 (match_dup 1)))
1224 (clobber (match_dup 2))])])
1225
1226 ;; "addhi3_clobber"
1227 ;; "addhq3_clobber" "adduhq3_clobber"
1228 ;; "addha3_clobber" "adduha3_clobber"
1229 (define_insn "add<mode>3_clobber"
1230 [(set (match_operand:ALL2 0 "register_operand" "=!w ,d ,r")
1231 (plus:ALL2 (match_operand:ALL2 1 "register_operand" "%0 ,0 ,0")
1232 (match_operand:ALL2 2 "const_operand" "IJ YIJ,n Ynn,n Ynn")))
1233 (clobber (match_scratch:QI 3 "=X ,X ,&d"))]
1234 ""
1235 {
1236 return avr_out_plus (insn, operands);
1237 }
1238 [(set_attr "length" "4")
1239 (set_attr "adjust_len" "plus")
1240 (set_attr "cc" "plus")])
1241
1242
1243 ;; "addsi3"
1244 ;; "addsq3" "addusq3"
1245 ;; "addsa3" "addusa3"
1246 (define_insn "add<mode>3"
1247 [(set (match_operand:ALL4 0 "register_operand" "=??r,d ,r")
1248 (plus:ALL4 (match_operand:ALL4 1 "register_operand" "%0,0 ,0")
1249 (match_operand:ALL4 2 "nonmemory_operand" "r,i ,n Ynn")))
1250 (clobber (match_scratch:QI 3 "=X,X ,&d"))]
1251 ""
1252 {
1253 return avr_out_plus (insn, operands);
1254 }
1255 [(set_attr "length" "4")
1256 (set_attr "adjust_len" "plus")
1257 (set_attr "cc" "plus")])
1258
1259 (define_insn "*addpsi3_zero_extend.qi"
1260 [(set (match_operand:PSI 0 "register_operand" "=r")
1261 (plus:PSI (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))
1262 (match_operand:PSI 2 "register_operand" "0")))]
1263 ""
1264 "add %A0,%A1\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__"
1265 [(set_attr "length" "3")
1266 (set_attr "cc" "set_n")])
1267
1268 (define_insn "*addpsi3_zero_extend.hi"
1269 [(set (match_operand:PSI 0 "register_operand" "=r")
1270 (plus:PSI (zero_extend:PSI (match_operand:HI 1 "register_operand" "r"))
1271 (match_operand:PSI 2 "register_operand" "0")))]
1272 ""
1273 "add %A0,%A1\;adc %B0,%B1\;adc %C0,__zero_reg__"
1274 [(set_attr "length" "3")
1275 (set_attr "cc" "set_n")])
1276
1277 (define_insn "*addpsi3_sign_extend.hi"
1278 [(set (match_operand:PSI 0 "register_operand" "=r")
1279 (plus:PSI (sign_extend:PSI (match_operand:HI 1 "register_operand" "r"))
1280 (match_operand:PSI 2 "register_operand" "0")))]
1281 ""
1282 "add %A0,%1\;adc %B0,%B1\;adc %C0,__zero_reg__\;sbrc %B1,7\;dec %C0"
1283 [(set_attr "length" "5")
1284 (set_attr "cc" "set_n")])
1285
1286 (define_insn "*addsi3_zero_extend"
1287 [(set (match_operand:SI 0 "register_operand" "=r")
1288 (plus:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
1289 (match_operand:SI 2 "register_operand" "0")))]
1290 ""
1291 "add %A0,%1\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__"
1292 [(set_attr "length" "4")
1293 (set_attr "cc" "set_n")])
1294
1295 (define_insn "*addsi3_zero_extend.hi"
1296 [(set (match_operand:SI 0 "register_operand" "=r")
1297 (plus:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
1298 (match_operand:SI 2 "register_operand" "0")))]
1299 ""
1300 "add %A0,%1\;adc %B0,%B1\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__"
1301 [(set_attr "length" "4")
1302 (set_attr "cc" "set_n")])
1303
1304 (define_insn "addpsi3"
1305 [(set (match_operand:PSI 0 "register_operand" "=??r,d ,d,r")
1306 (plus:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0,0")
1307 (match_operand:PSI 2 "nonmemory_operand" "r,s ,n,n")))
1308 (clobber (match_scratch:QI 3 "=X,X ,X,&d"))]
1309 ""
1310 {
1311 return avr_out_plus (insn, operands);
1312 }
1313 [(set_attr "length" "3")
1314 (set_attr "adjust_len" "plus")
1315 (set_attr "cc" "plus")])
1316
1317 (define_insn "subpsi3"
1318 [(set (match_operand:PSI 0 "register_operand" "=r")
1319 (minus:PSI (match_operand:PSI 1 "register_operand" "0")
1320 (match_operand:PSI 2 "register_operand" "r")))]
1321 ""
1322 "sub %0,%2\;sbc %B0,%B2\;sbc %C0,%C2"
1323 [(set_attr "length" "3")
1324 (set_attr "cc" "set_czn")])
1325
1326 (define_insn "*subpsi3_zero_extend.qi"
1327 [(set (match_operand:PSI 0 "register_operand" "=r")
1328 (minus:PSI (match_operand:SI 1 "register_operand" "0")
1329 (zero_extend:PSI (match_operand:QI 2 "register_operand" "r"))))]
1330 ""
1331 "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__"
1332 [(set_attr "length" "3")
1333 (set_attr "cc" "set_czn")])
1334
1335 (define_insn "*subpsi3_zero_extend.hi"
1336 [(set (match_operand:PSI 0 "register_operand" "=r")
1337 (minus:PSI (match_operand:PSI 1 "register_operand" "0")
1338 (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
1339 ""
1340 "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__"
1341 [(set_attr "length" "3")
1342 (set_attr "cc" "set_czn")])
1343
1344 (define_insn "*subpsi3_sign_extend.hi"
1345 [(set (match_operand:PSI 0 "register_operand" "=r")
1346 (minus:PSI (match_operand:PSI 1 "register_operand" "0")
1347 (sign_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
1348 ""
1349 "sub %A0,%A2\;sbc %B0,%B2\;sbc %C0,__zero_reg__\;sbrc %B2,7\;inc %C0"
1350 [(set_attr "length" "5")
1351 (set_attr "cc" "set_czn")])
1352
1353 ;-----------------------------------------------------------------------------
1354 ; sub bytes
1355
1356 ;; "subqi3"
1357 ;; "subqq3" "subuqq3"
1358 (define_insn "sub<mode>3"
1359 [(set (match_operand:ALL1 0 "register_operand" "=??r,d ,r ,r ,r ,r")
1360 (minus:ALL1 (match_operand:ALL1 1 "register_operand" "0,0 ,0 ,0 ,0 ,0")
1361 (match_operand:ALL1 2 "nonmemory_or_const_operand" "r,n Ynn,Y01,Ym1,Y02,Ym2")))]
1362 ""
1363 "@
1364 sub %0,%2
1365 subi %0,lo8(%2)
1366 dec %0
1367 inc %0
1368 dec %0\;dec %0
1369 inc %0\;inc %0"
1370 [(set_attr "length" "1,1,1,1,2,2")
1371 (set_attr "cc" "set_czn,set_czn,set_zn,set_zn,set_zn,set_zn")])
1372
1373 ;; "subhi3"
1374 ;; "subhq3" "subuhq3"
1375 ;; "subha3" "subuha3"
1376 (define_insn "sub<mode>3"
1377 [(set (match_operand:ALL2 0 "register_operand" "=??r,d ,*r")
1378 (minus:ALL2 (match_operand:ALL2 1 "register_operand" "0,0 ,0")
1379 (match_operand:ALL2 2 "nonmemory_or_const_operand" "r,i Ynn,Ynn")))
1380 (clobber (match_scratch:QI 3 "=X,X ,&d"))]
1381 ""
1382 {
1383 return avr_out_plus (insn, operands);
1384 }
1385 [(set_attr "adjust_len" "plus")
1386 (set_attr "cc" "plus")])
1387
1388 (define_insn "*subhi3_zero_extend1"
1389 [(set (match_operand:HI 0 "register_operand" "=r")
1390 (minus:HI (match_operand:HI 1 "register_operand" "0")
1391 (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1392 ""
1393 "sub %A0,%2\;sbc %B0,__zero_reg__"
1394 [(set_attr "length" "2")
1395 (set_attr "cc" "set_czn")])
1396
1397 (define_insn "*subhi3.sign_extend2"
1398 [(set (match_operand:HI 0 "register_operand" "=r")
1399 (minus:HI (match_operand:HI 1 "register_operand" "0")
1400 (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1401 ""
1402 {
1403 return reg_overlap_mentioned_p (operands[0], operands[2])
1404 ? "mov __tmp_reg__,%2\;sub %A0,%2\;sbc %B0,__zero_reg__\;sbrc __tmp_reg__,7\;inc %B0"
1405 : "sub %A0,%2\;sbc %B0,__zero_reg__\;sbrc %2,7\;inc %B0";
1406 }
1407 [(set_attr "length" "5")
1408 (set_attr "cc" "clobber")])
1409
1410 ;; "subsi3"
1411 ;; "subsq3" "subusq3"
1412 ;; "subsa3" "subusa3"
1413 (define_insn "sub<mode>3"
1414 [(set (match_operand:ALL4 0 "register_operand" "=??r,d ,r")
1415 (minus:ALL4 (match_operand:ALL4 1 "register_operand" "0,0 ,0")
1416 (match_operand:ALL4 2 "nonmemory_or_const_operand" "r,n Ynn,Ynn")))
1417 (clobber (match_scratch:QI 3 "=X,X ,&d"))]
1418 ""
1419 {
1420 return avr_out_plus (insn, operands);
1421 }
1422 [(set_attr "adjust_len" "plus")
1423 (set_attr "cc" "plus")])
1424
1425 (define_insn "*subsi3_zero_extend"
1426 [(set (match_operand:SI 0 "register_operand" "=r")
1427 (minus:SI (match_operand:SI 1 "register_operand" "0")
1428 (zero_extend:SI (match_operand:QI 2 "register_operand" "r"))))]
1429 ""
1430 "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
1431 [(set_attr "length" "4")
1432 (set_attr "cc" "set_czn")])
1433
1434 (define_insn "*subsi3_zero_extend.hi"
1435 [(set (match_operand:SI 0 "register_operand" "=r")
1436 (minus:SI (match_operand:SI 1 "register_operand" "0")
1437 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1438 ""
1439 "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
1440 [(set_attr "length" "4")
1441 (set_attr "cc" "set_czn")])
1442
1443 ;******************************************************************************
1444 ; mul
1445
1446 (define_expand "mulqi3"
1447 [(set (match_operand:QI 0 "register_operand" "")
1448 (mult:QI (match_operand:QI 1 "register_operand" "")
1449 (match_operand:QI 2 "register_operand" "")))]
1450 ""
1451 {
1452 if (!AVR_HAVE_MUL)
1453 {
1454 emit_insn (gen_mulqi3_call (operands[0], operands[1], operands[2]));
1455 DONE;
1456 }
1457 })
1458
1459 (define_insn "*mulqi3_enh"
1460 [(set (match_operand:QI 0 "register_operand" "=r")
1461 (mult:QI (match_operand:QI 1 "register_operand" "r")
1462 (match_operand:QI 2 "register_operand" "r")))]
1463 "AVR_HAVE_MUL"
1464 "mul %1,%2
1465 mov %0,r0
1466 clr r1"
1467 [(set_attr "length" "3")
1468 (set_attr "cc" "clobber")])
1469
1470 (define_expand "mulqi3_call"
1471 [(set (reg:QI 24) (match_operand:QI 1 "register_operand" ""))
1472 (set (reg:QI 22) (match_operand:QI 2 "register_operand" ""))
1473 (parallel [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22)))
1474 (clobber (reg:QI 22))])
1475 (set (match_operand:QI 0 "register_operand" "") (reg:QI 24))])
1476
1477 (define_insn "*mulqi3_call"
1478 [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22)))
1479 (clobber (reg:QI 22))]
1480 "!AVR_HAVE_MUL"
1481 "%~call __mulqi3"
1482 [(set_attr "type" "xcall")
1483 (set_attr "cc" "clobber")])
1484
1485 ;; "umulqi3_highpart"
1486 ;; "smulqi3_highpart"
1487 (define_insn "<extend_su>mulqi3_highpart"
1488 [(set (match_operand:QI 0 "register_operand" "=r")
1489 (truncate:QI
1490 (lshiftrt:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1491 (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))
1492 (const_int 8))))]
1493 "AVR_HAVE_MUL"
1494 "mul<extend_s> %1,%2
1495 mov %0,r1
1496 clr __zero_reg__"
1497 [(set_attr "length" "3")
1498 (set_attr "cc" "clobber")])
1499
1500
1501 ;; Used when expanding div or mod inline for some special values
1502 (define_insn "*subqi3.ashiftrt7"
1503 [(set (match_operand:QI 0 "register_operand" "=r")
1504 (minus:QI (match_operand:QI 1 "register_operand" "0")
1505 (ashiftrt:QI (match_operand:QI 2 "register_operand" "r")
1506 (const_int 7))))]
1507 ""
1508 "sbrc %2,7\;inc %0"
1509 [(set_attr "length" "2")
1510 (set_attr "cc" "clobber")])
1511
1512 (define_insn "*addqi3.lt0"
1513 [(set (match_operand:QI 0 "register_operand" "=r")
1514 (plus:QI (lt:QI (match_operand:QI 1 "register_operand" "r")
1515 (const_int 0))
1516 (match_operand:QI 2 "register_operand" "0")))]
1517 ""
1518 "sbrc %1,7\;inc %0"
1519 [(set_attr "length" "2")
1520 (set_attr "cc" "clobber")])
1521
1522 (define_insn "*addhi3.lt0"
1523 [(set (match_operand:HI 0 "register_operand" "=w,r")
1524 (plus:HI (lt:HI (match_operand:QI 1 "register_operand" "r,r")
1525 (const_int 0))
1526 (match_operand:HI 2 "register_operand" "0,0")))
1527 (clobber (match_scratch:QI 3 "=X,&1"))]
1528 ""
1529 "@
1530 sbrc %1,7\;adiw %0,1
1531 lsl %1\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__"
1532 [(set_attr "length" "2,3")
1533 (set_attr "cc" "clobber")])
1534
1535 (define_insn "*addpsi3.lt0"
1536 [(set (match_operand:PSI 0 "register_operand" "=r")
1537 (plus:PSI (lshiftrt:PSI (match_operand:PSI 1 "register_operand" "r")
1538 (const_int 23))
1539 (match_operand:PSI 2 "register_operand" "0")))]
1540 ""
1541 "mov __tmp_reg__,%C1\;lsl __tmp_reg__
1542 adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__"
1543 [(set_attr "length" "5")
1544 (set_attr "cc" "clobber")])
1545
1546 (define_insn "*addsi3.lt0"
1547 [(set (match_operand:SI 0 "register_operand" "=r")
1548 (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
1549 (const_int 31))
1550 (match_operand:SI 2 "register_operand" "0")))]
1551 ""
1552 "mov __tmp_reg__,%D1\;lsl __tmp_reg__
1553 adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__"
1554 [(set_attr "length" "6")
1555 (set_attr "cc" "clobber")])
1556
1557 (define_insn "*umulqihi3.call"
1558 [(set (reg:HI 24)
1559 (mult:HI (zero_extend:HI (reg:QI 22))
1560 (zero_extend:HI (reg:QI 24))))
1561 (clobber (reg:QI 21))
1562 (clobber (reg:HI 22))]
1563 "!AVR_HAVE_MUL"
1564 "%~call __umulqihi3"
1565 [(set_attr "type" "xcall")
1566 (set_attr "cc" "clobber")])
1567
1568 ;; "umulqihi3"
1569 ;; "mulqihi3"
1570 (define_insn "<extend_u>mulqihi3"
1571 [(set (match_operand:HI 0 "register_operand" "=r")
1572 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1573 (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>"))))]
1574 "AVR_HAVE_MUL"
1575 "mul<extend_s> %1,%2
1576 movw %0,r0
1577 clr __zero_reg__"
1578 [(set_attr "length" "3")
1579 (set_attr "cc" "clobber")])
1580
1581 (define_insn "usmulqihi3"
1582 [(set (match_operand:HI 0 "register_operand" "=r")
1583 (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "a"))
1584 (sign_extend:HI (match_operand:QI 2 "register_operand" "a"))))]
1585 "AVR_HAVE_MUL"
1586 "mulsu %2,%1
1587 movw %0,r0
1588 clr __zero_reg__"
1589 [(set_attr "length" "3")
1590 (set_attr "cc" "clobber")])
1591
1592 ;; Above insn is not canonicalized by insn combine, so here is a version with
1593 ;; operands swapped.
1594
1595 (define_insn "*sumulqihi3"
1596 [(set (match_operand:HI 0 "register_operand" "=r")
1597 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1598 (zero_extend:HI (match_operand:QI 2 "register_operand" "a"))))]
1599 "AVR_HAVE_MUL"
1600 "mulsu %1,%2
1601 movw %0,r0
1602 clr __zero_reg__"
1603 [(set_attr "length" "3")
1604 (set_attr "cc" "clobber")])
1605
1606 ;; One-extend operand 1
1607
1608 (define_insn "*osmulqihi3"
1609 [(set (match_operand:HI 0 "register_operand" "=&r")
1610 (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "a"))))
1611 (sign_extend:HI (match_operand:QI 2 "register_operand" "a"))))]
1612 "AVR_HAVE_MUL"
1613 "mulsu %2,%1
1614 movw %0,r0
1615 sub %B0,%2
1616 clr __zero_reg__"
1617 [(set_attr "length" "4")
1618 (set_attr "cc" "clobber")])
1619
1620 (define_insn "*oumulqihi3"
1621 [(set (match_operand:HI 0 "register_operand" "=&r")
1622 (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "r"))))
1623 (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1624 "AVR_HAVE_MUL"
1625 "mul %2,%1
1626 movw %0,r0
1627 sub %B0,%2
1628 clr __zero_reg__"
1629 [(set_attr "length" "4")
1630 (set_attr "cc" "clobber")])
1631
1632 ;******************************************************************************
1633 ; multiply-add/sub QI: $0 = $3 +/- $1*$2
1634 ;******************************************************************************
1635
1636 (define_insn "*maddqi4"
1637 [(set (match_operand:QI 0 "register_operand" "=r")
1638 (plus:QI (mult:QI (match_operand:QI 1 "register_operand" "r")
1639 (match_operand:QI 2 "register_operand" "r"))
1640 (match_operand:QI 3 "register_operand" "0")))]
1641
1642 "AVR_HAVE_MUL"
1643 "mul %1,%2
1644 add %A0,r0
1645 clr __zero_reg__"
1646 [(set_attr "length" "4")
1647 (set_attr "cc" "clobber")])
1648
1649 (define_insn "*msubqi4"
1650 [(set (match_operand:QI 0 "register_operand" "=r")
1651 (minus:QI (match_operand:QI 3 "register_operand" "0")
1652 (mult:QI (match_operand:QI 1 "register_operand" "r")
1653 (match_operand:QI 2 "register_operand" "r"))))]
1654 "AVR_HAVE_MUL"
1655 "mul %1,%2
1656 sub %A0,r0
1657 clr __zero_reg__"
1658 [(set_attr "length" "4")
1659 (set_attr "cc" "clobber")])
1660
1661 (define_insn_and_split "*maddqi4.const"
1662 [(set (match_operand:QI 0 "register_operand" "=r")
1663 (plus:QI (mult:QI (match_operand:QI 1 "register_operand" "r")
1664 (match_operand:QI 2 "const_int_operand" "n"))
1665 (match_operand:QI 3 "register_operand" "0")))
1666 (clobber (match_scratch:QI 4 "=&d"))]
1667 "AVR_HAVE_MUL"
1668 "#"
1669 "&& reload_completed"
1670 [(set (match_dup 4)
1671 (match_dup 2))
1672 ; *maddqi4
1673 (set (match_dup 0)
1674 (plus:QI (mult:QI (match_dup 1)
1675 (match_dup 4))
1676 (match_dup 3)))])
1677
1678 (define_insn_and_split "*msubqi4.const"
1679 [(set (match_operand:QI 0 "register_operand" "=r")
1680 (minus:QI (match_operand:QI 3 "register_operand" "0")
1681 (mult:QI (match_operand:QI 1 "register_operand" "r")
1682 (match_operand:QI 2 "const_int_operand" "n"))))
1683 (clobber (match_scratch:QI 4 "=&d"))]
1684 "AVR_HAVE_MUL"
1685 "#"
1686 "&& reload_completed"
1687 [(set (match_dup 4)
1688 (match_dup 2))
1689 ; *msubqi4
1690 (set (match_dup 0)
1691 (minus:QI (match_dup 3)
1692 (mult:QI (match_dup 1)
1693 (match_dup 4))))])
1694
1695
1696 ;******************************************************************************
1697 ; multiply-add/sub HI: $0 = $3 +/- $1*$2 with 8-bit values $1, $2
1698 ;******************************************************************************
1699
1700 ;; We don't use standard insns/expanders as they lead to cumbersome code for,
1701 ;; e.g,
1702 ;;
1703 ;; int foo (unsigned char z)
1704 ;; {
1705 ;; extern int aInt[];
1706 ;; return aInt[3*z+2];
1707 ;; }
1708 ;;
1709 ;; because the constant +4 then is added explicitely instead of consuming it
1710 ;; with the aInt symbol. Therefore, we rely on insn combine which takes costs
1711 ;; into account more accurately and doesn't do burte-force multiply-add/sub.
1712 ;; The implementational effort is the same so we are fine with that approach.
1713
1714
1715 ;; "*maddqihi4"
1716 ;; "*umaddqihi4"
1717 (define_insn "*<extend_u>maddqihi4"
1718 [(set (match_operand:HI 0 "register_operand" "=r")
1719 (plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1720 (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))
1721 (match_operand:HI 3 "register_operand" "0")))]
1722
1723 "AVR_HAVE_MUL"
1724 "mul<extend_s> %1,%2
1725 add %A0,r0
1726 adc %B0,r1
1727 clr __zero_reg__"
1728 [(set_attr "length" "4")
1729 (set_attr "cc" "clobber")])
1730
1731 ;; "*msubqihi4"
1732 ;; "*umsubqihi4"
1733 (define_insn "*<extend_u>msubqihi4"
1734 [(set (match_operand:HI 0 "register_operand" "=r")
1735 (minus:HI (match_operand:HI 3 "register_operand" "0")
1736 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1737 (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))))]
1738 "AVR_HAVE_MUL"
1739 "mul<extend_s> %1,%2
1740 sub %A0,r0
1741 sbc %B0,r1
1742 clr __zero_reg__"
1743 [(set_attr "length" "4")
1744 (set_attr "cc" "clobber")])
1745
1746 ;; "*usmaddqihi4"
1747 ;; "*sumaddqihi4"
1748 (define_insn "*<any_extend:extend_su><any_extend2:extend_su>msubqihi4"
1749 [(set (match_operand:HI 0 "register_operand" "=r")
1750 (plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "a"))
1751 (any_extend2:HI (match_operand:QI 2 "register_operand" "a")))
1752 (match_operand:HI 3 "register_operand" "0")))]
1753 "AVR_HAVE_MUL
1754 && reload_completed
1755 && <any_extend:CODE> != <any_extend2:CODE>"
1756 {
1757 output_asm_insn (<any_extend:CODE> == SIGN_EXTEND
1758 ? "mulsu %1,%2" : "mulsu %2,%1", operands);
1759
1760 return "add %A0,r0\;adc %B0,r1\;clr __zero_reg__";
1761 }
1762 [(set_attr "length" "4")
1763 (set_attr "cc" "clobber")])
1764
1765 ;; "*usmsubqihi4"
1766 ;; "*sumsubqihi4"
1767 (define_insn "*<any_extend:extend_su><any_extend2:extend_su>msubqihi4"
1768 [(set (match_operand:HI 0 "register_operand" "=r")
1769 (minus:HI (match_operand:HI 3 "register_operand" "0")
1770 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "a"))
1771 (any_extend2:HI (match_operand:QI 2 "register_operand" "a")))))]
1772 "AVR_HAVE_MUL
1773 && reload_completed
1774 && <any_extend:CODE> != <any_extend2:CODE>"
1775 {
1776 output_asm_insn (<any_extend:CODE> == SIGN_EXTEND
1777 ? "mulsu %1,%2" : "mulsu %2,%1", operands);
1778
1779 return "sub %A0,r0\;sbc %B0,r1\;clr __zero_reg__";
1780 }
1781 [(set_attr "length" "4")
1782 (set_attr "cc" "clobber")])
1783
1784 ;; Handle small constants
1785
1786 ;; Special case of a += 2*b as frequently seen with accesses to int arrays.
1787 ;; This is shorter, faster than MUL and has lower register pressure.
1788
1789 (define_insn_and_split "*umaddqihi4.2"
1790 [(set (match_operand:HI 0 "register_operand" "=r")
1791 (plus:HI (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1792 (const_int 2))
1793 (match_operand:HI 2 "register_operand" "r")))]
1794 "!reload_completed
1795 && !reg_overlap_mentioned_p (operands[0], operands[1])"
1796 { gcc_unreachable(); }
1797 "&& 1"
1798 [(set (match_dup 0)
1799 (match_dup 2))
1800 ; *addhi3_zero_extend
1801 (set (match_dup 0)
1802 (plus:HI (zero_extend:HI (match_dup 1))
1803 (match_dup 0)))
1804 ; *addhi3_zero_extend
1805 (set (match_dup 0)
1806 (plus:HI (zero_extend:HI (match_dup 1))
1807 (match_dup 0)))])
1808
1809 ;; "umaddqihi4.uconst"
1810 ;; "maddqihi4.sconst"
1811 (define_insn_and_split "*<extend_u>maddqihi4.<extend_su>const"
1812 [(set (match_operand:HI 0 "register_operand" "=r")
1813 (plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1814 (match_operand:HI 2 "<extend_su>8_operand" "n"))
1815 (match_operand:HI 3 "register_operand" "0")))
1816 (clobber (match_scratch:QI 4 "=&d"))]
1817 "AVR_HAVE_MUL"
1818 "#"
1819 "&& reload_completed"
1820 [(set (match_dup 4)
1821 (match_dup 2))
1822 ; *umaddqihi4 resp. *maddqihi4
1823 (set (match_dup 0)
1824 (plus:HI (mult:HI (any_extend:HI (match_dup 1))
1825 (any_extend:HI (match_dup 4)))
1826 (match_dup 3)))]
1827 {
1828 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1829 })
1830
1831 ;; "*umsubqihi4.uconst"
1832 ;; "*msubqihi4.sconst"
1833 (define_insn_and_split "*<extend_u>msubqihi4.<extend_su>const"
1834 [(set (match_operand:HI 0 "register_operand" "=r")
1835 (minus:HI (match_operand:HI 3 "register_operand" "0")
1836 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1837 (match_operand:HI 2 "<extend_su>8_operand" "n"))))
1838 (clobber (match_scratch:QI 4 "=&d"))]
1839 "AVR_HAVE_MUL"
1840 "#"
1841 "&& reload_completed"
1842 [(set (match_dup 4)
1843 (match_dup 2))
1844 ; *umsubqihi4 resp. *msubqihi4
1845 (set (match_dup 0)
1846 (minus:HI (match_dup 3)
1847 (mult:HI (any_extend:HI (match_dup 1))
1848 (any_extend:HI (match_dup 4)))))]
1849 {
1850 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1851 })
1852
1853 ;; Same as the insn above, but combiner tries versions canonicalized to ASHIFT
1854 ;; for MULT with power of 2 and skips trying MULT insn above.
1855
1856 (define_insn_and_split "*umsubqihi4.uconst.ashift"
1857 [(set (match_operand:HI 0 "register_operand" "=r")
1858 (minus:HI (match_operand:HI 3 "register_operand" "0")
1859 (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1860 (match_operand:HI 2 "const_2_to_7_operand" "n"))))
1861 (clobber (match_scratch:QI 4 "=&d"))]
1862 "AVR_HAVE_MUL"
1863 "#"
1864 "&& reload_completed"
1865 [(set (match_dup 4)
1866 (match_dup 2))
1867 ; *umsubqihi4
1868 (set (match_dup 0)
1869 (minus:HI (match_dup 3)
1870 (mult:HI (zero_extend:HI (match_dup 1))
1871 (zero_extend:HI (match_dup 4)))))]
1872 {
1873 operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
1874 })
1875
1876 ;; Same as the insn above, but combiner tries versions canonicalized to ASHIFT
1877 ;; for MULT with power of 2 and skips trying MULT insn above. We omit 128
1878 ;; because this would require an extra pattern for just one value.
1879
1880 (define_insn_and_split "*msubqihi4.sconst.ashift"
1881 [(set (match_operand:HI 0 "register_operand" "=r")
1882 (minus:HI (match_operand:HI 3 "register_operand" "0")
1883 (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
1884 (match_operand:HI 2 "const_1_to_6_operand" "M"))))
1885 (clobber (match_scratch:QI 4 "=&d"))]
1886 "AVR_HAVE_MUL"
1887 "#"
1888 "&& reload_completed"
1889 [(set (match_dup 4)
1890 (match_dup 2))
1891 ; *smsubqihi4
1892 (set (match_dup 0)
1893 (minus:HI (match_dup 3)
1894 (mult:HI (sign_extend:HI (match_dup 1))
1895 (sign_extend:HI (match_dup 4)))))]
1896 {
1897 operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
1898 })
1899
1900 ;; For signed/unsigned combinations that require narrow constraint "a"
1901 ;; just provide a pattern if signed/unsigned combination is actually needed.
1902
1903 (define_insn_and_split "*sumaddqihi4.uconst"
1904 [(set (match_operand:HI 0 "register_operand" "=r")
1905 (plus:HI (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1906 (match_operand:HI 2 "u8_operand" "M"))
1907 (match_operand:HI 3 "register_operand" "0")))
1908 (clobber (match_scratch:QI 4 "=&a"))]
1909 "AVR_HAVE_MUL
1910 && !s8_operand (operands[2], VOIDmode)"
1911 "#"
1912 "&& reload_completed"
1913 [(set (match_dup 4)
1914 (match_dup 2))
1915 ; *sumaddqihi4
1916 (set (match_dup 0)
1917 (plus:HI (mult:HI (sign_extend:HI (match_dup 1))
1918 (zero_extend:HI (match_dup 4)))
1919 (match_dup 3)))]
1920 {
1921 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1922 })
1923
1924 (define_insn_and_split "*sumsubqihi4.uconst"
1925 [(set (match_operand:HI 0 "register_operand" "=r")
1926 (minus:HI (match_operand:HI 3 "register_operand" "0")
1927 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1928 (match_operand:HI 2 "u8_operand" "M"))))
1929 (clobber (match_scratch:QI 4 "=&a"))]
1930 "AVR_HAVE_MUL
1931 && !s8_operand (operands[2], VOIDmode)"
1932 "#"
1933 "&& reload_completed"
1934 [(set (match_dup 4)
1935 (match_dup 2))
1936 ; *sumsubqihi4
1937 (set (match_dup 0)
1938 (minus:HI (match_dup 3)
1939 (mult:HI (sign_extend:HI (match_dup 1))
1940 (zero_extend:HI (match_dup 4)))))]
1941 {
1942 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1943 })
1944
1945 ;******************************************************************************
1946 ; mul HI: $1 = sign/zero-extend, $2 = small constant
1947 ;******************************************************************************
1948
1949 ;; "*muluqihi3.uconst"
1950 ;; "*mulsqihi3.sconst"
1951 (define_insn_and_split "*mul<extend_su>qihi3.<extend_su>const"
1952 [(set (match_operand:HI 0 "register_operand" "=r")
1953 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1954 (match_operand:HI 2 "<extend_su>8_operand" "n")))
1955 (clobber (match_scratch:QI 3 "=&d"))]
1956 "AVR_HAVE_MUL"
1957 "#"
1958 "&& reload_completed"
1959 [(set (match_dup 3)
1960 (match_dup 2))
1961 ; umulqihi3 resp. mulqihi3
1962 (set (match_dup 0)
1963 (mult:HI (any_extend:HI (match_dup 1))
1964 (any_extend:HI (match_dup 3))))]
1965 {
1966 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1967 })
1968
1969 (define_insn_and_split "*muluqihi3.sconst"
1970 [(set (match_operand:HI 0 "register_operand" "=r")
1971 (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "a"))
1972 (match_operand:HI 2 "s8_operand" "n")))
1973 (clobber (match_scratch:QI 3 "=&a"))]
1974 "AVR_HAVE_MUL"
1975 "#"
1976 "&& reload_completed"
1977 [(set (match_dup 3)
1978 (match_dup 2))
1979 ; usmulqihi3
1980 (set (match_dup 0)
1981 (mult:HI (zero_extend:HI (match_dup 1))
1982 (sign_extend:HI (match_dup 3))))]
1983 {
1984 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1985 })
1986
1987 (define_insn_and_split "*mulsqihi3.uconst"
1988 [(set (match_operand:HI 0 "register_operand" "=r")
1989 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1990 (match_operand:HI 2 "u8_operand" "M")))
1991 (clobber (match_scratch:QI 3 "=&a"))]
1992 "AVR_HAVE_MUL"
1993 "#"
1994 "&& reload_completed"
1995 [(set (match_dup 3)
1996 (match_dup 2))
1997 ; usmulqihi3
1998 (set (match_dup 0)
1999 (mult:HI (zero_extend:HI (match_dup 3))
2000 (sign_extend:HI (match_dup 1))))]
2001 {
2002 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
2003 })
2004
2005 (define_insn_and_split "*mulsqihi3.oconst"
2006 [(set (match_operand:HI 0 "register_operand" "=&r")
2007 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
2008 (match_operand:HI 2 "o8_operand" "n")))
2009 (clobber (match_scratch:QI 3 "=&a"))]
2010 "AVR_HAVE_MUL"
2011 "#"
2012 "&& reload_completed"
2013 [(set (match_dup 3)
2014 (match_dup 2))
2015 ; *osmulqihi3
2016 (set (match_dup 0)
2017 (mult:HI (not:HI (zero_extend:HI (not:QI (match_dup 3))))
2018 (sign_extend:HI (match_dup 1))))]
2019 {
2020 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
2021 })
2022
2023 ;; The EXTEND of $1 only appears in combine, we don't see it in expand so that
2024 ;; expand decides to use ASHIFT instead of MUL because ASHIFT costs are cheaper
2025 ;; at that time. Fix that.
2026
2027 (define_insn "*ashiftqihi2.signx.1"
2028 [(set (match_operand:HI 0 "register_operand" "=r,*r")
2029 (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "0,r"))
2030 (const_int 1)))]
2031 ""
2032 "@
2033 lsl %A0\;sbc %B0,%B0
2034 mov %A0,%1\;lsl %A0\;sbc %B0,%B0"
2035 [(set_attr "length" "2,3")
2036 (set_attr "cc" "clobber")])
2037
2038 (define_insn_and_split "*ashifthi3.signx.const"
2039 [(set (match_operand:HI 0 "register_operand" "=r")
2040 (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
2041 (match_operand:HI 2 "const_2_to_6_operand" "I")))
2042 (clobber (match_scratch:QI 3 "=&d"))]
2043 "AVR_HAVE_MUL"
2044 "#"
2045 "&& reload_completed"
2046 [(set (match_dup 3)
2047 (match_dup 2))
2048 ; mulqihi3
2049 (set (match_dup 0)
2050 (mult:HI (sign_extend:HI (match_dup 1))
2051 (sign_extend:HI (match_dup 3))))]
2052 {
2053 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
2054 })
2055
2056 (define_insn_and_split "*ashifthi3.signx.const7"
2057 [(set (match_operand:HI 0 "register_operand" "=r")
2058 (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
2059 (const_int 7)))
2060 (clobber (match_scratch:QI 2 "=&a"))]
2061 "AVR_HAVE_MUL"
2062 "#"
2063 "&& reload_completed"
2064 [(set (match_dup 2)
2065 (match_dup 3))
2066 ; usmulqihi3
2067 (set (match_dup 0)
2068 (mult:HI (zero_extend:HI (match_dup 2))
2069 (sign_extend:HI (match_dup 1))))]
2070 {
2071 operands[3] = gen_int_mode (1 << 7, QImode);
2072 })
2073
2074 (define_insn_and_split "*ashifthi3.zerox.const"
2075 [(set (match_operand:HI 0 "register_operand" "=r")
2076 (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
2077 (match_operand:HI 2 "const_2_to_7_operand" "I")))
2078 (clobber (match_scratch:QI 3 "=&d"))]
2079 "AVR_HAVE_MUL"
2080 "#"
2081 "&& reload_completed"
2082 [(set (match_dup 3)
2083 (match_dup 2))
2084 ; umulqihi3
2085 (set (match_dup 0)
2086 (mult:HI (zero_extend:HI (match_dup 1))
2087 (zero_extend:HI (match_dup 3))))]
2088 {
2089 operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
2090 })
2091
2092 ;******************************************************************************
2093 ; mul HI: $1 = sign-/zero-/one-extend, $2 = reg
2094 ;******************************************************************************
2095
2096 (define_insn "mulsqihi3"
2097 [(set (match_operand:HI 0 "register_operand" "=&r")
2098 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
2099 (match_operand:HI 2 "register_operand" "a")))]
2100 "AVR_HAVE_MUL"
2101 "mulsu %1,%A2
2102 movw %0,r0
2103 mul %1,%B2
2104 add %B0,r0
2105 clr __zero_reg__"
2106 [(set_attr "length" "5")
2107 (set_attr "cc" "clobber")])
2108
2109 (define_insn "muluqihi3"
2110 [(set (match_operand:HI 0 "register_operand" "=&r")
2111 (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
2112 (match_operand:HI 2 "register_operand" "r")))]
2113 "AVR_HAVE_MUL"
2114 "mul %1,%A2
2115 movw %0,r0
2116 mul %1,%B2
2117 add %B0,r0
2118 clr __zero_reg__"
2119 [(set_attr "length" "5")
2120 (set_attr "cc" "clobber")])
2121
2122 ;; one-extend operand 1
2123
2124 (define_insn "muloqihi3"
2125 [(set (match_operand:HI 0 "register_operand" "=&r")
2126 (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "r"))))
2127 (match_operand:HI 2 "register_operand" "r")))]
2128 "AVR_HAVE_MUL"
2129 "mul %1,%A2
2130 movw %0,r0
2131 mul %1,%B2
2132 add %B0,r0
2133 sub %B0,%A2
2134 clr __zero_reg__"
2135 [(set_attr "length" "6")
2136 (set_attr "cc" "clobber")])
2137
2138 ;******************************************************************************
2139
2140 (define_expand "mulhi3"
2141 [(set (match_operand:HI 0 "register_operand" "")
2142 (mult:HI (match_operand:HI 1 "register_operand" "")
2143 (match_operand:HI 2 "register_or_s9_operand" "")))]
2144 ""
2145 {
2146 if (!AVR_HAVE_MUL)
2147 {
2148 if (!register_operand (operands[2], HImode))
2149 operands[2] = force_reg (HImode, operands[2]);
2150
2151 emit_insn (gen_mulhi3_call (operands[0], operands[1], operands[2]));
2152 DONE;
2153 }
2154
2155 /* For small constants we can do better by extending them on the fly.
2156 The constant can be loaded in one instruction and the widening
2157 multiplication is shorter. First try the unsigned variant because it
2158 allows constraint "d" instead of "a" for the signed version. */
2159
2160 if (s9_operand (operands[2], HImode))
2161 {
2162 rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
2163
2164 if (u8_operand (operands[2], HImode))
2165 {
2166 emit_insn (gen_muluqihi3 (operands[0], reg, operands[1]));
2167 }
2168 else if (s8_operand (operands[2], HImode))
2169 {
2170 emit_insn (gen_mulsqihi3 (operands[0], reg, operands[1]));
2171 }
2172 else
2173 {
2174 emit_insn (gen_muloqihi3 (operands[0], reg, operands[1]));
2175 }
2176
2177 DONE;
2178 }
2179
2180 if (!register_operand (operands[2], HImode))
2181 operands[2] = force_reg (HImode, operands[2]);
2182 })
2183
2184 (define_insn "*mulhi3_enh"
2185 [(set (match_operand:HI 0 "register_operand" "=&r")
2186 (mult:HI (match_operand:HI 1 "register_operand" "r")
2187 (match_operand:HI 2 "register_operand" "r")))]
2188 "AVR_HAVE_MUL"
2189 {
2190 return REGNO (operands[1]) == REGNO (operands[2])
2191 ? "mul %A1,%A1\;movw %0,r0\;mul %A1,%B1\;add %B0,r0\;add %B0,r0\;clr r1"
2192 : "mul %A1,%A2\;movw %0,r0\;mul %A1,%B2\;add %B0,r0\;mul %B1,%A2\;add %B0,r0\;clr r1";
2193 }
2194 [(set_attr "length" "7")
2195 (set_attr "cc" "clobber")])
2196
2197 (define_expand "mulhi3_call"
2198 [(set (reg:HI 24) (match_operand:HI 1 "register_operand" ""))
2199 (set (reg:HI 22) (match_operand:HI 2 "register_operand" ""))
2200 (parallel [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22)))
2201 (clobber (reg:HI 22))
2202 (clobber (reg:QI 21))])
2203 (set (match_operand:HI 0 "register_operand" "") (reg:HI 24))])
2204
2205 (define_insn "*mulhi3_call"
2206 [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22)))
2207 (clobber (reg:HI 22))
2208 (clobber (reg:QI 21))]
2209 "!AVR_HAVE_MUL"
2210 "%~call __mulhi3"
2211 [(set_attr "type" "xcall")
2212 (set_attr "cc" "clobber")])
2213
2214 ;; To support widening multiplication with constant we postpone
2215 ;; expanding to the implicit library call until post combine and
2216 ;; prior to register allocation. Clobber all hard registers that
2217 ;; might be used by the (widening) multiply until it is split and
2218 ;; it's final register footprint is worked out.
2219
2220 (define_expand "mulsi3"
2221 [(parallel [(set (match_operand:SI 0 "register_operand" "")
2222 (mult:SI (match_operand:SI 1 "register_operand" "")
2223 (match_operand:SI 2 "nonmemory_operand" "")))
2224 (clobber (reg:HI 26))
2225 (clobber (reg:DI 18))])]
2226 "AVR_HAVE_MUL"
2227 {
2228 if (u16_operand (operands[2], SImode))
2229 {
2230 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2231 emit_insn (gen_muluhisi3 (operands[0], operands[2], operands[1]));
2232 DONE;
2233 }
2234
2235 if (o16_operand (operands[2], SImode))
2236 {
2237 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2238 emit_insn (gen_mulohisi3 (operands[0], operands[2], operands[1]));
2239 DONE;
2240 }
2241 })
2242
2243 (define_insn_and_split "*mulsi3"
2244 [(set (match_operand:SI 0 "pseudo_register_operand" "=r")
2245 (mult:SI (match_operand:SI 1 "pseudo_register_operand" "r")
2246 (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn")))
2247 (clobber (reg:HI 26))
2248 (clobber (reg:DI 18))]
2249 "AVR_HAVE_MUL && !reload_completed"
2250 { gcc_unreachable(); }
2251 "&& 1"
2252 [(set (reg:SI 18)
2253 (match_dup 1))
2254 (set (reg:SI 22)
2255 (match_dup 2))
2256 (parallel [(set (reg:SI 22)
2257 (mult:SI (reg:SI 22)
2258 (reg:SI 18)))
2259 (clobber (reg:HI 26))])
2260 (set (match_dup 0)
2261 (reg:SI 22))]
2262 {
2263 if (u16_operand (operands[2], SImode))
2264 {
2265 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2266 emit_insn (gen_muluhisi3 (operands[0], operands[2], operands[1]));
2267 DONE;
2268 }
2269
2270 if (o16_operand (operands[2], SImode))
2271 {
2272 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2273 emit_insn (gen_mulohisi3 (operands[0], operands[2], operands[1]));
2274 DONE;
2275 }
2276 })
2277
2278 ;; "muluqisi3"
2279 ;; "muluhisi3"
2280 (define_insn_and_split "mulu<mode>si3"
2281 [(set (match_operand:SI 0 "pseudo_register_operand" "=r")
2282 (mult:SI (zero_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r"))
2283 (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn")))
2284 (clobber (reg:HI 26))
2285 (clobber (reg:DI 18))]
2286 "AVR_HAVE_MUL && !reload_completed"
2287 { gcc_unreachable(); }
2288 "&& 1"
2289 [(set (reg:HI 26)
2290 (match_dup 1))
2291 (set (reg:SI 18)
2292 (match_dup 2))
2293 (set (reg:SI 22)
2294 (mult:SI (zero_extend:SI (reg:HI 26))
2295 (reg:SI 18)))
2296 (set (match_dup 0)
2297 (reg:SI 22))]
2298 {
2299 /* Do the QI -> HI extension explicitely before the multiplication. */
2300 /* Do the HI -> SI extension implicitely and after the multiplication. */
2301
2302 if (QImode == <MODE>mode)
2303 operands[1] = gen_rtx_ZERO_EXTEND (HImode, operands[1]);
2304
2305 if (u16_operand (operands[2], SImode))
2306 {
2307 operands[1] = force_reg (HImode, operands[1]);
2308 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2309 emit_insn (gen_umulhisi3 (operands[0], operands[1], operands[2]));
2310 DONE;
2311 }
2312 })
2313
2314 ;; "mulsqisi3"
2315 ;; "mulshisi3"
2316 (define_insn_and_split "muls<mode>si3"
2317 [(set (match_operand:SI 0 "pseudo_register_operand" "=r")
2318 (mult:SI (sign_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r"))
2319 (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn")))
2320 (clobber (reg:HI 26))
2321 (clobber (reg:DI 18))]
2322 "AVR_HAVE_MUL && !reload_completed"
2323 { gcc_unreachable(); }
2324 "&& 1"
2325 [(set (reg:HI 26)
2326 (match_dup 1))
2327 (set (reg:SI 18)
2328 (match_dup 2))
2329 (set (reg:SI 22)
2330 (mult:SI (sign_extend:SI (reg:HI 26))
2331 (reg:SI 18)))
2332 (set (match_dup 0)
2333 (reg:SI 22))]
2334 {
2335 /* Do the QI -> HI extension explicitely before the multiplication. */
2336 /* Do the HI -> SI extension implicitely and after the multiplication. */
2337
2338 if (QImode == <MODE>mode)
2339 operands[1] = gen_rtx_SIGN_EXTEND (HImode, operands[1]);
2340
2341 if (u16_operand (operands[2], SImode)
2342 || s16_operand (operands[2], SImode))
2343 {
2344 rtx xop2 = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2345
2346 operands[1] = force_reg (HImode, operands[1]);
2347
2348 if (u16_operand (operands[2], SImode))
2349 emit_insn (gen_usmulhisi3 (operands[0], xop2, operands[1]));
2350 else
2351 emit_insn (gen_mulhisi3 (operands[0], operands[1], xop2));
2352
2353 DONE;
2354 }
2355 })
2356
2357 ;; One-extend operand 1
2358
2359 (define_insn_and_split "mulohisi3"
2360 [(set (match_operand:SI 0 "pseudo_register_operand" "=r")
2361 (mult:SI (not:SI (zero_extend:SI
2362 (not:HI (match_operand:HI 1 "pseudo_register_operand" "r"))))
2363 (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn")))
2364 (clobber (reg:HI 26))
2365 (clobber (reg:DI 18))]
2366 "AVR_HAVE_MUL && !reload_completed"
2367 { gcc_unreachable(); }
2368 "&& 1"
2369 [(set (reg:HI 26)
2370 (match_dup 1))
2371 (set (reg:SI 18)
2372 (match_dup 2))
2373 (set (reg:SI 22)
2374 (mult:SI (not:SI (zero_extend:SI (not:HI (reg:HI 26))))
2375 (reg:SI 18)))
2376 (set (match_dup 0)
2377 (reg:SI 22))])
2378
2379 ;; "mulhisi3"
2380 ;; "umulhisi3"
2381 (define_expand "<extend_u>mulhisi3"
2382 [(parallel [(set (match_operand:SI 0 "register_operand" "")
2383 (mult:SI (any_extend:SI (match_operand:HI 1 "register_operand" ""))
2384 (any_extend:SI (match_operand:HI 2 "register_operand" ""))))
2385 (clobber (reg:HI 26))
2386 (clobber (reg:DI 18))])]
2387 "AVR_HAVE_MUL")
2388
2389 (define_expand "usmulhisi3"
2390 [(parallel [(set (match_operand:SI 0 "register_operand" "")
2391 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" ""))
2392 (sign_extend:SI (match_operand:HI 2 "register_operand" ""))))
2393 (clobber (reg:HI 26))
2394 (clobber (reg:DI 18))])]
2395 "AVR_HAVE_MUL")
2396
2397 ;; "*uumulqihisi3" "*uumulhiqisi3" "*uumulhihisi3" "*uumulqiqisi3"
2398 ;; "*usmulqihisi3" "*usmulhiqisi3" "*usmulhihisi3" "*usmulqiqisi3"
2399 ;; "*sumulqihisi3" "*sumulhiqisi3" "*sumulhihisi3" "*sumulqiqisi3"
2400 ;; "*ssmulqihisi3" "*ssmulhiqisi3" "*ssmulhihisi3" "*ssmulqiqisi3"
2401 (define_insn_and_split
2402 "*<any_extend:extend_su><any_extend2:extend_su>mul<QIHI:mode><QIHI2:mode>si3"
2403 [(set (match_operand:SI 0 "pseudo_register_operand" "=r")
2404 (mult:SI (any_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r"))
2405 (any_extend2:SI (match_operand:QIHI2 2 "pseudo_register_operand" "r"))))
2406 (clobber (reg:HI 26))
2407 (clobber (reg:DI 18))]
2408 "AVR_HAVE_MUL && !reload_completed"
2409 { gcc_unreachable(); }
2410 "&& 1"
2411 [(set (reg:HI 18)
2412 (match_dup 1))
2413 (set (reg:HI 26)
2414 (match_dup 2))
2415 (set (reg:SI 22)
2416 (mult:SI (match_dup 3)
2417 (match_dup 4)))
2418 (set (match_dup 0)
2419 (reg:SI 22))]
2420 {
2421 rtx xop1 = operands[1];
2422 rtx xop2 = operands[2];
2423
2424 /* Do the QI -> HI extension explicitely before the multiplication. */
2425 /* Do the HI -> SI extension implicitely and after the multiplication. */
2426
2427 if (QImode == <QIHI:MODE>mode)
2428 xop1 = gen_rtx_fmt_e (<any_extend:CODE>, HImode, xop1);
2429
2430 if (QImode == <QIHI2:MODE>mode)
2431 xop2 = gen_rtx_fmt_e (<any_extend2:CODE>, HImode, xop2);
2432
2433 if (<any_extend:CODE> == <any_extend2:CODE>
2434 || <any_extend:CODE> == ZERO_EXTEND)
2435 {
2436 operands[1] = xop1;
2437 operands[2] = xop2;
2438 operands[3] = gen_rtx_fmt_e (<any_extend:CODE>, SImode, gen_rtx_REG (HImode, 18));
2439 operands[4] = gen_rtx_fmt_e (<any_extend2:CODE>, SImode, gen_rtx_REG (HImode, 26));
2440 }
2441 else
2442 {
2443 /* <any_extend:CODE> = SIGN_EXTEND */
2444 /* <any_extend2:CODE> = ZERO_EXTEND */
2445
2446 operands[1] = xop2;
2447 operands[2] = xop1;
2448 operands[3] = gen_rtx_ZERO_EXTEND (SImode, gen_rtx_REG (HImode, 18));
2449 operands[4] = gen_rtx_SIGN_EXTEND (SImode, gen_rtx_REG (HImode, 26));
2450 }
2451 })
2452
2453 ;; "smulhi3_highpart"
2454 ;; "umulhi3_highpart"
2455 (define_expand "<extend_su>mulhi3_highpart"
2456 [(set (reg:HI 18)
2457 (match_operand:HI 1 "nonmemory_operand" ""))
2458 (set (reg:HI 26)
2459 (match_operand:HI 2 "nonmemory_operand" ""))
2460 (parallel [(set (reg:HI 24)
2461 (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
2462 (any_extend:SI (reg:HI 26)))
2463 (const_int 16))))
2464 (clobber (reg:HI 22))])
2465 (set (match_operand:HI 0 "register_operand" "")
2466 (reg:HI 24))]
2467 "AVR_HAVE_MUL")
2468
2469
2470 (define_insn "*mulsi3_call"
2471 [(set (reg:SI 22)
2472 (mult:SI (reg:SI 22)
2473 (reg:SI 18)))
2474 (clobber (reg:HI 26))]
2475 "AVR_HAVE_MUL"
2476 "%~call __mulsi3"
2477 [(set_attr "type" "xcall")
2478 (set_attr "cc" "clobber")])
2479
2480 ;; "*mulhisi3_call"
2481 ;; "*umulhisi3_call"
2482 (define_insn "*<extend_u>mulhisi3_call"
2483 [(set (reg:SI 22)
2484 (mult:SI (any_extend:SI (reg:HI 18))
2485 (any_extend:SI (reg:HI 26))))]
2486 "AVR_HAVE_MUL"
2487 "%~call __<extend_u>mulhisi3"
2488 [(set_attr "type" "xcall")
2489 (set_attr "cc" "clobber")])
2490
2491 ;; "*umulhi3_highpart_call"
2492 ;; "*smulhi3_highpart_call"
2493 (define_insn "*<extend_su>mulhi3_highpart_call"
2494 [(set (reg:HI 24)
2495 (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
2496 (any_extend:SI (reg:HI 26)))
2497 (const_int 16))))
2498 (clobber (reg:HI 22))]
2499 "AVR_HAVE_MUL"
2500 "%~call __<extend_u>mulhisi3"
2501 [(set_attr "type" "xcall")
2502 (set_attr "cc" "clobber")])
2503
2504 (define_insn "*usmulhisi3_call"
2505 [(set (reg:SI 22)
2506 (mult:SI (zero_extend:SI (reg:HI 18))
2507 (sign_extend:SI (reg:HI 26))))]
2508 "AVR_HAVE_MUL"
2509 "%~call __usmulhisi3"
2510 [(set_attr "type" "xcall")
2511 (set_attr "cc" "clobber")])
2512
2513 (define_insn "*mul<extend_su>hisi3_call"
2514 [(set (reg:SI 22)
2515 (mult:SI (any_extend:SI (reg:HI 26))
2516 (reg:SI 18)))]
2517 "AVR_HAVE_MUL"
2518 "%~call __mul<extend_su>hisi3"
2519 [(set_attr "type" "xcall")
2520 (set_attr "cc" "clobber")])
2521
2522 (define_insn "*mulohisi3_call"
2523 [(set (reg:SI 22)
2524 (mult:SI (not:SI (zero_extend:SI (not:HI (reg:HI 26))))
2525 (reg:SI 18)))]
2526 "AVR_HAVE_MUL"
2527 "%~call __mulohisi3"
2528 [(set_attr "type" "xcall")
2529 (set_attr "cc" "clobber")])
2530
2531 ; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / %
2532 ; divmod
2533
2534 ;; Generate lib1funcs.S calls ourselves, because:
2535 ;; - we know exactly which registers are clobbered (for QI and HI
2536 ;; modes, some of the call-used registers are preserved)
2537 ;; - we get both the quotient and the remainder at no extra cost
2538 ;; - we split the patterns only after the first CSE passes because
2539 ;; CSE has problems to operate on hard regs.
2540 ;;
2541 (define_insn_and_split "divmodqi4"
2542 [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "")
2543 (div:QI (match_operand:QI 1 "pseudo_register_operand" "")
2544 (match_operand:QI 2 "pseudo_register_operand" "")))
2545 (set (match_operand:QI 3 "pseudo_register_operand" "")
2546 (mod:QI (match_dup 1) (match_dup 2)))
2547 (clobber (reg:QI 22))
2548 (clobber (reg:QI 23))
2549 (clobber (reg:QI 24))
2550 (clobber (reg:QI 25))])]
2551 ""
2552 "this divmodqi4 pattern should have been splitted;"
2553 ""
2554 [(set (reg:QI 24) (match_dup 1))
2555 (set (reg:QI 22) (match_dup 2))
2556 (parallel [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
2557 (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
2558 (clobber (reg:QI 22))
2559 (clobber (reg:QI 23))])
2560 (set (match_dup 0) (reg:QI 24))
2561 (set (match_dup 3) (reg:QI 25))])
2562
2563 (define_insn "*divmodqi4_call"
2564 [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
2565 (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
2566 (clobber (reg:QI 22))
2567 (clobber (reg:QI 23))]
2568 ""
2569 "%~call __divmodqi4"
2570 [(set_attr "type" "xcall")
2571 (set_attr "cc" "clobber")])
2572
2573 (define_insn_and_split "udivmodqi4"
2574 [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "")
2575 (udiv:QI (match_operand:QI 1 "pseudo_register_operand" "")
2576 (match_operand:QI 2 "pseudo_register_operand" "")))
2577 (set (match_operand:QI 3 "pseudo_register_operand" "")
2578 (umod:QI (match_dup 1) (match_dup 2)))
2579 (clobber (reg:QI 22))
2580 (clobber (reg:QI 23))
2581 (clobber (reg:QI 24))
2582 (clobber (reg:QI 25))])]
2583 ""
2584 "this udivmodqi4 pattern should have been splitted;"
2585 ""
2586 [(set (reg:QI 24) (match_dup 1))
2587 (set (reg:QI 22) (match_dup 2))
2588 (parallel [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
2589 (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
2590 (clobber (reg:QI 23))])
2591 (set (match_dup 0) (reg:QI 24))
2592 (set (match_dup 3) (reg:QI 25))])
2593
2594 (define_insn "*udivmodqi4_call"
2595 [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
2596 (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
2597 (clobber (reg:QI 23))]
2598 ""
2599 "%~call __udivmodqi4"
2600 [(set_attr "type" "xcall")
2601 (set_attr "cc" "clobber")])
2602
2603 (define_insn_and_split "divmodhi4"
2604 [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "")
2605 (div:HI (match_operand:HI 1 "pseudo_register_operand" "")
2606 (match_operand:HI 2 "pseudo_register_operand" "")))
2607 (set (match_operand:HI 3 "pseudo_register_operand" "")
2608 (mod:HI (match_dup 1) (match_dup 2)))
2609 (clobber (reg:QI 21))
2610 (clobber (reg:HI 22))
2611 (clobber (reg:HI 24))
2612 (clobber (reg:HI 26))])]
2613 ""
2614 "this should have been splitted;"
2615 ""
2616 [(set (reg:HI 24) (match_dup 1))
2617 (set (reg:HI 22) (match_dup 2))
2618 (parallel [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
2619 (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
2620 (clobber (reg:HI 26))
2621 (clobber (reg:QI 21))])
2622 (set (match_dup 0) (reg:HI 22))
2623 (set (match_dup 3) (reg:HI 24))])
2624
2625 (define_insn "*divmodhi4_call"
2626 [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
2627 (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
2628 (clobber (reg:HI 26))
2629 (clobber (reg:QI 21))]
2630 ""
2631 "%~call __divmodhi4"
2632 [(set_attr "type" "xcall")
2633 (set_attr "cc" "clobber")])
2634
2635 (define_insn_and_split "udivmodhi4"
2636 [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "")
2637 (udiv:HI (match_operand:HI 1 "pseudo_register_operand" "")
2638 (match_operand:HI 2 "pseudo_register_operand" "")))
2639 (set (match_operand:HI 3 "pseudo_register_operand" "")
2640 (umod:HI (match_dup 1) (match_dup 2)))
2641 (clobber (reg:QI 21))
2642 (clobber (reg:HI 22))
2643 (clobber (reg:HI 24))
2644 (clobber (reg:HI 26))])]
2645 ""
2646 "this udivmodhi4 pattern should have been splitted.;"
2647 ""
2648 [(set (reg:HI 24) (match_dup 1))
2649 (set (reg:HI 22) (match_dup 2))
2650 (parallel [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
2651 (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
2652 (clobber (reg:HI 26))
2653 (clobber (reg:QI 21))])
2654 (set (match_dup 0) (reg:HI 22))
2655 (set (match_dup 3) (reg:HI 24))])
2656
2657 (define_insn "*udivmodhi4_call"
2658 [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
2659 (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
2660 (clobber (reg:HI 26))
2661 (clobber (reg:QI 21))]
2662 ""
2663 "%~call __udivmodhi4"
2664 [(set_attr "type" "xcall")
2665 (set_attr "cc" "clobber")])
2666
2667 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2668 ;; 24-bit multiply
2669
2670 ;; To support widening multiplication with constant we postpone
2671 ;; expanding to the implicit library call until post combine and
2672 ;; prior to register allocation. Clobber all hard registers that
2673 ;; might be used by the (widening) multiply until it is split and
2674 ;; it's final register footprint is worked out.
2675
2676 (define_expand "mulpsi3"
2677 [(parallel [(set (match_operand:PSI 0 "register_operand" "")
2678 (mult:PSI (match_operand:PSI 1 "register_operand" "")
2679 (match_operand:PSI 2 "nonmemory_operand" "")))
2680 (clobber (reg:HI 26))
2681 (clobber (reg:DI 18))])]
2682 "AVR_HAVE_MUL"
2683 {
2684 if (s8_operand (operands[2], PSImode))
2685 {
2686 rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
2687 emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1]));
2688 DONE;
2689 }
2690 })
2691
2692 (define_insn "*umulqihipsi3"
2693 [(set (match_operand:PSI 0 "register_operand" "=&r")
2694 (mult:PSI (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))
2695 (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
2696 "AVR_HAVE_MUL"
2697 "mul %1,%A2
2698 movw %A0,r0
2699 mul %1,%B2
2700 clr %C0
2701 add %B0,r0
2702 adc %C0,r1
2703 clr __zero_reg__"
2704 [(set_attr "length" "7")
2705 (set_attr "cc" "clobber")])
2706
2707 (define_insn "*umulhiqipsi3"
2708 [(set (match_operand:PSI 0 "register_operand" "=&r")
2709 (mult:PSI (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))
2710 (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))))]
2711 "AVR_HAVE_MUL"
2712 "mul %1,%A2
2713 movw %A0,r0
2714 mul %1,%B2
2715 add %B0,r0
2716 mov %C0,r1
2717 clr __zero_reg__
2718 adc %C0,__zero_reg__"
2719 [(set_attr "length" "7")
2720 (set_attr "cc" "clobber")])
2721
2722 (define_insn_and_split "mulsqipsi3"
2723 [(set (match_operand:PSI 0 "pseudo_register_operand" "=r")
2724 (mult:PSI (sign_extend:PSI (match_operand:QI 1 "pseudo_register_operand" "r"))
2725 (match_operand:PSI 2 "pseudo_register_or_const_int_operand" "rn")))
2726 (clobber (reg:HI 26))
2727 (clobber (reg:DI 18))]
2728 "AVR_HAVE_MUL && !reload_completed"
2729 { gcc_unreachable(); }
2730 "&& 1"
2731 [(set (reg:QI 25)
2732 (match_dup 1))
2733 (set (reg:PSI 22)
2734 (match_dup 2))
2735 (set (reg:PSI 18)
2736 (mult:PSI (sign_extend:PSI (reg:QI 25))
2737 (reg:PSI 22)))
2738 (set (match_dup 0)
2739 (reg:PSI 18))])
2740
2741 (define_insn_and_split "*mulpsi3"
2742 [(set (match_operand:PSI 0 "pseudo_register_operand" "=r")
2743 (mult:PSI (match_operand:PSI 1 "pseudo_register_operand" "r")
2744 (match_operand:PSI 2 "pseudo_register_or_const_int_operand" "rn")))
2745 (clobber (reg:HI 26))
2746 (clobber (reg:DI 18))]
2747 "AVR_HAVE_MUL && !reload_completed"
2748 { gcc_unreachable(); }
2749 "&& 1"
2750 [(set (reg:PSI 18)
2751 (match_dup 1))
2752 (set (reg:PSI 22)
2753 (match_dup 2))
2754 (parallel [(set (reg:PSI 22)
2755 (mult:PSI (reg:PSI 22)
2756 (reg:PSI 18)))
2757 (clobber (reg:QI 21))
2758 (clobber (reg:QI 25))
2759 (clobber (reg:HI 26))])
2760 (set (match_dup 0)
2761 (reg:PSI 22))]
2762 {
2763 if (s8_operand (operands[2], PSImode))
2764 {
2765 rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
2766 emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1]));
2767 DONE;
2768 }
2769 })
2770
2771 (define_insn "*mulsqipsi3.libgcc"
2772 [(set (reg:PSI 18)
2773 (mult:PSI (sign_extend:PSI (reg:QI 25))
2774 (reg:PSI 22)))]
2775 "AVR_HAVE_MUL"
2776 "%~call __mulsqipsi3"
2777 [(set_attr "type" "xcall")
2778 (set_attr "cc" "clobber")])
2779
2780 (define_insn "*mulpsi3.libgcc"
2781 [(set (reg:PSI 22)
2782 (mult:PSI (reg:PSI 22)
2783 (reg:PSI 18)))
2784 (clobber (reg:QI 21))
2785 (clobber (reg:QI 25))
2786 (clobber (reg:HI 26))]
2787 "AVR_HAVE_MUL"
2788 "%~call __mulpsi3"
2789 [(set_attr "type" "xcall")
2790 (set_attr "cc" "clobber")])
2791
2792
2793 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2794 ;; 24-bit signed/unsigned division and modulo.
2795 ;; Notice that the libgcc implementation return the quotient in R22
2796 ;; and the remainder in R18 whereas the 32-bit [u]divmodsi4
2797 ;; implementation works the other way round.
2798
2799 (define_insn_and_split "divmodpsi4"
2800 [(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "")
2801 (div:PSI (match_operand:PSI 1 "pseudo_register_operand" "")
2802 (match_operand:PSI 2 "pseudo_register_operand" "")))
2803 (set (match_operand:PSI 3 "pseudo_register_operand" "")
2804 (mod:PSI (match_dup 1)
2805 (match_dup 2)))
2806 (clobber (reg:DI 18))
2807 (clobber (reg:QI 26))])]
2808 ""
2809 { gcc_unreachable(); }
2810 ""
2811 [(set (reg:PSI 22) (match_dup 1))
2812 (set (reg:PSI 18) (match_dup 2))
2813 (parallel [(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18)))
2814 (set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18)))
2815 (clobber (reg:QI 21))
2816 (clobber (reg:QI 25))
2817 (clobber (reg:QI 26))])
2818 (set (match_dup 0) (reg:PSI 22))
2819 (set (match_dup 3) (reg:PSI 18))])
2820
2821 (define_insn "*divmodpsi4_call"
2822 [(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18)))
2823 (set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18)))
2824 (clobber (reg:QI 21))
2825 (clobber (reg:QI 25))
2826 (clobber (reg:QI 26))]
2827 ""
2828 "%~call __divmodpsi4"
2829 [(set_attr "type" "xcall")
2830 (set_attr "cc" "clobber")])
2831
2832 (define_insn_and_split "udivmodpsi4"
2833 [(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "")
2834 (udiv:PSI (match_operand:PSI 1 "pseudo_register_operand" "")
2835 (match_operand:PSI 2 "pseudo_register_operand" "")))
2836 (set (match_operand:PSI 3 "pseudo_register_operand" "")
2837 (umod:PSI (match_dup 1)
2838 (match_dup 2)))
2839 (clobber (reg:DI 18))
2840 (clobber (reg:QI 26))])]
2841 ""
2842 { gcc_unreachable(); }
2843 ""
2844 [(set (reg:PSI 22) (match_dup 1))
2845 (set (reg:PSI 18) (match_dup 2))
2846 (parallel [(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18)))
2847 (set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18)))
2848 (clobber (reg:QI 21))
2849 (clobber (reg:QI 25))
2850 (clobber (reg:QI 26))])
2851 (set (match_dup 0) (reg:PSI 22))
2852 (set (match_dup 3) (reg:PSI 18))])
2853
2854 (define_insn "*udivmodpsi4_call"
2855 [(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18)))
2856 (set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18)))
2857 (clobber (reg:QI 21))
2858 (clobber (reg:QI 25))
2859 (clobber (reg:QI 26))]
2860 ""
2861 "%~call __udivmodpsi4"
2862 [(set_attr "type" "xcall")
2863 (set_attr "cc" "clobber")])
2864
2865 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2866
2867 (define_insn_and_split "divmodsi4"
2868 [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "")
2869 (div:SI (match_operand:SI 1 "pseudo_register_operand" "")
2870 (match_operand:SI 2 "pseudo_register_operand" "")))
2871 (set (match_operand:SI 3 "pseudo_register_operand" "")
2872 (mod:SI (match_dup 1) (match_dup 2)))
2873 (clobber (reg:SI 18))
2874 (clobber (reg:SI 22))
2875 (clobber (reg:HI 26))
2876 (clobber (reg:HI 30))])]
2877 ""
2878 "this divmodsi4 pattern should have been splitted;"
2879 ""
2880 [(set (reg:SI 22) (match_dup 1))
2881 (set (reg:SI 18) (match_dup 2))
2882 (parallel [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
2883 (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
2884 (clobber (reg:HI 26))
2885 (clobber (reg:HI 30))])
2886 (set (match_dup 0) (reg:SI 18))
2887 (set (match_dup 3) (reg:SI 22))])
2888
2889 (define_insn "*divmodsi4_call"
2890 [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
2891 (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
2892 (clobber (reg:HI 26))
2893 (clobber (reg:HI 30))]
2894 ""
2895 "%~call __divmodsi4"
2896 [(set_attr "type" "xcall")
2897 (set_attr "cc" "clobber")])
2898
2899 (define_insn_and_split "udivmodsi4"
2900 [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "")
2901 (udiv:SI (match_operand:SI 1 "pseudo_register_operand" "")
2902 (match_operand:SI 2 "pseudo_register_operand" "")))
2903 (set (match_operand:SI 3 "pseudo_register_operand" "")
2904 (umod:SI (match_dup 1) (match_dup 2)))
2905 (clobber (reg:SI 18))
2906 (clobber (reg:SI 22))
2907 (clobber (reg:HI 26))
2908 (clobber (reg:HI 30))])]
2909 ""
2910 "this udivmodsi4 pattern should have been splitted;"
2911 ""
2912 [(set (reg:SI 22) (match_dup 1))
2913 (set (reg:SI 18) (match_dup 2))
2914 (parallel [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
2915 (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
2916 (clobber (reg:HI 26))
2917 (clobber (reg:HI 30))])
2918 (set (match_dup 0) (reg:SI 18))
2919 (set (match_dup 3) (reg:SI 22))])
2920
2921 (define_insn "*udivmodsi4_call"
2922 [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
2923 (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
2924 (clobber (reg:HI 26))
2925 (clobber (reg:HI 30))]
2926 ""
2927 "%~call __udivmodsi4"
2928 [(set_attr "type" "xcall")
2929 (set_attr "cc" "clobber")])
2930
2931 ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2932 ; and
2933
2934 (define_insn "andqi3"
2935 [(set (match_operand:QI 0 "register_operand" "=??r,d")
2936 (and:QI (match_operand:QI 1 "register_operand" "%0,0")
2937 (match_operand:QI 2 "nonmemory_operand" "r,i")))]
2938 ""
2939 "@
2940 and %0,%2
2941 andi %0,lo8(%2)"
2942 [(set_attr "length" "1,1")
2943 (set_attr "cc" "set_zn,set_zn")])
2944
2945 (define_insn "andhi3"
2946 [(set (match_operand:HI 0 "register_operand" "=??r,d,d,r ,r")
2947 (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0 ,0")
2948 (match_operand:HI 2 "nonmemory_operand" "r,s,n,Ca2,n")))
2949 (clobber (match_scratch:QI 3 "=X,X,X,X ,&d"))]
2950 ""
2951 {
2952 if (which_alternative == 0)
2953 return "and %A0,%A2\;and %B0,%B2";
2954 else if (which_alternative == 1)
2955 return "andi %A0,lo8(%2)\;andi %B0,hi8(%2)";
2956
2957 return avr_out_bitop (insn, operands, NULL);
2958 }
2959 [(set_attr "length" "2,2,2,4,4")
2960 (set_attr "adjust_len" "*,*,out_bitop,out_bitop,out_bitop")
2961 (set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
2962
2963 (define_insn "andpsi3"
2964 [(set (match_operand:PSI 0 "register_operand" "=??r,d,r ,r")
2965 (and:PSI (match_operand:PSI 1 "register_operand" "%0,0,0 ,0")
2966 (match_operand:PSI 2 "nonmemory_operand" "r,n,Ca3,n")))
2967 (clobber (match_scratch:QI 3 "=X,X,X ,&d"))]
2968 ""
2969 {
2970 if (which_alternative == 0)
2971 return "and %A0,%A2" CR_TAB
2972 "and %B0,%B2" CR_TAB
2973 "and %C0,%C2";
2974
2975 return avr_out_bitop (insn, operands, NULL);
2976 }
2977 [(set_attr "length" "3,3,6,6")
2978 (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
2979 (set_attr "cc" "set_n,clobber,clobber,clobber")])
2980
2981 (define_insn "andsi3"
2982 [(set (match_operand:SI 0 "register_operand" "=??r,d,r ,r")
2983 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0 ,0")
2984 (match_operand:SI 2 "nonmemory_operand" "r,n,Ca4,n")))
2985 (clobber (match_scratch:QI 3 "=X,X,X ,&d"))]
2986 ""
2987 {
2988 if (which_alternative == 0)
2989 return "and %0,%2" CR_TAB
2990 "and %B0,%B2" CR_TAB
2991 "and %C0,%C2" CR_TAB
2992 "and %D0,%D2";
2993
2994 return avr_out_bitop (insn, operands, NULL);
2995 }
2996 [(set_attr "length" "4,4,8,8")
2997 (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
2998 (set_attr "cc" "set_n,clobber,clobber,clobber")])
2999
3000 (define_peephole2 ; andi
3001 [(set (match_operand:QI 0 "d_register_operand" "")
3002 (and:QI (match_dup 0)
3003 (match_operand:QI 1 "const_int_operand" "")))
3004 (set (match_dup 0)
3005 (and:QI (match_dup 0)
3006 (match_operand:QI 2 "const_int_operand" "")))]
3007 ""
3008 [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
3009 {
3010 operands[1] = GEN_INT (INTVAL (operands[1]) & INTVAL (operands[2]));
3011 })
3012
3013 ;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
3014 ;; ior
3015
3016 (define_insn "iorqi3"
3017 [(set (match_operand:QI 0 "register_operand" "=??r,d")
3018 (ior:QI (match_operand:QI 1 "register_operand" "%0,0")
3019 (match_operand:QI 2 "nonmemory_operand" "r,i")))]
3020 ""
3021 "@
3022 or %0,%2
3023 ori %0,lo8(%2)"
3024 [(set_attr "length" "1,1")
3025 (set_attr "cc" "set_zn,set_zn")])
3026
3027 (define_insn "iorhi3"
3028 [(set (match_operand:HI 0 "register_operand" "=??r,d,d,r ,r")
3029 (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0 ,0")
3030 (match_operand:HI 2 "nonmemory_operand" "r,s,n,Co2,n")))
3031 (clobber (match_scratch:QI 3 "=X,X,X,X ,&d"))]
3032 ""
3033 {
3034 if (which_alternative == 0)
3035 return "or %A0,%A2\;or %B0,%B2";
3036 else if (which_alternative == 1)
3037 return "ori %A0,lo8(%2)\;ori %B0,hi8(%2)";
3038
3039 return avr_out_bitop (insn, operands, NULL);
3040 }
3041 [(set_attr "length" "2,2,2,4,4")
3042 (set_attr "adjust_len" "*,*,out_bitop,out_bitop,out_bitop")
3043 (set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
3044
3045 (define_insn "iorpsi3"
3046 [(set (match_operand:PSI 0 "register_operand" "=??r,d,r ,r")
3047 (ior:PSI (match_operand:PSI 1 "register_operand" "%0,0,0 ,0")
3048 (match_operand:PSI 2 "nonmemory_operand" "r,n,Co3,n")))
3049 (clobber (match_scratch:QI 3 "=X,X,X ,&d"))]
3050 ""
3051 {
3052 if (which_alternative == 0)
3053 return "or %A0,%A2" CR_TAB
3054 "or %B0,%B2" CR_TAB
3055 "or %C0,%C2";
3056
3057 return avr_out_bitop (insn, operands, NULL);
3058 }
3059 [(set_attr "length" "3,3,6,6")
3060 (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
3061 (set_attr "cc" "set_n,clobber,clobber,clobber")])
3062
3063 (define_insn "iorsi3"
3064 [(set (match_operand:SI 0 "register_operand" "=??r,d,r ,r")
3065 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0 ,0")
3066 (match_operand:SI 2 "nonmemory_operand" "r,n,Co4,n")))
3067 (clobber (match_scratch:QI 3 "=X,X,X ,&d"))]
3068 ""
3069 {
3070 if (which_alternative == 0)
3071 return "or %0,%2" CR_TAB
3072 "or %B0,%B2" CR_TAB
3073 "or %C0,%C2" CR_TAB
3074 "or %D0,%D2";
3075
3076 return avr_out_bitop (insn, operands, NULL);
3077 }
3078 [(set_attr "length" "4,4,8,8")
3079 (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
3080 (set_attr "cc" "set_n,clobber,clobber,clobber")])
3081
3082 ;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3083 ;; xor
3084
3085 (define_insn "xorqi3"
3086 [(set (match_operand:QI 0 "register_operand" "=r")
3087 (xor:QI (match_operand:QI 1 "register_operand" "%0")
3088 (match_operand:QI 2 "register_operand" "r")))]
3089 ""
3090 "eor %0,%2"
3091 [(set_attr "length" "1")
3092 (set_attr "cc" "set_zn")])
3093
3094 (define_insn "xorhi3"
3095 [(set (match_operand:HI 0 "register_operand" "=??r,r ,r")
3096 (xor:HI (match_operand:HI 1 "register_operand" "%0,0 ,0")
3097 (match_operand:HI 2 "nonmemory_operand" "r,Cx2,n")))
3098 (clobber (match_scratch:QI 3 "=X,X ,&d"))]
3099 ""
3100 {
3101 if (which_alternative == 0)
3102 return "eor %A0,%A2\;eor %B0,%B2";
3103
3104 return avr_out_bitop (insn, operands, NULL);
3105 }
3106 [(set_attr "length" "2,2,4")
3107 (set_attr "adjust_len" "*,out_bitop,out_bitop")
3108 (set_attr "cc" "set_n,clobber,clobber")])
3109
3110 (define_insn "xorpsi3"
3111 [(set (match_operand:PSI 0 "register_operand" "=??r,r ,r")
3112 (xor:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0")
3113 (match_operand:PSI 2 "nonmemory_operand" "r,Cx3,n")))
3114 (clobber (match_scratch:QI 3 "=X,X ,&d"))]
3115 ""
3116 {
3117 if (which_alternative == 0)
3118 return "eor %A0,%A2" CR_TAB
3119 "eor %B0,%B2" CR_TAB
3120 "eor %C0,%C2";
3121
3122 return avr_out_bitop (insn, operands, NULL);
3123 }
3124 [(set_attr "length" "3,6,6")
3125 (set_attr "adjust_len" "*,out_bitop,out_bitop")
3126 (set_attr "cc" "set_n,clobber,clobber")])
3127
3128 (define_insn "xorsi3"
3129 [(set (match_operand:SI 0 "register_operand" "=??r,r ,r")
3130 (xor:SI (match_operand:SI 1 "register_operand" "%0,0 ,0")
3131 (match_operand:SI 2 "nonmemory_operand" "r,Cx4,n")))
3132 (clobber (match_scratch:QI 3 "=X,X ,&d"))]
3133 ""
3134 {
3135 if (which_alternative == 0)
3136 return "eor %0,%2" CR_TAB
3137 "eor %B0,%B2" CR_TAB
3138 "eor %C0,%C2" CR_TAB
3139 "eor %D0,%D2";
3140
3141 return avr_out_bitop (insn, operands, NULL);
3142 }
3143 [(set_attr "length" "4,8,8")
3144 (set_attr "adjust_len" "*,out_bitop,out_bitop")
3145 (set_attr "cc" "set_n,clobber,clobber")])
3146
3147 ;; swap swap swap swap swap swap swap swap swap swap swap swap swap swap swap
3148 ;; swap
3149
3150 (define_expand "rotlqi3"
3151 [(set (match_operand:QI 0 "register_operand" "")
3152 (rotate:QI (match_operand:QI 1 "register_operand" "")
3153 (match_operand:QI 2 "const_0_to_7_operand" "")))]
3154 ""
3155 {
3156 if (!CONST_INT_P (operands[2]))
3157 FAIL;
3158
3159 operands[2] = gen_int_mode (INTVAL (operands[2]) & 7, QImode);
3160 })
3161
3162 ;; Expander used by __builtin_avr_swap
3163 (define_expand "rotlqi3_4"
3164 [(set (match_operand:QI 0 "register_operand" "")
3165 (rotate:QI (match_operand:QI 1 "register_operand" "")
3166 (const_int 4)))])
3167
3168 (define_insn "*rotlqi3"
3169 [(set (match_operand:QI 0 "register_operand" "=r,r,r ,r ,r ,r ,r ,r")
3170 (rotate:QI (match_operand:QI 1 "register_operand" "0,0,0 ,0 ,0 ,0 ,0 ,0")
3171 (match_operand:QI 2 "const_0_to_7_operand" "P,K,C03,C04,C05,C06,C07,L")))]
3172 ""
3173 "@
3174 lsl %0\;adc %0,__zero_reg__
3175 lsl %0\;adc %0,__zero_reg__\;lsl %0\;adc %0,__zero_reg__
3176 swap %0\;bst %0,0\;ror %0\;bld %0,7
3177 swap %0
3178 swap %0\;lsl %0\;adc %0,__zero_reg__
3179 swap %0\;lsl %0\;adc %0,__zero_reg__\;lsl %0\;adc %0,__zero_reg__
3180 bst %0,0\;ror %0\;bld %0,7
3181 "
3182 [(set_attr "length" "2,4,4,1,3,5,3,0")
3183 (set_attr "cc" "set_n,set_n,clobber,none,set_n,set_n,clobber,none")])
3184
3185 ;; Split all rotates of HI,SI and PSImode registers where rotation is by
3186 ;; a whole number of bytes. The split creates the appropriate moves and
3187 ;; considers all overlap situations.
3188
3189 ;; HImode does not need scratch. Use attribute for this constraint.
3190
3191 (define_mode_attr rotx [(SI "&r,&r,X") (PSI "&r,&r,X") (HI "X,X,X")])
3192 (define_mode_attr rotsmode [(SI "HI") (PSI "QI") (HI "QI")])
3193
3194 ;; "rotlhi3"
3195 ;; "rotlpsi3"
3196 ;; "rotlsi3"
3197 (define_expand "rotl<mode>3"
3198 [(parallel [(set (match_operand:HISI 0 "register_operand" "")
3199 (rotate:HISI (match_operand:HISI 1 "register_operand" "")
3200 (match_operand:VOID 2 "const_int_operand" "")))
3201 (clobber (match_dup 3))])]
3202 ""
3203 {
3204 int offset;
3205
3206 if (!CONST_INT_P (operands[2]))
3207 FAIL;
3208
3209 offset = INTVAL (operands[2]);
3210
3211 if (0 == offset % 8)
3212 {
3213 if (AVR_HAVE_MOVW && 0 == offset % 16)
3214 operands[3] = gen_rtx_SCRATCH (<rotsmode>mode);
3215 else
3216 operands[3] = gen_rtx_SCRATCH (QImode);
3217 }
3218 else if (offset == 1
3219 || offset == GET_MODE_BITSIZE (<MODE>mode) -1)
3220 {
3221 /*; Support rotate left/right by 1 */
3222
3223 emit_move_insn (operands[0],
3224 gen_rtx_ROTATE (<MODE>mode, operands[1], operands[2]));
3225 DONE;
3226 }
3227 else
3228 FAIL;
3229 })
3230
3231 (define_insn "*rotlhi2.1"
3232 [(set (match_operand:HI 0 "register_operand" "=r")
3233 (rotate:HI (match_operand:HI 1 "register_operand" "0")
3234 (const_int 1)))]
3235 ""
3236 "lsl %A0\;rol %B0\;adc %A0,__zero_reg__"
3237 [(set_attr "length" "3")
3238 (set_attr "cc" "clobber")])
3239
3240 (define_insn "*rotlhi2.15"
3241 [(set (match_operand:HI 0 "register_operand" "=r")
3242 (rotate:HI (match_operand:HI 1 "register_operand" "0")
3243 (const_int 15)))]
3244 ""
3245 "bst %A0,0\;ror %B0\;ror %A0\;bld %B0,7"
3246 [(set_attr "length" "4")
3247 (set_attr "cc" "clobber")])
3248
3249 (define_insn "*rotlpsi2.1"
3250 [(set (match_operand:PSI 0 "register_operand" "=r")
3251 (rotate:PSI (match_operand:PSI 1 "register_operand" "0")
3252 (const_int 1)))]
3253 ""
3254 "lsl %A0\;rol %B0\;rol %C0\;adc %A0,__zero_reg__"
3255 [(set_attr "length" "4")
3256 (set_attr "cc" "clobber")])
3257
3258 (define_insn "*rotlpsi2.23"
3259 [(set (match_operand:PSI 0 "register_operand" "=r")
3260 (rotate:PSI (match_operand:PSI 1 "register_operand" "0")
3261 (const_int 23)))]
3262 ""
3263 "bst %A0,0\;ror %C0\;ror %B0\;ror %A0\;bld %C0,7"
3264 [(set_attr "length" "5")
3265 (set_attr "cc" "clobber")])
3266
3267 (define_insn "*rotlsi2.1"
3268 [(set (match_operand:SI 0 "register_operand" "=r")
3269 (rotate:SI (match_operand:SI 1 "register_operand" "0")
3270 (const_int 1)))]
3271 ""
3272 "lsl %A0\;rol %B0\;rol %C0\;rol %D0\;adc %A0,__zero_reg__"
3273 [(set_attr "length" "5")
3274 (set_attr "cc" "clobber")])
3275
3276 (define_insn "*rotlsi2.31"
3277 [(set (match_operand:SI 0 "register_operand" "=r")
3278 (rotate:SI (match_operand:SI 1 "register_operand" "0")
3279 (const_int 31)))]
3280 ""
3281 "bst %A0,0\;ror %D0\;ror %C0\;ror %B0\;ror %A0\;bld %D0,7"
3282 [(set_attr "length" "6")
3283 (set_attr "cc" "clobber")])
3284
3285 ;; Overlapping non-HImode registers often (but not always) need a scratch.
3286 ;; The best we can do is use early clobber alternative "#&r" so that
3287 ;; completely non-overlapping operands dont get a scratch but # so register
3288 ;; allocation does not prefer non-overlapping.
3289
3290
3291 ;; Split word aligned rotates using scratch that is mode dependent.
3292
3293 ;; "*rotwhi"
3294 ;; "*rotwsi"
3295 (define_insn_and_split "*rotw<mode>"
3296 [(set (match_operand:HISI 0 "register_operand" "=r,r,#&r")
3297 (rotate:HISI (match_operand:HISI 1 "register_operand" "0,r,r")
3298 (match_operand 2 "const_int_operand" "n,n,n")))
3299 (clobber (match_scratch:<rotsmode> 3 "=<rotx>"))]
3300 "AVR_HAVE_MOVW
3301 && CONST_INT_P (operands[2])
3302 && GET_MODE_SIZE (<MODE>mode) % 2 == 0
3303 && 0 == INTVAL (operands[2]) % 16"
3304 "#"
3305 "&& reload_completed"
3306 [(const_int 0)]
3307 {
3308 avr_rotate_bytes (operands);
3309 DONE;
3310 })
3311
3312
3313 ;; Split byte aligned rotates using scratch that is always QI mode.
3314
3315 ;; "*rotbhi"
3316 ;; "*rotbpsi"
3317 ;; "*rotbsi"
3318 (define_insn_and_split "*rotb<mode>"
3319 [(set (match_operand:HISI 0 "register_operand" "=r,r,#&r")
3320 (rotate:HISI (match_operand:HISI 1 "register_operand" "0,r,r")
3321 (match_operand 2 "const_int_operand" "n,n,n")))
3322 (clobber (match_scratch:QI 3 "=<rotx>"))]
3323 "CONST_INT_P (operands[2])
3324 && (8 == INTVAL (operands[2]) % 16
3325 || ((!AVR_HAVE_MOVW
3326 || GET_MODE_SIZE (<MODE>mode) % 2 != 0)
3327 && 0 == INTVAL (operands[2]) % 16))"
3328 "#"
3329 "&& reload_completed"
3330 [(const_int 0)]
3331 {
3332 avr_rotate_bytes (operands);
3333 DONE;
3334 })
3335
3336
3337 ;;<< << << << << << << << << << << << << << << << << << << << << << << << << <<
3338 ;; arithmetic shift left
3339
3340 ;; "ashlqi3"
3341 ;; "ashlqq3" "ashluqq3"
3342 (define_expand "ashl<mode>3"
3343 [(set (match_operand:ALL1 0 "register_operand" "")
3344 (ashift:ALL1 (match_operand:ALL1 1 "register_operand" "")
3345 (match_operand:QI 2 "nop_general_operand" "")))])
3346
3347 (define_split ; ashlqi3_const4
3348 [(set (match_operand:ALL1 0 "d_register_operand" "")
3349 (ashift:ALL1 (match_dup 0)
3350 (const_int 4)))]
3351 ""
3352 [(set (match_dup 1)
3353 (rotate:QI (match_dup 1)
3354 (const_int 4)))
3355 (set (match_dup 1)
3356 (and:QI (match_dup 1)
3357 (const_int -16)))]
3358 {
3359 operands[1] = avr_to_int_mode (operands[0]);
3360 })
3361
3362 (define_split ; ashlqi3_const5
3363 [(set (match_operand:ALL1 0 "d_register_operand" "")
3364 (ashift:ALL1 (match_dup 0)
3365 (const_int 5)))]
3366 ""
3367 [(set (match_dup 1) (rotate:QI (match_dup 1) (const_int 4)))
3368 (set (match_dup 1) (ashift:QI (match_dup 1) (const_int 1)))
3369 (set (match_dup 1) (and:QI (match_dup 1) (const_int -32)))]
3370 {
3371 operands[1] = avr_to_int_mode (operands[0]);
3372 })
3373
3374 (define_split ; ashlqi3_const6
3375 [(set (match_operand:ALL1 0 "d_register_operand" "")
3376 (ashift:ALL1 (match_dup 0)
3377 (const_int 6)))]
3378 ""
3379 [(set (match_dup 1) (rotate:QI (match_dup 1) (const_int 4)))
3380 (set (match_dup 1) (ashift:QI (match_dup 1) (const_int 2)))
3381 (set (match_dup 1) (and:QI (match_dup 1) (const_int -64)))]
3382 {
3383 operands[1] = avr_to_int_mode (operands[0]);
3384 })
3385
3386 ;; "*ashlqi3"
3387 ;; "*ashlqq3" "*ashluqq3"
3388 (define_insn "*ashl<mode>3"
3389 [(set (match_operand:ALL1 0 "register_operand" "=r,r,r,r,!d,r,r")
3390 (ashift:ALL1 (match_operand:ALL1 1 "register_operand" "0,0,0,0,0 ,0,0")
3391 (match_operand:QI 2 "nop_general_operand" "r,L,P,K,n ,n,Qm")))]
3392 ""
3393 {
3394 return ashlqi3_out (insn, operands, NULL);
3395 }
3396 [(set_attr "length" "5,0,1,2,4,6,9")
3397 (set_attr "adjust_len" "ashlqi")
3398 (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")])
3399
3400 (define_insn "ashl<mode>3"
3401 [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r,r,r")
3402 (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r,0,0,0")
3403 (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
3404 ""
3405 {
3406 return ashlhi3_out (insn, operands, NULL);
3407 }
3408 [(set_attr "length" "6,0,2,2,4,10,10")
3409 (set_attr "adjust_len" "ashlhi")
3410 (set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")])
3411
3412
3413 ;; Insns like the following are generated when (implicitly) extending 8-bit shifts
3414 ;; like char1 = char2 << char3. Only the low-byte is needed in that situation.
3415
3416 ;; "*ashluqihiqi3"
3417 ;; "*ashlsqihiqi3"
3418 (define_insn_and_split "*ashl<extend_su>qihiqi3"
3419 [(set (match_operand:QI 0 "register_operand" "=r")
3420 (subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "0"))
3421 (match_operand:QI 2 "register_operand" "r"))
3422 0))]
3423 ""
3424 "#"
3425 ""
3426 [(set (match_dup 0)
3427 (ashift:QI (match_dup 1)
3428 (match_dup 2)))])
3429
3430 ;; ??? Combiner does not recognize that it could split the following insn;
3431 ;; presumably because he has no register handy?
3432
3433 ;; "*ashluqihiqi3.mem"
3434 ;; "*ashlsqihiqi3.mem"
3435 (define_insn_and_split "*ashl<extend_su>qihiqi3.mem"
3436 [(set (match_operand:QI 0 "memory_operand" "=m")
3437 (subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "r"))
3438 (match_operand:QI 2 "register_operand" "r"))
3439 0))]
3440 "!reload_completed"
3441 { gcc_unreachable(); }
3442 "&& 1"
3443 [(set (match_dup 3)
3444 (ashift:QI (match_dup 1)
3445 (match_dup 2)))
3446 (set (match_dup 0)
3447 (match_dup 3))]
3448 {
3449 operands[3] = gen_reg_rtx (QImode);
3450 })
3451
3452 ;; Similar.
3453
3454 (define_insn_and_split "*ashlhiqi3"
3455 [(set (match_operand:QI 0 "nonimmediate_operand" "=r")
3456 (subreg:QI (ashift:HI (match_operand:HI 1 "register_operand" "0")
3457 (match_operand:QI 2 "register_operand" "r")) 0))]
3458 "!reload_completed"
3459 { gcc_unreachable(); }
3460 "&& 1"
3461 [(set (match_dup 4)
3462 (ashift:QI (match_dup 3)
3463 (match_dup 2)))
3464 (set (match_dup 0)
3465 (match_dup 4))]
3466 {
3467 operands[3] = simplify_gen_subreg (QImode, operands[1], HImode, 0);
3468 operands[4] = gen_reg_rtx (QImode);
3469 })
3470
3471 ;; High part of 16-bit shift is unused after the instruction:
3472 ;; No need to compute it, map to 8-bit shift.
3473
3474 (define_peephole2
3475 [(set (match_operand:HI 0 "register_operand" "")
3476 (ashift:HI (match_dup 0)
3477 (match_operand:QI 1 "register_operand" "")))]
3478 ""
3479 [(set (match_dup 2)
3480 (ashift:QI (match_dup 2)
3481 (match_dup 1)))
3482 (clobber (match_dup 3))]
3483 {
3484 operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 1);
3485
3486 if (!peep2_reg_dead_p (1, operands[3]))
3487 FAIL;
3488
3489 operands[2] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
3490 })
3491
3492
3493 ;; "ashlsi3"
3494 ;; "ashlsq3" "ashlusq3"
3495 ;; "ashlsa3" "ashlusa3"
3496 (define_insn "ashl<mode>3"
3497 [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r,r,r,r")
3498 (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r,0,0,0")
3499 (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
3500 ""
3501 {
3502 return ashlsi3_out (insn, operands, NULL);
3503 }
3504 [(set_attr "length" "8,0,4,4,8,10,12")
3505 (set_attr "adjust_len" "ashlsi")
3506 (set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")])
3507
3508 ;; Optimize if a scratch register from LD_REGS happens to be available.
3509
3510 (define_peephole2 ; ashlqi3_l_const4
3511 [(set (match_operand:ALL1 0 "l_register_operand" "")
3512 (ashift:ALL1 (match_dup 0)
3513 (const_int 4)))
3514 (match_scratch:QI 1 "d")]
3515 ""
3516 [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4)))
3517 (set (match_dup 1) (const_int -16))
3518 (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))]
3519 {
3520 operands[2] = avr_to_int_mode (operands[0]);
3521 })
3522
3523 (define_peephole2 ; ashlqi3_l_const5
3524 [(set (match_operand:ALL1 0 "l_register_operand" "")
3525 (ashift:ALL1 (match_dup 0)
3526 (const_int 5)))
3527 (match_scratch:QI 1 "d")]
3528 ""
3529 [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4)))
3530 (set (match_dup 2) (ashift:QI (match_dup 2) (const_int 1)))
3531 (set (match_dup 1) (const_int -32))
3532 (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))]
3533 {
3534 operands[2] = avr_to_int_mode (operands[0]);
3535 })
3536
3537 (define_peephole2 ; ashlqi3_l_const6
3538 [(set (match_operand:ALL1 0 "l_register_operand" "")
3539 (ashift:ALL1 (match_dup 0)
3540 (const_int 6)))
3541 (match_scratch:QI 1 "d")]
3542 ""
3543 [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4)))
3544 (set (match_dup 2) (ashift:QI (match_dup 2) (const_int 2)))
3545 (set (match_dup 1) (const_int -64))
3546 (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))]
3547 {
3548 operands[2] = avr_to_int_mode (operands[0]);
3549 })
3550
3551 (define_peephole2
3552 [(match_scratch:QI 3 "d")
3553 (set (match_operand:ALL2 0 "register_operand" "")
3554 (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "")
3555 (match_operand:QI 2 "const_int_operand" "")))]
3556 ""
3557 [(parallel [(set (match_dup 0)
3558 (ashift:ALL2 (match_dup 1)
3559 (match_dup 2)))
3560 (clobber (match_dup 3))])])
3561
3562 ;; "*ashlhi3_const"
3563 ;; "*ashlhq3_const" "*ashluhq3_const"
3564 ;; "*ashlha3_const" "*ashluha3_const"
3565 (define_insn "*ashl<mode>3_const"
3566 [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r")
3567 (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r,0,0")
3568 (match_operand:QI 2 "const_int_operand" "L,P,O,K,n")))
3569 (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
3570 "reload_completed"
3571 {
3572 return ashlhi3_out (insn, operands, NULL);
3573 }
3574 [(set_attr "length" "0,2,2,4,10")
3575 (set_attr "adjust_len" "ashlhi")
3576 (set_attr "cc" "none,set_n,clobber,set_n,clobber")])
3577
3578 (define_peephole2
3579 [(match_scratch:QI 3 "d")
3580 (set (match_operand:ALL4 0 "register_operand" "")
3581 (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "")
3582 (match_operand:QI 2 "const_int_operand" "")))]
3583 ""
3584 [(parallel [(set (match_dup 0)
3585 (ashift:ALL4 (match_dup 1)
3586 (match_dup 2)))
3587 (clobber (match_dup 3))])])
3588
3589 ;; "*ashlsi3_const"
3590 ;; "*ashlsq3_const" "*ashlusq3_const"
3591 ;; "*ashlsa3_const" "*ashlusa3_const"
3592 (define_insn "*ashl<mode>3_const"
3593 [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r")
3594 (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r,0")
3595 (match_operand:QI 2 "const_int_operand" "L,P,O,n")))
3596 (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
3597 "reload_completed"
3598 {
3599 return ashlsi3_out (insn, operands, NULL);
3600 }
3601 [(set_attr "length" "0,4,4,10")
3602 (set_attr "adjust_len" "ashlsi")
3603 (set_attr "cc" "none,set_n,clobber,clobber")])
3604
3605 (define_expand "ashlpsi3"
3606 [(parallel [(set (match_operand:PSI 0 "register_operand" "")
3607 (ashift:PSI (match_operand:PSI 1 "register_operand" "")
3608 (match_operand:QI 2 "nonmemory_operand" "")))
3609 (clobber (scratch:QI))])]
3610 ""
3611 {
3612 if (AVR_HAVE_MUL
3613 && CONST_INT_P (operands[2]))
3614 {
3615 if (IN_RANGE (INTVAL (operands[2]), 3, 6))
3616 {
3617 rtx xoffset = force_reg (QImode, gen_int_mode (1 << INTVAL (operands[2]), QImode));
3618 emit_insn (gen_mulsqipsi3 (operands[0], xoffset, operands[1]));
3619 DONE;
3620 }
3621 else if (optimize_insn_for_speed_p ()
3622 && INTVAL (operands[2]) != 16
3623 && IN_RANGE (INTVAL (operands[2]), 9, 22))
3624 {
3625 rtx xoffset = force_reg (PSImode, gen_int_mode (1 << INTVAL (operands[2]), PSImode));
3626 emit_insn (gen_mulpsi3 (operands[0], operands[1], xoffset));
3627 DONE;
3628 }
3629 }
3630 })
3631
3632 (define_insn "*ashlpsi3"
3633 [(set (match_operand:PSI 0 "register_operand" "=r,r,r,r")
3634 (ashift:PSI (match_operand:PSI 1 "register_operand" "0,0,r,0")
3635 (match_operand:QI 2 "nonmemory_operand" "r,P,O,n")))
3636 (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
3637 ""
3638 {
3639 return avr_out_ashlpsi3 (insn, operands, NULL);
3640 }
3641 [(set_attr "adjust_len" "ashlpsi")
3642 (set_attr "cc" "clobber")])
3643
3644 ;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>
3645 ;; arithmetic shift right
3646
3647 ;; "ashrqi3"
3648 ;; "ashrqq3" "ashruqq3"
3649 (define_insn "ashr<mode>3"
3650 [(set (match_operand:ALL1 0 "register_operand" "=r,r,r,r,r ,r ,r")
3651 (ashiftrt:ALL1 (match_operand:ALL1 1 "register_operand" "0,0,0,0,0 ,0 ,0")
3652 (match_operand:QI 2 "nop_general_operand" "r,L,P,K,C03 C04 C05,C06 C07,Qm")))]
3653 ""
3654 {
3655 return ashrqi3_out (insn, operands, NULL);
3656 }
3657 [(set_attr "length" "5,0,1,2,5,4,9")
3658 (set_attr "adjust_len" "ashrqi")
3659 (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,clobber,clobber")])
3660
3661 ;; "ashrhi3"
3662 ;; "ashrhq3" "ashruhq3"
3663 ;; "ashrha3" "ashruha3"
3664 (define_insn "ashr<mode>3"
3665 [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r,r,r")
3666 (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r,0,0,0")
3667 (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
3668 ""
3669 {
3670 return ashrhi3_out (insn, operands, NULL);
3671 }
3672 [(set_attr "length" "6,0,2,4,4,10,10")
3673 (set_attr "adjust_len" "ashrhi")
3674 (set_attr "cc" "clobber,none,clobber,set_n,clobber,clobber,clobber")])
3675
3676 (define_insn "ashrpsi3"
3677 [(set (match_operand:PSI 0 "register_operand" "=r,r,r,r,r")
3678 (ashiftrt:PSI (match_operand:PSI 1 "register_operand" "0,0,0,r,0")
3679 (match_operand:QI 2 "nonmemory_operand" "r,P,K,O,n")))
3680 (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
3681 ""
3682 {
3683 return avr_out_ashrpsi3 (insn, operands, NULL);
3684 }
3685 [(set_attr "adjust_len" "ashrpsi")
3686 (set_attr "cc" "clobber")])
3687
3688 ;; "ashrsi3"
3689 ;; "ashrsq3" "ashrusq3"
3690 ;; "ashrsa3" "ashrusa3"
3691 (define_insn "ashr<mode>3"
3692 [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r,r,r,r")
3693 (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r,0,0,0")
3694 (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
3695 ""
3696 {
3697 return ashrsi3_out (insn, operands, NULL);
3698 }
3699 [(set_attr "length" "8,0,4,6,8,10,12")
3700 (set_attr "adjust_len" "ashrsi")
3701 (set_attr "cc" "clobber,none,clobber,set_n,clobber,clobber,clobber")])
3702
3703 ;; Optimize if a scratch register from LD_REGS happens to be available.
3704
3705 (define_peephole2
3706 [(match_scratch:QI 3 "d")
3707 (set (match_operand:ALL2 0 "register_operand" "")
3708 (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "")
3709 (match_operand:QI 2 "const_int_operand" "")))]
3710 ""
3711 [(parallel [(set (match_dup 0)
3712 (ashiftrt:ALL2 (match_dup 1)
3713 (match_dup 2)))
3714 (clobber (match_dup 3))])])
3715
3716 ;; "*ashrhi3_const"
3717 ;; "*ashrhq3_const" "*ashruhq3_const"
3718 ;; "*ashrha3_const" "*ashruha3_const"
3719 (define_insn "*ashr<mode>3_const"
3720 [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r")
3721 (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r,0,0")
3722 (match_operand:QI 2 "const_int_operand" "L,P,O,K,n")))
3723 (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
3724 "reload_completed"
3725 {
3726 return ashrhi3_out (insn, operands, NULL);
3727 }
3728 [(set_attr "length" "0,2,4,4,10")
3729 (set_attr "adjust_len" "ashrhi")
3730 (set_attr "cc" "none,clobber,set_n,clobber,clobber")])
3731
3732 (define_peephole2
3733 [(match_scratch:QI 3 "d")
3734 (set (match_operand:ALL4 0 "register_operand" "")
3735 (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "")
3736 (match_operand:QI 2 "const_int_operand" "")))]
3737 ""
3738 [(parallel [(set (match_dup 0)
3739 (ashiftrt:ALL4 (match_dup 1)
3740 (match_dup 2)))
3741 (clobber (match_dup 3))])])
3742
3743 ;; "*ashrsi3_const"
3744 ;; "*ashrsq3_const" "*ashrusq3_const"
3745 ;; "*ashrsa3_const" "*ashrusa3_const"
3746 (define_insn "*ashr<mode>3_const"
3747 [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r")
3748 (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r,0")
3749 (match_operand:QI 2 "const_int_operand" "L,P,O,n")))
3750 (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
3751 "reload_completed"
3752 {
3753 return ashrsi3_out (insn, operands, NULL);
3754 }
3755 [(set_attr "length" "0,4,4,10")
3756 (set_attr "adjust_len" "ashrsi")
3757 (set_attr "cc" "none,clobber,set_n,clobber")])
3758
3759 ;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>
3760 ;; logical shift right
3761
3762 ;; "lshrqi3"
3763 ;; "lshrqq3 "lshruqq3"
3764 (define_expand "lshr<mode>3"
3765 [(set (match_operand:ALL1 0 "register_operand" "")
3766 (lshiftrt:ALL1 (match_operand:ALL1 1 "register_operand" "")
3767 (match_operand:QI 2 "nop_general_operand" "")))])
3768
3769 (define_split ; lshrqi3_const4
3770 [(set (match_operand:ALL1 0 "d_register_operand" "")
3771 (lshiftrt:ALL1 (match_dup 0)
3772 (const_int 4)))]
3773 ""
3774 [(set (match_dup 1)
3775 (rotate:QI (match_dup 1)
3776 (const_int 4)))
3777 (set (match_dup 1)
3778 (and:QI (match_dup 1)
3779 (const_int 15)))]
3780 {
3781 operands[1] = avr_to_int_mode (operands[0]);
3782 })
3783
3784 (define_split ; lshrqi3_const5
3785 [(set (match_operand:ALL1 0 "d_register_operand" "")
3786 (lshiftrt:ALL1 (match_dup 0)
3787 (const_int 5)))]
3788 ""
3789 [(set (match_dup 1) (rotate:QI (match_dup 1) (const_int 4)))
3790 (set (match_dup 1) (lshiftrt:QI (match_dup 1) (const_int 1)))
3791 (set (match_dup 1) (and:QI (match_dup 1) (const_int 7)))]
3792 {
3793 operands[1] = avr_to_int_mode (operands[0]);
3794 })
3795
3796 (define_split ; lshrqi3_const6
3797 [(set (match_operand:QI 0 "d_register_operand" "")
3798 (lshiftrt:QI (match_dup 0)
3799 (const_int 6)))]
3800 ""
3801 [(set (match_dup 1) (rotate:QI (match_dup 1) (const_int 4)))
3802 (set (match_dup 1) (lshiftrt:QI (match_dup 1) (const_int 2)))
3803 (set (match_dup 1) (and:QI (match_dup 1) (const_int 3)))]
3804 {
3805 operands[1] = avr_to_int_mode (operands[0]);
3806 })
3807
3808 ;; "*lshrqi3"
3809 ;; "*lshrqq3"
3810 ;; "*lshruqq3"
3811 (define_insn "*lshr<mode>3"
3812 [(set (match_operand:ALL1 0 "register_operand" "=r,r,r,r,!d,r,r")
3813 (lshiftrt:ALL1 (match_operand:ALL1 1 "register_operand" "0,0,0,0,0 ,0,0")
3814 (match_operand:QI 2 "nop_general_operand" "r,L,P,K,n ,n,Qm")))]
3815 ""
3816 {
3817 return lshrqi3_out (insn, operands, NULL);
3818 }
3819 [(set_attr "length" "5,0,1,2,4,6,9")
3820 (set_attr "adjust_len" "lshrqi")
3821 (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")])
3822
3823 ;; "lshrhi3"
3824 ;; "lshrhq3" "lshruhq3"
3825 ;; "lshrha3" "lshruha3"
3826 (define_insn "lshr<mode>3"
3827 [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r,r,r")
3828 (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r,0,0,0")
3829 (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
3830 ""
3831 {
3832 return lshrhi3_out (insn, operands, NULL);
3833 }
3834 [(set_attr "length" "6,0,2,2,4,10,10")
3835 (set_attr "adjust_len" "lshrhi")
3836 (set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber,clobber")])
3837
3838 (define_insn "lshrpsi3"
3839 [(set (match_operand:PSI 0 "register_operand" "=r,r,r,r,r")
3840 (lshiftrt:PSI (match_operand:PSI 1 "register_operand" "0,0,r,0,0")
3841 (match_operand:QI 2 "nonmemory_operand" "r,P,O,K,n")))
3842 (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
3843 ""
3844 {
3845 return avr_out_lshrpsi3 (insn, operands, NULL);
3846 }
3847 [(set_attr "adjust_len" "lshrpsi")
3848 (set_attr "cc" "clobber")])
3849
3850 ;; "lshrsi3"
3851 ;; "lshrsq3" "lshrusq3"
3852 ;; "lshrsa3" "lshrusa3"
3853 (define_insn "lshr<mode>3"
3854 [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r,r,r,r")
3855 (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r,0,0,0")
3856 (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
3857 ""
3858 {
3859 return lshrsi3_out (insn, operands, NULL);
3860 }
3861 [(set_attr "length" "8,0,4,4,8,10,12")
3862 (set_attr "adjust_len" "lshrsi")
3863 (set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber,clobber")])
3864
3865 ;; Optimize if a scratch register from LD_REGS happens to be available.
3866
3867 (define_peephole2 ; lshrqi3_l_const4
3868 [(set (match_operand:ALL1 0 "l_register_operand" "")
3869 (lshiftrt:ALL1 (match_dup 0)
3870 (const_int 4)))
3871 (match_scratch:QI 1 "d")]
3872 ""
3873 [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4)))
3874 (set (match_dup 1) (const_int 15))
3875 (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))]
3876 {
3877 operands[2] = avr_to_int_mode (operands[0]);
3878 })
3879
3880 (define_peephole2 ; lshrqi3_l_const5
3881 [(set (match_operand:ALL1 0 "l_register_operand" "")
3882 (lshiftrt:ALL1 (match_dup 0)
3883 (const_int 5)))
3884 (match_scratch:QI 1 "d")]
3885 ""
3886 [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4)))
3887 (set (match_dup 2) (lshiftrt:QI (match_dup 2) (const_int 1)))
3888 (set (match_dup 1) (const_int 7))
3889 (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))]
3890 {
3891 operands[2] = avr_to_int_mode (operands[0]);
3892 })
3893
3894 (define_peephole2 ; lshrqi3_l_const6
3895 [(set (match_operand:ALL1 0 "l_register_operand" "")
3896 (lshiftrt:ALL1 (match_dup 0)
3897 (const_int 6)))
3898 (match_scratch:QI 1 "d")]
3899 ""
3900 [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4)))
3901 (set (match_dup 2) (lshiftrt:QI (match_dup 2) (const_int 2)))
3902 (set (match_dup 1) (const_int 3))
3903 (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))]
3904 {
3905 operands[2] = avr_to_int_mode (operands[0]);
3906 })
3907
3908 (define_peephole2
3909 [(match_scratch:QI 3 "d")
3910 (set (match_operand:ALL2 0 "register_operand" "")
3911 (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "")
3912 (match_operand:QI 2 "const_int_operand" "")))]
3913 ""
3914 [(parallel [(set (match_dup 0)
3915 (lshiftrt:ALL2 (match_dup 1)
3916 (match_dup 2)))
3917 (clobber (match_dup 3))])])
3918
3919 ;; "*lshrhi3_const"
3920 ;; "*lshrhq3_const" "*lshruhq3_const"
3921 ;; "*lshrha3_const" "*lshruha3_const"
3922 (define_insn "*lshr<mode>3_const"
3923 [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r")
3924 (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r,0,0")
3925 (match_operand:QI 2 "const_int_operand" "L,P,O,K,n")))
3926 (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
3927 "reload_completed"
3928 {
3929 return lshrhi3_out (insn, operands, NULL);
3930 }
3931 [(set_attr "length" "0,2,2,4,10")
3932 (set_attr "adjust_len" "lshrhi")
3933 (set_attr "cc" "none,clobber,clobber,clobber,clobber")])
3934
3935 (define_peephole2
3936 [(match_scratch:QI 3 "d")
3937 (set (match_operand:ALL4 0 "register_operand" "")
3938 (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "")
3939 (match_operand:QI 2 "const_int_operand" "")))]
3940 ""
3941 [(parallel [(set (match_dup 0)
3942 (lshiftrt:ALL4 (match_dup 1)
3943 (match_dup 2)))
3944 (clobber (match_dup 3))])])
3945
3946 ;; "*lshrsi3_const"
3947 ;; "*lshrsq3_const" "*lshrusq3_const"
3948 ;; "*lshrsa3_const" "*lshrusa3_const"
3949 (define_insn "*lshr<mode>3_const"
3950 [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r")
3951 (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r,0")
3952 (match_operand:QI 2 "const_int_operand" "L,P,O,n")))
3953 (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
3954 "reload_completed"
3955 {
3956 return lshrsi3_out (insn, operands, NULL);
3957 }
3958 [(set_attr "length" "0,4,4,10")
3959 (set_attr "adjust_len" "lshrsi")
3960 (set_attr "cc" "none,clobber,clobber,clobber")])
3961
3962 ;; abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x)
3963 ;; abs
3964
3965 (define_insn "absqi2"
3966 [(set (match_operand:QI 0 "register_operand" "=r")
3967 (abs:QI (match_operand:QI 1 "register_operand" "0")))]
3968 ""
3969 "sbrc %0,7
3970 neg %0"
3971 [(set_attr "length" "2")
3972 (set_attr "cc" "clobber")])
3973
3974
3975 (define_insn "abssf2"
3976 [(set (match_operand:SF 0 "register_operand" "=d,r")
3977 (abs:SF (match_operand:SF 1 "register_operand" "0,0")))]
3978 ""
3979 "@
3980 andi %D0,0x7f
3981 clt\;bld %D0,7"
3982 [(set_attr "length" "1,2")
3983 (set_attr "cc" "set_n,clobber")])
3984
3985 ;; 0 - x 0 - x 0 - x 0 - x 0 - x 0 - x 0 - x 0 - x 0 - x 0 - x 0 - x
3986 ;; neg
3987
3988 (define_insn "negqi2"
3989 [(set (match_operand:QI 0 "register_operand" "=r")
3990 (neg:QI (match_operand:QI 1 "register_operand" "0")))]
3991 ""
3992 "neg %0"
3993 [(set_attr "length" "1")
3994 (set_attr "cc" "set_zn")])
3995
3996 (define_insn "*negqihi2"
3997 [(set (match_operand:HI 0 "register_operand" "=r")
3998 (neg:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "0"))))]
3999 ""
4000 "clr %B0\;neg %A0\;brge .+2\;com %B0"
4001 [(set_attr "length" "4")
4002 (set_attr "cc" "set_n")])
4003
4004 (define_insn "neghi2"
4005 [(set (match_operand:HI 0 "register_operand" "=r,&r")
4006 (neg:HI (match_operand:HI 1 "register_operand" "0,r")))]
4007 ""
4008 "@
4009 neg %B0\;neg %A0\;sbc %B0,__zero_reg__
4010 clr %A0\;clr %B0\;sub %A0,%A1\;sbc %B0,%B1"
4011 [(set_attr "length" "3,4")
4012 (set_attr "cc" "set_czn")])
4013
4014 (define_insn "negpsi2"
4015 [(set (match_operand:PSI 0 "register_operand" "=!d,r,&r")
4016 (neg:PSI (match_operand:PSI 1 "register_operand" "0,0,r")))]
4017 ""
4018 "@
4019 com %C0\;com %B0\;neg %A0\;sbci %B0,-1\;sbci %C0,-1
4020 com %C0\;com %B0\;com %A0\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__
4021 clr %A0\;clr %B0\;clr %C0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1"
4022 [(set_attr "length" "5,6,6")
4023 (set_attr "cc" "set_czn,set_n,set_czn")])
4024
4025 (define_insn "negsi2"
4026 [(set (match_operand:SI 0 "register_operand" "=!d,r,&r,&r")
4027 (neg:SI (match_operand:SI 1 "register_operand" "0,0,r ,r")))]
4028 ""
4029 "@
4030 com %D0\;com %C0\;com %B0\;neg %A0\;sbci %B0,lo8(-1)\;sbci %C0,lo8(-1)\;sbci %D0,lo8(-1)
4031 com %D0\;com %C0\;com %B0\;com %A0\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__
4032 clr %A0\;clr %B0\;clr %C0\;clr %D0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1
4033 clr %A0\;clr %B0\;movw %C0,%A0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1"
4034 [(set_attr "length" "7,8,8,7")
4035 (set_attr "isa" "*,*,mov,movw")
4036 (set_attr "cc" "set_czn,set_n,set_czn,set_czn")])
4037
4038 (define_insn "negsf2"
4039 [(set (match_operand:SF 0 "register_operand" "=d,r")
4040 (neg:SF (match_operand:SF 1 "register_operand" "0,0")))]
4041 ""
4042 "@
4043 subi %D0,0x80
4044 bst %D0,7\;com %D0\;bld %D0,7\;com %D0"
4045 [(set_attr "length" "1,4")
4046 (set_attr "cc" "set_n,set_n")])
4047
4048 ;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4049 ;; not
4050
4051 (define_insn "one_cmplqi2"
4052 [(set (match_operand:QI 0 "register_operand" "=r")
4053 (not:QI (match_operand:QI 1 "register_operand" "0")))]
4054 ""
4055 "com %0"
4056 [(set_attr "length" "1")
4057 (set_attr "cc" "set_czn")])
4058
4059 (define_insn "one_cmplhi2"
4060 [(set (match_operand:HI 0 "register_operand" "=r")
4061 (not:HI (match_operand:HI 1 "register_operand" "0")))]
4062 ""
4063 "com %0
4064 com %B0"
4065 [(set_attr "length" "2")
4066 (set_attr "cc" "set_n")])
4067
4068 (define_insn "one_cmplpsi2"
4069 [(set (match_operand:PSI 0 "register_operand" "=r")
4070 (not:PSI (match_operand:PSI 1 "register_operand" "0")))]
4071 ""
4072 "com %0\;com %B0\;com %C0"
4073 [(set_attr "length" "3")
4074 (set_attr "cc" "set_n")])
4075
4076 (define_insn "one_cmplsi2"
4077 [(set (match_operand:SI 0 "register_operand" "=r")
4078 (not:SI (match_operand:SI 1 "register_operand" "0")))]
4079 ""
4080 "com %0
4081 com %B0
4082 com %C0
4083 com %D0"
4084 [(set_attr "length" "4")
4085 (set_attr "cc" "set_n")])
4086
4087 ;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
4088 ;; sign extend
4089
4090 ;; We keep combiner from inserting hard registers into the input of sign- and
4091 ;; zero-extends. A hard register in the input operand is not wanted because
4092 ;; 32-bit multiply patterns clobber some hard registers and extends with a
4093 ;; hard register that overlaps these clobbers won't be combined to a widening
4094 ;; multiplication. There is no need for combine to propagate hard registers,
4095 ;; register allocation can do it just as well.
4096
4097 (define_insn "extendqihi2"
4098 [(set (match_operand:HI 0 "register_operand" "=r,r")
4099 (sign_extend:HI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))]
4100 ""
4101 "@
4102 clr %B0\;sbrc %0,7\;com %B0
4103 mov %A0,%A1\;clr %B0\;sbrc %A0,7\;com %B0"
4104 [(set_attr "length" "3,4")
4105 (set_attr "cc" "set_n,set_n")])
4106
4107 (define_insn "extendqipsi2"
4108 [(set (match_operand:PSI 0 "register_operand" "=r,r")
4109 (sign_extend:PSI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))]
4110 ""
4111 "@
4112 clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0
4113 mov %A0,%A1\;clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0"
4114 [(set_attr "length" "4,5")
4115 (set_attr "cc" "set_n,set_n")])
4116
4117 (define_insn "extendqisi2"
4118 [(set (match_operand:SI 0 "register_operand" "=r,r")
4119 (sign_extend:SI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))]
4120 ""
4121 "@
4122 clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0\;mov %D0,%B0
4123 mov %A0,%A1\;clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0\;mov %D0,%B0"
4124 [(set_attr "length" "5,6")
4125 (set_attr "cc" "set_n,set_n")])
4126
4127 (define_insn "extendhipsi2"
4128 [(set (match_operand:PSI 0 "register_operand" "=r,r ,r")
4129 (sign_extend:PSI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r,*r")))]
4130 ""
4131 "@
4132 clr %C0\;sbrc %B0,7\;com %C0
4133 mov %A0,%A1\;mov %B0,%B1\;clr %C0\;sbrc %B0,7\;com %C0
4134 movw %A0,%A1\;clr %C0\;sbrc %B0,7\;com %C0"
4135 [(set_attr "length" "3,5,4")
4136 (set_attr "isa" "*,mov,movw")
4137 (set_attr "cc" "set_n")])
4138
4139 (define_insn "extendhisi2"
4140 [(set (match_operand:SI 0 "register_operand" "=r,r ,r")
4141 (sign_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r,*r")))]
4142 ""
4143 "@
4144 clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0
4145 mov %A0,%A1\;mov %B0,%B1\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0
4146 movw %A0,%A1\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0"
4147 [(set_attr "length" "4,6,5")
4148 (set_attr "isa" "*,mov,movw")
4149 (set_attr "cc" "set_n")])
4150
4151 (define_insn "extendpsisi2"
4152 [(set (match_operand:SI 0 "register_operand" "=r")
4153 (sign_extend:SI (match_operand:PSI 1 "combine_pseudo_register_operand" "0")))]
4154 ""
4155 "clr %D0\;sbrc %C0,7\;com %D0"
4156 [(set_attr "length" "3")
4157 (set_attr "cc" "set_n")])
4158
4159 ;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
4160 ;; zero extend
4161
4162 (define_insn_and_split "zero_extendqihi2"
4163 [(set (match_operand:HI 0 "register_operand" "=r")
4164 (zero_extend:HI (match_operand:QI 1 "combine_pseudo_register_operand" "r")))]
4165 ""
4166 "#"
4167 "reload_completed"
4168 [(set (match_dup 2) (match_dup 1))
4169 (set (match_dup 3) (const_int 0))]
4170 {
4171 unsigned int low_off = subreg_lowpart_offset (QImode, HImode);
4172 unsigned int high_off = subreg_highpart_offset (QImode, HImode);
4173
4174 operands[2] = simplify_gen_subreg (QImode, operands[0], HImode, low_off);
4175 operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, high_off);
4176 })
4177
4178 (define_insn_and_split "zero_extendqipsi2"
4179 [(set (match_operand:PSI 0 "register_operand" "=r")
4180 (zero_extend:PSI (match_operand:QI 1 "combine_pseudo_register_operand" "r")))]
4181 ""
4182 "#"
4183 "reload_completed"
4184 [(set (match_dup 2) (match_dup 1))
4185 (set (match_dup 3) (const_int 0))
4186 (set (match_dup 4) (const_int 0))]
4187 {
4188 operands[2] = simplify_gen_subreg (QImode, operands[0], PSImode, 0);
4189 operands[3] = simplify_gen_subreg (QImode, operands[0], PSImode, 1);
4190 operands[4] = simplify_gen_subreg (QImode, operands[0], PSImode, 2);
4191 })
4192
4193 (define_insn_and_split "zero_extendqisi2"
4194 [(set (match_operand:SI 0 "register_operand" "=r")
4195 (zero_extend:SI (match_operand:QI 1 "combine_pseudo_register_operand" "r")))]
4196 ""
4197 "#"
4198 "reload_completed"
4199 [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
4200 (set (match_dup 3) (const_int 0))]
4201 {
4202 unsigned int low_off = subreg_lowpart_offset (HImode, SImode);
4203 unsigned int high_off = subreg_highpart_offset (HImode, SImode);
4204
4205 operands[2] = simplify_gen_subreg (HImode, operands[0], SImode, low_off);
4206 operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off);
4207 })
4208
4209 (define_insn_and_split "zero_extendhipsi2"
4210 [(set (match_operand:PSI 0 "register_operand" "=r")
4211 (zero_extend:PSI (match_operand:HI 1 "combine_pseudo_register_operand" "r")))]
4212 ""
4213 "#"
4214 "reload_completed"
4215 [(set (match_dup 2) (match_dup 1))
4216 (set (match_dup 3) (const_int 0))]
4217 {
4218 operands[2] = simplify_gen_subreg (HImode, operands[0], PSImode, 0);
4219 operands[3] = simplify_gen_subreg (QImode, operands[0], PSImode, 2);
4220 })
4221
4222 (define_insn_and_split "n_extendhipsi2"
4223 [(set (match_operand:PSI 0 "register_operand" "=r,r,d,r")
4224 (lo_sum:PSI (match_operand:QI 1 "const_int_operand" "L,P,n,n")
4225 (match_operand:HI 2 "register_operand" "r,r,r,r")))
4226 (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
4227 ""
4228 "#"
4229 "reload_completed"
4230 [(set (match_dup 4) (match_dup 2))
4231 (set (match_dup 3) (match_dup 6))
4232 ; no-op move in the case where no scratch is needed
4233 (set (match_dup 5) (match_dup 3))]
4234 {
4235 operands[4] = simplify_gen_subreg (HImode, operands[0], PSImode, 0);
4236 operands[5] = simplify_gen_subreg (QImode, operands[0], PSImode, 2);
4237 operands[6] = operands[1];
4238
4239 if (GET_CODE (operands[3]) == SCRATCH)
4240 operands[3] = operands[5];
4241 })
4242
4243 (define_insn_and_split "zero_extendhisi2"
4244 [(set (match_operand:SI 0 "register_operand" "=r")
4245 (zero_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "r")))]
4246 ""
4247 "#"
4248 "reload_completed"
4249 [(set (match_dup 2) (match_dup 1))
4250 (set (match_dup 3) (const_int 0))]
4251 {
4252 unsigned int low_off = subreg_lowpart_offset (HImode, SImode);
4253 unsigned int high_off = subreg_highpart_offset (HImode, SImode);
4254
4255 operands[2] = simplify_gen_subreg (HImode, operands[0], SImode, low_off);
4256 operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off);
4257 })
4258
4259 (define_insn_and_split "zero_extendpsisi2"
4260 [(set (match_operand:SI 0 "register_operand" "=r")
4261 (zero_extend:SI (match_operand:PSI 1 "combine_pseudo_register_operand" "r")))]
4262 ""
4263 "#"
4264 "reload_completed"
4265 [(set (match_dup 2) (match_dup 1))
4266 (set (match_dup 3) (const_int 0))]
4267 {
4268 operands[2] = simplify_gen_subreg (PSImode, operands[0], SImode, 0);
4269 operands[3] = simplify_gen_subreg (QImode, operands[0], SImode, 3);
4270 })
4271
4272 (define_insn_and_split "zero_extendqidi2"
4273 [(set (match_operand:DI 0 "register_operand" "=r")
4274 (zero_extend:DI (match_operand:QI 1 "register_operand" "r")))]
4275 ""
4276 "#"
4277 "reload_completed"
4278 [(set (match_dup 2) (zero_extend:SI (match_dup 1)))
4279 (set (match_dup 3) (const_int 0))]
4280 {
4281 unsigned int low_off = subreg_lowpart_offset (SImode, DImode);
4282 unsigned int high_off = subreg_highpart_offset (SImode, DImode);
4283
4284 operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off);
4285 operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off);
4286 })
4287
4288 (define_insn_and_split "zero_extendhidi2"
4289 [(set (match_operand:DI 0 "register_operand" "=r")
4290 (zero_extend:DI (match_operand:HI 1 "register_operand" "r")))]
4291 ""
4292 "#"
4293 "reload_completed"
4294 [(set (match_dup 2) (zero_extend:SI (match_dup 1)))
4295 (set (match_dup 3) (const_int 0))]
4296 {
4297 unsigned int low_off = subreg_lowpart_offset (SImode, DImode);
4298 unsigned int high_off = subreg_highpart_offset (SImode, DImode);
4299
4300 operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off);
4301 operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off);
4302 })
4303
4304 (define_insn_and_split "zero_extendsidi2"
4305 [(set (match_operand:DI 0 "register_operand" "=r")
4306 (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
4307 ""
4308 "#"
4309 "reload_completed"
4310 [(set (match_dup 2) (match_dup 1))
4311 (set (match_dup 3) (const_int 0))]
4312 {
4313 unsigned int low_off = subreg_lowpart_offset (SImode, DImode);
4314 unsigned int high_off = subreg_highpart_offset (SImode, DImode);
4315
4316 operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off);
4317 operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off);
4318 })
4319
4320 ;;<=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=>
4321 ;; compare
4322
4323 ; Optimize negated tests into reverse compare if overflow is undefined.
4324 (define_insn "*negated_tstqi"
4325 [(set (cc0)
4326 (compare (neg:QI (match_operand:QI 0 "register_operand" "r"))
4327 (const_int 0)))]
4328 "!flag_wrapv && !flag_trapv && flag_strict_overflow"
4329 "cp __zero_reg__,%0"
4330 [(set_attr "cc" "compare")
4331 (set_attr "length" "1")])
4332
4333 (define_insn "*reversed_tstqi"
4334 [(set (cc0)
4335 (compare (const_int 0)
4336 (match_operand:QI 0 "register_operand" "r")))]
4337 ""
4338 "cp __zero_reg__,%0"
4339 [(set_attr "cc" "compare")
4340 (set_attr "length" "2")])
4341
4342 (define_insn "*negated_tsthi"
4343 [(set (cc0)
4344 (compare (neg:HI (match_operand:HI 0 "register_operand" "r"))
4345 (const_int 0)))]
4346 "!flag_wrapv && !flag_trapv && flag_strict_overflow"
4347 "cp __zero_reg__,%A0
4348 cpc __zero_reg__,%B0"
4349 [(set_attr "cc" "compare")
4350 (set_attr "length" "2")])
4351
4352 ;; Leave here the clobber used by the cmphi pattern for simplicity, even
4353 ;; though it is unused, because this pattern is synthesized by avr_reorg.
4354 (define_insn "*reversed_tsthi"
4355 [(set (cc0)
4356 (compare (const_int 0)
4357 (match_operand:HI 0 "register_operand" "r")))
4358 (clobber (match_scratch:QI 1 "=X"))]
4359 ""
4360 "cp __zero_reg__,%A0
4361 cpc __zero_reg__,%B0"
4362 [(set_attr "cc" "compare")
4363 (set_attr "length" "2")])
4364
4365 (define_insn "*negated_tstpsi"
4366 [(set (cc0)
4367 (compare (neg:PSI (match_operand:PSI 0 "register_operand" "r"))
4368 (const_int 0)))]
4369 "!flag_wrapv && !flag_trapv && flag_strict_overflow"
4370 "cp __zero_reg__,%A0\;cpc __zero_reg__,%B0\;cpc __zero_reg__,%C0"
4371 [(set_attr "cc" "compare")
4372 (set_attr "length" "3")])
4373
4374 (define_insn "*reversed_tstpsi"
4375 [(set (cc0)
4376 (compare (const_int 0)
4377 (match_operand:PSI 0 "register_operand" "r")))
4378 (clobber (match_scratch:QI 1 "=X"))]
4379 ""
4380 "cp __zero_reg__,%A0\;cpc __zero_reg__,%B0\;cpc __zero_reg__,%C0"
4381 [(set_attr "cc" "compare")
4382 (set_attr "length" "3")])
4383
4384 (define_insn "*negated_tstsi"
4385 [(set (cc0)
4386 (compare (neg:SI (match_operand:SI 0 "register_operand" "r"))
4387 (const_int 0)))]
4388 "!flag_wrapv && !flag_trapv && flag_strict_overflow"
4389 "cp __zero_reg__,%A0
4390 cpc __zero_reg__,%B0
4391 cpc __zero_reg__,%C0
4392 cpc __zero_reg__,%D0"
4393 [(set_attr "cc" "compare")
4394 (set_attr "length" "4")])
4395
4396 ;; "*reversed_tstsi"
4397 ;; "*reversed_tstsq" "*reversed_tstusq"
4398 ;; "*reversed_tstsa" "*reversed_tstusa"
4399 (define_insn "*reversed_tst<mode>"
4400 [(set (cc0)
4401 (compare (match_operand:ALL4 0 "const0_operand" "Y00")
4402 (match_operand:ALL4 1 "register_operand" "r")))
4403 (clobber (match_scratch:QI 2 "=X"))]
4404 ""
4405 "cp __zero_reg__,%A1
4406 cpc __zero_reg__,%B1
4407 cpc __zero_reg__,%C1
4408 cpc __zero_reg__,%D1"
4409 [(set_attr "cc" "compare")
4410 (set_attr "length" "4")])
4411
4412
4413 ;; "*cmpqi"
4414 ;; "*cmpqq" "*cmpuqq"
4415 (define_insn "*cmp<mode>"
4416 [(set (cc0)
4417 (compare (match_operand:ALL1 0 "register_operand" "r ,r,d")
4418 (match_operand:ALL1 1 "nonmemory_operand" "Y00,r,i")))]
4419 ""
4420 "@
4421 tst %0
4422 cp %0,%1
4423 cpi %0,lo8(%1)"
4424 [(set_attr "cc" "compare,compare,compare")
4425 (set_attr "length" "1,1,1")])
4426
4427 (define_insn "*cmpqi_sign_extend"
4428 [(set (cc0)
4429 (compare (sign_extend:HI (match_operand:QI 0 "register_operand" "d"))
4430 (match_operand:HI 1 "s8_operand" "n")))]
4431 ""
4432 "cpi %0,lo8(%1)"
4433 [(set_attr "cc" "compare")
4434 (set_attr "length" "1")])
4435
4436 ;; "*cmphi"
4437 ;; "*cmphq" "*cmpuhq"
4438 ;; "*cmpha" "*cmpuha"
4439 (define_insn "*cmp<mode>"
4440 [(set (cc0)
4441 (compare (match_operand:ALL2 0 "register_operand" "!w ,r ,r,d ,r ,d,r")
4442 (match_operand:ALL2 1 "nonmemory_operand" "Y00,Y00,r,s ,s ,M,n Ynn")))
4443 (clobber (match_scratch:QI 2 "=X ,X ,X,&d,&d ,X,&d"))]
4444 ""
4445 {
4446 switch (which_alternative)
4447 {
4448 case 0:
4449 case 1:
4450 return avr_out_tsthi (insn, operands, NULL);
4451
4452 case 2:
4453 return "cp %A0,%A1\;cpc %B0,%B1";
4454
4455 case 3:
4456 if (<MODE>mode != HImode)
4457 break;
4458 return reg_unused_after (insn, operands[0])
4459 ? "subi %A0,lo8(%1)\;sbci %B0,hi8(%1)"
4460 : "ldi %2,hi8(%1)\;cpi %A0,lo8(%1)\;cpc %B0,%2";
4461
4462 case 4:
4463 if (<MODE>mode != HImode)
4464 break;
4465 return "ldi %2,lo8(%1)\;cp %A0,%2\;ldi %2,hi8(%1)\;cpc %B0,%2";
4466 }
4467
4468 return avr_out_compare (insn, operands, NULL);
4469 }
4470 [(set_attr "cc" "compare")
4471 (set_attr "length" "1,2,2,3,4,2,4")
4472 (set_attr "adjust_len" "tsthi,tsthi,*,*,*,compare,compare")])
4473
4474 (define_insn "*cmppsi"
4475 [(set (cc0)
4476 (compare (match_operand:PSI 0 "register_operand" "r,r,d ,r ,d,r")
4477 (match_operand:PSI 1 "nonmemory_operand" "L,r,s ,s ,M,n")))
4478 (clobber (match_scratch:QI 2 "=X,X,&d,&d ,X,&d"))]
4479 ""
4480 {
4481 switch (which_alternative)
4482 {
4483 case 0:
4484 return avr_out_tstpsi (insn, operands, NULL);
4485
4486 case 1:
4487 return "cp %A0,%A1\;cpc %B0,%B1\;cpc %C0,%C1";
4488
4489 case 2:
4490 return reg_unused_after (insn, operands[0])
4491 ? "subi %A0,lo8(%1)\;sbci %B0,hi8(%1)\;sbci %C0,hh8(%1)"
4492 : "cpi %A0,lo8(%1)\;ldi %2,hi8(%1)\;cpc %B0,%2\;ldi %2,hh8(%1)\;cpc %C0,%2";
4493
4494 case 3:
4495 return "ldi %2,lo8(%1)\;cp %A0,%2\;ldi %2,hi8(%1)\;cpc %B0,%2\;ldi %2,hh8(%1)\;cpc %C0,%2";
4496 }
4497
4498 return avr_out_compare (insn, operands, NULL);
4499 }
4500 [(set_attr "cc" "compare")
4501 (set_attr "length" "3,3,5,6,3,7")
4502 (set_attr "adjust_len" "tstpsi,*,*,*,compare,compare")])
4503
4504 ;; "*cmpsi"
4505 ;; "*cmpsq" "*cmpusq"
4506 ;; "*cmpsa" "*cmpusa"
4507 (define_insn "*cmp<mode>"
4508 [(set (cc0)
4509 (compare (match_operand:ALL4 0 "register_operand" "r ,r ,d,r ,r")
4510 (match_operand:ALL4 1 "nonmemory_operand" "Y00,r ,M,M ,n Ynn")))
4511 (clobber (match_scratch:QI 2 "=X ,X ,X,&d,&d"))]
4512 ""
4513 {
4514 if (0 == which_alternative)
4515 return avr_out_tstsi (insn, operands, NULL);
4516 else if (1 == which_alternative)
4517 return "cp %A0,%A1\;cpc %B0,%B1\;cpc %C0,%C1\;cpc %D0,%D1";
4518
4519 return avr_out_compare (insn, operands, NULL);
4520 }
4521 [(set_attr "cc" "compare")
4522 (set_attr "length" "4,4,4,5,8")
4523 (set_attr "adjust_len" "tstsi,*,compare,compare,compare")])
4524
4525
4526 ;; ----------------------------------------------------------------------
4527 ;; JUMP INSTRUCTIONS
4528 ;; ----------------------------------------------------------------------
4529 ;; Conditional jump instructions
4530
4531 ;; "cbranchqi4"
4532 ;; "cbranchqq4" "cbranchuqq4"
4533 (define_expand "cbranch<mode>4"
4534 [(set (cc0)
4535 (compare (match_operand:ALL1 1 "register_operand" "")
4536 (match_operand:ALL1 2 "nonmemory_operand" "")))
4537 (set (pc)
4538 (if_then_else
4539 (match_operator 0 "ordered_comparison_operator" [(cc0)
4540 (const_int 0)])
4541 (label_ref (match_operand 3 "" ""))
4542 (pc)))])
4543
4544 ;; "cbranchhi4" "cbranchhq4" "cbranchuhq4" "cbranchha4" "cbranchuha4"
4545 ;; "cbranchsi4" "cbranchsq4" "cbranchusq4" "cbranchsa4" "cbranchusa4"
4546 ;; "cbranchpsi4"
4547 (define_expand "cbranch<mode>4"
4548 [(parallel [(set (cc0)
4549 (compare (match_operand:ORDERED234 1 "register_operand" "")
4550 (match_operand:ORDERED234 2 "nonmemory_operand" "")))
4551 (clobber (match_scratch:QI 4 ""))])
4552 (set (pc)
4553 (if_then_else
4554 (match_operator 0 "ordered_comparison_operator" [(cc0)
4555 (const_int 0)])
4556 (label_ref (match_operand 3 "" ""))
4557 (pc)))])
4558
4559
4560 ;; Test a single bit in a QI/HI/SImode register.
4561 ;; Combine will create zero extract patterns for single bit tests.
4562 ;; permit any mode in source pattern by using VOIDmode.
4563
4564 (define_insn "*sbrx_branch<mode>"
4565 [(set (pc)
4566 (if_then_else
4567 (match_operator 0 "eqne_operator"
4568 [(zero_extract:QIDI
4569 (match_operand:VOID 1 "register_operand" "r")
4570 (const_int 1)
4571 (match_operand 2 "const_int_operand" "n"))
4572 (const_int 0)])
4573 (label_ref (match_operand 3 "" ""))
4574 (pc)))]
4575 ""
4576 {
4577 return avr_out_sbxx_branch (insn, operands);
4578 }
4579 [(set (attr "length")
4580 (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
4581 (le (minus (pc) (match_dup 3)) (const_int 2046)))
4582 (const_int 2)
4583 (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
4584 (const_int 2)
4585 (const_int 4))))
4586 (set_attr "cc" "clobber")])
4587
4588 ;; Same test based on bitwise AND. Keep this in case gcc changes patterns.
4589 ;; or for old peepholes.
4590 ;; Fixme - bitwise Mask will not work for DImode
4591
4592 (define_insn "*sbrx_and_branch<mode>"
4593 [(set (pc)
4594 (if_then_else
4595 (match_operator 0 "eqne_operator"
4596 [(and:QISI
4597 (match_operand:QISI 1 "register_operand" "r")
4598 (match_operand:QISI 2 "single_one_operand" "n"))
4599 (const_int 0)])
4600 (label_ref (match_operand 3 "" ""))
4601 (pc)))]
4602 ""
4603 {
4604 HOST_WIDE_INT bitnumber;
4605 bitnumber = exact_log2 (GET_MODE_MASK (<MODE>mode) & INTVAL (operands[2]));
4606 operands[2] = GEN_INT (bitnumber);
4607 return avr_out_sbxx_branch (insn, operands);
4608 }
4609 [(set (attr "length")
4610 (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
4611 (le (minus (pc) (match_dup 3)) (const_int 2046)))
4612 (const_int 2)
4613 (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
4614 (const_int 2)
4615 (const_int 4))))
4616 (set_attr "cc" "clobber")])
4617
4618 ;; Convert sign tests to bit 7/15/31 tests that match the above insns.
4619 (define_peephole2
4620 [(set (cc0) (compare (match_operand:QI 0 "register_operand" "")
4621 (const_int 0)))
4622 (set (pc) (if_then_else (ge (cc0) (const_int 0))
4623 (label_ref (match_operand 1 "" ""))
4624 (pc)))]
4625 ""
4626 [(set (pc) (if_then_else (eq (zero_extract:HI (match_dup 0)
4627 (const_int 1)
4628 (const_int 7))
4629 (const_int 0))
4630 (label_ref (match_dup 1))
4631 (pc)))])
4632
4633 (define_peephole2
4634 [(set (cc0) (compare (match_operand:QI 0 "register_operand" "")
4635 (const_int 0)))
4636 (set (pc) (if_then_else (lt (cc0) (const_int 0))
4637 (label_ref (match_operand 1 "" ""))
4638 (pc)))]
4639 ""
4640 [(set (pc) (if_then_else (ne (zero_extract:HI (match_dup 0)
4641 (const_int 1)
4642 (const_int 7))
4643 (const_int 0))
4644 (label_ref (match_dup 1))
4645 (pc)))])
4646
4647 (define_peephole2
4648 [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "")
4649 (const_int 0)))
4650 (clobber (match_operand:HI 2 ""))])
4651 (set (pc) (if_then_else (ge (cc0) (const_int 0))
4652 (label_ref (match_operand 1 "" ""))
4653 (pc)))]
4654 ""
4655 [(set (pc) (if_then_else (eq (and:HI (match_dup 0) (const_int -32768))
4656 (const_int 0))
4657 (label_ref (match_dup 1))
4658 (pc)))])
4659
4660 (define_peephole2
4661 [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "")
4662 (const_int 0)))
4663 (clobber (match_operand:HI 2 ""))])
4664 (set (pc) (if_then_else (lt (cc0) (const_int 0))
4665 (label_ref (match_operand 1 "" ""))
4666 (pc)))]
4667 ""
4668 [(set (pc) (if_then_else (ne (and:HI (match_dup 0) (const_int -32768))
4669 (const_int 0))
4670 (label_ref (match_dup 1))
4671 (pc)))])
4672
4673 (define_peephole2
4674 [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
4675 (const_int 0)))
4676 (clobber (match_operand:SI 2 ""))])
4677 (set (pc) (if_then_else (ge (cc0) (const_int 0))
4678 (label_ref (match_operand 1 "" ""))
4679 (pc)))]
4680 ""
4681 [(set (pc) (if_then_else (eq (and:SI (match_dup 0) (match_dup 2))
4682 (const_int 0))
4683 (label_ref (match_dup 1))
4684 (pc)))]
4685 "operands[2] = gen_int_mode (-2147483647 - 1, SImode);")
4686
4687 (define_peephole2
4688 [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
4689 (const_int 0)))
4690 (clobber (match_operand:SI 2 ""))])
4691 (set (pc) (if_then_else (lt (cc0) (const_int 0))
4692 (label_ref (match_operand 1 "" ""))
4693 (pc)))]
4694 ""
4695 [(set (pc) (if_then_else (ne (and:SI (match_dup 0) (match_dup 2))
4696 (const_int 0))
4697 (label_ref (match_dup 1))
4698 (pc)))]
4699 "operands[2] = gen_int_mode (-2147483647 - 1, SImode);")
4700
4701 ;; ************************************************************************
4702 ;; Implementation of conditional jumps here.
4703 ;; Compare with 0 (test) jumps
4704 ;; ************************************************************************
4705
4706 (define_insn "branch"
4707 [(set (pc)
4708 (if_then_else (match_operator 1 "simple_comparison_operator"
4709 [(cc0)
4710 (const_int 0)])
4711 (label_ref (match_operand 0 "" ""))
4712 (pc)))]
4713 ""
4714 {
4715 return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 0);
4716 }
4717 [(set_attr "type" "branch")
4718 (set_attr "cc" "clobber")])
4719
4720
4721 ;; Same as above but wrap SET_SRC so that this branch won't be transformed
4722 ;; or optimized in the remainder.
4723
4724 (define_insn "branch_unspec"
4725 [(set (pc)
4726 (unspec [(if_then_else (match_operator 1 "simple_comparison_operator"
4727 [(cc0)
4728 (const_int 0)])
4729 (label_ref (match_operand 0 "" ""))
4730 (pc))
4731 ] UNSPEC_IDENTITY))]
4732 ""
4733 {
4734 return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 0);
4735 }
4736 [(set_attr "type" "branch")
4737 (set_attr "cc" "none")])
4738
4739 ;; ****************************************************************
4740 ;; AVR does not have following conditional jumps: LE,LEU,GT,GTU.
4741 ;; Convert them all to proper jumps.
4742 ;; ****************************************************************/
4743
4744 (define_insn "difficult_branch"
4745 [(set (pc)
4746 (if_then_else (match_operator 1 "difficult_comparison_operator"
4747 [(cc0)
4748 (const_int 0)])
4749 (label_ref (match_operand 0 "" ""))
4750 (pc)))]
4751 ""
4752 {
4753 return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 0);
4754 }
4755 [(set_attr "type" "branch1")
4756 (set_attr "cc" "clobber")])
4757
4758 ;; revers branch
4759
4760 (define_insn "rvbranch"
4761 [(set (pc)
4762 (if_then_else (match_operator 1 "simple_comparison_operator"
4763 [(cc0)
4764 (const_int 0)])
4765 (pc)
4766 (label_ref (match_operand 0 "" ""))))]
4767 ""
4768 {
4769 return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 1);
4770 }
4771 [(set_attr "type" "branch1")
4772 (set_attr "cc" "clobber")])
4773
4774 (define_insn "difficult_rvbranch"
4775 [(set (pc)
4776 (if_then_else (match_operator 1 "difficult_comparison_operator"
4777 [(cc0)
4778 (const_int 0)])
4779 (pc)
4780 (label_ref (match_operand 0 "" ""))))]
4781 ""
4782 {
4783 return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 1);
4784 }
4785 [(set_attr "type" "branch")
4786 (set_attr "cc" "clobber")])
4787
4788 ;; **************************************************************************
4789 ;; Unconditional and other jump instructions.
4790
4791 (define_insn "jump"
4792 [(set (pc)
4793 (label_ref (match_operand 0 "" "")))]
4794 ""
4795 {
4796 return AVR_HAVE_JMP_CALL && get_attr_length (insn) != 1
4797 ? "jmp %x0"
4798 : "rjmp %x0";
4799 }
4800 [(set (attr "length")
4801 (if_then_else (match_operand 0 "symbol_ref_operand" "")
4802 (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
4803 (const_int 1)
4804 (const_int 2))
4805 (if_then_else (and (ge (minus (pc) (match_dup 0)) (const_int -2047))
4806 (le (minus (pc) (match_dup 0)) (const_int 2047)))
4807 (const_int 1)
4808 (const_int 2))))
4809 (set_attr "cc" "none")])
4810
4811 ;; call
4812
4813 ;; Operand 1 not used on the AVR.
4814 ;; Operand 2 is 1 for tail-call, 0 otherwise.
4815 (define_expand "call"
4816 [(parallel[(call (match_operand:HI 0 "call_insn_operand" "")
4817 (match_operand:HI 1 "general_operand" ""))
4818 (use (const_int 0))])])
4819
4820 ;; Operand 1 not used on the AVR.
4821 ;; Operand 2 is 1 for tail-call, 0 otherwise.
4822 (define_expand "sibcall"
4823 [(parallel[(call (match_operand:HI 0 "call_insn_operand" "")
4824 (match_operand:HI 1 "general_operand" ""))
4825 (use (const_int 1))])])
4826
4827 ;; call value
4828
4829 ;; Operand 2 not used on the AVR.
4830 ;; Operand 3 is 1 for tail-call, 0 otherwise.
4831 (define_expand "call_value"
4832 [(parallel[(set (match_operand 0 "register_operand" "")
4833 (call (match_operand:HI 1 "call_insn_operand" "")
4834 (match_operand:HI 2 "general_operand" "")))
4835 (use (const_int 0))])])
4836
4837 ;; Operand 2 not used on the AVR.
4838 ;; Operand 3 is 1 for tail-call, 0 otherwise.
4839 (define_expand "sibcall_value"
4840 [(parallel[(set (match_operand 0 "register_operand" "")
4841 (call (match_operand:HI 1 "call_insn_operand" "")
4842 (match_operand:HI 2 "general_operand" "")))
4843 (use (const_int 1))])])
4844
4845 (define_insn "call_insn"
4846 [(parallel[(call (mem:HI (match_operand:HI 0 "nonmemory_operand" "z,s,z,s"))
4847 (match_operand:HI 1 "general_operand" "X,X,X,X"))
4848 (use (match_operand:HI 2 "const_int_operand" "L,L,P,P"))])]
4849 ;; Operand 1 not used on the AVR.
4850 ;; Operand 2 is 1 for tail-call, 0 otherwise.
4851 ""
4852 "@
4853 %!icall
4854 %~call %x0
4855 %!ijmp
4856 %~jmp %x0"
4857 [(set_attr "cc" "clobber")
4858 (set_attr "length" "1,*,1,*")
4859 (set_attr "adjust_len" "*,call,*,call")])
4860
4861 (define_insn "call_value_insn"
4862 [(parallel[(set (match_operand 0 "register_operand" "=r,r,r,r")
4863 (call (mem:HI (match_operand:HI 1 "nonmemory_operand" "z,s,z,s"))
4864 (match_operand:HI 2 "general_operand" "X,X,X,X")))
4865 (use (match_operand:HI 3 "const_int_operand" "L,L,P,P"))])]
4866 ;; Operand 2 not used on the AVR.
4867 ;; Operand 3 is 1 for tail-call, 0 otherwise.
4868 ""
4869 "@
4870 %!icall
4871 %~call %x1
4872 %!ijmp
4873 %~jmp %x1"
4874 [(set_attr "cc" "clobber")
4875 (set_attr "length" "1,*,1,*")
4876 (set_attr "adjust_len" "*,call,*,call")])
4877
4878 (define_insn "nop"
4879 [(const_int 0)]
4880 ""
4881 "nop"
4882 [(set_attr "cc" "none")
4883 (set_attr "length" "1")])
4884
4885 ; indirect jump
4886
4887 (define_expand "indirect_jump"
4888 [(set (pc)
4889 (match_operand:HI 0 "nonmemory_operand" ""))]
4890 ""
4891 {
4892 if (!AVR_HAVE_JMP_CALL && !register_operand (operands[0], HImode))
4893 {
4894 operands[0] = copy_to_mode_reg (HImode, operands[0]);
4895 }
4896 })
4897
4898 ; indirect jump
4899 (define_insn "*indirect_jump"
4900 [(set (pc)
4901 (match_operand:HI 0 "nonmemory_operand" "i,i,!z,*r,z"))]
4902 ""
4903 "@
4904 rjmp %x0
4905 jmp %x0
4906 ijmp
4907 push %A0\;push %B0\;ret
4908 eijmp"
4909 [(set_attr "length" "1,2,1,3,1")
4910 (set_attr "isa" "rjmp,jmp,ijmp,ijmp,eijmp")
4911 (set_attr "cc" "none")])
4912
4913 ;; table jump
4914 ;; For entries in jump table see avr_output_addr_vec_elt.
4915
4916 ;; Table made from
4917 ;; "rjmp .L<n>" instructions for <= 8K devices
4918 ;; ".word gs(.L<n>)" addresses for > 8K devices
4919 (define_insn "*tablejump"
4920 [(set (pc)
4921 (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r,z")]
4922 UNSPEC_INDEX_JMP))
4923 (use (label_ref (match_operand 1 "" "")))
4924 (clobber (match_dup 0))]
4925 ""
4926 "@
4927 ijmp
4928 push %A0\;push %B0\;ret
4929 jmp __tablejump2__"
4930 [(set_attr "length" "1,3,2")
4931 (set_attr "isa" "rjmp,rjmp,jmp")
4932 (set_attr "cc" "none,none,clobber")])
4933
4934
4935 (define_expand "casesi"
4936 [(parallel [(set (match_dup 6)
4937 (minus:HI (subreg:HI (match_operand:SI 0 "register_operand" "") 0)
4938 (match_operand:HI 1 "register_operand" "")))
4939 (clobber (scratch:QI))])
4940 (parallel [(set (cc0)
4941 (compare (match_dup 6)
4942 (match_operand:HI 2 "register_operand" "")))
4943 (clobber (match_scratch:QI 9 ""))])
4944
4945 (set (pc)
4946 (if_then_else (gtu (cc0)
4947 (const_int 0))
4948 (label_ref (match_operand 4 "" ""))
4949 (pc)))
4950
4951 (set (match_dup 6)
4952 (plus:HI (match_dup 6) (label_ref (match_operand:HI 3 "" ""))))
4953
4954 (parallel [(set (pc) (unspec:HI [(match_dup 6)] UNSPEC_INDEX_JMP))
4955 (use (label_ref (match_dup 3)))
4956 (clobber (match_dup 6))])]
4957 ""
4958 {
4959 operands[6] = gen_reg_rtx (HImode);
4960 })
4961
4962
4963 ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4964 ;; This instruction sets Z flag
4965
4966 (define_insn "sez"
4967 [(set (cc0) (const_int 0))]
4968 ""
4969 "sez"
4970 [(set_attr "length" "1")
4971 (set_attr "cc" "compare")])
4972
4973 ;; Clear/set/test a single bit in I/O address space.
4974
4975 (define_insn "*cbi"
4976 [(set (mem:QI (match_operand 0 "low_io_address_operand" "n"))
4977 (and:QI (mem:QI (match_dup 0))
4978 (match_operand:QI 1 "single_zero_operand" "n")))]
4979 ""
4980 {
4981 operands[2] = GEN_INT (exact_log2 (~INTVAL (operands[1]) & 0xff));
4982 return "cbi %i0,%2";
4983 }
4984 [(set_attr "length" "1")
4985 (set_attr "cc" "none")])
4986
4987 (define_insn "*sbi"
4988 [(set (mem:QI (match_operand 0 "low_io_address_operand" "n"))
4989 (ior:QI (mem:QI (match_dup 0))
4990 (match_operand:QI 1 "single_one_operand" "n")))]
4991 ""
4992 {
4993 operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff));
4994 return "sbi %i0,%2";
4995 }
4996 [(set_attr "length" "1")
4997 (set_attr "cc" "none")])
4998
4999 ;; Lower half of the I/O space - use sbic/sbis directly.
5000 (define_insn "*sbix_branch"
5001 [(set (pc)
5002 (if_then_else
5003 (match_operator 0 "eqne_operator"
5004 [(zero_extract:QIHI
5005 (mem:QI (match_operand 1 "low_io_address_operand" "n"))
5006 (const_int 1)
5007 (match_operand 2 "const_int_operand" "n"))
5008 (const_int 0)])
5009 (label_ref (match_operand 3 "" ""))
5010 (pc)))]
5011 ""
5012 {
5013 return avr_out_sbxx_branch (insn, operands);
5014 }
5015 [(set (attr "length")
5016 (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
5017 (le (minus (pc) (match_dup 3)) (const_int 2046)))
5018 (const_int 2)
5019 (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
5020 (const_int 2)
5021 (const_int 4))))
5022 (set_attr "cc" "clobber")])
5023
5024 ;; Tests of bit 7 are pessimized to sign tests, so we need this too...
5025 (define_insn "*sbix_branch_bit7"
5026 [(set (pc)
5027 (if_then_else
5028 (match_operator 0 "gelt_operator"
5029 [(mem:QI (match_operand 1 "low_io_address_operand" "n"))
5030 (const_int 0)])
5031 (label_ref (match_operand 2 "" ""))
5032 (pc)))]
5033 ""
5034 {
5035 operands[3] = operands[2];
5036 operands[2] = GEN_INT (7);
5037 return avr_out_sbxx_branch (insn, operands);
5038 }
5039 [(set (attr "length")
5040 (if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046))
5041 (le (minus (pc) (match_dup 2)) (const_int 2046)))
5042 (const_int 2)
5043 (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
5044 (const_int 2)
5045 (const_int 4))))
5046 (set_attr "cc" "clobber")])
5047
5048 ;; Upper half of the I/O space - read port to __tmp_reg__ and use sbrc/sbrs.
5049 (define_insn "*sbix_branch_tmp"
5050 [(set (pc)
5051 (if_then_else
5052 (match_operator 0 "eqne_operator"
5053 [(zero_extract:QIHI
5054 (mem:QI (match_operand 1 "high_io_address_operand" "n"))
5055 (const_int 1)
5056 (match_operand 2 "const_int_operand" "n"))
5057 (const_int 0)])
5058 (label_ref (match_operand 3 "" ""))
5059 (pc)))]
5060 ""
5061 {
5062 return avr_out_sbxx_branch (insn, operands);
5063 }
5064 [(set (attr "length")
5065 (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
5066 (le (minus (pc) (match_dup 3)) (const_int 2045)))
5067 (const_int 3)
5068 (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
5069 (const_int 3)
5070 (const_int 5))))
5071 (set_attr "cc" "clobber")])
5072
5073 (define_insn "*sbix_branch_tmp_bit7"
5074 [(set (pc)
5075 (if_then_else
5076 (match_operator 0 "gelt_operator"
5077 [(mem:QI (match_operand 1 "high_io_address_operand" "n"))
5078 (const_int 0)])
5079 (label_ref (match_operand 2 "" ""))
5080 (pc)))]
5081 ""
5082 {
5083 operands[3] = operands[2];
5084 operands[2] = GEN_INT (7);
5085 return avr_out_sbxx_branch (insn, operands);
5086 }
5087 [(set (attr "length")
5088 (if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046))
5089 (le (minus (pc) (match_dup 2)) (const_int 2045)))
5090 (const_int 3)
5091 (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
5092 (const_int 3)
5093 (const_int 5))))
5094 (set_attr "cc" "clobber")])
5095
5096 ;; ************************* Peepholes ********************************
5097
5098 (define_peephole ; "*dec-and-branchsi!=-1.d.clobber"
5099 [(parallel [(set (match_operand:SI 0 "d_register_operand" "")
5100 (plus:SI (match_dup 0)
5101 (const_int -1)))
5102 (clobber (scratch:QI))])
5103 (parallel [(set (cc0)
5104 (compare (match_dup 0)
5105 (const_int -1)))
5106 (clobber (match_operand:QI 1 "d_register_operand" ""))])
5107 (set (pc)
5108 (if_then_else (eqne (cc0)
5109 (const_int 0))
5110 (label_ref (match_operand 2 "" ""))
5111 (pc)))]
5112 ""
5113 {
5114 const char *op;
5115 int jump_mode;
5116 CC_STATUS_INIT;
5117 if (test_hard_reg_class (ADDW_REGS, operands[0]))
5118 output_asm_insn ("sbiw %0,1" CR_TAB
5119 "sbc %C0,__zero_reg__" CR_TAB
5120 "sbc %D0,__zero_reg__", operands);
5121 else
5122 output_asm_insn ("subi %A0,1" CR_TAB
5123 "sbc %B0,__zero_reg__" CR_TAB
5124 "sbc %C0,__zero_reg__" CR_TAB
5125 "sbc %D0,__zero_reg__", operands);
5126
5127 jump_mode = avr_jump_mode (operands[2], insn);
5128 op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs";
5129 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
5130
5131 switch (jump_mode)
5132 {
5133 case 1: return "%1 %2";
5134 case 2: return "%1 .+2\;rjmp %2";
5135 case 3: return "%1 .+4\;jmp %2";
5136 }
5137
5138 gcc_unreachable();
5139 return "";
5140 })
5141
5142 (define_peephole ; "*dec-and-branchhi!=-1"
5143 [(set (match_operand:HI 0 "d_register_operand" "")
5144 (plus:HI (match_dup 0)
5145 (const_int -1)))
5146 (parallel [(set (cc0)
5147 (compare (match_dup 0)
5148 (const_int -1)))
5149 (clobber (match_operand:QI 1 "d_register_operand" ""))])
5150 (set (pc)
5151 (if_then_else (eqne (cc0)
5152 (const_int 0))
5153 (label_ref (match_operand 2 "" ""))
5154 (pc)))]
5155 ""
5156 {
5157 const char *op;
5158 int jump_mode;
5159 CC_STATUS_INIT;
5160 if (test_hard_reg_class (ADDW_REGS, operands[0]))
5161 output_asm_insn ("sbiw %0,1", operands);
5162 else
5163 output_asm_insn ("subi %A0,1" CR_TAB
5164 "sbc %B0,__zero_reg__", operands);
5165
5166 jump_mode = avr_jump_mode (operands[2], insn);
5167 op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs";
5168 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
5169
5170 switch (jump_mode)
5171 {
5172 case 1: return "%1 %2";
5173 case 2: return "%1 .+2\;rjmp %2";
5174 case 3: return "%1 .+4\;jmp %2";
5175 }
5176
5177 gcc_unreachable();
5178 return "";
5179 })
5180
5181 ;; Same as above but with clobber flavour of addhi3
5182 (define_peephole ; "*dec-and-branchhi!=-1.d.clobber"
5183 [(parallel [(set (match_operand:HI 0 "d_register_operand" "")
5184 (plus:HI (match_dup 0)
5185 (const_int -1)))
5186 (clobber (scratch:QI))])
5187 (parallel [(set (cc0)
5188 (compare (match_dup 0)
5189 (const_int -1)))
5190 (clobber (match_operand:QI 1 "d_register_operand" ""))])
5191 (set (pc)
5192 (if_then_else (eqne (cc0)
5193 (const_int 0))
5194 (label_ref (match_operand 2 "" ""))
5195 (pc)))]
5196 ""
5197 {
5198 const char *op;
5199 int jump_mode;
5200 CC_STATUS_INIT;
5201 if (test_hard_reg_class (ADDW_REGS, operands[0]))
5202 output_asm_insn ("sbiw %0,1", operands);
5203 else
5204 output_asm_insn ("subi %A0,1" CR_TAB
5205 "sbc %B0,__zero_reg__", operands);
5206
5207 jump_mode = avr_jump_mode (operands[2], insn);
5208 op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs";
5209 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
5210
5211 switch (jump_mode)
5212 {
5213 case 1: return "%1 %2";
5214 case 2: return "%1 .+2\;rjmp %2";
5215 case 3: return "%1 .+4\;jmp %2";
5216 }
5217
5218 gcc_unreachable();
5219 return "";
5220 })
5221
5222 ;; Same as above but with clobber flavour of addhi3
5223 (define_peephole ; "*dec-and-branchhi!=-1.l.clobber"
5224 [(parallel [(set (match_operand:HI 0 "l_register_operand" "")
5225 (plus:HI (match_dup 0)
5226 (const_int -1)))
5227 (clobber (match_operand:QI 3 "d_register_operand" ""))])
5228 (parallel [(set (cc0)
5229 (compare (match_dup 0)
5230 (const_int -1)))
5231 (clobber (match_operand:QI 1 "d_register_operand" ""))])
5232 (set (pc)
5233 (if_then_else (eqne (cc0)
5234 (const_int 0))
5235 (label_ref (match_operand 2 "" ""))
5236 (pc)))]
5237 ""
5238 {
5239 const char *op;
5240 int jump_mode;
5241 CC_STATUS_INIT;
5242 output_asm_insn ("ldi %3,1" CR_TAB
5243 "sub %A0,%3" CR_TAB
5244 "sbc %B0,__zero_reg__", operands);
5245
5246 jump_mode = avr_jump_mode (operands[2], insn);
5247 op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs";
5248 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
5249
5250 switch (jump_mode)
5251 {
5252 case 1: return "%1 %2";
5253 case 2: return "%1 .+2\;rjmp %2";
5254 case 3: return "%1 .+4\;jmp %2";
5255 }
5256
5257 gcc_unreachable();
5258 return "";
5259 })
5260
5261 (define_peephole ; "*dec-and-branchqi!=-1"
5262 [(set (match_operand:QI 0 "d_register_operand" "")
5263 (plus:QI (match_dup 0)
5264 (const_int -1)))
5265 (set (cc0)
5266 (compare (match_dup 0)
5267 (const_int -1)))
5268 (set (pc)
5269 (if_then_else (eqne (cc0)
5270 (const_int 0))
5271 (label_ref (match_operand 1 "" ""))
5272 (pc)))]
5273 ""
5274 {
5275 const char *op;
5276 int jump_mode;
5277 CC_STATUS_INIT;
5278 cc_status.value1 = operands[0];
5279 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
5280
5281 output_asm_insn ("subi %A0,1", operands);
5282
5283 jump_mode = avr_jump_mode (operands[1], insn);
5284 op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs";
5285 operands[0] = gen_rtx_CONST_STRING (VOIDmode, op);
5286
5287 switch (jump_mode)
5288 {
5289 case 1: return "%0 %1";
5290 case 2: return "%0 .+2\;rjmp %1";
5291 case 3: return "%0 .+4\;jmp %1";
5292 }
5293
5294 gcc_unreachable();
5295 return "";
5296 })
5297
5298
5299 (define_peephole ; "*cpse.eq"
5300 [(set (cc0)
5301 (compare (match_operand:ALL1 1 "register_operand" "r,r")
5302 (match_operand:ALL1 2 "reg_or_0_operand" "r,Y00")))
5303 (set (pc)
5304 (if_then_else (eq (cc0)
5305 (const_int 0))
5306 (label_ref (match_operand 0 "" ""))
5307 (pc)))]
5308 "jump_over_one_insn_p (insn, operands[0])"
5309 "@
5310 cpse %1,%2
5311 cpse %1,__zero_reg__")
5312
5313 ;; This peephole avoids code like
5314 ;;
5315 ;; TST Rn ; *cmpqi
5316 ;; BREQ .+2 ; branch
5317 ;; RJMP .Lm
5318 ;;
5319 ;; Notice that the peephole is always shorter than cmpqi + branch.
5320 ;; The reason to write it as peephole is that sequences like
5321 ;;
5322 ;; AND Rm, Rn
5323 ;; BRNE .La
5324 ;;
5325 ;; shall not be superseeded. With a respective combine pattern
5326 ;; the latter sequence would be
5327 ;;
5328 ;; AND Rm, Rn
5329 ;; CPSE Rm, __zero_reg__
5330 ;; RJMP .La
5331 ;;
5332 ;; and thus longer and slower and not easy to be rolled back.
5333
5334 (define_peephole ; "*cpse.ne"
5335 [(set (cc0)
5336 (compare (match_operand:ALL1 1 "register_operand" "")
5337 (match_operand:ALL1 2 "reg_or_0_operand" "")))
5338 (set (pc)
5339 (if_then_else (ne (cc0)
5340 (const_int 0))
5341 (label_ref (match_operand 0 "" ""))
5342 (pc)))]
5343 "!AVR_HAVE_JMP_CALL
5344 || !avr_current_device->errata_skip"
5345 {
5346 if (operands[2] == CONST0_RTX (<MODE>mode))
5347 operands[2] = zero_reg_rtx;
5348
5349 return 3 == avr_jump_mode (operands[0], insn)
5350 ? "cpse %1,%2\;jmp %0"
5351 : "cpse %1,%2\;rjmp %0";
5352 })
5353
5354 ;;pppppppppppppppppppppppppppppppppppppppppppppppppppp
5355 ;;prologue/epilogue support instructions
5356
5357 (define_insn "popqi"
5358 [(set (match_operand:QI 0 "register_operand" "=r")
5359 (mem:QI (pre_inc:HI (reg:HI REG_SP))))]
5360 ""
5361 "pop %0"
5362 [(set_attr "cc" "none")
5363 (set_attr "length" "1")])
5364
5365 ;; Enable Interrupts
5366 (define_expand "enable_interrupt"
5367 [(clobber (const_int 0))]
5368 ""
5369 {
5370 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
5371 MEM_VOLATILE_P (mem) = 1;
5372 emit_insn (gen_cli_sei (const1_rtx, mem));
5373 DONE;
5374 })
5375
5376 ;; Disable Interrupts
5377 (define_expand "disable_interrupt"
5378 [(clobber (const_int 0))]
5379 ""
5380 {
5381 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
5382 MEM_VOLATILE_P (mem) = 1;
5383 emit_insn (gen_cli_sei (const0_rtx, mem));
5384 DONE;
5385 })
5386
5387 (define_insn "cli_sei"
5388 [(unspec_volatile [(match_operand:QI 0 "const_int_operand" "L,P")]
5389 UNSPECV_ENABLE_IRQS)
5390 (set (match_operand:BLK 1 "" "")
5391 (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))]
5392 ""
5393 "@
5394 cli
5395 sei"
5396 [(set_attr "length" "1")
5397 (set_attr "cc" "none")])
5398
5399 ;; Library prologue saves
5400 (define_insn "call_prologue_saves"
5401 [(unspec_volatile:HI [(const_int 0)] UNSPECV_PROLOGUE_SAVES)
5402 (match_operand:HI 0 "immediate_operand" "i,i")
5403 (set (reg:HI REG_SP)
5404 (minus:HI (reg:HI REG_SP)
5405 (match_operand:HI 1 "immediate_operand" "i,i")))
5406 (use (reg:HI REG_X))
5407 (clobber (reg:HI REG_Z))]
5408 ""
5409 "ldi r30,lo8(gs(1f))
5410 ldi r31,hi8(gs(1f))
5411 %~jmp __prologue_saves__+((18 - %0) * 2)
5412 1:"
5413 [(set_attr "length" "5,6")
5414 (set_attr "cc" "clobber")
5415 (set_attr "isa" "rjmp,jmp")])
5416
5417 ; epilogue restores using library
5418 (define_insn "epilogue_restores"
5419 [(unspec_volatile:QI [(const_int 0)] UNSPECV_EPILOGUE_RESTORES)
5420 (set (reg:HI REG_Y)
5421 (plus:HI (reg:HI REG_Y)
5422 (match_operand:HI 0 "immediate_operand" "i,i")))
5423 (set (reg:HI REG_SP)
5424 (plus:HI (reg:HI REG_Y)
5425 (match_dup 0)))
5426 (clobber (reg:QI REG_Z))]
5427 ""
5428 "ldi r30, lo8(%0)
5429 %~jmp __epilogue_restores__ + ((18 - %0) * 2)"
5430 [(set_attr "length" "2,3")
5431 (set_attr "cc" "clobber")
5432 (set_attr "isa" "rjmp,jmp")])
5433
5434 ; return
5435 (define_insn "return"
5436 [(return)]
5437 "reload_completed && avr_simple_epilogue ()"
5438 "ret"
5439 [(set_attr "cc" "none")
5440 (set_attr "length" "1")])
5441
5442 (define_insn "return_from_epilogue"
5443 [(return)]
5444 "reload_completed
5445 && cfun->machine
5446 && !(cfun->machine->is_interrupt || cfun->machine->is_signal)
5447 && !cfun->machine->is_naked"
5448 "ret"
5449 [(set_attr "cc" "none")
5450 (set_attr "length" "1")])
5451
5452 (define_insn "return_from_interrupt_epilogue"
5453 [(return)]
5454 "reload_completed
5455 && cfun->machine
5456 && (cfun->machine->is_interrupt || cfun->machine->is_signal)
5457 && !cfun->machine->is_naked"
5458 "reti"
5459 [(set_attr "cc" "none")
5460 (set_attr "length" "1")])
5461
5462 (define_insn "return_from_naked_epilogue"
5463 [(return)]
5464 "reload_completed
5465 && cfun->machine
5466 && cfun->machine->is_naked"
5467 ""
5468 [(set_attr "cc" "none")
5469 (set_attr "length" "0")])
5470
5471 (define_expand "prologue"
5472 [(const_int 0)]
5473 ""
5474 {
5475 expand_prologue ();
5476 DONE;
5477 })
5478
5479 (define_expand "epilogue"
5480 [(const_int 0)]
5481 ""
5482 {
5483 expand_epilogue (false /* sibcall_p */);
5484 DONE;
5485 })
5486
5487 (define_expand "sibcall_epilogue"
5488 [(const_int 0)]
5489 ""
5490 {
5491 expand_epilogue (true /* sibcall_p */);
5492 DONE;
5493 })
5494
5495 ;; Some instructions resp. instruction sequences available
5496 ;; via builtins.
5497
5498 (define_insn "delay_cycles_1"
5499 [(unspec_volatile [(match_operand:QI 0 "const_int_operand" "n")
5500 (const_int 1)]
5501 UNSPECV_DELAY_CYCLES)
5502 (set (match_operand:BLK 1 "" "")
5503 (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))
5504 (clobber (match_scratch:QI 2 "=&d"))]
5505 ""
5506 "ldi %2,lo8(%0)
5507 1: dec %2
5508 brne 1b"
5509 [(set_attr "length" "3")
5510 (set_attr "cc" "clobber")])
5511
5512 (define_insn "delay_cycles_2"
5513 [(unspec_volatile [(match_operand:HI 0 "const_int_operand" "n")
5514 (const_int 2)]
5515 UNSPECV_DELAY_CYCLES)
5516 (set (match_operand:BLK 1 "" "")
5517 (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))
5518 (clobber (match_scratch:HI 2 "=&w"))]
5519 ""
5520 "ldi %A2,lo8(%0)
5521 ldi %B2,hi8(%0)
5522 1: sbiw %A2,1
5523 brne 1b"
5524 [(set_attr "length" "4")
5525 (set_attr "cc" "clobber")])
5526
5527 (define_insn "delay_cycles_3"
5528 [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n")
5529 (const_int 3)]
5530 UNSPECV_DELAY_CYCLES)
5531 (set (match_operand:BLK 1 "" "")
5532 (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))
5533 (clobber (match_scratch:QI 2 "=&d"))
5534 (clobber (match_scratch:QI 3 "=&d"))
5535 (clobber (match_scratch:QI 4 "=&d"))]
5536 ""
5537 "ldi %2,lo8(%0)
5538 ldi %3,hi8(%0)
5539 ldi %4,hlo8(%0)
5540 1: subi %2,1
5541 sbci %3,0
5542 sbci %4,0
5543 brne 1b"
5544 [(set_attr "length" "7")
5545 (set_attr "cc" "clobber")])
5546
5547 (define_insn "delay_cycles_4"
5548 [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n")
5549 (const_int 4)]
5550 UNSPECV_DELAY_CYCLES)
5551 (set (match_operand:BLK 1 "" "")
5552 (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))
5553 (clobber (match_scratch:QI 2 "=&d"))
5554 (clobber (match_scratch:QI 3 "=&d"))
5555 (clobber (match_scratch:QI 4 "=&d"))
5556 (clobber (match_scratch:QI 5 "=&d"))]
5557 ""
5558 "ldi %2,lo8(%0)
5559 ldi %3,hi8(%0)
5560 ldi %4,hlo8(%0)
5561 ldi %5,hhi8(%0)
5562 1: subi %2,1
5563 sbci %3,0
5564 sbci %4,0
5565 sbci %5,0
5566 brne 1b"
5567 [(set_attr "length" "9")
5568 (set_attr "cc" "clobber")])
5569
5570
5571 ;; __builtin_avr_insert_bits
5572
5573 (define_insn "insert_bits"
5574 [(set (match_operand:QI 0 "register_operand" "=r ,d ,r")
5575 (unspec:QI [(match_operand:SI 1 "const_int_operand" "C0f,Cxf,C0f")
5576 (match_operand:QI 2 "register_operand" "r ,r ,r")
5577 (match_operand:QI 3 "nonmemory_operand" "n ,0 ,0")]
5578 UNSPEC_INSERT_BITS))]
5579 ""
5580 {
5581 return avr_out_insert_bits (operands, NULL);
5582 }
5583 [(set_attr "adjust_len" "insert_bits")
5584 (set_attr "cc" "clobber")])
5585
5586
5587 ;; __builtin_avr_flash_segment
5588
5589 ;; Just a helper for the next "official" expander.
5590
5591 (define_expand "flash_segment1"
5592 [(set (match_operand:QI 0 "register_operand" "")
5593 (subreg:QI (match_operand:PSI 1 "register_operand" "")
5594 2))
5595 (set (cc0)
5596 (compare (match_dup 0)
5597 (const_int 0)))
5598 (set (pc)
5599 (if_then_else (ge (cc0)
5600 (const_int 0))
5601 (label_ref (match_operand 2 "" ""))
5602 (pc)))
5603 (set (match_dup 0)
5604 (const_int -1))])
5605
5606 (define_expand "flash_segment"
5607 [(parallel [(match_operand:QI 0 "register_operand" "")
5608 (match_operand:PSI 1 "register_operand" "")])]
5609 ""
5610 {
5611 rtx label = gen_label_rtx ();
5612 emit (gen_flash_segment1 (operands[0], operands[1], label));
5613 emit_label (label);
5614 DONE;
5615 })
5616
5617 ;; Actually, it's too late now to work out address spaces known at compiletime.
5618 ;; Best place would be to fold ADDR_SPACE_CONVERT_EXPR in avr_fold_builtin.
5619 ;; However, avr_addr_space_convert can add some built-in knowledge for PSTR
5620 ;; so that ADDR_SPACE_CONVERT_EXPR in the built-in must not be resolved.
5621
5622 (define_insn_and_split "*split.flash_segment"
5623 [(set (match_operand:QI 0 "register_operand" "=d")
5624 (subreg:QI (lo_sum:PSI (match_operand:QI 1 "nonmemory_operand" "ri")
5625 (match_operand:HI 2 "register_operand" "r"))
5626 2))]
5627 ""
5628 { gcc_unreachable(); }
5629 ""
5630 [(set (match_dup 0)
5631 (match_dup 1))])
5632
5633
5634 ;; Parity
5635
5636 ;; Postpone expansion of 16-bit parity to libgcc call until after combine for
5637 ;; better 8-bit parity recognition.
5638
5639 (define_expand "parityhi2"
5640 [(parallel [(set (match_operand:HI 0 "register_operand" "")
5641 (parity:HI (match_operand:HI 1 "register_operand" "")))
5642 (clobber (reg:HI 24))])])
5643
5644 (define_insn_and_split "*parityhi2"
5645 [(set (match_operand:HI 0 "register_operand" "=r")
5646 (parity:HI (match_operand:HI 1 "register_operand" "r")))
5647 (clobber (reg:HI 24))]
5648 "!reload_completed"
5649 { gcc_unreachable(); }
5650 "&& 1"
5651 [(set (reg:HI 24)
5652 (match_dup 1))
5653 (set (reg:HI 24)
5654 (parity:HI (reg:HI 24)))
5655 (set (match_dup 0)
5656 (reg:HI 24))])
5657
5658 (define_insn_and_split "*parityqihi2"
5659 [(set (match_operand:HI 0 "register_operand" "=r")
5660 (parity:HI (match_operand:QI 1 "register_operand" "r")))
5661 (clobber (reg:HI 24))]
5662 "!reload_completed"
5663 { gcc_unreachable(); }
5664 "&& 1"
5665 [(set (reg:QI 24)
5666 (match_dup 1))
5667 (set (reg:HI 24)
5668 (zero_extend:HI (parity:QI (reg:QI 24))))
5669 (set (match_dup 0)
5670 (reg:HI 24))])
5671
5672 (define_expand "paritysi2"
5673 [(set (reg:SI 22)
5674 (match_operand:SI 1 "register_operand" ""))
5675 (set (reg:HI 24)
5676 (truncate:HI (parity:SI (reg:SI 22))))
5677 (set (match_dup 2)
5678 (reg:HI 24))
5679 (set (match_operand:SI 0 "register_operand" "")
5680 (zero_extend:SI (match_dup 2)))]
5681 ""
5682 {
5683 operands[2] = gen_reg_rtx (HImode);
5684 })
5685
5686 (define_insn "*parityhi2.libgcc"
5687 [(set (reg:HI 24)
5688 (parity:HI (reg:HI 24)))]
5689 ""
5690 "%~call __parityhi2"
5691 [(set_attr "type" "xcall")
5692 (set_attr "cc" "clobber")])
5693
5694 (define_insn "*parityqihi2.libgcc"
5695 [(set (reg:HI 24)
5696 (zero_extend:HI (parity:QI (reg:QI 24))))]
5697 ""
5698 "%~call __parityqi2"
5699 [(set_attr "type" "xcall")
5700 (set_attr "cc" "clobber")])
5701
5702 (define_insn "*paritysihi2.libgcc"
5703 [(set (reg:HI 24)
5704 (truncate:HI (parity:SI (reg:SI 22))))]
5705 ""
5706 "%~call __paritysi2"
5707 [(set_attr "type" "xcall")
5708 (set_attr "cc" "clobber")])
5709
5710
5711 ;; Popcount
5712
5713 (define_expand "popcounthi2"
5714 [(set (reg:HI 24)
5715 (match_operand:HI 1 "register_operand" ""))
5716 (set (reg:HI 24)
5717 (popcount:HI (reg:HI 24)))
5718 (set (match_operand:HI 0 "register_operand" "")
5719 (reg:HI 24))]
5720 ""
5721 "")
5722
5723 (define_expand "popcountsi2"
5724 [(set (reg:SI 22)
5725 (match_operand:SI 1 "register_operand" ""))
5726 (set (reg:HI 24)
5727 (truncate:HI (popcount:SI (reg:SI 22))))
5728 (set (match_dup 2)
5729 (reg:HI 24))
5730 (set (match_operand:SI 0 "register_operand" "")
5731 (zero_extend:SI (match_dup 2)))]
5732 ""
5733 {
5734 operands[2] = gen_reg_rtx (HImode);
5735 })
5736
5737 (define_insn "*popcounthi2.libgcc"
5738 [(set (reg:HI 24)
5739 (popcount:HI (reg:HI 24)))]
5740 ""
5741 "%~call __popcounthi2"
5742 [(set_attr "type" "xcall")
5743 (set_attr "cc" "clobber")])
5744
5745 (define_insn "*popcountsi2.libgcc"
5746 [(set (reg:HI 24)
5747 (truncate:HI (popcount:SI (reg:SI 22))))]
5748 ""
5749 "%~call __popcountsi2"
5750 [(set_attr "type" "xcall")
5751 (set_attr "cc" "clobber")])
5752
5753 (define_insn "*popcountqi2.libgcc"
5754 [(set (reg:QI 24)
5755 (popcount:QI (reg:QI 24)))]
5756 ""
5757 "%~call __popcountqi2"
5758 [(set_attr "type" "xcall")
5759 (set_attr "cc" "clobber")])
5760
5761 (define_insn_and_split "*popcountqihi2.libgcc"
5762 [(set (reg:HI 24)
5763 (zero_extend:HI (popcount:QI (reg:QI 24))))]
5764 ""
5765 "#"
5766 ""
5767 [(set (reg:QI 24)
5768 (popcount:QI (reg:QI 24)))
5769 (set (reg:QI 25)
5770 (const_int 0))])
5771
5772 ;; Count Leading Zeros
5773
5774 (define_expand "clzhi2"
5775 [(set (reg:HI 24)
5776 (match_operand:HI 1 "register_operand" ""))
5777 (parallel [(set (reg:HI 24)
5778 (clz:HI (reg:HI 24)))
5779 (clobber (reg:QI 26))])
5780 (set (match_operand:HI 0 "register_operand" "")
5781 (reg:HI 24))])
5782
5783 (define_expand "clzsi2"
5784 [(set (reg:SI 22)
5785 (match_operand:SI 1 "register_operand" ""))
5786 (parallel [(set (reg:HI 24)
5787 (truncate:HI (clz:SI (reg:SI 22))))
5788 (clobber (reg:QI 26))])
5789 (set (match_dup 2)
5790 (reg:HI 24))
5791 (set (match_operand:SI 0 "register_operand" "")
5792 (zero_extend:SI (match_dup 2)))]
5793 ""
5794 {
5795 operands[2] = gen_reg_rtx (HImode);
5796 })
5797
5798 (define_insn "*clzhi2.libgcc"
5799 [(set (reg:HI 24)
5800 (clz:HI (reg:HI 24)))
5801 (clobber (reg:QI 26))]
5802 ""
5803 "%~call __clzhi2"
5804 [(set_attr "type" "xcall")
5805 (set_attr "cc" "clobber")])
5806
5807 (define_insn "*clzsihi2.libgcc"
5808 [(set (reg:HI 24)
5809 (truncate:HI (clz:SI (reg:SI 22))))
5810 (clobber (reg:QI 26))]
5811 ""
5812 "%~call __clzsi2"
5813 [(set_attr "type" "xcall")
5814 (set_attr "cc" "clobber")])
5815
5816 ;; Count Trailing Zeros
5817
5818 (define_expand "ctzhi2"
5819 [(set (reg:HI 24)
5820 (match_operand:HI 1 "register_operand" ""))
5821 (parallel [(set (reg:HI 24)
5822 (ctz:HI (reg:HI 24)))
5823 (clobber (reg:QI 26))])
5824 (set (match_operand:HI 0 "register_operand" "")
5825 (reg:HI 24))])
5826
5827 (define_expand "ctzsi2"
5828 [(set (reg:SI 22)
5829 (match_operand:SI 1 "register_operand" ""))
5830 (parallel [(set (reg:HI 24)
5831 (truncate:HI (ctz:SI (reg:SI 22))))
5832 (clobber (reg:QI 22))
5833 (clobber (reg:QI 26))])
5834 (set (match_dup 2)
5835 (reg:HI 24))
5836 (set (match_operand:SI 0 "register_operand" "")
5837 (zero_extend:SI (match_dup 2)))]
5838 ""
5839 {
5840 operands[2] = gen_reg_rtx (HImode);
5841 })
5842
5843 (define_insn "*ctzhi2.libgcc"
5844 [(set (reg:HI 24)
5845 (ctz:HI (reg:HI 24)))
5846 (clobber (reg:QI 26))]
5847 ""
5848 "%~call __ctzhi2"
5849 [(set_attr "type" "xcall")
5850 (set_attr "cc" "clobber")])
5851
5852 (define_insn "*ctzsihi2.libgcc"
5853 [(set (reg:HI 24)
5854 (truncate:HI (ctz:SI (reg:SI 22))))
5855 (clobber (reg:QI 22))
5856 (clobber (reg:QI 26))]
5857 ""
5858 "%~call __ctzsi2"
5859 [(set_attr "type" "xcall")
5860 (set_attr "cc" "clobber")])
5861
5862 ;; Find First Set
5863
5864 (define_expand "ffshi2"
5865 [(set (reg:HI 24)
5866 (match_operand:HI 1 "register_operand" ""))
5867 (parallel [(set (reg:HI 24)
5868 (ffs:HI (reg:HI 24)))
5869 (clobber (reg:QI 26))])
5870 (set (match_operand:HI 0 "register_operand" "")
5871 (reg:HI 24))])
5872
5873 (define_expand "ffssi2"
5874 [(set (reg:SI 22)
5875 (match_operand:SI 1 "register_operand" ""))
5876 (parallel [(set (reg:HI 24)
5877 (truncate:HI (ffs:SI (reg:SI 22))))
5878 (clobber (reg:QI 22))
5879 (clobber (reg:QI 26))])
5880 (set (match_dup 2)
5881 (reg:HI 24))
5882 (set (match_operand:SI 0 "register_operand" "")
5883 (zero_extend:SI (match_dup 2)))]
5884 ""
5885 {
5886 operands[2] = gen_reg_rtx (HImode);
5887 })
5888
5889 (define_insn "*ffshi2.libgcc"
5890 [(set (reg:HI 24)
5891 (ffs:HI (reg:HI 24)))
5892 (clobber (reg:QI 26))]
5893 ""
5894 "%~call __ffshi2"
5895 [(set_attr "type" "xcall")
5896 (set_attr "cc" "clobber")])
5897
5898 (define_insn "*ffssihi2.libgcc"
5899 [(set (reg:HI 24)
5900 (truncate:HI (ffs:SI (reg:SI 22))))
5901 (clobber (reg:QI 22))
5902 (clobber (reg:QI 26))]
5903 ""
5904 "%~call __ffssi2"
5905 [(set_attr "type" "xcall")
5906 (set_attr "cc" "clobber")])
5907
5908 ;; Copysign
5909
5910 (define_insn "copysignsf3"
5911 [(set (match_operand:SF 0 "register_operand" "=r")
5912 (unspec:SF [(match_operand:SF 1 "register_operand" "0")
5913 (match_operand:SF 2 "register_operand" "r")]
5914 UNSPEC_COPYSIGN))]
5915 ""
5916 "bst %D2,7\;bld %D0,7"
5917 [(set_attr "length" "2")
5918 (set_attr "cc" "none")])
5919
5920 ;; Swap Bytes (change byte-endianess)
5921
5922 (define_expand "bswapsi2"
5923 [(set (reg:SI 22)
5924 (match_operand:SI 1 "register_operand" ""))
5925 (set (reg:SI 22)
5926 (bswap:SI (reg:SI 22)))
5927 (set (match_operand:SI 0 "register_operand" "")
5928 (reg:SI 22))])
5929
5930 (define_insn "*bswapsi2.libgcc"
5931 [(set (reg:SI 22)
5932 (bswap:SI (reg:SI 22)))]
5933 ""
5934 "%~call __bswapsi2"
5935 [(set_attr "type" "xcall")
5936 (set_attr "cc" "clobber")])
5937
5938
5939 ;; CPU instructions
5940
5941 ;; NOP taking 1 or 2 Ticks
5942 (define_expand "nopv"
5943 [(parallel [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "")]
5944 UNSPECV_NOP)
5945 (set (match_dup 1)
5946 (unspec_volatile:BLK [(match_dup 1)]
5947 UNSPECV_MEMORY_BARRIER))])]
5948 ""
5949 {
5950 operands[1] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
5951 MEM_VOLATILE_P (operands[1]) = 1;
5952 })
5953
5954 (define_insn "*nopv"
5955 [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "P,K")]
5956 UNSPECV_NOP)
5957 (set (match_operand:BLK 1 "" "")
5958 (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))]
5959 ""
5960 "@
5961 nop
5962 rjmp ."
5963 [(set_attr "length" "1")
5964 (set_attr "cc" "none")])
5965
5966 ;; SLEEP
5967 (define_expand "sleep"
5968 [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_SLEEP)
5969 (set (match_dup 0)
5970 (unspec_volatile:BLK [(match_dup 0)]
5971 UNSPECV_MEMORY_BARRIER))])]
5972 ""
5973 {
5974 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
5975 MEM_VOLATILE_P (operands[0]) = 1;
5976 })
5977
5978 (define_insn "*sleep"
5979 [(unspec_volatile [(const_int 0)] UNSPECV_SLEEP)
5980 (set (match_operand:BLK 0 "" "")
5981 (unspec_volatile:BLK [(match_dup 0)] UNSPECV_MEMORY_BARRIER))]
5982 ""
5983 "sleep"
5984 [(set_attr "length" "1")
5985 (set_attr "cc" "none")])
5986
5987 ;; WDR
5988 (define_expand "wdr"
5989 [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_WDR)
5990 (set (match_dup 0)
5991 (unspec_volatile:BLK [(match_dup 0)]
5992 UNSPECV_MEMORY_BARRIER))])]
5993 ""
5994 {
5995 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
5996 MEM_VOLATILE_P (operands[0]) = 1;
5997 })
5998
5999 (define_insn "*wdr"
6000 [(unspec_volatile [(const_int 0)] UNSPECV_WDR)
6001 (set (match_operand:BLK 0 "" "")
6002 (unspec_volatile:BLK [(match_dup 0)] UNSPECV_MEMORY_BARRIER))]
6003 ""
6004 "wdr"
6005 [(set_attr "length" "1")
6006 (set_attr "cc" "none")])
6007
6008 ;; FMUL
6009 (define_expand "fmul"
6010 [(set (reg:QI 24)
6011 (match_operand:QI 1 "register_operand" ""))
6012 (set (reg:QI 25)
6013 (match_operand:QI 2 "register_operand" ""))
6014 (parallel [(set (reg:HI 22)
6015 (unspec:HI [(reg:QI 24)
6016 (reg:QI 25)] UNSPEC_FMUL))
6017 (clobber (reg:HI 24))])
6018 (set (match_operand:HI 0 "register_operand" "")
6019 (reg:HI 22))]
6020 ""
6021 {
6022 if (AVR_HAVE_MUL)
6023 {
6024 emit_insn (gen_fmul_insn (operand0, operand1, operand2));
6025 DONE;
6026 }
6027 })
6028
6029 (define_insn "fmul_insn"
6030 [(set (match_operand:HI 0 "register_operand" "=r")
6031 (unspec:HI [(match_operand:QI 1 "register_operand" "a")
6032 (match_operand:QI 2 "register_operand" "a")]
6033 UNSPEC_FMUL))]
6034 "AVR_HAVE_MUL"
6035 "fmul %1,%2
6036 movw %0,r0
6037 clr __zero_reg__"
6038 [(set_attr "length" "3")
6039 (set_attr "cc" "clobber")])
6040
6041 (define_insn "*fmul.call"
6042 [(set (reg:HI 22)
6043 (unspec:HI [(reg:QI 24)
6044 (reg:QI 25)] UNSPEC_FMUL))
6045 (clobber (reg:HI 24))]
6046 "!AVR_HAVE_MUL"
6047 "%~call __fmul"
6048 [(set_attr "type" "xcall")
6049 (set_attr "cc" "clobber")])
6050
6051 ;; FMULS
6052 (define_expand "fmuls"
6053 [(set (reg:QI 24)
6054 (match_operand:QI 1 "register_operand" ""))
6055 (set (reg:QI 25)
6056 (match_operand:QI 2 "register_operand" ""))
6057 (parallel [(set (reg:HI 22)
6058 (unspec:HI [(reg:QI 24)
6059 (reg:QI 25)] UNSPEC_FMULS))
6060 (clobber (reg:HI 24))])
6061 (set (match_operand:HI 0 "register_operand" "")
6062 (reg:HI 22))]
6063 ""
6064 {
6065 if (AVR_HAVE_MUL)
6066 {
6067 emit_insn (gen_fmuls_insn (operand0, operand1, operand2));
6068 DONE;
6069 }
6070 })
6071
6072 (define_insn "fmuls_insn"
6073 [(set (match_operand:HI 0 "register_operand" "=r")
6074 (unspec:HI [(match_operand:QI 1 "register_operand" "a")
6075 (match_operand:QI 2 "register_operand" "a")]
6076 UNSPEC_FMULS))]
6077 "AVR_HAVE_MUL"
6078 "fmuls %1,%2
6079 movw %0,r0
6080 clr __zero_reg__"
6081 [(set_attr "length" "3")
6082 (set_attr "cc" "clobber")])
6083
6084 (define_insn "*fmuls.call"
6085 [(set (reg:HI 22)
6086 (unspec:HI [(reg:QI 24)
6087 (reg:QI 25)] UNSPEC_FMULS))
6088 (clobber (reg:HI 24))]
6089 "!AVR_HAVE_MUL"
6090 "%~call __fmuls"
6091 [(set_attr "type" "xcall")
6092 (set_attr "cc" "clobber")])
6093
6094 ;; FMULSU
6095 (define_expand "fmulsu"
6096 [(set (reg:QI 24)
6097 (match_operand:QI 1 "register_operand" ""))
6098 (set (reg:QI 25)
6099 (match_operand:QI 2 "register_operand" ""))
6100 (parallel [(set (reg:HI 22)
6101 (unspec:HI [(reg:QI 24)
6102 (reg:QI 25)] UNSPEC_FMULSU))
6103 (clobber (reg:HI 24))])
6104 (set (match_operand:HI 0 "register_operand" "")
6105 (reg:HI 22))]
6106 ""
6107 {
6108 if (AVR_HAVE_MUL)
6109 {
6110 emit_insn (gen_fmulsu_insn (operand0, operand1, operand2));
6111 DONE;
6112 }
6113 })
6114
6115 (define_insn "fmulsu_insn"
6116 [(set (match_operand:HI 0 "register_operand" "=r")
6117 (unspec:HI [(match_operand:QI 1 "register_operand" "a")
6118 (match_operand:QI 2 "register_operand" "a")]
6119 UNSPEC_FMULSU))]
6120 "AVR_HAVE_MUL"
6121 "fmulsu %1,%2
6122 movw %0,r0
6123 clr __zero_reg__"
6124 [(set_attr "length" "3")
6125 (set_attr "cc" "clobber")])
6126
6127 (define_insn "*fmulsu.call"
6128 [(set (reg:HI 22)
6129 (unspec:HI [(reg:QI 24)
6130 (reg:QI 25)] UNSPEC_FMULSU))
6131 (clobber (reg:HI 24))]
6132 "!AVR_HAVE_MUL"
6133 "%~call __fmulsu"
6134 [(set_attr "type" "xcall")
6135 (set_attr "cc" "clobber")])
6136
6137 \f
6138 ;; Some combiner patterns dealing with bits.
6139 ;; See PR42210
6140
6141 ;; Move bit $3.0 into bit $0.$4
6142 (define_insn "*movbitqi.1-6.a"
6143 [(set (match_operand:QI 0 "register_operand" "=r")
6144 (ior:QI (and:QI (match_operand:QI 1 "register_operand" "0")
6145 (match_operand:QI 2 "single_zero_operand" "n"))
6146 (and:QI (ashift:QI (match_operand:QI 3 "register_operand" "r")
6147 (match_operand:QI 4 "const_0_to_7_operand" "n"))
6148 (match_operand:QI 5 "single_one_operand" "n"))))]
6149 "INTVAL(operands[4]) == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))
6150 && INTVAL(operands[4]) == exact_log2 (INTVAL(operands[5]) & GET_MODE_MASK (QImode))"
6151 "bst %3,0\;bld %0,%4"
6152 [(set_attr "length" "2")
6153 (set_attr "cc" "none")])
6154
6155 ;; Move bit $3.0 into bit $0.$4
6156 ;; Variation of above. Unfortunately, there is no canonicalized representation
6157 ;; of moving around bits. So what we see here depends on how user writes down
6158 ;; bit manipulations.
6159 (define_insn "*movbitqi.1-6.b"
6160 [(set (match_operand:QI 0 "register_operand" "=r")
6161 (ior:QI (and:QI (match_operand:QI 1 "register_operand" "0")
6162 (match_operand:QI 2 "single_zero_operand" "n"))
6163 (ashift:QI (and:QI (match_operand:QI 3 "register_operand" "r")
6164 (const_int 1))
6165 (match_operand:QI 4 "const_0_to_7_operand" "n"))))]
6166 "INTVAL(operands[4]) == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))"
6167 "bst %3,0\;bld %0,%4"
6168 [(set_attr "length" "2")
6169 (set_attr "cc" "none")])
6170
6171 ;; Move bit $3.0 into bit $0.0.
6172 ;; For bit 0, combiner generates slightly different pattern.
6173 (define_insn "*movbitqi.0"
6174 [(set (match_operand:QI 0 "register_operand" "=r")
6175 (ior:QI (and:QI (match_operand:QI 1 "register_operand" "0")
6176 (match_operand:QI 2 "single_zero_operand" "n"))
6177 (and:QI (match_operand:QI 3 "register_operand" "r")
6178 (const_int 1))))]
6179 "0 == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))"
6180 "bst %3,0\;bld %0,0"
6181 [(set_attr "length" "2")
6182 (set_attr "cc" "none")])
6183
6184 ;; Move bit $2.0 into bit $0.7.
6185 ;; For bit 7, combiner generates slightly different pattern
6186 (define_insn "*movbitqi.7"
6187 [(set (match_operand:QI 0 "register_operand" "=r")
6188 (ior:QI (and:QI (match_operand:QI 1 "register_operand" "0")
6189 (const_int 127))
6190 (ashift:QI (match_operand:QI 2 "register_operand" "r")
6191 (const_int 7))))]
6192 ""
6193 "bst %2,0\;bld %0,7"
6194 [(set_attr "length" "2")
6195 (set_attr "cc" "none")])
6196
6197 ;; Combiner transforms above four pattern into ZERO_EXTRACT if it sees MEM
6198 ;; and input/output match. We provide a special pattern for this, because
6199 ;; in contrast to a IN/BST/BLD/OUT sequence we need less registers and the
6200 ;; operation on I/O is atomic.
6201 (define_insn "*insv.io"
6202 [(set (zero_extract:QI (mem:QI (match_operand 0 "low_io_address_operand" "n,n,n"))
6203 (const_int 1)
6204 (match_operand:QI 1 "const_0_to_7_operand" "n,n,n"))
6205 (match_operand:QI 2 "nonmemory_operand" "L,P,r"))]
6206 ""
6207 "@
6208 cbi %i0,%1
6209 sbi %i0,%1
6210 sbrc %2,0\;sbi %i0,%1\;sbrs %2,0\;cbi %i0,%1"
6211 [(set_attr "length" "1,1,4")
6212 (set_attr "cc" "none")])
6213
6214 (define_insn "*insv.not.io"
6215 [(set (zero_extract:QI (mem:QI (match_operand 0 "low_io_address_operand" "n"))
6216 (const_int 1)
6217 (match_operand:QI 1 "const_0_to_7_operand" "n"))
6218 (not:QI (match_operand:QI 2 "register_operand" "r")))]
6219 ""
6220 "sbrs %2,0\;sbi %i0,%1\;sbrc %2,0\;cbi %i0,%1"
6221 [(set_attr "length" "4")
6222 (set_attr "cc" "none")])
6223
6224 ;; The insv expander.
6225 ;; We only support 1-bit inserts
6226 (define_expand "insv"
6227 [(set (zero_extract:QI (match_operand:QI 0 "register_operand" "")
6228 (match_operand:QI 1 "const1_operand" "") ; width
6229 (match_operand:QI 2 "const_0_to_7_operand" "")) ; pos
6230 (match_operand:QI 3 "nonmemory_operand" ""))]
6231 "optimize")
6232
6233 ;; Insert bit $2.0 into $0.$1
6234 (define_insn "*insv.reg"
6235 [(set (zero_extract:QI (match_operand:QI 0 "register_operand" "+r,d,d,l,l")
6236 (const_int 1)
6237 (match_operand:QI 1 "const_0_to_7_operand" "n,n,n,n,n"))
6238 (match_operand:QI 2 "nonmemory_operand" "r,L,P,L,P"))]
6239 ""
6240 "@
6241 bst %2,0\;bld %0,%1
6242 andi %0,lo8(~(1<<%1))
6243 ori %0,lo8(1<<%1)
6244 clt\;bld %0,%1
6245 set\;bld %0,%1"
6246 [(set_attr "length" "2,1,1,2,2")
6247 (set_attr "cc" "none,set_zn,set_zn,none,none")])
6248
6249 \f
6250 ;; Some combine patterns that try to fix bad code when a value is composed
6251 ;; from byte parts like in PR27663.
6252 ;; The patterns give some release but the code still is not optimal,
6253 ;; in particular when subreg lowering (-fsplit-wide-types) is turned on.
6254 ;; That switch obfuscates things here and in many other places.
6255
6256 ;; "*iorhiqi.byte0" "*iorpsiqi.byte0" "*iorsiqi.byte0"
6257 ;; "*xorhiqi.byte0" "*xorpsiqi.byte0" "*xorsiqi.byte0"
6258 (define_insn_and_split "*<code_stdname><mode>qi.byte0"
6259 [(set (match_operand:HISI 0 "register_operand" "=r")
6260 (xior:HISI
6261 (zero_extend:HISI (match_operand:QI 1 "register_operand" "r"))
6262 (match_operand:HISI 2 "register_operand" "0")))]
6263 ""
6264 "#"
6265 "reload_completed"
6266 [(set (match_dup 3)
6267 (xior:QI (match_dup 3)
6268 (match_dup 1)))]
6269 {
6270 operands[3] = simplify_gen_subreg (QImode, operands[0], <MODE>mode, 0);
6271 })
6272
6273 ;; "*iorhiqi.byte1-3" "*iorpsiqi.byte1-3" "*iorsiqi.byte1-3"
6274 ;; "*xorhiqi.byte1-3" "*xorpsiqi.byte1-3" "*xorsiqi.byte1-3"
6275 (define_insn_and_split "*<code_stdname><mode>qi.byte1-3"
6276 [(set (match_operand:HISI 0 "register_operand" "=r")
6277 (xior:HISI
6278 (ashift:HISI (zero_extend:HISI (match_operand:QI 1 "register_operand" "r"))
6279 (match_operand:QI 2 "const_8_16_24_operand" "n"))
6280 (match_operand:HISI 3 "register_operand" "0")))]
6281 "INTVAL(operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
6282 "#"
6283 "&& reload_completed"
6284 [(set (match_dup 4)
6285 (xior:QI (match_dup 4)
6286 (match_dup 1)))]
6287 {
6288 int byteno = INTVAL(operands[2]) / BITS_PER_UNIT;
6289 operands[4] = simplify_gen_subreg (QImode, operands[0], <MODE>mode, byteno);
6290 })
6291
6292 (define_expand "extzv"
6293 [(set (match_operand:QI 0 "register_operand" "")
6294 (zero_extract:QI (match_operand:QI 1 "register_operand" "")
6295 (match_operand:QI 2 "const1_operand" "")
6296 (match_operand:QI 3 "const_0_to_7_operand" "")))])
6297
6298 (define_insn "*extzv"
6299 [(set (match_operand:QI 0 "register_operand" "=*d,*d,*d,*d,r")
6300 (zero_extract:QI (match_operand:QI 1 "register_operand" "0,r,0,0,r")
6301 (const_int 1)
6302 (match_operand:QI 2 "const_0_to_7_operand" "L,L,P,C04,n")))]
6303 ""
6304 "@
6305 andi %0,1
6306 mov %0,%1\;andi %0,1
6307 lsr %0\;andi %0,1
6308 swap %0\;andi %0,1
6309 bst %1,%2\;clr %0\;bld %0,0"
6310 [(set_attr "length" "1,2,2,2,3")
6311 (set_attr "cc" "set_zn,set_zn,set_zn,set_zn,clobber")])
6312
6313 (define_insn_and_split "*extzv.qihi1"
6314 [(set (match_operand:HI 0 "register_operand" "=r")
6315 (zero_extract:HI (match_operand:QI 1 "register_operand" "r")
6316 (const_int 1)
6317 (match_operand:QI 2 "const_0_to_7_operand" "n")))]
6318 ""
6319 "#"
6320 ""
6321 [(set (match_dup 3)
6322 (zero_extract:QI (match_dup 1)
6323 (const_int 1)
6324 (match_dup 2)))
6325 (set (match_dup 4)
6326 (const_int 0))]
6327 {
6328 operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
6329 operands[4] = simplify_gen_subreg (QImode, operands[0], HImode, 1);
6330 })
6331
6332 (define_insn_and_split "*extzv.qihi2"
6333 [(set (match_operand:HI 0 "register_operand" "=r")
6334 (zero_extend:HI
6335 (zero_extract:QI (match_operand:QI 1 "register_operand" "r")
6336 (const_int 1)
6337 (match_operand:QI 2 "const_0_to_7_operand" "n"))))]
6338 ""
6339 "#"
6340 ""
6341 [(set (match_dup 3)
6342 (zero_extract:QI (match_dup 1)
6343 (const_int 1)
6344 (match_dup 2)))
6345 (set (match_dup 4)
6346 (const_int 0))]
6347 {
6348 operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
6349 operands[4] = simplify_gen_subreg (QImode, operands[0], HImode, 1);
6350 })
6351
6352 \f
6353 ;; Fixed-point instructions
6354 (include "avr-fixed.md")
6355
6356 ;; Operations on 64-bit registers
6357 (include "avr-dimode.md")