* config/avr/avr.md: Fix indentation from r177991.
[official-gcc.git] / gcc / config / avr / avr.md
blob7163099b2c5ff42773cb51b2c6041f4a79ee7bce
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 Free Software Foundation, Inc.
5 ;;   Contributed by Denis Chertykov (chertykov@gmail.com)
7 ;; This file is part of GCC.
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.
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.
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/>.
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 ;;  o  Displacement for (mem (plus (reg) (const_int))) operands.
32 ;;  p  POST_INC or PRE_DEC address as a pointer (X, Y, Z)
33 ;;  r  POST_INC or PRE_DEC address as a register (r26, r28, r30)
34 ;;..x..Constant Direct Program memory address.
35 ;;  ~  Output 'r' if not AVR_HAVE_JMP_CALL.
36 ;;  !  Output 'e' if AVR_HAVE_EIJMP_EICALL.
39 (define_constants
40   [(REG_X       26)
41    (REG_Y       28)
42    (REG_Z       30)
43    (REG_W       24)
44    (REG_SP      32)
45    (TMP_REGNO   0)      ; temporary register r0
46    (ZERO_REGNO  1)      ; zero register r1
47    
48    (SREG_ADDR   0x5F)
49    (RAMPZ_ADDR  0x5B)
50    ])
52 (define_c_enum "unspec"
53   [UNSPEC_STRLEN
54    UNSPEC_INDEX_JMP
55    UNSPEC_FMUL
56    UNSPEC_FMULS
57    UNSPEC_FMULSU
58    UNSPEC_COPYSIGN
59    UNSPEC_IDENTITY
60    ])
62 (define_c_enum "unspecv"
63   [UNSPECV_PROLOGUE_SAVES
64    UNSPECV_EPILOGUE_RESTORES
65    UNSPECV_WRITE_SP_IRQ_ON
66    UNSPECV_WRITE_SP_IRQ_OFF
67    UNSPECV_GOTO_RECEIVER
68    UNSPECV_ENABLE_IRQS
69    UNSPECV_NOP
70    UNSPECV_SLEEP
71    UNSPECV_WDR
72    UNSPECV_DELAY_CYCLES
73    ])
74     
76 (include "predicates.md")
77 (include "constraints.md")
78   
79 ;; Condition code settings.
80 (define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber"
81   (const_string "none"))
83 (define_attr "type" "branch,branch1,arith,xcall"
84   (const_string "arith"))
86 (define_attr "mcu_have_movw" "yes,no"
87   (const (if_then_else (symbol_ref "AVR_HAVE_MOVW")
88                        (const_string "yes")
89                        (const_string "no"))))
91 (define_attr "mcu_mega" "yes,no"
92   (const (if_then_else (symbol_ref "AVR_HAVE_JMP_CALL")
93                        (const_string "yes")
94                        (const_string "no"))))
95   
97 ;; The size of instructions in bytes.
98 ;; XXX may depend from "cc"
100 (define_attr "length" ""
101   (cond [(eq_attr "type" "branch")
102          (if_then_else (and (ge (minus (pc) (match_dup 0))
103                                 (const_int -63))
104                             (le (minus (pc) (match_dup 0))
105                                 (const_int 62)))
106                        (const_int 1)
107                        (if_then_else (and (ge (minus (pc) (match_dup 0))
108                                               (const_int -2045))
109                                           (le (minus (pc) (match_dup 0))
110                                               (const_int 2045)))
111                                      (const_int 2)
112                                      (const_int 3)))
113          (eq_attr "type" "branch1")
114          (if_then_else (and (ge (minus (pc) (match_dup 0))
115                                 (const_int -62))
116                             (le (minus (pc) (match_dup 0))
117                                 (const_int 61)))
118                        (const_int 2)
119                        (if_then_else (and (ge (minus (pc) (match_dup 0))
120                                               (const_int -2044))
121                                           (le (minus (pc) (match_dup 0))
122                                               (const_int 2043)))
123                                      (const_int 3)
124                                      (const_int 4)))
125          (eq_attr "type" "xcall")
126          (if_then_else (eq_attr "mcu_mega" "no")
127                        (const_int 1)
128                        (const_int 2))]
129         (const_int 2)))
131 ;; Define mode iterators
132 (define_mode_iterator QIHI  [(QI "") (HI "")])
133 (define_mode_iterator QIHI2 [(QI "") (HI "")])
134 (define_mode_iterator QISI [(QI "") (HI "") (SI "")])
135 (define_mode_iterator QIDI [(QI "") (HI "") (SI "") (DI "")])
136 (define_mode_iterator HIDI [(HI "") (SI "") (DI "")])
137 (define_mode_iterator HISI [(HI "") (SI "")])
139 ;; Define code iterators
140 ;; Define two incarnations so that we can build the cross product.
141 (define_code_iterator any_extend  [sign_extend zero_extend])
142 (define_code_iterator any_extend2 [sign_extend zero_extend])
144 ;; Define code attributes
145 (define_code_attr extend_su
146   [(sign_extend "s")
147    (zero_extend "u")])
149 (define_code_attr extend_u
150   [(sign_extend "")
151    (zero_extend "u")])
154 ;;========================================================================
155 ;; The following is used by nonlocal_goto and setjmp.
156 ;; The receiver pattern will create no instructions since internally
157 ;; virtual_stack_vars = hard_frame_pointer + 1 so the RTL become R28=R28
158 ;; This avoids creating add/sub offsets in frame_pointer save/resore.
159 ;; The 'null' receiver also avoids  problems with optimisation
160 ;; not recognising incoming jmp and removing code that resets frame_pointer.
161 ;; The code derived from builtins.c.
163 (define_expand "nonlocal_goto_receiver"
164   [(set (reg:HI REG_Y) 
165         (unspec_volatile:HI [(const_int 0)] UNSPECV_GOTO_RECEIVER))]
166   ""
167   {
168     emit_move_insn (virtual_stack_vars_rtx, 
169                     gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, 
170                                   gen_int_mode (STARTING_FRAME_OFFSET,
171                                                 Pmode)));
172   /* This might change the hard frame pointer in ways that aren't
173     apparent to early optimization passes, so force a clobber.  */
174     emit_clobber (hard_frame_pointer_rtx);
175     DONE;
176   })
177   
179 ;; Defining nonlocal_goto_receiver means we must also define this.
180 ;; even though its function is identical to that in builtins.c
182 (define_expand "nonlocal_goto"
183   [
184   (use (match_operand 0 "general_operand"))
185   (use (match_operand 1 "general_operand"))
186   (use (match_operand 2 "general_operand"))
187   (use (match_operand 3 "general_operand"))
188   ]
189   ""
191   rtx r_label = copy_to_reg (operands[1]);
192   rtx r_fp = operands[3];
193   rtx r_sp = operands[2];
195   emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
197   emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
199   emit_move_insn (hard_frame_pointer_rtx, r_fp);
200   emit_stack_restore (SAVE_NONLOCAL, r_sp);
202   emit_use (hard_frame_pointer_rtx);
203   emit_use (stack_pointer_rtx);
205   emit_indirect_jump (r_label);
207   DONE;
210 (define_insn "pushqi1"
211   [(set (mem:QI (post_dec:HI (reg:HI REG_SP)))
212         (match_operand:QI 0 "reg_or_0_operand" "r,L"))]
213   ""
214   "@
215         push %0
216         push __zero_reg__"
217   [(set_attr "length" "1,1")])
219 ;; All modes for a multi-byte push.  We must include complex modes here too,
220 ;; lest emit_single_push_insn "helpfully " create the auto-inc itself.
221 (define_mode_iterator MPUSH
222   [(CQI "")
223    (HI "") (CHI "")
224    (SI "") (CSI "")
225    (DI "") (CDI "")
226    (SF "") (SC "")])
228 (define_expand "push<mode>1"
229   [(match_operand:MPUSH 0 "" "")]
230   ""
232   int i;
233   for (i = GET_MODE_SIZE (<MODE>mode) - 1; i >= 0; --i)
234     {
235       rtx part = simplify_gen_subreg (QImode, operands[0], <MODE>mode, i);
236       if (part != const0_rtx)
237         part = force_reg (QImode, part);
238       emit_insn (gen_pushqi1 (part));
239     }
240   DONE;
243 ;; Notice a special-case when adding N to SP where N results in a
244 ;; zero REG_ARGS_SIZE.  This is equivalent to a move from FP.
245 (define_split
246   [(set (reg:HI REG_SP) (match_operand:HI 0 "register_operand" ""))]
247   "reload_completed
248    && frame_pointer_needed
249    && !cfun->calls_alloca
250    && find_reg_note (insn, REG_ARGS_SIZE, const0_rtx)"
251   [(set (reg:HI REG_SP) (reg:HI REG_Y))]
252   "")
254 ;;========================================================================
255 ;; move byte
256 ;; The last alternative (any immediate constant to any register) is
257 ;; very expensive.  It should be optimized by peephole2 if a scratch
258 ;; register is available, but then that register could just as well be
259 ;; allocated for the variable we are loading.  But, most of NO_LD_REGS
260 ;; are call-saved registers, and most of LD_REGS are call-used registers,
261 ;; so this may still be a win for registers live across function calls.
263 (define_expand "movqi"
264   [(set (match_operand:QI 0 "nonimmediate_operand" "")
265         (match_operand:QI 1 "general_operand" ""))]
266   ""
267   "/* One of the ops has to be in a register.  */
268    if (!register_operand(operand0, QImode)
269        && ! (register_operand(operand1, QImode) || const0_rtx == operand1))
270        operands[1] = copy_to_mode_reg(QImode, operand1);
271   ")
273 (define_insn "*movqi"
274   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,d,Qm,r,q,r,*r")
275         (match_operand:QI 1 "general_operand"       "rL,i,rL,Qm,r,q,i"))]
276   "(register_operand (operands[0],QImode)
277     || register_operand (operands[1], QImode) || const0_rtx == operands[1])"
278   "* return output_movqi (insn, operands, NULL);"
279   [(set_attr "length" "1,1,5,5,1,1,4")
280    (set_attr "cc" "none,none,clobber,clobber,none,none,clobber")])
282 ;; This is used in peephole2 to optimize loading immediate constants
283 ;; if a scratch register from LD_REGS happens to be available.
285 (define_insn "*reload_inqi"
286   [(set (match_operand:QI 0 "register_operand" "=l")
287         (match_operand:QI 1 "immediate_operand" "i"))
288    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
289   "reload_completed"
290   "ldi %2,lo8(%1)
291         mov %0,%2"
292   [(set_attr "length" "2")
293    (set_attr "cc" "none")])
295 (define_peephole2
296   [(match_scratch:QI 2 "d")
297    (set (match_operand:QI 0 "l_register_operand" "")
298         (match_operand:QI 1 "immediate_operand" ""))]
299   "(operands[1] != const0_rtx
300     && operands[1] != const1_rtx
301     && operands[1] != constm1_rtx)"
302   [(parallel [(set (match_dup 0) (match_dup 1))
303               (clobber (match_dup 2))])]
304   "")
306 ;;============================================================================
307 ;; move word (16 bit)
309 (define_expand "movhi"
310   [(set (match_operand:HI 0 "nonimmediate_operand" "")
311         (match_operand:HI 1 "general_operand"       ""))]
312   ""
313   "
315    /* One of the ops has to be in a register.  */
316   if (!register_operand(operand0, HImode)
317       && !(register_operand(operand1, HImode) || const0_rtx == operands[1]))
318     {
319       operands[1] = copy_to_mode_reg(HImode, operand1);
320     }
323 (define_insn "*movhi_sp"
324   [(set (match_operand:HI 0 "register_operand" "=q,r")
325         (match_operand:HI 1 "register_operand"  "r,q"))]
326   "((stack_register_operand(operands[0], HImode) && register_operand (operands[1], HImode))
327     || (register_operand (operands[0], HImode) && stack_register_operand(operands[1], HImode)))"
328   "* return output_movhi (insn, operands, NULL);"
329   [(set_attr "length" "5,2")
330    (set_attr "cc" "none,none")])
332 (define_insn "movhi_sp_r_irq_off"
333   [(set (match_operand:HI 0 "stack_register_operand" "=q")
334         (unspec_volatile:HI [(match_operand:HI 1 "register_operand"  "r")] 
335                             UNSPECV_WRITE_SP_IRQ_OFF))]
336   ""
337   "out __SP_H__, %B1
338         out __SP_L__, %A1"
339   [(set_attr "length" "2")
340    (set_attr "cc" "none")])
342 (define_insn "movhi_sp_r_irq_on"
343   [(set (match_operand:HI 0 "stack_register_operand" "=q")
344         (unspec_volatile:HI [(match_operand:HI 1 "register_operand"  "r")] 
345                             UNSPECV_WRITE_SP_IRQ_ON))]
346   ""
347   "cli
348         out __SP_H__, %B1
349         sei
350         out __SP_L__, %A1"
351   [(set_attr "length" "4")
352    (set_attr "cc" "none")])
354 (define_peephole2
355   [(match_scratch:QI 2 "d")
356    (set (match_operand:HI 0 "l_register_operand" "")
357         (match_operand:HI 1 "immediate_operand" ""))]
358   "(operands[1] != const0_rtx 
359     && operands[1] != constm1_rtx)"
360   [(parallel [(set (match_dup 0) (match_dup 1))
361               (clobber (match_dup 2))])]
362   "")
364 ;; '*' because it is not used in rtl generation, only in above peephole
365 (define_insn "*reload_inhi"
366   [(set (match_operand:HI 0 "register_operand" "=r")
367         (match_operand:HI 1 "immediate_operand" "i"))
368    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
369   "reload_completed"
370   "* return output_reload_inhi (insn, operands, NULL);"
371   [(set_attr "length" "4")
372    (set_attr "cc" "none")])
374 (define_insn "*movhi"
375   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,d,*r,q,r")
376         (match_operand:HI 1 "general_operand"       "rL,m,rL,i,i,r,q"))]
377   "(register_operand (operands[0],HImode)
378     || register_operand (operands[1],HImode) || const0_rtx == operands[1])"
379   "* return output_movhi (insn, operands, NULL);"
380   [(set_attr "length" "2,6,7,2,6,5,2")
381    (set_attr "cc" "none,clobber,clobber,none,clobber,none,none")])
383 (define_peephole2 ; movw
384   [(set (match_operand:QI 0 "even_register_operand" "")
385         (match_operand:QI 1 "even_register_operand" ""))
386    (set (match_operand:QI 2 "odd_register_operand" "")
387         (match_operand:QI 3 "odd_register_operand" ""))]
388   "(AVR_HAVE_MOVW
389     && REGNO (operands[0]) == REGNO (operands[2]) - 1
390     && REGNO (operands[1]) == REGNO (operands[3]) - 1)"
391   [(set (match_dup 4) (match_dup 5))]
392   {
393     operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
394     operands[5] = gen_rtx_REG (HImode, REGNO (operands[1]));
395   })
397 (define_peephole2 ; movw_r
398   [(set (match_operand:QI 0 "odd_register_operand" "")
399         (match_operand:QI 1 "odd_register_operand" ""))
400    (set (match_operand:QI 2 "even_register_operand" "")
401         (match_operand:QI 3 "even_register_operand" ""))]
402   "(AVR_HAVE_MOVW
403     && REGNO (operands[2]) == REGNO (operands[0]) - 1
404     && REGNO (operands[3]) == REGNO (operands[1]) - 1)"
405   [(set (match_dup 4) (match_dup 5))]
406   {
407     operands[4] = gen_rtx_REG (HImode, REGNO (operands[2]));
408     operands[5] = gen_rtx_REG (HImode, REGNO (operands[3]));
409   })
411 ;;==========================================================================
412 ;; move double word (32 bit)
414 (define_expand "movsi"
415   [(set (match_operand:SI 0 "nonimmediate_operand" "")
416         (match_operand:SI 1 "general_operand"  ""))]
417   ""
418   "
420   /* One of the ops has to be in a register.  */
421   if (!register_operand (operand0, SImode)
422       && !(register_operand (operand1, SImode) || const0_rtx == operand1))
423     {
424       operands[1] = copy_to_mode_reg (SImode, operand1);
425     }
430 (define_peephole2 ; *reload_insi
431   [(match_scratch:QI 2 "d")
432    (set (match_operand:SI 0 "l_register_operand" "")
433         (match_operand:SI 1 "const_int_operand" ""))
434    (match_dup 2)]
435   "(operands[1] != const0_rtx
436     && operands[1] != constm1_rtx)"
437   [(parallel [(set (match_dup 0) (match_dup 1))
438               (clobber (match_dup 2))])]
439   "")
441 ;; '*' because it is not used in rtl generation.
442 (define_insn "*reload_insi"
443   [(set (match_operand:SI 0 "register_operand" "=r")
444         (match_operand:SI 1 "const_int_operand" "n"))
445    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
446   "reload_completed"
447   {
448     return output_reload_insisf (insn, operands, operands[2], NULL);
449   }
450   [(set_attr "length" "8")
451    (set_attr "cc" "clobber")])
454 (define_insn "*movsi"
455   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,Qm,!d,r")
456         (match_operand:SI 1 "general_operand"       "r,L,Qm,rL,i,i"))]
457   "(register_operand (operands[0],SImode)
458     || register_operand (operands[1],SImode) || const0_rtx == operands[1])"
459   {
460     return output_movsisf (insn, operands, NULL_RTX, NULL);
461   }
462   [(set_attr "length" "4,4,8,9,4,10")
463    (set_attr "cc" "none,set_zn,clobber,clobber,clobber,clobber")])
465 ;; fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
466 ;; move floating point numbers (32 bit)
468 (define_expand "movsf"
469   [(set (match_operand:SF 0 "nonimmediate_operand" "")
470         (match_operand:SF 1 "general_operand"  ""))]
471   ""
472   "
474   /* One of the ops has to be in a register.  */
475   if (!register_operand (operand1, SFmode)
476       && !register_operand (operand0, SFmode))
477     {
478       operands[1] = copy_to_mode_reg (SFmode, operand1);
479     }
482 (define_insn "*movsf"
483   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,Qm,!d,r")
484         (match_operand:SF 1 "general_operand"       "r,G,Qm,rG,F,F"))]
485   "register_operand (operands[0], SFmode)
486    || register_operand (operands[1], SFmode)
487    || operands[1] == CONST0_RTX (SFmode)"
488   {
489     return output_movsisf (insn, operands, NULL_RTX, NULL);
490   }
491   [(set_attr "length" "4,4,8,9,4,10")
492    (set_attr "cc" "none,set_zn,clobber,clobber,clobber,clobber")])
494 (define_peephole2 ; *reload_insf
495   [(match_scratch:QI 2 "d")
496    (set (match_operand:SF 0 "l_register_operand" "")
497         (match_operand:SF 1 "const_double_operand" ""))
498    (match_dup 2)]
499   "operands[1] != CONST0_RTX (SFmode)"
500   [(parallel [(set (match_dup 0) 
501                    (match_dup 1))
502               (clobber (match_dup 2))])]
503   "")
505 ;; '*' because it is not used in rtl generation.
506 (define_insn "*reload_insf"
507   [(set (match_operand:SF 0 "register_operand" "=r")
508         (match_operand:SF 1 "const_double_operand" "F"))
509    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
510   "reload_completed"
511   {
512     return output_reload_insisf (insn, operands, operands[2], NULL);
513   }
514   [(set_attr "length" "8")
515    (set_attr "cc" "clobber")])
517 ;;=========================================================================
518 ;; move string (like memcpy)
519 ;; implement as RTL loop
521 (define_expand "movmemhi"
522   [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
523           (match_operand:BLK 1 "memory_operand" ""))
524           (use (match_operand:HI 2 "const_int_operand" ""))
525           (use (match_operand:HI 3 "const_int_operand" ""))])]
526   ""
527   "{
528   int prob;
529   HOST_WIDE_INT count;
530   enum machine_mode mode;
531   rtx label = gen_label_rtx ();
532   rtx loop_reg;
533   rtx jump;
535   /* Copy pointers into new psuedos - they will be changed.  */
536   rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
537   rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
539   /* Create rtx for tmp register - we use this as scratch.  */
540   rtx tmp_reg_rtx  = gen_rtx_REG (QImode, TMP_REGNO);
542   if (GET_CODE (operands[2]) != CONST_INT)
543     FAIL;
545   count = INTVAL (operands[2]);
546   if (count <= 0)
547     FAIL;
549   /* Work out branch probability for latter use.  */
550   prob = REG_BR_PROB_BASE - REG_BR_PROB_BASE / count;
552   /* See if constant fit 8 bits.  */
553   mode = (count < 0x100) ? QImode : HImode;
554   /* Create loop counter register.  */
555   loop_reg = copy_to_mode_reg (mode, gen_int_mode (count, mode));
557   /* Now create RTL code for move loop.  */
558   /* Label at top of loop.  */
559   emit_label (label);
561   /* Move one byte into scratch and inc pointer.  */
562   emit_move_insn (tmp_reg_rtx, gen_rtx_MEM (QImode, addr1));
563   emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));
565   /* Move to mem and inc pointer.  */
566   emit_move_insn (gen_rtx_MEM (QImode, addr0), tmp_reg_rtx);
567   emit_move_insn (addr0, gen_rtx_PLUS (Pmode, addr0, const1_rtx));
569   /* Decrement count.  */
570   emit_move_insn (loop_reg, gen_rtx_PLUS (mode, loop_reg, constm1_rtx));
572   /* Compare with zero and jump if not equal. */
573   emit_cmp_and_jump_insns (loop_reg, const0_rtx, NE, NULL_RTX, mode, 1,
574                            label);
575   /* Set jump probability based on loop count.  */
576   jump = get_last_insn ();
577   add_reg_note (jump, REG_BR_PROB, GEN_INT (prob));
578   DONE;
581 ;; =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2
582 ;; memset (%0, %2, %1)
584 (define_expand "setmemhi"
585   [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
586                    (match_operand 2 "const_int_operand" ""))
587               (use (match_operand:HI 1 "const_int_operand" ""))
588               (use (match_operand:HI 3 "const_int_operand" "n"))
589               (clobber (match_scratch:HI 4 ""))
590               (clobber (match_dup 5))])]
591   ""
592   "{
593   rtx addr0;
594   int cnt8;
595   enum machine_mode mode;
597   /* If value to set is not zero, use the library routine.  */
598   if (operands[2] != const0_rtx)
599     FAIL;
601   if (GET_CODE (operands[1]) != CONST_INT)
602     FAIL;
604   cnt8 = byte_immediate_operand (operands[1], GET_MODE (operands[1]));
605   mode = cnt8 ? QImode : HImode;
606   operands[5] = gen_rtx_SCRATCH (mode);
607   operands[1] = copy_to_mode_reg (mode,
608                                   gen_int_mode (INTVAL (operands[1]), mode));
609   addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
610   operands[0] = gen_rtx_MEM (BLKmode, addr0);
613 (define_insn "*clrmemqi"
614   [(set (mem:BLK (match_operand:HI 0 "register_operand" "e"))
615         (const_int 0))
616    (use (match_operand:QI 1 "register_operand" "r"))
617    (use (match_operand:QI 2 "const_int_operand" "n"))
618    (clobber (match_scratch:HI 3 "=0"))
619    (clobber (match_scratch:QI 4 "=&1"))]
620   ""
621   "st %a0+,__zero_reg__
622         dec %1
623         brne .-6"
624   [(set_attr "length" "3")
625    (set_attr "cc" "clobber")])
627 (define_insn "*clrmemhi"
628   [(set (mem:BLK (match_operand:HI 0 "register_operand" "e,e"))
629         (const_int 0))
630    (use (match_operand:HI 1 "register_operand" "!w,d"))
631    (use (match_operand:HI 2 "const_int_operand" "n,n"))
632    (clobber (match_scratch:HI 3 "=0,0"))
633    (clobber (match_scratch:HI 4 "=&1,&1"))]
634   ""
635   "*{
636      if (which_alternative==0)
637        return (AS2 (st,%a0+,__zero_reg__) CR_TAB
638                AS2 (sbiw,%A1,1) CR_TAB
639                AS1 (brne,.-6));
640      else
641        return (AS2 (st,%a0+,__zero_reg__) CR_TAB
642                AS2 (subi,%A1,1) CR_TAB
643                AS2 (sbci,%B1,0) CR_TAB
644                AS1 (brne,.-8));
646   [(set_attr "length" "3,4")
647    (set_attr "cc" "clobber,clobber")])
649 (define_expand "strlenhi"
650     [(set (match_dup 4)
651           (unspec:HI [(match_operand:BLK 1 "memory_operand" "")
652                       (match_operand:QI 2 "const_int_operand" "")
653                       (match_operand:HI 3 "immediate_operand" "")]
654                      UNSPEC_STRLEN))
655      (set (match_dup 4) (plus:HI (match_dup 4)
656                                  (const_int -1)))
657      (set (match_operand:HI 0 "register_operand" "")
658           (minus:HI (match_dup 4)
659                     (match_dup 5)))]
660    ""
661    "{
662   rtx addr;
663   if (! (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0))
664     FAIL;
665   addr = copy_to_mode_reg (Pmode, XEXP (operands[1],0));
666   operands[1] = gen_rtx_MEM (BLKmode, addr); 
667   operands[5] = addr;
668   operands[4] = gen_reg_rtx (HImode);
671 (define_insn "*strlenhi"
672   [(set (match_operand:HI 0 "register_operand" "=e")
673         (unspec:HI [(mem:BLK (match_operand:HI 1 "register_operand" "%0"))
674                     (const_int 0)
675                     (match_operand:HI 2 "immediate_operand" "i")]
676                    UNSPEC_STRLEN))]
677   ""
678   "ld __tmp_reg__,%a0+
679         tst __tmp_reg__
680         brne .-6"
681   [(set_attr "length" "3")
682    (set_attr "cc" "clobber")])
684 ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
685 ; add bytes
687 (define_insn "addqi3"
688   [(set (match_operand:QI 0 "register_operand" "=r,d,r,r")
689         (plus:QI (match_operand:QI 1 "register_operand" "%0,0,0,0")
690                  (match_operand:QI 2 "nonmemory_operand" "r,i,P,N")))]
691   ""
692   "@
693         add %0,%2
694         subi %0,lo8(-(%2))
695         inc %0
696         dec %0"
697   [(set_attr "length" "1,1,1,1")
698    (set_attr "cc" "set_czn,set_czn,set_zn,set_zn")])
701 (define_expand "addhi3"
702   [(set (match_operand:HI 0 "register_operand" "")
703         (plus:HI (match_operand:HI 1 "register_operand" "")
704                  (match_operand:HI 2 "nonmemory_operand" "")))]
705   ""
706   "
708   if (GET_CODE (operands[2]) == CONST_INT)
709     {
710       short tmp = INTVAL (operands[2]);
711       operands[2] = GEN_INT(tmp);
712     }
716 (define_insn "*addhi3_zero_extend"
717   [(set (match_operand:HI 0 "register_operand" "=r")
718         (plus:HI (zero_extend:HI
719                   (match_operand:QI 1 "register_operand" "r"))
720                  (match_operand:HI 2 "register_operand" "0")))]
721   ""
722   "add %A0,%1
723         adc %B0,__zero_reg__"
724   [(set_attr "length" "2")
725    (set_attr "cc" "set_n")])
727 (define_insn "*addhi3_zero_extend1"
728   [(set (match_operand:HI 0 "register_operand" "=r")
729         (plus:HI (match_operand:HI 1 "register_operand" "%0")
730                  (zero_extend:HI
731                   (match_operand:QI 2 "register_operand" "r"))))]
732   ""
733   "add %A0,%2
734         adc %B0,__zero_reg__"
735   [(set_attr "length" "2")
736    (set_attr "cc" "set_n")])
738 (define_insn "*addhi3_sp_R_pc2"
739   [(set (match_operand:HI 1 "stack_register_operand" "=q")
740         (plus:HI (match_operand:HI 2 "stack_register_operand" "q")
741                  (match_operand:HI 0 "avr_sp_immediate_operand" "R")))]
742   "AVR_2_BYTE_PC"
743   "*{
744       if (CONST_INT_P (operands[0]))
745         {
746           switch(INTVAL (operands[0]))
747             {
748             case -6: 
749               return \"rcall .\" CR_TAB 
750                      \"rcall .\" CR_TAB 
751                      \"rcall .\";
752             case -5: 
753               return \"rcall .\" CR_TAB 
754                      \"rcall .\" CR_TAB 
755                      \"push __tmp_reg__\";
756             case -4: 
757               return \"rcall .\" CR_TAB 
758                      \"rcall .\";
759             case -3: 
760               return \"rcall .\" CR_TAB 
761                      \"push __tmp_reg__\";
762             case -2: 
763               return \"rcall .\";
764             case -1: 
765               return \"push __tmp_reg__\";
766             case 0: 
767               return \"\";
768             case 1: 
769               return \"pop __tmp_reg__\";
770             case 2: 
771               return \"pop __tmp_reg__\" CR_TAB 
772                      \"pop __tmp_reg__\";
773             case 3: 
774               return \"pop __tmp_reg__\" CR_TAB 
775                      \"pop __tmp_reg__\" CR_TAB 
776                      \"pop __tmp_reg__\";
777             case 4: 
778               return \"pop __tmp_reg__\" CR_TAB 
779                      \"pop __tmp_reg__\" CR_TAB 
780                      \"pop __tmp_reg__\" CR_TAB 
781                      \"pop __tmp_reg__\";
782             case 5: 
783               return \"pop __tmp_reg__\" CR_TAB 
784                      \"pop __tmp_reg__\" CR_TAB 
785                      \"pop __tmp_reg__\" CR_TAB 
786                      \"pop __tmp_reg__\" CR_TAB 
787                      \"pop __tmp_reg__\";
788             }
789         }
790       return \"bug\";
791     }"
792   [(set (attr "length") 
793         (cond [(eq (const_int -6) (symbol_ref "INTVAL (operands[0])")) (const_int 3)
794                (eq (const_int -5) (symbol_ref "INTVAL (operands[0])")) (const_int 3)
795                (eq (const_int -4) (symbol_ref "INTVAL (operands[0])")) (const_int 2)
796                (eq (const_int -3) (symbol_ref "INTVAL (operands[0])")) (const_int 2)
797                (eq (const_int -2) (symbol_ref "INTVAL (operands[0])")) (const_int 1)
798                (eq (const_int -1) (symbol_ref "INTVAL (operands[0])")) (const_int 1)
799                (eq (const_int  0) (symbol_ref "INTVAL (operands[0])")) (const_int 0)
800                (eq (const_int  1) (symbol_ref "INTVAL (operands[0])")) (const_int 1)
801                (eq (const_int  2) (symbol_ref "INTVAL (operands[0])")) (const_int 2)
802                (eq (const_int  3) (symbol_ref "INTVAL (operands[0])")) (const_int 3)
803                (eq (const_int  4) (symbol_ref "INTVAL (operands[0])")) (const_int 4)
804                (eq (const_int  5) (symbol_ref "INTVAL (operands[0])")) (const_int 5)]
805                (const_int 0)))])
807 (define_insn "*addhi3_sp_R_pc3"
808   [(set (match_operand:HI 1 "stack_register_operand" "=q")
809         (plus:HI (match_operand:HI 2 "stack_register_operand" "q")
810                  (match_operand:QI 0 "avr_sp_immediate_operand" "R")))]
811   "AVR_3_BYTE_PC"
812   "*{
813       if (CONST_INT_P (operands[0]))
814         {
815           switch(INTVAL (operands[0]))
816             {
817             case -6: 
818               return \"rcall .\" CR_TAB 
819                      \"rcall .\";
820             case -5: 
821               return \"rcall .\" CR_TAB 
822                      \"push __tmp_reg__\" CR_TAB 
823                      \"push __tmp_reg__\";
824             case -4: 
825               return \"rcall .\" CR_TAB 
826                      \"push __tmp_reg__\";
827             case -3: 
828               return \"rcall .\";
829             case -2: 
830               return \"push __tmp_reg__\" CR_TAB 
831                      \"push __tmp_reg__\";
832             case -1: 
833               return \"push __tmp_reg__\";
834             case 0: 
835               return \"\";
836             case 1: 
837               return \"pop __tmp_reg__\";
838             case 2: 
839               return \"pop __tmp_reg__\" CR_TAB 
840                      \"pop __tmp_reg__\";
841             case 3: 
842               return \"pop __tmp_reg__\" CR_TAB 
843                      \"pop __tmp_reg__\" CR_TAB 
844                      \"pop __tmp_reg__\";
845             case 4: 
846               return \"pop __tmp_reg__\" CR_TAB 
847                      \"pop __tmp_reg__\" CR_TAB 
848                      \"pop __tmp_reg__\" CR_TAB 
849                      \"pop __tmp_reg__\";
850             case 5: 
851               return \"pop __tmp_reg__\" CR_TAB 
852                      \"pop __tmp_reg__\" CR_TAB 
853                      \"pop __tmp_reg__\" CR_TAB 
854                      \"pop __tmp_reg__\" CR_TAB 
855                      \"pop __tmp_reg__\";
856             }
857         }
858       return \"bug\";
859     }"
860   [(set (attr "length") 
861         (cond [(eq (const_int -6) (symbol_ref "INTVAL (operands[0])")) (const_int 2)
862                (eq (const_int -5) (symbol_ref "INTVAL (operands[0])")) (const_int 3)
863                (eq (const_int -4) (symbol_ref "INTVAL (operands[0])")) (const_int 2)
864                (eq (const_int -3) (symbol_ref "INTVAL (operands[0])")) (const_int 1)
865                (eq (const_int -2) (symbol_ref "INTVAL (operands[0])")) (const_int 2)
866                (eq (const_int -1) (symbol_ref "INTVAL (operands[0])")) (const_int 1)
867                (eq (const_int  0) (symbol_ref "INTVAL (operands[0])")) (const_int 0)
868                (eq (const_int  1) (symbol_ref "INTVAL (operands[0])")) (const_int 1)
869                (eq (const_int  2) (symbol_ref "INTVAL (operands[0])")) (const_int 2)
870                (eq (const_int  3) (symbol_ref "INTVAL (operands[0])")) (const_int 3)
871                (eq (const_int  4) (symbol_ref "INTVAL (operands[0])")) (const_int 4)
872                (eq (const_int  5) (symbol_ref "INTVAL (operands[0])")) (const_int 5)]
873                (const_int 0)))])
875 (define_insn "*addhi3"
876   [(set (match_operand:HI 0 "register_operand" "=r,!w,!w,d,r,r")
877         (plus:HI
878          (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0")
879          (match_operand:HI 2 "nonmemory_operand" "r,I,J,i,P,N")))]
880   ""
881   "@
882         add %A0,%A2\;adc %B0,%B2
883         adiw %A0,%2
884         sbiw %A0,%n2
885         subi %A0,lo8(-(%2))\;sbci %B0,hi8(-(%2))
886         sec\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__
887         sec\;sbc %A0,__zero_reg__\;sbc %B0,__zero_reg__"
888   [(set_attr "length" "2,1,1,2,3,3")
889    (set_attr "cc" "set_n,set_czn,set_czn,set_czn,set_n,set_n")])
891 (define_insn "addsi3"
892   [(set (match_operand:SI 0 "register_operand" "=r,!w,!w,d,r,r")
893           (plus:SI
894            (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
895            (match_operand:SI 2 "nonmemory_operand" "r,I,J,i,P,N")))]
896   ""
897   "@
898         add %A0,%A2\;adc %B0,%B2\;adc %C0,%C2\;adc %D0,%D2
899         adiw %0,%2\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__
900         sbiw %0,%n2\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__
901         subi %0,lo8(-(%2))\;sbci %B0,hi8(-(%2))\;sbci %C0,hlo8(-(%2))\;sbci %D0,hhi8(-(%2))
902         sec\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__
903         sec\;sbc %A0,__zero_reg__\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
904   [(set_attr "length" "4,3,3,4,5,5")
905    (set_attr "cc" "set_n,set_n,set_czn,set_czn,set_n,set_n")])
907 (define_insn "*addsi3_zero_extend"
908   [(set (match_operand:SI 0 "register_operand" "=r")
909         (plus:SI (zero_extend:SI
910                   (match_operand:QI 1 "register_operand" "r"))
911                  (match_operand:SI 2 "register_operand" "0")))]
912   ""
913   "add %A0,%1
914         adc %B0,__zero_reg__
915         adc %C0,__zero_reg__
916         adc %D0,__zero_reg__"
917   [(set_attr "length" "4")
918    (set_attr "cc" "set_n")])
920 ;-----------------------------------------------------------------------------
921 ; sub bytes
922 (define_insn "subqi3"
923   [(set (match_operand:QI 0 "register_operand" "=r,d")
924         (minus:QI (match_operand:QI 1 "register_operand" "0,0")
925                   (match_operand:QI 2 "nonmemory_operand" "r,i")))]
926   ""
927   "@
928         sub %0,%2
929         subi %0,lo8(%2)"
930   [(set_attr "length" "1,1")
931    (set_attr "cc" "set_czn,set_czn")])
933 (define_insn "subhi3"
934   [(set (match_operand:HI 0 "register_operand" "=r,d")
935         (minus:HI (match_operand:HI 1 "register_operand" "0,0")
936                   (match_operand:HI 2 "nonmemory_operand" "r,i")))]
937   ""
938   "@
939         sub %A0,%A2\;sbc %B0,%B2
940         subi %A0,lo8(%2)\;sbci %B0,hi8(%2)"
941   [(set_attr "length" "2,2")
942    (set_attr "cc" "set_czn,set_czn")])
944 (define_insn "*subhi3_zero_extend1"
945   [(set (match_operand:HI 0 "register_operand" "=r")
946         (minus:HI (match_operand:HI 1 "register_operand" "0")
947                   (zero_extend:HI
948                    (match_operand:QI 2 "register_operand" "r"))))]
949   ""
950   "sub %A0,%2
951         sbc %B0,__zero_reg__"
952   [(set_attr "length" "2")
953    (set_attr "cc" "set_n")])
955 (define_insn "subsi3"
956   [(set (match_operand:SI 0 "register_operand" "=r,d")
957         (minus:SI (match_operand:SI 1 "register_operand" "0,0")
958                  (match_operand:SI 2 "nonmemory_operand" "r,i")))]
959   ""
960   "@
961         sub %0,%2\;sbc %B0,%B2\;sbc %C0,%C2\;sbc %D0,%D2
962         subi %A0,lo8(%2)\;sbci %B0,hi8(%2)\;sbci %C0,hlo8(%2)\;sbci %D0,hhi8(%2)"
963   [(set_attr "length" "4,4")
964    (set_attr "cc" "set_czn,set_czn")])
966 (define_insn "*subsi3_zero_extend"
967   [(set (match_operand:SI 0 "register_operand" "=r")
968         (minus:SI (match_operand:SI 1 "register_operand" "0")
969                   (zero_extend:SI
970                    (match_operand:QI 2 "register_operand" "r"))))]
971   ""
972   "sub %A0,%2
973         sbc %B0,__zero_reg__
974         sbc %C0,__zero_reg__
975         sbc %D0,__zero_reg__"
976   [(set_attr "length" "4")
977    (set_attr "cc" "set_n")])
979 ;******************************************************************************
980 ; mul
982 (define_expand "mulqi3"
983   [(set (match_operand:QI 0 "register_operand" "")
984         (mult:QI (match_operand:QI 1 "register_operand" "")
985                  (match_operand:QI 2 "register_operand" "")))]
986   ""
987   "{
988   if (!AVR_HAVE_MUL)
989     {
990       emit_insn (gen_mulqi3_call (operands[0], operands[1], operands[2]));
991       DONE;
992     }
995 (define_insn "*mulqi3_enh"
996   [(set (match_operand:QI 0 "register_operand" "=r")
997         (mult:QI (match_operand:QI 1 "register_operand" "r")
998                  (match_operand:QI 2 "register_operand" "r")))]
999   "AVR_HAVE_MUL"
1000   "mul %1,%2
1001         mov %0,r0
1002         clr r1"
1003   [(set_attr "length" "3")
1004    (set_attr "cc" "clobber")])
1006 (define_expand "mulqi3_call"
1007   [(set (reg:QI 24) (match_operand:QI 1 "register_operand" ""))
1008    (set (reg:QI 22) (match_operand:QI 2 "register_operand" ""))
1009    (parallel [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22)))
1010               (clobber (reg:QI 22))])
1011    (set (match_operand:QI 0 "register_operand" "") (reg:QI 24))]
1012   ""
1013   "")
1015 (define_insn "*mulqi3_call"
1016   [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22)))
1017    (clobber (reg:QI 22))]
1018   "!AVR_HAVE_MUL"
1019   "%~call __mulqi3"
1020   [(set_attr "type" "xcall")
1021    (set_attr "cc" "clobber")])
1023 (define_insn "smulqi3_highpart"
1024   [(set (match_operand:QI 0 "register_operand" "=r")
1025         (truncate:QI
1026          (lshiftrt:HI (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
1027                                (sign_extend:HI (match_operand:QI 2 "register_operand" "d")))
1028                       (const_int 8))))]
1029   "AVR_HAVE_MUL"
1030   "muls %1,%2
1031         mov %0,r1
1032         clr __zero_reg__"
1033   [(set_attr "length" "3")
1034    (set_attr "cc" "clobber")])
1035   
1036 (define_insn "umulqi3_highpart"
1037   [(set (match_operand:QI 0 "register_operand" "=r")
1038         (truncate:QI
1039          (lshiftrt:HI (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1040                                (zero_extend:HI (match_operand:QI 2 "register_operand" "r")))
1041                       (const_int 8))))]
1042   "AVR_HAVE_MUL"
1043   "mul %1,%2
1044         mov %0,r1
1045         clr __zero_reg__"
1046   [(set_attr "length" "3")
1047    (set_attr "cc" "clobber")])
1049 ;; Used when expanding div or mod inline for some special values
1050 (define_insn "*subqi3.ashiftrt7"
1051   [(set (match_operand:QI 0 "register_operand"                       "=r")
1052         (minus:QI (match_operand:QI 1 "register_operand"              "0")
1053                   (ashiftrt:QI (match_operand:QI 2 "register_operand" "r")
1054                                (const_int 7))))]
1055   ""
1056   "sbrc %2,7\;inc %0"
1057   [(set_attr "length" "2")
1058    (set_attr "cc" "clobber")])
1060 (define_insn "mulqihi3"
1061   [(set (match_operand:HI 0 "register_operand" "=r")
1062         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
1063                  (sign_extend:HI (match_operand:QI 2 "register_operand" "d"))))]
1064   "AVR_HAVE_MUL"
1065   "muls %1,%2
1066         movw %0,r0
1067         clr r1"
1068   [(set_attr "length" "3")
1069    (set_attr "cc" "clobber")])
1071 (define_insn "umulqihi3"
1072   [(set (match_operand:HI 0 "register_operand" "=r")
1073         (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1074                  (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1075   "AVR_HAVE_MUL"
1076   "mul %1,%2
1077         movw %0,r0
1078         clr r1"
1079   [(set_attr "length" "3")
1080    (set_attr "cc" "clobber")])
1082 (define_insn "usmulqihi3"
1083   [(set (match_operand:HI 0 "register_operand"                         "=r")
1084         (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "a"))
1085                  (sign_extend:HI (match_operand:QI 2 "register_operand" "a"))))]
1086   "AVR_HAVE_MUL"
1087   "mulsu %2,%1
1088         movw %0,r0
1089         clr __zero_reg__"
1090   [(set_attr "length" "3")
1091    (set_attr "cc" "clobber")])
1093 ;; Above insn is not canonicalized by insn combine, so here is a version with
1094 ;; operands swapped.
1096 (define_insn "*sumulqihi3"
1097   [(set (match_operand:HI 0 "register_operand"                         "=r")
1098         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1099                  (zero_extend:HI (match_operand:QI 2 "register_operand" "a"))))]
1100   "AVR_HAVE_MUL"
1101   "mulsu %1,%2
1102         movw %0,r0
1103         clr __zero_reg__"
1104   [(set_attr "length" "3")
1105    (set_attr "cc" "clobber")])
1107 ;; One-extend operand 1
1109 (define_insn "*osmulqihi3"
1110   [(set (match_operand:HI 0 "register_operand"                                        "=&r")
1111         (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "a"))))
1112                  (sign_extend:HI (match_operand:QI 2 "register_operand"                 "a"))))]
1113   "AVR_HAVE_MUL"
1114   "mulsu %2,%1
1115         movw %0,r0
1116         sub %B0,%2
1117         clr __zero_reg__"
1118   [(set_attr "length" "4")
1119    (set_attr "cc" "clobber")])
1121 (define_insn "*oumulqihi3"
1122   [(set (match_operand:HI 0 "register_operand"                                        "=&r")
1123         (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "r"))))
1124                  (zero_extend:HI (match_operand:QI 2 "register_operand"                 "r"))))]
1125   "AVR_HAVE_MUL"
1126   "mul %2,%1
1127         movw %0,r0
1128         sub %B0,%2
1129         clr __zero_reg__"
1130   [(set_attr "length" "4")
1131    (set_attr "cc" "clobber")])
1134 ;******************************************************************************
1135 ; mul HI: $1 = sign/zero-extend, $2 = small constant
1136 ;******************************************************************************
1138 (define_insn_and_split "*muluqihi3.uconst"
1139   [(set (match_operand:HI 0 "register_operand"                         "=r")
1140         (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1141                  (match_operand:HI 2 "u8_operand"                       "M")))
1142    (clobber (match_scratch:QI 3                                       "=&d"))]
1143   "AVR_HAVE_MUL"
1144   "#"
1145   "&& reload_completed"
1146   [(set (match_dup 3)
1147         (match_dup 2))
1148    ; umulqihi3
1149    (set (match_dup 0)
1150         (mult:HI (zero_extend:HI (match_dup 1))
1151                  (zero_extend:HI (match_dup 3))))]
1152   {
1153     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1154   })
1156 (define_insn_and_split "*muluqihi3.sconst"
1157   [(set (match_operand:HI 0 "register_operand"                         "=r")
1158         (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "a"))
1159                  (match_operand:HI 2 "s8_operand"                       "n")))
1160    (clobber (match_scratch:QI 3                                       "=&a"))]
1161   "AVR_HAVE_MUL"
1162   "#"
1163   "&& reload_completed"
1164   [(set (match_dup 3)
1165         (match_dup 2))
1166    ; usmulqihi3
1167    (set (match_dup 0)
1168         (mult:HI (zero_extend:HI (match_dup 1))
1169                  (sign_extend:HI (match_dup 3))))]
1170   {
1171     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1172   })
1174 (define_insn_and_split "*mulsqihi3.sconst"
1175   [(set (match_operand:HI 0 "register_operand"                         "=r")
1176         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
1177                  (match_operand:HI 2 "s8_operand"                       "n")))
1178    (clobber (match_scratch:QI 3                                       "=&d"))]
1179   "AVR_HAVE_MUL"
1180   "#"
1181   "&& reload_completed"
1182   [(set (match_dup 3)
1183         (match_dup 2))
1184    ; mulqihi3
1185    (set (match_dup 0)
1186         (mult:HI (sign_extend:HI (match_dup 1))
1187                  (sign_extend:HI (match_dup 3))))]
1188   {
1189     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1190   })
1192 (define_insn_and_split "*mulsqihi3.uconst"
1193   [(set (match_operand:HI 0 "register_operand"                         "=r")
1194         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1195                  (match_operand:HI 2 "u8_operand"                       "M")))
1196    (clobber (match_scratch:QI 3                                       "=&a"))]
1197   "AVR_HAVE_MUL"
1198   "#"
1199   "&& reload_completed"
1200   [(set (match_dup 3)
1201         (match_dup 2))
1202    ; usmulqihi3
1203    (set (match_dup 0)
1204         (mult:HI (zero_extend:HI (match_dup 3))
1205                  (sign_extend:HI (match_dup 1))))]
1206   {
1207     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1208   })
1210 (define_insn_and_split "*mulsqihi3.oconst"
1211   [(set (match_operand:HI 0 "register_operand"                        "=&r")
1212         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1213                  (match_operand:HI 2 "o8_operand"                       "n")))
1214    (clobber (match_scratch:QI 3                                       "=&a"))]
1215   "AVR_HAVE_MUL"
1216   "#"
1217   "&& reload_completed"
1218   [(set (match_dup 3)
1219         (match_dup 2))
1220    ; *osmulqihi3
1221    (set (match_dup 0)
1222         (mult:HI (not:HI (zero_extend:HI (not:QI (match_dup 3))))
1223                  (sign_extend:HI (match_dup 1))))]
1224   {
1225     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1226   })
1228 ;; The EXTEND of $1 only appears in combine, we don't see it in expand so that
1229 ;; expand decides to use ASHIFT instead of MUL because ASHIFT costs are cheaper
1230 ;; at that time.  Fix that.
1232 (define_insn_and_split "*ashifthi3.signx.const"
1233   [(set (match_operand:HI 0 "register_operand"                           "=r")
1234         (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
1235                    (match_operand:HI 2 "const_2_to_6_operand"             "I")))
1236    (clobber (match_scratch:QI 3                                         "=&d"))]
1237   "AVR_HAVE_MUL"
1238   "#"
1239   "&& reload_completed"
1240   [(set (match_dup 3)
1241         (match_dup 2))
1242    ; mulqihi3
1243    (set (match_dup 0)
1244         (mult:HI (sign_extend:HI (match_dup 1))
1245                  (sign_extend:HI (match_dup 3))))]
1246   {
1247     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
1248   })
1250 (define_insn_and_split "*ashifthi3.signx.const7"
1251   [(set (match_operand:HI 0 "register_operand"                           "=r")
1252         (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1253                    (const_int 7)))
1254    (clobber (match_scratch:QI 2                                         "=&a"))]
1255   "AVR_HAVE_MUL"
1256   "#"
1257   "&& reload_completed"
1258   [(set (match_dup 2)
1259         (match_dup 3))
1260    ; usmulqihi3
1261    (set (match_dup 0)
1262         (mult:HI (zero_extend:HI (match_dup 2))
1263                  (sign_extend:HI (match_dup 1))))]
1264   {
1265     operands[3] = gen_int_mode (1 << 7, QImode);
1266   })
1268 (define_insn_and_split "*ashifthi3.zerox.const"
1269   [(set (match_operand:HI 0 "register_operand"                           "=r")
1270         (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1271                    (match_operand:HI 2 "const_2_to_7_operand"             "I")))
1272    (clobber (match_scratch:QI 3                                         "=&d"))]
1273   "AVR_HAVE_MUL"
1274   "#"
1275   "&& reload_completed"
1276   [(set (match_dup 3)
1277         (match_dup 2))
1278    ; umulqihi3
1279    (set (match_dup 0)
1280         (mult:HI (zero_extend:HI (match_dup 1))
1281                  (zero_extend:HI (match_dup 3))))]
1282   {
1283     operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
1284   })
1286 ;******************************************************************************
1287 ; mul HI: $1 = sign-/zero-/one-extend, $2 = reg
1288 ;******************************************************************************
1290 (define_insn "mulsqihi3"
1291   [(set (match_operand:HI 0 "register_operand"                        "=&r")
1292         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1293                  (match_operand:HI 2 "register_operand"                 "a")))]
1294   "AVR_HAVE_MUL"
1295   "mulsu %1,%A2
1296         movw %0,r0
1297         mul %1,%B2
1298         add %B0,r0
1299         clr __zero_reg__"
1300   [(set_attr "length" "5")
1301    (set_attr "cc" "clobber")])
1303 (define_insn "muluqihi3"
1304   [(set (match_operand:HI 0 "register_operand"                        "=&r")
1305         (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1306                  (match_operand:HI 2 "register_operand"                 "r")))]
1307   "AVR_HAVE_MUL"
1308   "mul %1,%A2
1309         movw %0,r0
1310         mul %1,%B2
1311         add %B0,r0
1312         clr __zero_reg__"
1313   [(set_attr "length" "5")
1314    (set_attr "cc" "clobber")])
1316 ;; one-extend operand 1
1318 (define_insn "muloqihi3"
1319   [(set (match_operand:HI 0 "register_operand"                                        "=&r")
1320         (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "r"))))
1321                  (match_operand:HI 2 "register_operand"                                 "r")))]
1322   "AVR_HAVE_MUL"
1323   "mul %1,%A2
1324         movw %0,r0
1325         mul %1,%B2
1326         add %B0,r0
1327         sub %B0,%A2
1328         clr __zero_reg__"
1329   [(set_attr "length" "6")
1330    (set_attr "cc" "clobber")])
1332 ;******************************************************************************
1334 (define_expand "mulhi3"
1335   [(set (match_operand:HI 0 "register_operand" "")
1336         (mult:HI (match_operand:HI 1 "register_operand" "")
1337                  (match_operand:HI 2 "register_or_s9_operand" "")))]
1338   ""
1339   {
1340     if (!AVR_HAVE_MUL)
1341       {
1342         if (!register_operand (operands[2], HImode))
1343           operands[2] = force_reg (HImode, operands[2]);
1345         emit_insn (gen_mulhi3_call (operands[0], operands[1], operands[2]));
1346         DONE;
1347       }
1349     /* For small constants we can do better by extending them on the fly.
1350        The constant can be loaded in one instruction and the widening
1351        multiplication is shorter.  First try the unsigned variant because it
1352        allows constraint "d" instead of "a" for the signed version.  */
1354     if (s9_operand (operands[2], HImode))
1355       {
1356         rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
1358         if (u8_operand (operands[2], HImode))
1359           {
1360             emit_insn (gen_muluqihi3 (operands[0], reg, operands[1]));
1361           } 
1362         else if (s8_operand (operands[2], HImode))
1363           {
1364             emit_insn (gen_mulsqihi3 (operands[0], reg, operands[1]));
1365           }
1366         else
1367           {
1368             emit_insn (gen_muloqihi3 (operands[0], reg, operands[1]));
1369           }
1371         DONE;
1372       }
1374     if (!register_operand (operands[2], HImode))
1375       operands[2] = force_reg (HImode, operands[2]);
1376   })
1378 (define_insn "*mulhi3_enh"
1379   [(set (match_operand:HI 0 "register_operand" "=&r")
1380         (mult:HI (match_operand:HI 1 "register_operand" "r")
1381                  (match_operand:HI 2 "register_operand" "r")))]
1382   "AVR_HAVE_MUL"
1383   "mul %A1,%A2
1384         movw %0,r0
1385         mul %A1,%B2
1386         add %B0,r0
1387         mul %B1,%A2
1388         add %B0,r0
1389         clr r1"
1390   [(set_attr "length" "7")
1391    (set_attr "cc" "clobber")])
1393 (define_expand "mulhi3_call"
1394   [(set (reg:HI 24) (match_operand:HI 1 "register_operand" ""))
1395    (set (reg:HI 22) (match_operand:HI 2 "register_operand" ""))
1396    (parallel [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22)))
1397               (clobber (reg:HI 22))
1398               (clobber (reg:QI 21))])
1399    (set (match_operand:HI 0 "register_operand" "") (reg:HI 24))]
1400   ""
1401   "")
1403 (define_insn "*mulhi3_call"
1404   [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22)))
1405    (clobber (reg:HI 22))
1406    (clobber (reg:QI 21))]
1407   "!AVR_HAVE_MUL"
1408   "%~call __mulhi3"
1409   [(set_attr "type" "xcall")
1410    (set_attr "cc" "clobber")])
1412 ;; To support widening multiplicatioon with constant we postpone
1413 ;; expanding to the implicit library call until post combine and
1414 ;; prior to register allocation.  Clobber all hard registers that
1415 ;; might be used by the (widening) multiply until it is split and
1416 ;; it's final register footprint is worked out.
1418 (define_expand "mulsi3"
1419   [(parallel [(set (match_operand:SI 0 "register_operand" "")
1420                    (mult:SI (match_operand:SI 1 "register_operand" "")
1421                             (match_operand:SI 2 "nonmemory_operand" "")))
1422               (clobber (reg:HI 26))
1423               (clobber (reg:DI 18))])]
1424   "AVR_HAVE_MUL"
1425   {
1426     if (u16_operand (operands[2], SImode))
1427       {
1428         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
1429         emit_insn (gen_muluhisi3 (operands[0], operands[2], operands[1]));
1430         DONE;
1431       }
1433     if (o16_operand (operands[2], SImode))
1434       {
1435         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
1436         emit_insn (gen_mulohisi3 (operands[0], operands[2], operands[1]));
1437         DONE;
1438       }
1439   })
1441 (define_insn_and_split "*mulsi3"
1442   [(set (match_operand:SI 0 "pseudo_register_operand"                      "=r")
1443         (mult:SI (match_operand:SI 1 "pseudo_register_operand"              "r")
1444                  (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn")))
1445    (clobber (reg:HI 26))
1446    (clobber (reg:DI 18))]
1447   "AVR_HAVE_MUL && !reload_completed"
1448   { gcc_unreachable(); }
1449   "&& 1"
1450   [(set (reg:SI 18)
1451         (match_dup 1))
1452    (set (reg:SI 22) 
1453         (match_dup 2))
1454    (parallel [(set (reg:SI 22)
1455                    (mult:SI (reg:SI 22)
1456                             (reg:SI 18)))
1457               (clobber (reg:HI 26))])
1458    (set (match_dup 0)
1459         (reg:SI 22))]
1460   {
1461     if (u16_operand (operands[2], SImode))
1462       {
1463         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
1464         emit_insn (gen_muluhisi3 (operands[0], operands[2], operands[1]));
1465         DONE;
1466       }
1468     if (o16_operand (operands[2], SImode))
1469       {
1470         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
1471         emit_insn (gen_mulohisi3 (operands[0], operands[2], operands[1]));
1472         DONE;
1473       }
1474   })
1476 ;; "muluqisi3"
1477 ;; "muluhisi3"
1478 (define_insn_and_split "mulu<mode>si3"
1479   [(set (match_operand:SI 0 "pseudo_register_operand"                           "=r")
1480         (mult:SI (zero_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r"))
1481                  (match_operand:SI 2 "pseudo_register_or_const_int_operand"      "rn")))
1482    (clobber (reg:HI 26))
1483    (clobber (reg:DI 18))]
1484   "AVR_HAVE_MUL && !reload_completed"
1485   { gcc_unreachable(); }
1486   "&& 1"
1487   [(set (reg:HI 26)
1488         (match_dup 1))
1489    (set (reg:SI 18)
1490         (match_dup 2))
1491    (set (reg:SI 22)
1492         (mult:SI (zero_extend:SI (reg:HI 26))
1493                  (reg:SI 18)))
1494    (set (match_dup 0)
1495         (reg:SI 22))]
1496   {
1497     /* Do the QI -> HI extension explicitely before the multiplication.  */
1498     /* Do the HI -> SI extension implicitely and after the multiplication.  */
1499        
1500     if (QImode == <MODE>mode)
1501       operands[1] = gen_rtx_ZERO_EXTEND (HImode, operands[1]);
1503     if (u16_operand (operands[2], SImode))
1504       {
1505         operands[1] = force_reg (HImode, operands[1]);
1506         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
1507         emit_insn (gen_umulhisi3 (operands[0], operands[1], operands[2]));
1508         DONE;
1509       }
1510   })
1512 ;; "mulsqisi3"
1513 ;; "mulshisi3"
1514 (define_insn_and_split "muls<mode>si3"
1515   [(set (match_operand:SI 0 "pseudo_register_operand"                           "=r")
1516         (mult:SI (sign_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r"))
1517                  (match_operand:SI 2 "pseudo_register_or_const_int_operand"      "rn")))
1518    (clobber (reg:HI 26))
1519    (clobber (reg:DI 18))]
1520   "AVR_HAVE_MUL && !reload_completed"
1521   { gcc_unreachable(); }
1522   "&& 1"
1523   [(set (reg:HI 26)
1524         (match_dup 1))
1525    (set (reg:SI 18)
1526         (match_dup 2))
1527    (set (reg:SI 22)
1528         (mult:SI (sign_extend:SI (reg:HI 26))
1529                  (reg:SI 18)))
1530    (set (match_dup 0)
1531         (reg:SI 22))]
1532   {
1533     /* Do the QI -> HI extension explicitely before the multiplication.  */
1534     /* Do the HI -> SI extension implicitely and after the multiplication.  */
1535        
1536     if (QImode == <MODE>mode)
1537       operands[1] = gen_rtx_SIGN_EXTEND (HImode, operands[1]);
1539     if (u16_operand (operands[2], SImode)
1540         || s16_operand (operands[2], SImode))
1541       {
1542         rtx xop2 = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
1544         operands[1] = force_reg (HImode, operands[1]);
1546         if (u16_operand (operands[2], SImode))
1547           emit_insn (gen_usmulhisi3 (operands[0], xop2, operands[1]));
1548         else
1549           emit_insn (gen_mulhisi3 (operands[0], operands[1], xop2));
1551         DONE;
1552       }
1553   })
1555 ;; One-extend operand 1
1557 (define_insn_and_split "mulohisi3"
1558   [(set (match_operand:SI 0 "pseudo_register_operand"                          "=r")
1559         (mult:SI (not:SI (zero_extend:SI 
1560                           (not:HI (match_operand:HI 1 "pseudo_register_operand" "r"))))
1561                  (match_operand:SI 2 "pseudo_register_or_const_int_operand"     "rn")))
1562    (clobber (reg:HI 26))
1563    (clobber (reg:DI 18))]
1564   "AVR_HAVE_MUL && !reload_completed"
1565   { gcc_unreachable(); }
1566   "&& 1"
1567   [(set (reg:HI 26)
1568         (match_dup 1))
1569    (set (reg:SI 18)
1570         (match_dup 2))
1571    (set (reg:SI 22)
1572         (mult:SI (not:SI (zero_extend:SI (not:HI (reg:HI 26))))
1573                  (reg:SI 18)))
1574    (set (match_dup 0)
1575         (reg:SI 22))]
1576   "")
1578 ;; "mulhisi3"
1579 ;; "umulhisi3"
1580 (define_expand "<extend_u>mulhisi3"
1581   [(parallel [(set (match_operand:SI 0 "register_operand" "")
1582                    (mult:SI (any_extend:SI (match_operand:HI 1 "register_operand" ""))
1583                             (any_extend:SI (match_operand:HI 2 "register_operand" ""))))
1584               (clobber (reg:HI 26))
1585               (clobber (reg:DI 18))])]
1586   "AVR_HAVE_MUL"
1587   "")
1589 (define_expand "usmulhisi3"
1590   [(parallel [(set (match_operand:SI 0 "register_operand" "")
1591                    (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" ""))
1592                             (sign_extend:SI (match_operand:HI 2 "register_operand" ""))))
1593               (clobber (reg:HI 26))
1594               (clobber (reg:DI 18))])]
1595   "AVR_HAVE_MUL"
1596   "")
1598 ;; "*uumulqihisi3" "*uumulhiqisi3" "*uumulhihisi3" "*uumulqiqisi3"
1599 ;; "*usmulqihisi3" "*usmulhiqisi3" "*usmulhihisi3" "*usmulqiqisi3"
1600 ;; "*sumulqihisi3" "*sumulhiqisi3" "*sumulhihisi3" "*sumulqiqisi3"
1601 ;; "*ssmulqihisi3" "*ssmulhiqisi3" "*ssmulhihisi3" "*ssmulqiqisi3"
1602 (define_insn_and_split
1603   "*<any_extend:extend_su><any_extend2:extend_su>mul<QIHI:mode><QIHI2:mode>si3"
1604   [(set (match_operand:SI 0 "pseudo_register_operand"                            "=r")
1605         (mult:SI (any_extend:SI (match_operand:QIHI 1 "pseudo_register_operand"   "r"))
1606                  (any_extend2:SI (match_operand:QIHI2 2 "pseudo_register_operand" "r"))))
1607    (clobber (reg:HI 26))
1608    (clobber (reg:DI 18))]
1609   "AVR_HAVE_MUL && !reload_completed"
1610   { gcc_unreachable(); }
1611   "&& 1"
1612   [(set (reg:HI 18)
1613         (match_dup 1))
1614    (set (reg:HI 26)
1615         (match_dup 2))
1616    (set (reg:SI 22)
1617         (mult:SI (match_dup 3)
1618                  (match_dup 4)))
1619    (set (match_dup 0)
1620         (reg:SI 22))]
1621   {
1622     rtx xop1 = operands[1];
1623     rtx xop2 = operands[2];
1625     /* Do the QI -> HI extension explicitely before the multiplication.  */
1626     /* Do the HI -> SI extension implicitely and after the multiplication.  */
1627        
1628     if (QImode == <QIHI:MODE>mode)
1629       xop1 = gen_rtx_fmt_e (<any_extend:CODE>, HImode, xop1);
1631     if (QImode == <QIHI2:MODE>mode)
1632       xop2 = gen_rtx_fmt_e (<any_extend2:CODE>, HImode, xop2);
1634     if (<any_extend:CODE> == <any_extend2:CODE>
1635         || <any_extend:CODE> == ZERO_EXTEND)
1636       {
1637         operands[1] = xop1;
1638         operands[2] = xop2;
1639         operands[3] = gen_rtx_fmt_e (<any_extend:CODE>, SImode, gen_rtx_REG (HImode, 18));
1640         operands[4] = gen_rtx_fmt_e (<any_extend2:CODE>, SImode, gen_rtx_REG (HImode, 26));
1641       }
1642     else
1643       {
1644         /* <any_extend:CODE>  = SIGN_EXTEND */
1645         /* <any_extend2:CODE> = ZERO_EXTEND */
1647         operands[1] = xop2;
1648         operands[2] = xop1;
1649         operands[3] = gen_rtx_ZERO_EXTEND (SImode, gen_rtx_REG (HImode, 18));
1650         operands[4] = gen_rtx_SIGN_EXTEND (SImode, gen_rtx_REG (HImode, 26));
1651       }
1652   })
1654 ;; "smulhi3_highpart"
1655 ;; "umulhi3_highpart"
1656 (define_expand "<extend_su>mulhi3_highpart"
1657   [(set (reg:HI 18)
1658         (match_operand:HI 1 "nonmemory_operand" ""))
1659    (set (reg:HI 26)
1660         (match_operand:HI 2 "nonmemory_operand" ""))
1661    (parallel [(set (reg:HI 24)
1662                    (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
1663                                                       (any_extend:SI (reg:HI 26)))
1664                                              (const_int 16))))
1665               (clobber (reg:HI 22))])
1666    (set (match_operand:HI 0 "register_operand" "")
1667         (reg:HI 24))]
1668   "AVR_HAVE_MUL"
1669   "")
1672 (define_insn "*mulsi3_call"
1673   [(set (reg:SI 22)
1674         (mult:SI (reg:SI 22)
1675                  (reg:SI 18)))
1676    (clobber (reg:HI 26))]
1677   "AVR_HAVE_MUL"
1678   "%~call __mulsi3"
1679   [(set_attr "type" "xcall")
1680    (set_attr "cc" "clobber")])
1682 ;; "*mulhisi3_call"
1683 ;; "*umulhisi3_call"
1684 (define_insn "*<extend_u>mulhisi3_call"
1685   [(set (reg:SI 22)
1686         (mult:SI (any_extend:SI (reg:HI 18))
1687                  (any_extend:SI (reg:HI 26))))]
1688   "AVR_HAVE_MUL"
1689   "%~call __<extend_u>mulhisi3"
1690   [(set_attr "type" "xcall")
1691    (set_attr "cc" "clobber")])
1693 ;; "*umulhi3_highpart_call"
1694 ;; "*smulhi3_highpart_call"
1695 (define_insn "*<extend_su>mulhi3_highpart_call"
1696   [(set (reg:HI 24)
1697         (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
1698                                            (any_extend:SI (reg:HI 26)))
1699                                   (const_int 16))))
1700    (clobber (reg:HI 22))]
1701   "AVR_HAVE_MUL"
1702   "%~call __<extend_u>mulhisi3"
1703   [(set_attr "type" "xcall")
1704    (set_attr "cc" "clobber")])
1706 (define_insn "*usmulhisi3_call"
1707   [(set (reg:SI 22)
1708         (mult:SI (zero_extend:SI (reg:HI 18))
1709                  (sign_extend:SI (reg:HI 26))))]
1710   "AVR_HAVE_MUL"
1711   "%~call __usmulhisi3"
1712   [(set_attr "type" "xcall")
1713    (set_attr "cc" "clobber")])
1715 (define_insn "*mul<extend_su>hisi3_call"
1716   [(set (reg:SI 22)
1717         (mult:SI (any_extend:SI (reg:HI 26))
1718                  (reg:SI 18)))]
1719   "AVR_HAVE_MUL"
1720   "%~call __mul<extend_su>hisi3"
1721   [(set_attr "type" "xcall")
1722    (set_attr "cc" "clobber")])
1724 (define_insn "*mulohisi3_call"
1725   [(set (reg:SI 22)
1726         (mult:SI (not:SI (zero_extend:SI (not:HI (reg:HI 26))))
1727                  (reg:SI 18)))]
1728   "AVR_HAVE_MUL"
1729   "%~call __mulohisi3"
1730   [(set_attr "type" "xcall")
1731    (set_attr "cc" "clobber")])
1733 ; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / %
1734 ; divmod
1736 ;; Generate libgcc.S calls ourselves, because:
1737 ;;  - we know exactly which registers are clobbered (for QI and HI
1738 ;;    modes, some of the call-used registers are preserved)
1739 ;;  - we get both the quotient and the remainder at no extra cost
1740 ;;  - we split the patterns only after the first CSE passes because
1741 ;;    CSE has problems to operate on hard regs.
1742 ;; 
1743 (define_insn_and_split "divmodqi4"
1744   [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "") 
1745                    (div:QI (match_operand:QI 1 "pseudo_register_operand" "") 
1746                            (match_operand:QI 2 "pseudo_register_operand" "")))
1747               (set (match_operand:QI 3 "pseudo_register_operand" "") 
1748                    (mod:QI (match_dup 1) (match_dup 2)))
1749               (clobber (reg:QI 22)) 
1750               (clobber (reg:QI 23)) 
1751               (clobber (reg:QI 24)) 
1752               (clobber (reg:QI 25))])]
1753   ""
1754   "this divmodqi4 pattern should have been splitted;"
1755   ""
1756   [(set (reg:QI 24) (match_dup 1))
1757    (set (reg:QI 22) (match_dup 2))
1758    (parallel [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
1759               (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
1760               (clobber (reg:QI 22))
1761               (clobber (reg:QI 23))])
1762    (set (match_dup 0) (reg:QI 24))
1763    (set (match_dup 3) (reg:QI 25))]
1764   "")
1766 (define_insn "*divmodqi4_call"
1767   [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
1768    (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
1769    (clobber (reg:QI 22))
1770    (clobber (reg:QI 23))]
1771   ""
1772   "%~call __divmodqi4"
1773   [(set_attr "type" "xcall")
1774    (set_attr "cc" "clobber")])
1776 (define_insn_and_split "udivmodqi4"
1777  [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "") 
1778                   (udiv:QI (match_operand:QI 1 "pseudo_register_operand" "") 
1779                            (match_operand:QI 2 "pseudo_register_operand" "")))
1780              (set (match_operand:QI 3 "pseudo_register_operand" "") 
1781                   (umod:QI (match_dup 1) (match_dup 2)))
1782              (clobber (reg:QI 22))
1783              (clobber (reg:QI 23))
1784              (clobber (reg:QI 24))
1785              (clobber (reg:QI 25))])]
1786   ""
1787   "this udivmodqi4 pattern should have been splitted;"
1788   "" 
1789   [(set (reg:QI 24) (match_dup 1))
1790    (set (reg:QI 22) (match_dup 2))
1791    (parallel [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
1792               (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
1793               (clobber (reg:QI 23))])
1794    (set (match_dup 0) (reg:QI 24))
1795    (set (match_dup 3) (reg:QI 25))]
1796   "")
1798 (define_insn "*udivmodqi4_call"
1799   [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
1800    (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
1801    (clobber (reg:QI 23))]
1802   ""
1803   "%~call __udivmodqi4"
1804   [(set_attr "type" "xcall")
1805    (set_attr "cc" "clobber")])
1807 (define_insn_and_split "divmodhi4"
1808   [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "") 
1809                    (div:HI (match_operand:HI 1 "pseudo_register_operand" "") 
1810                            (match_operand:HI 2 "pseudo_register_operand" "")))
1811               (set (match_operand:HI 3 "pseudo_register_operand" "") 
1812                    (mod:HI (match_dup 1) (match_dup 2)))
1813               (clobber (reg:QI 21))
1814               (clobber (reg:HI 22))
1815               (clobber (reg:HI 24))
1816               (clobber (reg:HI 26))])]
1817   ""
1818   "this should have been splitted;"
1819   ""
1820   [(set (reg:HI 24) (match_dup 1))
1821    (set (reg:HI 22) (match_dup 2))
1822    (parallel [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
1823               (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
1824               (clobber (reg:HI 26))
1825               (clobber (reg:QI 21))])
1826    (set (match_dup 0) (reg:HI 22))
1827    (set (match_dup 3) (reg:HI 24))]
1828   "") 
1830 (define_insn "*divmodhi4_call"
1831   [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
1832    (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
1833    (clobber (reg:HI 26))
1834    (clobber (reg:QI 21))]
1835   ""
1836   "%~call __divmodhi4"
1837   [(set_attr "type" "xcall")
1838    (set_attr "cc" "clobber")])
1840 (define_insn_and_split "udivmodhi4"
1841   [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "") 
1842                    (udiv:HI (match_operand:HI 1 "pseudo_register_operand" "")
1843                             (match_operand:HI 2 "pseudo_register_operand" "")))
1844               (set (match_operand:HI 3 "pseudo_register_operand" "") 
1845                    (umod:HI (match_dup 1) (match_dup 2)))
1846               (clobber (reg:QI 21))
1847               (clobber (reg:HI 22))
1848               (clobber (reg:HI 24))
1849               (clobber (reg:HI 26))])]
1850   ""
1851   "this udivmodhi4 pattern should have been splitted.;"
1852   ""
1853   [(set (reg:HI 24) (match_dup 1))
1854    (set (reg:HI 22) (match_dup 2))
1855    (parallel [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
1856               (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
1857               (clobber (reg:HI 26))
1858               (clobber (reg:QI 21))])
1859    (set (match_dup 0) (reg:HI 22))
1860    (set (match_dup 3) (reg:HI 24))]
1861   "")
1863 (define_insn "*udivmodhi4_call"
1864   [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
1865    (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
1866    (clobber (reg:HI 26))
1867    (clobber (reg:QI 21))]
1868   ""
1869   "%~call __udivmodhi4"
1870   [(set_attr "type" "xcall")
1871    (set_attr "cc" "clobber")])
1873 (define_insn_and_split "divmodsi4"
1874   [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") 
1875                    (div:SI (match_operand:SI 1 "pseudo_register_operand" "") 
1876                            (match_operand:SI 2 "pseudo_register_operand" "")))
1877               (set (match_operand:SI 3 "pseudo_register_operand" "") 
1878                    (mod:SI (match_dup 1) (match_dup 2)))
1879               (clobber (reg:SI 18))
1880               (clobber (reg:SI 22))
1881               (clobber (reg:HI 26))
1882               (clobber (reg:HI 30))])]
1883   ""
1884   "this divmodsi4 pattern should have been splitted;" 
1885   ""
1886   [(set (reg:SI 22) (match_dup 1))
1887    (set (reg:SI 18) (match_dup 2))
1888    (parallel [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
1889               (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
1890               (clobber (reg:HI 26))
1891               (clobber (reg:HI 30))])
1892    (set (match_dup 0) (reg:SI 18))
1893    (set (match_dup 3) (reg:SI 22))]
1894   "")
1896 (define_insn "*divmodsi4_call"
1897   [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
1898    (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
1899    (clobber (reg:HI 26))
1900    (clobber (reg:HI 30))]
1901   ""
1902   "%~call __divmodsi4"
1903   [(set_attr "type" "xcall")
1904    (set_attr "cc" "clobber")])
1906 (define_insn_and_split "udivmodsi4"
1907   [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") 
1908                    (udiv:SI (match_operand:SI 1 "pseudo_register_operand" "") 
1909                            (match_operand:SI 2 "pseudo_register_operand" "")))
1910               (set (match_operand:SI 3 "pseudo_register_operand" "") 
1911                    (umod:SI (match_dup 1) (match_dup 2)))
1912               (clobber (reg:SI 18))
1913               (clobber (reg:SI 22))
1914               (clobber (reg:HI 26))
1915               (clobber (reg:HI 30))])]
1916   ""
1917   "this udivmodsi4 pattern should have been splitted;"
1918   ""
1919   [(set (reg:SI 22) (match_dup 1))
1920    (set (reg:SI 18) (match_dup 2))
1921    (parallel [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
1922               (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
1923               (clobber (reg:HI 26))
1924               (clobber (reg:HI 30))])
1925    (set (match_dup 0) (reg:SI 18))
1926    (set (match_dup 3) (reg:SI 22))]
1927   "")
1929 (define_insn "*udivmodsi4_call"
1930   [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
1931    (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
1932    (clobber (reg:HI 26))
1933    (clobber (reg:HI 30))]
1934   ""
1935   "%~call __udivmodsi4"
1936   [(set_attr "type" "xcall")
1937    (set_attr "cc" "clobber")])
1939 ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1940 ; and
1942 (define_insn "andqi3"
1943   [(set (match_operand:QI 0 "register_operand" "=r,d")
1944         (and:QI (match_operand:QI 1 "register_operand" "%0,0")
1945                 (match_operand:QI 2 "nonmemory_operand" "r,i")))]
1946   ""
1947   "@
1948         and %0,%2
1949         andi %0,lo8(%2)"
1950   [(set_attr "length" "1,1")
1951    (set_attr "cc" "set_zn,set_zn")])
1953 (define_insn "andhi3"
1954   [(set (match_operand:HI 0 "register_operand" "=r,d,r")
1955           (and:HI (match_operand:HI 1 "register_operand" "%0,0,0")
1956                   (match_operand:HI 2 "nonmemory_operand" "r,i,M")))
1957    (clobber (match_scratch:QI 3 "=X,X,&d"))]
1958   ""
1960   if (which_alternative==0)
1961     return ("and %A0,%A2" CR_TAB
1962             "and %B0,%B2");
1963   else if (which_alternative==1)
1964     {
1965       if (GET_CODE (operands[2]) == CONST_INT)
1966         {
1967           int mask = INTVAL (operands[2]);
1968           if ((mask & 0xff) != 0xff)
1969             output_asm_insn (AS2 (andi,%A0,lo8(%2)), operands);
1970           if ((mask & 0xff00) != 0xff00)
1971             output_asm_insn (AS2 (andi,%B0,hi8(%2)), operands);
1972           return "";
1973         }
1974         return (AS2 (andi,%A0,lo8(%2)) CR_TAB
1975                 AS2 (andi,%B0,hi8(%2)));
1976      }
1977   return (AS2 (ldi,%3,lo8(%2)) CR_TAB
1978           "and %A0,%3"         CR_TAB
1979           AS1 (clr,%B0));
1981   [(set_attr "length" "2,2,3")
1982    (set_attr "cc" "set_n,clobber,set_n")])
1984 (define_insn "andsi3"
1985   [(set (match_operand:SI 0 "register_operand" "=r,d")
1986         (and:SI (match_operand:SI 1 "register_operand" "%0,0")
1987                 (match_operand:SI 2 "nonmemory_operand" "r,i")))]
1988   ""
1990   if (which_alternative==0)
1991     return ("and %0,%2"   CR_TAB
1992             "and %B0,%B2" CR_TAB
1993             "and %C0,%C2" CR_TAB
1994             "and %D0,%D2");
1995   else if (which_alternative==1)
1996     {
1997       if (GET_CODE (operands[2]) == CONST_INT)
1998         {
1999           HOST_WIDE_INT mask = INTVAL (operands[2]);
2000           if ((mask & 0xff) != 0xff)
2001             output_asm_insn (AS2 (andi,%A0,lo8(%2)), operands);
2002           if ((mask & 0xff00) != 0xff00)
2003             output_asm_insn (AS2 (andi,%B0,hi8(%2)), operands);
2004           if ((mask & 0xff0000L) != 0xff0000L)
2005             output_asm_insn (AS2 (andi,%C0,hlo8(%2)), operands);
2006           if ((mask & 0xff000000L) != 0xff000000L)
2007             output_asm_insn (AS2 (andi,%D0,hhi8(%2)), operands);
2008           return "";
2009         }
2010       return (AS2 (andi, %A0,lo8(%2))  CR_TAB
2011               AS2 (andi, %B0,hi8(%2)) CR_TAB
2012               AS2 (andi, %C0,hlo8(%2)) CR_TAB
2013               AS2 (andi, %D0,hhi8(%2)));
2014     }
2015   return "bug";
2017   [(set_attr "length" "4,4")
2018    (set_attr "cc" "set_n,clobber")])
2020 (define_peephole2 ; andi
2021   [(set (match_operand:QI 0 "d_register_operand" "")
2022         (and:QI (match_dup 0)
2023                 (match_operand:QI 1 "const_int_operand" "")))
2024    (set (match_dup 0)
2025         (and:QI (match_dup 0)
2026                 (match_operand:QI 2 "const_int_operand" "")))]
2027   ""
2028   [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
2029   {
2030     operands[1] = GEN_INT (INTVAL (operands[1]) & INTVAL (operands[2]));
2031   })
2033 ;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2034 ;; ior
2036 (define_insn "iorqi3"
2037   [(set (match_operand:QI 0 "register_operand" "=r,d")
2038         (ior:QI (match_operand:QI 1 "register_operand" "%0,0")
2039                 (match_operand:QI 2 "nonmemory_operand" "r,i")))]
2040   ""
2041   "@
2042         or %0,%2
2043         ori %0,lo8(%2)"
2044   [(set_attr "length" "1,1")
2045    (set_attr "cc" "set_zn,set_zn")])
2047 (define_insn "iorhi3"
2048   [(set (match_operand:HI 0 "register_operand" "=r,d")
2049         (ior:HI (match_operand:HI 1 "register_operand" "%0,0")
2050                 (match_operand:HI 2 "nonmemory_operand" "r,i")))]
2051   ""
2053   if (which_alternative==0)
2054     return ("or %A0,%A2" CR_TAB
2055             "or %B0,%B2");
2056   if (GET_CODE (operands[2]) == CONST_INT)
2057      {
2058         int mask = INTVAL (operands[2]);
2059         if (mask & 0xff)
2060           output_asm_insn (AS2 (ori,%A0,lo8(%2)), operands);
2061         if (mask & 0xff00)
2062           output_asm_insn (AS2 (ori,%B0,hi8(%2)), operands);
2063         return "";
2064       }
2065    return (AS2 (ori,%0,lo8(%2)) CR_TAB
2066            AS2 (ori,%B0,hi8(%2)));
2068   [(set_attr "length" "2,2")
2069    (set_attr "cc" "set_n,clobber")])
2071 (define_insn "*iorhi3_clobber"
2072   [(set (match_operand:HI 0 "register_operand" "=r,r")
2073         (ior:HI (match_operand:HI 1 "register_operand" "%0,0")
2074                 (match_operand:HI 2 "immediate_operand" "M,i")))
2075    (clobber (match_scratch:QI 3 "=&d,&d"))]
2076   ""
2077   "@
2078         ldi %3,lo8(%2)\;or %A0,%3
2079         ldi %3,lo8(%2)\;or %A0,%3\;ldi %3,hi8(%2)\;or %B0,%3"
2080   [(set_attr "length" "2,4")
2081    (set_attr "cc" "clobber,set_n")])
2083 (define_insn "iorsi3"
2084   [(set (match_operand:SI 0 "register_operand"        "=r,d")
2085         (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
2086                 (match_operand:SI 2 "nonmemory_operand" "r,i")))]
2087   ""
2089   if (which_alternative==0)
2090     return ("or %0,%2"   CR_TAB
2091             "or %B0,%B2" CR_TAB
2092             "or %C0,%C2" CR_TAB
2093             "or %D0,%D2");
2094   if (GET_CODE (operands[2]) == CONST_INT)
2095      {
2096         HOST_WIDE_INT mask = INTVAL (operands[2]);
2097         if (mask & 0xff)
2098           output_asm_insn (AS2 (ori,%A0,lo8(%2)), operands);
2099         if (mask & 0xff00)
2100           output_asm_insn (AS2 (ori,%B0,hi8(%2)), operands);
2101         if (mask & 0xff0000L)
2102           output_asm_insn (AS2 (ori,%C0,hlo8(%2)), operands);
2103         if (mask & 0xff000000L)
2104           output_asm_insn (AS2 (ori,%D0,hhi8(%2)), operands);
2105         return "";
2106       }
2107   return (AS2 (ori, %A0,lo8(%2))  CR_TAB
2108           AS2 (ori, %B0,hi8(%2)) CR_TAB
2109           AS2 (ori, %C0,hlo8(%2)) CR_TAB
2110           AS2 (ori, %D0,hhi8(%2)));
2112   [(set_attr "length" "4,4")
2113    (set_attr "cc" "set_n,clobber")])
2115 (define_insn "*iorsi3_clobber"
2116   [(set (match_operand:SI 0 "register_operand"        "=r,r")
2117         (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
2118                 (match_operand:SI 2 "immediate_operand" "M,i")))
2119    (clobber (match_scratch:QI 3 "=&d,&d"))]
2120   ""
2121   "@
2122         ldi %3,lo8(%2)\;or %A0,%3
2123         ldi %3,lo8(%2)\;or %A0,%3\;ldi %3,hi8(%2)\;or %B0,%3\;ldi %3,hlo8(%2)\;or %C0,%3\;ldi %3,hhi8(%2)\;or %D0,%3"
2124   [(set_attr "length" "2,8")
2125    (set_attr "cc" "clobber,set_n")])
2127 ;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2128 ;; xor
2130 (define_insn "xorqi3"
2131   [(set (match_operand:QI 0 "register_operand" "=r")
2132         (xor:QI (match_operand:QI 1 "register_operand" "%0")
2133                 (match_operand:QI 2 "register_operand" "r")))]
2134   ""
2135   "eor %0,%2"
2136   [(set_attr "length" "1")
2137    (set_attr "cc" "set_zn")])
2139 (define_insn "xorhi3"
2140   [(set (match_operand:HI 0 "register_operand" "=r")
2141         (xor:HI (match_operand:HI 1 "register_operand" "%0")
2142                 (match_operand:HI 2 "register_operand" "r")))]
2143   ""
2144   "eor %0,%2
2145         eor %B0,%B2"
2146   [(set_attr "length" "2")
2147    (set_attr "cc" "set_n")])
2149 (define_insn "xorsi3"
2150   [(set (match_operand:SI 0 "register_operand" "=r")
2151         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2152                 (match_operand:SI 2 "register_operand" "r")))]
2153   ""
2154   "eor %0,%2
2155         eor %B0,%B2
2156         eor %C0,%C2
2157         eor %D0,%D2"
2158   [(set_attr "length" "4")
2159    (set_attr "cc" "set_n")])
2161 ;; swap swap swap swap swap swap swap swap swap swap swap swap swap swap swap
2162 ;; swap
2164 (define_expand "rotlqi3"
2165   [(set (match_operand:QI 0 "register_operand" "")
2166         (rotate:QI (match_operand:QI 1 "register_operand" "")
2167                    (match_operand:QI 2 "const_int_operand" "")))]
2168   ""
2169   "
2171   if (!CONST_INT_P (operands[2]) || (INTVAL (operands[2]) != 4))
2172     FAIL;
2175 (define_insn "rotlqi3_4"
2176   [(set (match_operand:QI 0 "register_operand" "=r")
2177         (rotate:QI (match_operand:QI 1 "register_operand" "0")
2178                    (const_int 4)))]
2179   ""
2180   "swap %0"
2181   [(set_attr "length" "1")
2182    (set_attr "cc" "none")])
2184 ;; Split all rotates of HI,SI and DImode registers where rotation is by
2185 ;; a whole number of bytes.  The split creates the appropriate moves and
2186 ;; considers all overlap situations.  DImode is split before reload.
2188 ;; HImode does not need scratch.  Use attribute for this constraint.
2189 ;; Use QI scratch for DI mode as this is often split into byte sized operands.
2191 (define_mode_attr rotx [(DI "&r,&r,X") (SI "&r,&r,X") (HI "X,X,X")])
2192 (define_mode_attr rotsmode [(DI "QI") (SI "HI") (HI "QI")])
2194 (define_expand "rotl<mode>3"
2195   [(parallel [(set (match_operand:HIDI 0 "register_operand" "")
2196                    (rotate:HIDI (match_operand:HIDI 1 "register_operand" "")
2197                                 (match_operand:VOID 2 "const_int_operand" "")))
2198                 (clobber (match_dup 3))])]
2199   ""
2200   {
2201     if (CONST_INT_P (operands[2])
2202         && 0 == INTVAL (operands[2]) % 8)
2203       {
2204         if (AVR_HAVE_MOVW && 0 == INTVAL (operands[2]) % 16)
2205           operands[3] = gen_rtx_SCRATCH (<rotsmode>mode);
2206         else
2207           operands[3] = gen_rtx_SCRATCH (QImode);
2208       }
2209     else
2210       FAIL;
2211   })
2214 ;; Overlapping non-HImode registers often (but not always) need a scratch.
2215 ;; The best we can do is use early clobber alternative "#&r" so that
2216 ;; completely non-overlapping operands dont get a scratch but # so register
2217 ;; allocation does not prefer non-overlapping.
2220 ; Split word aligned rotates using scratch that is mode dependent.
2221 (define_insn_and_split "*rotw<mode>"
2222   [(set (match_operand:HIDI 0 "register_operand" "=r,r,#&r")
2223         (rotate:HIDI (match_operand:HIDI 1 "register_operand" "0,r,r")
2224                      (match_operand 2 "const_int_operand" "n,n,n")))
2225    (clobber (match_scratch:<rotsmode> 3 "=<rotx>"))]
2226   "AVR_HAVE_MOVW
2227    && CONST_INT_P (operands[2])
2228    && 0 == INTVAL (operands[2]) % 16"
2229   "#"
2230   "&& (reload_completed || <MODE>mode == DImode)"
2231   [(const_int 0)]
2232   {
2233     avr_rotate_bytes (operands);
2234     DONE;
2235   })
2238 ; Split byte aligned rotates using scratch that is always QI mode.
2239 (define_insn_and_split "*rotb<mode>"
2240   [(set (match_operand:HIDI 0 "register_operand" "=r,r,#&r")
2241         (rotate:HIDI (match_operand:HIDI 1 "register_operand" "0,r,r")
2242                      (match_operand 2 "const_int_operand" "n,n,n")))
2243    (clobber (match_scratch:QI 3 "=<rotx>"))]
2244   "CONST_INT_P (operands[2])
2245    && (8 == INTVAL (operands[2]) % 16
2246        || (!AVR_HAVE_MOVW
2247            && 0 == INTVAL (operands[2]) % 16))"
2248   "#"
2249   "&& (reload_completed || <MODE>mode == DImode)"
2250   [(const_int 0)]
2251   {
2252     avr_rotate_bytes (operands);
2253     DONE;
2254   })
2257 ;;<< << << << << << << << << << << << << << << << << << << << << << << << << <<
2258 ;; arithmetic shift left
2260 (define_expand "ashlqi3"
2261   [(set (match_operand:QI 0 "register_operand"            "")
2262         (ashift:QI (match_operand:QI 1 "register_operand" "")
2263                    (match_operand:QI 2 "general_operand"  "")))]
2264   ""
2265   "")
2267 (define_split ; ashlqi3_const4
2268   [(set (match_operand:QI 0 "d_register_operand" "")
2269         (ashift:QI (match_dup 0)
2270                    (const_int 4)))]
2271   ""
2272   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
2273    (set (match_dup 0) (and:QI (match_dup 0) (const_int -16)))]
2274   "")
2276 (define_split ; ashlqi3_const5
2277   [(set (match_operand:QI 0 "d_register_operand" "")
2278         (ashift:QI (match_dup 0)
2279                    (const_int 5)))]
2280   ""
2281   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
2282    (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))
2283    (set (match_dup 0) (and:QI (match_dup 0) (const_int -32)))]
2284   "")
2286 (define_split ; ashlqi3_const6
2287   [(set (match_operand:QI 0 "d_register_operand" "")
2288         (ashift:QI (match_dup 0)
2289                    (const_int 6)))]
2290   ""
2291   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
2292    (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 2)))
2293    (set (match_dup 0) (and:QI (match_dup 0) (const_int -64)))]
2294   "")
2296 (define_insn "*ashlqi3"
2297   [(set (match_operand:QI 0 "register_operand"           "=r,r,r,r,!d,r,r")
2298         (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0,0,0")
2299                    (match_operand:QI 2 "general_operand"  "r,L,P,K,n,n,Qm")))]
2300   ""
2301   "* return ashlqi3_out (insn, operands, NULL);"
2302   [(set_attr "length" "5,0,1,2,4,6,9")
2303    (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")])
2305 (define_insn "ashlhi3"
2306   [(set (match_operand:HI 0 "register_operand"           "=r,r,r,r,r,r,r")
2307         (ashift:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
2308                    (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
2309   ""
2310   "* return ashlhi3_out (insn, operands, NULL);"
2311   [(set_attr "length" "6,0,2,2,4,10,10")
2312    (set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")])
2315 ;; Insns like the following are generated when (implicitly) extending 8-bit shifts
2316 ;; like char1 = char2 << char3.  Only the low-byte is needed in that situation.
2318 ;; "*ashluqihiqi3"
2319 ;; "*ashlsqihiqi3"
2320 (define_insn_and_split "*ashl<extend_su>qihiqi3"
2321   [(set (match_operand:QI 0 "register_operand"                                     "=r")
2322         (subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "0"))
2323                               (match_operand:QI 2 "register_operand"                "r"))
2324                    0))]
2325   ""
2326   "#"
2327   ""
2328   [(set (match_dup 0)
2329         (ashift:QI (match_dup 1)
2330                    (match_dup 2)))]
2331   "")
2333 ;; ??? Combiner does not recognize that it could split the following insn;
2334 ;;     presumably because he has no register handy?
2336 ;; "*ashluqihiqi3.mem"
2337 ;; "*ashlsqihiqi3.mem"
2338 (define_insn_and_split "*ashl<extend_su>qihiqi3.mem"
2339   [(set (match_operand:QI 0 "memory_operand" "=m")
2340         (subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "r"))
2341                               (match_operand:QI 2 "register_operand" "r"))
2342                    0))]
2343   "!reload_completed"
2344   { gcc_unreachable(); }
2345   "&& 1"
2346   [(set (match_dup 3)
2347         (ashift:QI (match_dup 1)
2348                    (match_dup 2)))
2349    (set (match_dup 0)
2350         (match_dup 3))]
2351   {
2352     operands[3] = gen_reg_rtx (QImode);
2353   })
2355 ;; Similar.
2357 (define_insn_and_split "*ashlhiqi3"
2358   [(set (match_operand:QI 0 "nonimmediate_operand" "=r")
2359         (subreg:QI (ashift:HI (match_operand:HI 1 "register_operand" "0")
2360                               (match_operand:QI 2 "register_operand" "r")) 0))]
2361   "!reload_completed"
2362   { gcc_unreachable(); }
2363   "&& 1"
2364   [(set (match_dup 4)
2365         (ashift:QI (match_dup 3)
2366                    (match_dup 2)))
2367    (set (match_dup 0)
2368         (match_dup 4))]
2369   {
2370     operands[3] = simplify_gen_subreg (QImode, operands[1], HImode, 0);
2371     operands[4] = gen_reg_rtx (QImode);
2372   })
2374 ;; High part of 16-bit shift is unused after the instruction:
2375 ;; No need to compute it, map to 8-bit shift.
2377 (define_peephole2
2378   [(set (match_operand:HI 0 "register_operand" "")
2379         (ashift:HI (match_dup 0)
2380                    (match_operand:QI 1 "register_operand" "")))]
2381   ""
2382   [(set (match_dup 2)
2383         (ashift:QI (match_dup 2)
2384                    (match_dup 1)))
2385    (clobber (match_dup 3))]
2386   {
2387     operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 1);
2389     if (!peep2_reg_dead_p (1, operands[3]))
2390       FAIL;
2392     operands[2] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
2393   })
2396 (define_insn "ashlsi3"
2397   [(set (match_operand:SI 0 "register_operand"           "=r,r,r,r,r,r,r")
2398         (ashift:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
2399                    (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
2400   ""
2401   "* return ashlsi3_out (insn, operands, NULL);"
2402   [(set_attr "length" "8,0,4,4,8,10,12")
2403    (set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")])
2405 ;; Optimize if a scratch register from LD_REGS happens to be available.
2407 (define_peephole2 ; ashlqi3_l_const4
2408   [(set (match_operand:QI 0 "l_register_operand" "")
2409         (ashift:QI (match_dup 0)
2410                    (const_int 4)))
2411    (match_scratch:QI 1 "d")]
2412   ""
2413   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
2414    (set (match_dup 1) (const_int -16))
2415    (set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
2416   "")
2418 (define_peephole2 ; ashlqi3_l_const5
2419   [(set (match_operand:QI 0 "l_register_operand" "")
2420         (ashift:QI (match_dup 0)
2421                    (const_int 5)))
2422    (match_scratch:QI 1 "d")]
2423   ""
2424   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
2425    (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))
2426    (set (match_dup 1) (const_int -32))
2427    (set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
2428   "")
2430 (define_peephole2 ; ashlqi3_l_const6
2431   [(set (match_operand:QI 0 "l_register_operand" "")
2432         (ashift:QI (match_dup 0)
2433                    (const_int 6)))
2434    (match_scratch:QI 1 "d")]
2435   ""
2436   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
2437    (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 2)))
2438    (set (match_dup 1) (const_int -64))
2439    (set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
2440   "")
2442 (define_peephole2
2443   [(match_scratch:QI 3 "d")
2444    (set (match_operand:HI 0 "register_operand" "")
2445         (ashift:HI (match_operand:HI 1 "register_operand" "")
2446                    (match_operand:QI 2 "const_int_operand" "")))]
2447   ""
2448   [(parallel [(set (match_dup 0) (ashift:HI (match_dup 1) (match_dup 2)))
2449               (clobber (match_dup 3))])]
2450   "")
2452 (define_insn "*ashlhi3_const"
2453   [(set (match_operand:HI 0 "register_operand"            "=r,r,r,r,r")
2454         (ashift:HI (match_operand:HI 1 "register_operand"  "0,0,r,0,0")
2455                    (match_operand:QI 2 "const_int_operand" "L,P,O,K,n")))
2456    (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
2457   "reload_completed"
2458   "* return ashlhi3_out (insn, operands, NULL);"
2459   [(set_attr "length" "0,2,2,4,10")
2460    (set_attr "cc" "none,set_n,clobber,set_n,clobber")])
2462 (define_peephole2
2463   [(match_scratch:QI 3 "d")
2464    (set (match_operand:SI 0 "register_operand" "")
2465         (ashift:SI (match_operand:SI 1 "register_operand" "")
2466                    (match_operand:QI 2 "const_int_operand" "")))]
2467   ""
2468   [(parallel [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2469               (clobber (match_dup 3))])]
2470   "")
2472 (define_insn "*ashlsi3_const"
2473   [(set (match_operand:SI 0 "register_operand"            "=r,r,r,r")
2474         (ashift:SI (match_operand:SI 1 "register_operand"  "0,0,r,0")
2475                    (match_operand:QI 2 "const_int_operand" "L,P,O,n")))
2476    (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
2477   "reload_completed"
2478   "* return ashlsi3_out (insn, operands, NULL);"
2479   [(set_attr "length" "0,4,4,10")
2480    (set_attr "cc" "none,set_n,clobber,clobber")])
2482 ;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>
2483 ;; arithmetic shift right
2485 (define_insn "ashrqi3"
2486   [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r,r")
2487         (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0,0")
2488                      (match_operand:QI 2 "general_operand"  "r,L,P,K,n,Qm")))]
2489   ""
2490   "* return ashrqi3_out (insn, operands, NULL);"
2491   [(set_attr "length" "5,0,1,2,5,9")
2492    (set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber")])
2494 (define_insn "ashrhi3"
2495   [(set (match_operand:HI 0 "register_operand"             "=r,r,r,r,r,r,r")
2496         (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
2497                      (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
2498   ""
2499   "* return ashrhi3_out (insn, operands, NULL);"
2500   [(set_attr "length" "6,0,2,4,4,10,10")
2501    (set_attr "cc" "clobber,none,clobber,set_n,clobber,clobber,clobber")])
2503 (define_insn "ashrsi3"
2504   [(set (match_operand:SI 0 "register_operand"             "=r,r,r,r,r,r,r")
2505         (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
2506                      (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
2507   ""
2508   "* return ashrsi3_out (insn, operands, NULL);"
2509   [(set_attr "length" "8,0,4,6,8,10,12")
2510    (set_attr "cc" "clobber,none,clobber,set_n,clobber,clobber,clobber")])
2512 ;; Optimize if a scratch register from LD_REGS happens to be available.
2514 (define_peephole2
2515   [(match_scratch:QI 3 "d")
2516    (set (match_operand:HI 0 "register_operand" "")
2517         (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
2518                      (match_operand:QI 2 "const_int_operand" "")))]
2519   ""
2520   [(parallel [(set (match_dup 0) (ashiftrt:HI (match_dup 1) (match_dup 2)))
2521               (clobber (match_dup 3))])]
2522   "")
2524 (define_insn "*ashrhi3_const"
2525   [(set (match_operand:HI 0 "register_operand"              "=r,r,r,r,r")
2526         (ashiftrt:HI (match_operand:HI 1 "register_operand"  "0,0,r,0,0")
2527                      (match_operand:QI 2 "const_int_operand" "L,P,O,K,n")))
2528    (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
2529   "reload_completed"
2530   "* return ashrhi3_out (insn, operands, NULL);"
2531   [(set_attr "length" "0,2,4,4,10")
2532    (set_attr "cc" "none,clobber,set_n,clobber,clobber")])
2534 (define_peephole2
2535   [(match_scratch:QI 3 "d")
2536    (set (match_operand:SI 0 "register_operand" "")
2537         (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
2538                      (match_operand:QI 2 "const_int_operand" "")))]
2539   ""
2540   [(parallel [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (match_dup 2)))
2541               (clobber (match_dup 3))])]
2542   "")
2544 (define_insn "*ashrsi3_const"
2545   [(set (match_operand:SI 0 "register_operand"              "=r,r,r,r")
2546         (ashiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r,0")
2547                      (match_operand:QI 2 "const_int_operand" "L,P,O,n")))
2548    (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
2549   "reload_completed"
2550   "* return ashrsi3_out (insn, operands, NULL);"
2551   [(set_attr "length" "0,4,4,10")
2552    (set_attr "cc" "none,clobber,set_n,clobber")])
2554 ;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>
2555 ;; logical shift right
2557 (define_expand "lshrqi3"
2558   [(set (match_operand:QI 0 "register_operand"              "")
2559         (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
2560                      (match_operand:QI 2 "general_operand"  "")))]
2561   ""
2562   "")
2564 (define_split   ; lshrqi3_const4
2565   [(set (match_operand:QI 0 "d_register_operand" "")
2566         (lshiftrt:QI (match_dup 0)
2567                      (const_int 4)))]
2568   ""
2569   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
2570    (set (match_dup 0) (and:QI (match_dup 0) (const_int 15)))]
2571   "")
2573 (define_split   ; lshrqi3_const5
2574   [(set (match_operand:QI 0 "d_register_operand" "")
2575         (lshiftrt:QI (match_dup 0)
2576                      (const_int 5)))]
2577   ""
2578   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
2579    (set (match_dup 0) (lshiftrt:QI (match_dup 0) (const_int 1)))
2580    (set (match_dup 0) (and:QI (match_dup 0) (const_int 7)))]
2581   "")
2583 (define_split   ; lshrqi3_const6
2584   [(set (match_operand:QI 0 "d_register_operand" "")
2585         (lshiftrt:QI (match_dup 0)
2586                      (const_int 6)))]
2587   ""
2588   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
2589    (set (match_dup 0) (lshiftrt:QI (match_dup 0) (const_int 2)))
2590    (set (match_dup 0) (and:QI (match_dup 0) (const_int 3)))]
2591   "")
2593 (define_insn "*lshrqi3"
2594   [(set (match_operand:QI 0 "register_operand"             "=r,r,r,r,!d,r,r")
2595         (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0,0,0")
2596                      (match_operand:QI 2 "general_operand"  "r,L,P,K,n,n,Qm")))]
2597   ""
2598   "* return lshrqi3_out (insn, operands, NULL);"
2599   [(set_attr "length" "5,0,1,2,4,6,9")
2600    (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")])
2602 (define_insn "lshrhi3"
2603   [(set (match_operand:HI 0 "register_operand"             "=r,r,r,r,r,r,r")
2604         (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
2605                      (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
2606   ""
2607   "* return lshrhi3_out (insn, operands, NULL);"
2608   [(set_attr "length" "6,0,2,2,4,10,10")
2609    (set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber,clobber")])
2611 (define_insn "lshrsi3"
2612   [(set (match_operand:SI 0 "register_operand"             "=r,r,r,r,r,r,r")
2613         (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
2614                      (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
2615   ""
2616   "* return lshrsi3_out (insn, operands, NULL);"
2617   [(set_attr "length" "8,0,4,4,8,10,12")
2618    (set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber,clobber")])
2620 ;; Optimize if a scratch register from LD_REGS happens to be available.
2622 (define_peephole2 ; lshrqi3_l_const4
2623   [(set (match_operand:QI 0 "l_register_operand" "")
2624         (lshiftrt:QI (match_dup 0)
2625                      (const_int 4)))
2626    (match_scratch:QI 1 "d")]
2627   ""
2628   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
2629    (set (match_dup 1) (const_int 15))
2630    (set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
2631   "")
2633 (define_peephole2 ; lshrqi3_l_const5
2634   [(set (match_operand:QI 0 "l_register_operand" "")
2635         (lshiftrt:QI (match_dup 0)
2636                      (const_int 5)))
2637    (match_scratch:QI 1 "d")]
2638   ""
2639   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
2640    (set (match_dup 0) (lshiftrt:QI (match_dup 0) (const_int 1)))
2641    (set (match_dup 1) (const_int 7))
2642    (set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
2643   "")
2645 (define_peephole2 ; lshrqi3_l_const6
2646   [(set (match_operand:QI 0 "l_register_operand" "")
2647         (lshiftrt:QI (match_dup 0)
2648                      (const_int 6)))
2649    (match_scratch:QI 1 "d")]
2650   ""
2651   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
2652    (set (match_dup 0) (lshiftrt:QI (match_dup 0) (const_int 2)))
2653    (set (match_dup 1) (const_int 3))
2654    (set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
2655   "")
2657 (define_peephole2
2658   [(match_scratch:QI 3 "d")
2659    (set (match_operand:HI 0 "register_operand" "")
2660         (lshiftrt:HI (match_operand:HI 1 "register_operand" "")
2661                      (match_operand:QI 2 "const_int_operand" "")))]
2662   ""
2663   [(parallel [(set (match_dup 0) (lshiftrt:HI (match_dup 1) (match_dup 2)))
2664               (clobber (match_dup 3))])]
2665   "")
2667 (define_insn "*lshrhi3_const"
2668   [(set (match_operand:HI 0 "register_operand"              "=r,r,r,r,r")
2669         (lshiftrt:HI (match_operand:HI 1 "register_operand"  "0,0,r,0,0")
2670                      (match_operand:QI 2 "const_int_operand" "L,P,O,K,n")))
2671    (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
2672   "reload_completed"
2673   "* return lshrhi3_out (insn, operands, NULL);"
2674   [(set_attr "length" "0,2,2,4,10")
2675    (set_attr "cc" "none,clobber,clobber,clobber,clobber")])
2677 (define_peephole2
2678   [(match_scratch:QI 3 "d")
2679    (set (match_operand:SI 0 "register_operand" "")
2680         (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
2681                      (match_operand:QI 2 "const_int_operand" "")))]
2682   ""
2683   [(parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (match_dup 2)))
2684               (clobber (match_dup 3))])]
2685   "")
2687 (define_insn "*lshrsi3_const"
2688   [(set (match_operand:SI 0 "register_operand"              "=r,r,r,r")
2689         (lshiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r,0")
2690                      (match_operand:QI 2 "const_int_operand" "L,P,O,n")))
2691    (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
2692   "reload_completed"
2693   "* return lshrsi3_out (insn, operands, NULL);"
2694   [(set_attr "length" "0,4,4,10")
2695    (set_attr "cc" "none,clobber,clobber,clobber")])
2697 ;; abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x)
2698 ;; abs
2700 (define_insn "absqi2"
2701   [(set (match_operand:QI 0 "register_operand" "=r")
2702         (abs:QI (match_operand:QI 1 "register_operand" "0")))]
2703   ""
2704   "sbrc %0,7
2705         neg %0"
2706   [(set_attr "length" "2")
2707    (set_attr "cc" "clobber")])
2710 (define_insn "abssf2"
2711   [(set (match_operand:SF 0 "register_operand" "=d,r")
2712         (abs:SF (match_operand:SF 1 "register_operand" "0,0")))]
2713   ""
2714   "@
2715         andi %D0,0x7f
2716         clt\;bld %D0,7"
2717   [(set_attr "length" "1,2")
2718    (set_attr "cc" "set_n,clobber")])
2720 ;; 0 - x  0 - x  0 - x  0 - x  0 - x  0 - x  0 - x  0 - x  0 - x  0 - x  0 - x
2721 ;; neg
2723 (define_insn "negqi2"
2724   [(set (match_operand:QI 0 "register_operand" "=r")
2725         (neg:QI (match_operand:QI 1 "register_operand" "0")))]
2726   ""
2727   "neg %0"
2728   [(set_attr "length" "1")
2729    (set_attr "cc" "set_zn")])
2731 (define_insn "neghi2"
2732   [(set (match_operand:HI 0 "register_operand"       "=!d,r,&r")
2733         (neg:HI (match_operand:HI 1 "register_operand" "0,0,r")))]
2734   ""
2735   "@
2736         com %B0\;neg %A0\;sbci %B0,lo8(-1)
2737         com %B0\;neg %A0\;sbc %B0,__zero_reg__\;inc %B0
2738         clr %A0\;clr %B0\;sub %A0,%A1\;sbc %B0,%B1"
2739   [(set_attr "length" "3,4,4")
2740    (set_attr "cc" "set_czn,set_n,set_czn")])
2742 (define_insn "negsi2"
2743   [(set (match_operand:SI 0 "register_operand"       "=!d,r,&r")
2744         (neg:SI (match_operand:SI 1 "register_operand" "0,0,r")))]
2745   ""
2746   "@
2747         com %D0\;com %C0\;com %B0\;neg %A0\;sbci %B0,lo8(-1)\;sbci %C0,lo8(-1)\;sbci %D0,lo8(-1)
2748         com %D0\;com %C0\;com %B0\;com %A0\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__
2749         clr %A0\;clr %B0\;{clr %C0\;clr %D0|movw %C0,%A0}\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1"
2750   [(set_attr_alternative "length"
2751                          [(const_int 7)
2752                           (const_int 8)
2753                           (if_then_else (eq_attr "mcu_have_movw" "yes")
2754                                         (const_int 7)
2755                                         (const_int 8))])
2756    (set_attr "cc" "set_czn,set_n,set_czn")])
2758 (define_insn "negsf2"
2759   [(set (match_operand:SF 0 "register_operand" "=d,r")
2760         (neg:SF (match_operand:SF 1 "register_operand" "0,0")))]
2761   ""
2762   "@
2763         subi %D0,0x80
2764         bst %D0,7\;com %D0\;bld %D0,7\;com %D0"
2765   [(set_attr "length" "1,4")
2766    (set_attr "cc" "set_n,set_n")])
2768 ;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2769 ;; not
2771 (define_insn "one_cmplqi2"
2772   [(set (match_operand:QI 0 "register_operand" "=r")
2773         (not:QI (match_operand:QI 1 "register_operand" "0")))]
2774   ""
2775   "com %0"
2776   [(set_attr "length" "1")
2777    (set_attr "cc" "set_czn")])
2779 (define_insn "one_cmplhi2"
2780   [(set (match_operand:HI 0 "register_operand" "=r")
2781         (not:HI (match_operand:HI 1 "register_operand" "0")))]
2782   ""
2783   "com %0
2784         com %B0"
2785   [(set_attr "length" "2")
2786    (set_attr "cc" "set_n")])
2788 (define_insn "one_cmplsi2"
2789   [(set (match_operand:SI 0 "register_operand" "=r")
2790         (not:SI (match_operand:SI 1 "register_operand" "0")))]
2791   ""
2792   "com %0
2793         com %B0
2794         com %C0
2795         com %D0"
2796   [(set_attr "length" "4")
2797    (set_attr "cc" "set_n")])
2799 ;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
2800 ;; sign extend
2802 ;; We keep combiner from inserting hard registers into the input of sign- and
2803 ;; zero-extends.  A hard register in the input operand is not wanted because
2804 ;; 32-bit multiply patterns clobber some hard registers and extends with a
2805 ;; hard register that overlaps these clobbers won't be combined to a widening
2806 ;; multiplication.  There is no need for combine to propagate hard registers,
2807 ;; register allocation can do it just as well.
2809 (define_insn "extendqihi2"
2810   [(set (match_operand:HI 0 "register_operand" "=r,r")
2811         (sign_extend:HI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))]
2812   ""
2813   "@
2814         clr %B0\;sbrc %0,7\;com %B0
2815         mov %A0,%A1\;clr %B0\;sbrc %A0,7\;com %B0"
2816   [(set_attr "length" "3,4")
2817    (set_attr "cc" "set_n,set_n")])
2819 (define_insn "extendqisi2"
2820   [(set (match_operand:SI 0 "register_operand" "=r,r")
2821         (sign_extend:SI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))]
2822   ""
2823   "@
2824         clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0\;mov %D0,%B0
2825         mov %A0,%A1\;clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0\;mov %D0,%B0"
2826   [(set_attr "length" "5,6")
2827    (set_attr "cc" "set_n,set_n")])
2829 (define_insn "extendhisi2"
2830   [(set (match_operand:SI 0 "register_operand"                               "=r,r")
2831         (sign_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r")))]
2832   ""
2833   "@
2834         clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0
2835         {mov %A0,%A1\;mov %B0,%B1|movw %A0,%A1}\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0"
2836   [(set_attr_alternative "length"
2837                          [(const_int 4)
2838                           (if_then_else (eq_attr "mcu_have_movw" "yes")
2839                                         (const_int 5)
2840                                         (const_int 6))])
2841    (set_attr "cc" "set_n,set_n")])
2843 ;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
2844 ;; zero extend
2846 (define_insn_and_split "zero_extendqihi2"
2847   [(set (match_operand:HI 0 "register_operand" "=r")
2848         (zero_extend:HI (match_operand:QI 1 "combine_pseudo_register_operand" "r")))]
2849   ""
2850   "#"
2851   "reload_completed"
2852   [(set (match_dup 2) (match_dup 1))
2853    (set (match_dup 3) (const_int 0))]
2855   unsigned int low_off = subreg_lowpart_offset (QImode, HImode);
2856   unsigned int high_off = subreg_highpart_offset (QImode, HImode);
2858   operands[2] = simplify_gen_subreg (QImode, operands[0], HImode, low_off);
2859   operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, high_off);
2862 (define_insn_and_split "zero_extendqisi2"
2863   [(set (match_operand:SI 0 "register_operand" "=r")
2864         (zero_extend:SI (match_operand:QI 1 "combine_pseudo_register_operand" "r")))]
2865   ""
2866   "#"
2867   "reload_completed"
2868   [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
2869    (set (match_dup 3) (const_int 0))]
2871   unsigned int low_off = subreg_lowpart_offset (HImode, SImode);
2872   unsigned int high_off = subreg_highpart_offset (HImode, SImode);
2874   operands[2] = simplify_gen_subreg (HImode, operands[0], SImode, low_off);
2875   operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off);
2878 (define_insn_and_split "zero_extendhisi2"
2879   [(set (match_operand:SI 0 "register_operand"                               "=r")
2880         (zero_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "r")))]
2881   ""
2882   "#"
2883   "reload_completed"
2884   [(set (match_dup 2) (match_dup 1))
2885    (set (match_dup 3) (const_int 0))]
2887   unsigned int low_off = subreg_lowpart_offset (HImode, SImode);
2888   unsigned int high_off = subreg_highpart_offset (HImode, SImode);
2890   operands[2] = simplify_gen_subreg (HImode, operands[0], SImode, low_off);
2891   operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off);
2894 (define_insn_and_split "zero_extendqidi2"
2895   [(set (match_operand:DI 0 "register_operand" "=r")
2896         (zero_extend:DI (match_operand:QI 1 "register_operand" "r")))]
2897   ""
2898   "#"
2899   "reload_completed"
2900   [(set (match_dup 2) (zero_extend:SI (match_dup 1)))
2901    (set (match_dup 3) (const_int 0))]
2903   unsigned int low_off = subreg_lowpart_offset (SImode, DImode);
2904   unsigned int high_off = subreg_highpart_offset (SImode, DImode);
2906   operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off);
2907   operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off);
2910 (define_insn_and_split "zero_extendhidi2"
2911   [(set (match_operand:DI 0 "register_operand" "=r")
2912         (zero_extend:DI (match_operand:HI 1 "register_operand" "r")))]
2913   ""
2914   "#"
2915   "reload_completed"
2916   [(set (match_dup 2) (zero_extend:SI (match_dup 1)))
2917    (set (match_dup 3) (const_int 0))]
2919   unsigned int low_off = subreg_lowpart_offset (SImode, DImode);
2920   unsigned int high_off = subreg_highpart_offset (SImode, DImode);
2922   operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off);
2923   operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off);
2926 (define_insn_and_split "zero_extendsidi2"
2927   [(set (match_operand:DI 0 "register_operand" "=r")
2928         (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
2929   ""
2930   "#"
2931   "reload_completed"
2932   [(set (match_dup 2) (match_dup 1))
2933    (set (match_dup 3) (const_int 0))]
2935   unsigned int low_off = subreg_lowpart_offset (SImode, DImode);
2936   unsigned int high_off = subreg_highpart_offset (SImode, DImode);
2938   operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off);
2939   operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off);
2942 ;;<=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=>
2943 ;; compare
2945 ; Optimize negated tests into reverse compare if overflow is undefined.
2946 (define_insn "*negated_tstqi"
2947   [(set (cc0)
2948         (compare (neg:QI (match_operand:QI 0 "register_operand" "r"))
2949                  (const_int 0)))]
2950   "(!flag_wrapv && !flag_trapv && flag_strict_overflow)"
2951   "cp __zero_reg__,%0"
2952   [(set_attr "cc" "compare")
2953    (set_attr "length" "1")])
2955 (define_insn "*reversed_tstqi"
2956   [(set (cc0)
2957         (compare (const_int 0)
2958                  (match_operand:QI 0 "register_operand" "r")))]
2959   ""
2960   "cp __zero_reg__,%0"
2961 [(set_attr "cc" "compare")
2962  (set_attr "length" "2")])
2964 (define_insn "*negated_tsthi"
2965   [(set (cc0)
2966         (compare (neg:HI (match_operand:HI 0 "register_operand" "r"))
2967                  (const_int 0)))]
2968   "(!flag_wrapv && !flag_trapv && flag_strict_overflow)"
2969   "cp __zero_reg__,%A0
2970         cpc __zero_reg__,%B0"
2971 [(set_attr "cc" "compare")
2972  (set_attr "length" "2")])
2974 ;; Leave here the clobber used by the cmphi pattern for simplicity, even
2975 ;; though it is unused, because this pattern is synthesized by avr_reorg.
2976 (define_insn "*reversed_tsthi"
2977   [(set (cc0)
2978         (compare (const_int 0)
2979                  (match_operand:HI 0 "register_operand" "r")))
2980    (clobber (match_scratch:QI 1 "=X"))]
2981   ""
2982   "cp __zero_reg__,%A0
2983         cpc __zero_reg__,%B0"
2984 [(set_attr "cc" "compare")
2985  (set_attr "length" "2")])
2987 (define_insn "*negated_tstsi"
2988   [(set (cc0)
2989         (compare (neg:SI (match_operand:SI 0 "register_operand" "r"))
2990                  (const_int 0)))]
2991   "(!flag_wrapv && !flag_trapv && flag_strict_overflow)"
2992   "cp __zero_reg__,%A0
2993         cpc __zero_reg__,%B0
2994         cpc __zero_reg__,%C0
2995         cpc __zero_reg__,%D0"
2996   [(set_attr "cc" "compare")
2997    (set_attr "length" "4")])
2999 (define_insn "*reversed_tstsi"
3000   [(set (cc0)
3001         (compare (const_int 0)
3002                  (match_operand:SI 0 "register_operand" "r")))
3003    (clobber (match_scratch:QI 1 "=X"))]
3004   ""
3005   "cp __zero_reg__,%A0
3006         cpc __zero_reg__,%B0
3007         cpc __zero_reg__,%C0
3008         cpc __zero_reg__,%D0"
3009   [(set_attr "cc" "compare")
3010    (set_attr "length" "4")])
3013 (define_insn "*cmpqi"
3014   [(set (cc0)
3015         (compare (match_operand:QI 0 "register_operand"  "r,r,d")
3016                  (match_operand:QI 1 "nonmemory_operand" "L,r,i")))]
3017   ""
3018   "@
3019         tst %0
3020         cp %0,%1
3021         cpi %0,lo8(%1)"
3022   [(set_attr "cc" "compare,compare,compare")
3023    (set_attr "length" "1,1,1")])
3025 (define_insn "*cmpqi_sign_extend"
3026   [(set (cc0)
3027         (compare (sign_extend:HI
3028                   (match_operand:QI 0 "register_operand"  "d"))
3029                  (match_operand:HI 1 "const_int_operand" "n")))]
3030   "INTVAL (operands[1]) >= -128 && INTVAL (operands[1]) <= 127"
3031   "cpi %0,lo8(%1)"
3032   [(set_attr "cc" "compare")
3033    (set_attr "length" "1")])
3035 (define_insn "*cmphi"
3036   [(set (cc0)
3037         (compare (match_operand:HI 0 "register_operand"  "!w,r,r,d,d,r,r")
3038                  (match_operand:HI 1 "nonmemory_operand" "L,L,r,M,i,M,i")))
3039    (clobber (match_scratch:QI 2 "=X,X,X,X,&d,&d,&d"))]
3040   ""
3041   "*{
3042   switch (which_alternative)
3043     {
3044     case 0: case 1:
3045       return out_tsthi (insn, operands[0], NULL);
3047     case 2:
3048       return (AS2 (cp,%A0,%A1) CR_TAB
3049               AS2 (cpc,%B0,%B1));
3050     case 3:
3051       if (reg_unused_after (insn, operands[0])
3052           && INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 63
3053           && test_hard_reg_class (ADDW_REGS, operands[0]))
3054         return AS2 (sbiw,%0,%1);
3055        else
3056         return (AS2 (cpi,%0,%1) CR_TAB
3057                 AS2 (cpc,%B0,__zero_reg__));
3058     case 4:
3059       if (reg_unused_after (insn, operands[0]))
3060         return (AS2 (subi,%0,lo8(%1))  CR_TAB
3061                 AS2 (sbci,%B0,hi8(%1)));
3062       else
3063         return (AS2 (ldi, %2,hi8(%1))  CR_TAB
3064                 AS2 (cpi, %A0,lo8(%1)) CR_TAB
3065                 AS2 (cpc, %B0,%2));
3066    case 5:
3067       return (AS2 (ldi, %2,lo8(%1))  CR_TAB
3068               AS2 (cp, %A0,%2) CR_TAB
3069               AS2 (cpc, %B0,__zero_reg__));
3071    case 6:
3072       return (AS2 (ldi, %2,lo8(%1))  CR_TAB
3073               AS2 (cp, %A0,%2)       CR_TAB
3074               AS2 (ldi, %2,hi8(%1)) CR_TAB
3075               AS2 (cpc, %B0,%2));
3076     }
3077   return \"bug\";
3078 }" 
3079   [(set_attr "cc" "compare,compare,compare,compare,compare,compare,compare")
3080    (set_attr "length" "1,2,2,2,3,3,4")])
3083 (define_insn "*cmpsi"
3084   [(set (cc0)
3085         (compare (match_operand:SI 0 "register_operand"  "r,r,d,d,r,r")
3086                  (match_operand:SI 1 "nonmemory_operand" "L,r,M,i,M,i")))
3087    (clobber (match_scratch:QI 2 "=X,X,X,&d,&d,&d"))]
3088   ""
3089   "*{
3090   switch (which_alternative)
3091     {
3092     case 0:
3093       return out_tstsi (insn, operands[0], NULL);
3095     case 1:
3096       return (AS2 (cp,%A0,%A1) CR_TAB
3097               AS2 (cpc,%B0,%B1) CR_TAB
3098               AS2 (cpc,%C0,%C1) CR_TAB
3099               AS2 (cpc,%D0,%D1));
3100     case 2:
3101       if (reg_unused_after (insn, operands[0])
3102           && INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 63
3103           && test_hard_reg_class (ADDW_REGS, operands[0]))
3104         return (AS2 (sbiw,%0,%1) CR_TAB
3105                 AS2 (cpc,%C0,__zero_reg__) CR_TAB
3106                 AS2 (cpc,%D0,__zero_reg__));
3107       else
3108         return (AS2 (cpi,%A0,lo8(%1))  CR_TAB
3109                 AS2 (cpc,%B0,__zero_reg__) CR_TAB
3110                 AS2 (cpc,%C0,__zero_reg__) CR_TAB
3111                 AS2 (cpc,%D0,__zero_reg__));
3112     case 3:
3113       if (reg_unused_after (insn, operands[0]))
3114         return (AS2 (subi,%A0,lo8(%1))  CR_TAB
3115                 AS2 (sbci,%B0,hi8(%1))  CR_TAB
3116                 AS2 (sbci,%C0,hlo8(%1))  CR_TAB
3117                 AS2 (sbci,%D0,hhi8(%1)));
3118       else
3119        return (AS2 (cpi, %A0,lo8(%1))   CR_TAB
3120                AS2 (ldi, %2,hi8(%1))  CR_TAB
3121                AS2 (cpc, %B0,%2)       CR_TAB
3122                AS2 (ldi, %2,hlo8(%1))  CR_TAB
3123                AS2 (cpc, %C0,%2)       CR_TAB
3124                AS2 (ldi, %2,hhi8(%1)) CR_TAB
3125                AS2 (cpc, %D0,%2));
3126     case 4:
3127         return (AS2 (ldi,%2,lo8(%1))        CR_TAB
3128                 AS2 (cp,%A0,%2)            CR_TAB
3129                 AS2 (cpc,%B0,__zero_reg__) CR_TAB
3130                 AS2 (cpc,%C0,__zero_reg__) CR_TAB
3131                 AS2 (cpc,%D0,__zero_reg__));
3132     case 5:
3133        return (AS2 (ldi, %2,lo8(%1))   CR_TAB
3134                AS2 (cp, %A0,%2)        CR_TAB
3135                AS2 (ldi, %2,hi8(%1))  CR_TAB
3136                AS2 (cpc, %B0,%2)       CR_TAB
3137                AS2 (ldi, %2,hlo8(%1))  CR_TAB
3138                AS2 (cpc, %C0,%2)       CR_TAB
3139                AS2 (ldi, %2,hhi8(%1)) CR_TAB
3140                AS2 (cpc, %D0,%2));
3141     }
3142   return \"bug\";
3144   [(set_attr "cc" "compare,compare,compare,compare,compare,compare")
3145    (set_attr "length" "4,4,4,7,5,8")])
3148 ;; ----------------------------------------------------------------------
3149 ;; JUMP INSTRUCTIONS
3150 ;; ----------------------------------------------------------------------
3151 ;; Conditional jump instructions
3153 (define_expand "cbranchsi4"
3154   [(parallel [(set (cc0)
3155                    (compare (match_operand:SI 1 "register_operand" "")
3156                             (match_operand:SI 2 "nonmemory_operand" "")))
3157               (clobber (match_scratch:QI 4 ""))])
3158    (set (pc)
3159         (if_then_else
3160               (match_operator 0 "ordered_comparison_operator" [(cc0)
3161                                                                (const_int 0)])
3162               (label_ref (match_operand 3 "" ""))
3163               (pc)))]
3164  "")
3166 (define_expand "cbranchhi4"
3167   [(parallel [(set (cc0)
3168                    (compare (match_operand:HI 1 "register_operand" "")
3169                             (match_operand:HI 2 "nonmemory_operand" "")))
3170               (clobber (match_scratch:QI 4 ""))])
3171    (set (pc)
3172         (if_then_else
3173               (match_operator 0 "ordered_comparison_operator" [(cc0)
3174                                                                (const_int 0)])
3175               (label_ref (match_operand 3 "" ""))
3176               (pc)))]
3177  "")
3179 (define_expand "cbranchqi4"
3180   [(set (cc0)
3181         (compare (match_operand:QI 1 "register_operand" "")
3182                  (match_operand:QI 2 "nonmemory_operand" "")))
3183    (set (pc)
3184         (if_then_else
3185               (match_operator 0 "ordered_comparison_operator" [(cc0)
3186                                                                (const_int 0)])
3187               (label_ref (match_operand 3 "" ""))
3188               (pc)))]
3189  "")
3192 ;; Test a single bit in a QI/HI/SImode register.
3193 ;; Combine will create zero extract patterns for single bit tests.
3194 ;; permit any mode in source pattern by using VOIDmode.
3196 (define_insn "*sbrx_branch<mode>"
3197   [(set (pc)
3198         (if_then_else
3199          (match_operator 0 "eqne_operator"
3200                          [(zero_extract:QIDI
3201                            (match_operand:VOID 1 "register_operand" "r")
3202                            (const_int 1)
3203                            (match_operand 2 "const_int_operand" "n"))
3204                           (const_int 0)])
3205          (label_ref (match_operand 3 "" ""))
3206          (pc)))]
3207   ""
3208   "* return avr_out_sbxx_branch (insn, operands);"
3209   [(set (attr "length")
3210         (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
3211                            (le (minus (pc) (match_dup 3)) (const_int 2046)))
3212                       (const_int 2)
3213                       (if_then_else (eq_attr "mcu_mega" "no")
3214                                     (const_int 2)
3215                                     (const_int 4))))
3216    (set_attr "cc" "clobber")])
3218 ;; Same test based on Bitwise AND RTL. Keep this incase gcc changes patterns.
3219 ;; or for old peepholes.
3220 ;; Fixme - bitwise Mask will not work for DImode
3222 (define_insn "*sbrx_and_branch<mode>"
3223   [(set (pc)
3224         (if_then_else
3225          (match_operator 0 "eqne_operator"
3226                          [(and:QISI
3227                            (match_operand:QISI 1 "register_operand" "r")
3228                            (match_operand:QISI 2 "single_one_operand" "n"))
3229                           (const_int 0)])
3230          (label_ref (match_operand 3 "" ""))
3231          (pc)))]
3232   ""
3234     HOST_WIDE_INT bitnumber;
3235     bitnumber = exact_log2 (GET_MODE_MASK (<MODE>mode) & INTVAL (operands[2]));
3236     operands[2] = GEN_INT (bitnumber);
3237     return avr_out_sbxx_branch (insn, operands);
3239   [(set (attr "length")
3240         (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
3241                            (le (minus (pc) (match_dup 3)) (const_int 2046)))
3242                       (const_int 2)
3243                       (if_then_else (eq_attr "mcu_mega" "no")
3244                                     (const_int 2)
3245                                     (const_int 4))))
3246    (set_attr "cc" "clobber")])
3248 ;; Convert sign tests to bit 7/15/31 tests that match the above insns.
3249 (define_peephole2
3250   [(set (cc0) (compare (match_operand:QI 0 "register_operand" "")
3251                        (const_int 0)))
3252    (set (pc) (if_then_else (ge (cc0) (const_int 0))
3253                            (label_ref (match_operand 1 "" ""))
3254                            (pc)))]
3255   ""
3256   [(set (pc) (if_then_else (eq (zero_extract:HI (match_dup 0)
3257                                                 (const_int 1)
3258                                                 (const_int 7))
3259                                (const_int 0))
3260                            (label_ref (match_dup 1))
3261                            (pc)))]
3262   "")
3264 (define_peephole2
3265   [(set (cc0) (compare (match_operand:QI 0 "register_operand" "")
3266                        (const_int 0)))
3267    (set (pc) (if_then_else (lt (cc0) (const_int 0))
3268                            (label_ref (match_operand 1 "" ""))
3269                            (pc)))]
3270   ""
3271   [(set (pc) (if_then_else (ne (zero_extract:HI (match_dup 0)
3272                                                 (const_int 1)
3273                                                 (const_int 7))
3274                                (const_int 0))
3275                            (label_ref (match_dup 1))
3276                            (pc)))]
3277   "")
3279 (define_peephole2
3280   [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "")
3281                                   (const_int 0)))
3282               (clobber (match_operand:HI 2 ""))])
3283    (set (pc) (if_then_else (ge (cc0) (const_int 0))
3284                            (label_ref (match_operand 1 "" ""))
3285                            (pc)))]
3286   ""
3287   [(set (pc) (if_then_else (eq (and:HI (match_dup 0) (const_int -32768))
3288                                (const_int 0))
3289                            (label_ref (match_dup 1))
3290                            (pc)))]
3291   "")
3293 (define_peephole2
3294   [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "")
3295                                   (const_int 0)))
3296               (clobber (match_operand:HI 2 ""))])
3297    (set (pc) (if_then_else (lt (cc0) (const_int 0))
3298                            (label_ref (match_operand 1 "" ""))
3299                            (pc)))]
3300   ""
3301   [(set (pc) (if_then_else (ne (and:HI (match_dup 0) (const_int -32768))
3302                                (const_int 0))
3303                            (label_ref (match_dup 1))
3304                            (pc)))]
3305   "")
3307 (define_peephole2
3308   [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
3309                                   (const_int 0)))
3310               (clobber (match_operand:SI 2 ""))])
3311    (set (pc) (if_then_else (ge (cc0) (const_int 0))
3312                            (label_ref (match_operand 1 "" ""))
3313                            (pc)))]
3314   ""
3315   [(set (pc) (if_then_else (eq (and:SI (match_dup 0) (match_dup 2))
3316                                (const_int 0))
3317                            (label_ref (match_dup 1))
3318                            (pc)))]
3319   "operands[2] = GEN_INT (-2147483647 - 1);")
3321 (define_peephole2
3322   [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
3323                                   (const_int 0)))
3324               (clobber (match_operand:SI 2 ""))])
3325    (set (pc) (if_then_else (lt (cc0) (const_int 0))
3326                            (label_ref (match_operand 1 "" ""))
3327                            (pc)))]
3328   ""
3329   [(set (pc) (if_then_else (ne (and:SI (match_dup 0) (match_dup 2))
3330                                (const_int 0))
3331                            (label_ref (match_dup 1))
3332                            (pc)))]
3333   "operands[2] = GEN_INT (-2147483647 - 1);")
3335 ;; ************************************************************************
3336 ;; Implementation of conditional jumps here.
3337 ;;  Compare with 0 (test) jumps
3338 ;; ************************************************************************
3340 (define_insn "branch"
3341   [(set (pc)
3342         (if_then_else (match_operator 1 "simple_comparison_operator"
3343                                       [(cc0)
3344                                        (const_int 0)])
3345                       (label_ref (match_operand 0 "" ""))
3346                       (pc)))]
3347   ""
3348   {
3349     return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 0);
3350   }
3351   [(set_attr "type" "branch")
3352    (set_attr "cc" "clobber")])
3355 ;; Same as above but wrap SET_SRC so that this branch won't be transformed
3356 ;; or optimized in the remainder.
3358 (define_insn "branch_unspec"
3359   [(set (pc)
3360         (unspec [(if_then_else (match_operator 1 "simple_comparison_operator"
3361                                                [(cc0)
3362                                                 (const_int 0)])
3363                                (label_ref (match_operand 0 "" ""))
3364                                (pc))
3365                  ] UNSPEC_IDENTITY))]
3366   ""
3367   {
3368     return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 0);
3369   }
3370   [(set_attr "type" "branch")
3371    (set_attr "cc" "none")])
3373 ;; ****************************************************************
3374 ;; AVR does not have following conditional jumps: LE,LEU,GT,GTU.
3375 ;; Convert them all to proper jumps.
3376 ;; ****************************************************************/
3378 (define_insn "difficult_branch"
3379   [(set (pc)
3380         (if_then_else (match_operator 1 "difficult_comparison_operator"
3381                         [(cc0)
3382                          (const_int 0)])
3383                       (label_ref (match_operand 0 "" ""))
3384                       (pc)))]
3385   ""
3386   "*
3387    return ret_cond_branch (operands[1], avr_jump_mode (operands[0],insn), 0);"
3388   [(set_attr "type" "branch1")
3389    (set_attr "cc" "clobber")])
3391 ;; revers branch
3393 (define_insn "rvbranch"
3394   [(set (pc)
3395         (if_then_else (match_operator 1 "simple_comparison_operator" 
3396                         [(cc0)
3397                          (const_int 0)])
3398                       (pc)
3399                       (label_ref (match_operand 0 "" ""))))]
3400   ""
3401   "*
3402    return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 1);"
3403   [(set_attr "type" "branch1")
3404    (set_attr "cc" "clobber")])
3406 (define_insn "difficult_rvbranch"
3407   [(set (pc)
3408         (if_then_else (match_operator 1 "difficult_comparison_operator" 
3409                         [(cc0)
3410                          (const_int 0)])
3411                       (pc)
3412                       (label_ref (match_operand 0 "" ""))))]
3413   ""
3414   "*
3415    return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 1);"
3416   [(set_attr "type" "branch")
3417    (set_attr "cc" "clobber")])
3419 ;; **************************************************************************
3420 ;; Unconditional and other jump instructions.
3422 (define_insn "jump"
3423   [(set (pc)
3424         (label_ref (match_operand 0 "" "")))]
3425   ""
3426   "*{
3427   if (AVR_HAVE_JMP_CALL && get_attr_length (insn) != 1)
3428     return AS1 (jmp,%x0);
3429   return AS1 (rjmp,%x0);
3431   [(set (attr "length")
3432         (if_then_else (match_operand 0 "symbol_ref_operand" "") 
3433                 (if_then_else (eq_attr "mcu_mega" "no")
3434                               (const_int 1)
3435                               (const_int 2))
3436                 (if_then_else (and (ge (minus (pc) (match_dup 0)) (const_int -2047))
3437                                    (le (minus (pc) (match_dup 0)) (const_int 2047)))
3438                               (const_int 1)
3439                               (const_int 2))))
3440    (set_attr "cc" "none")])
3442 ;; call
3444 (define_expand "call"
3445   [(parallel[(call (match_operand:HI 0 "call_insn_operand" "")
3446                    (match_operand:HI 1 "general_operand" ""))
3447              (use (const_int 0))])]
3448   ;; Operand 1 not used on the AVR.
3449   ;; Operand 2 is 1 for tail-call, 0 otherwise.
3450   ""
3451   "")
3453 (define_expand "sibcall"
3454   [(parallel[(call (match_operand:HI 0 "call_insn_operand" "")
3455                    (match_operand:HI 1 "general_operand" ""))
3456              (use (const_int 1))])]
3457   ;; Operand 1 not used on the AVR.
3458   ;; Operand 2 is 1 for tail-call, 0 otherwise.
3459   ""
3460   "")
3462 ;; call value
3464 (define_expand "call_value"
3465   [(parallel[(set (match_operand 0 "register_operand" "")
3466                   (call (match_operand:HI 1 "call_insn_operand" "")
3467                         (match_operand:HI 2 "general_operand" "")))
3468              (use (const_int 0))])]
3469   ;; Operand 2 not used on the AVR.
3470   ;; Operand 3 is 1 for tail-call, 0 otherwise.
3471   ""
3472   "")
3474 (define_expand "sibcall_value"
3475   [(parallel[(set (match_operand 0 "register_operand" "")
3476                   (call (match_operand:HI 1 "call_insn_operand" "")
3477                         (match_operand:HI 2 "general_operand" "")))
3478              (use (const_int 1))])]
3479   ;; Operand 2 not used on the AVR.
3480   ;; Operand 3 is 1 for tail-call, 0 otherwise.
3481   ""
3482   "")
3484 (define_insn "*call_insn"
3485   [(parallel[(call (mem:HI (match_operand:HI 0 "nonmemory_operand" "z,s,z,s"))
3486                    (match_operand:HI 1 "general_operand"           "X,X,X,X"))
3487              (use (match_operand:HI 2 "const_int_operand"          "L,L,P,P"))])]
3488   ;; Operand 1 not used on the AVR.
3489   ;; Operand 2 is 1 for tail-call, 0 otherwise.
3490   ""
3491   "@
3492     %!icall
3493     %~call %x0
3494     %!ijmp
3495     %~jmp %x0"
3496   [(set_attr "cc" "clobber")
3497    (set_attr_alternative "length"
3498                          [(const_int 1)
3499                           (if_then_else (eq_attr "mcu_mega" "yes")
3500                                         (const_int 2)
3501                                         (const_int 1))
3502                           (const_int 1)
3503                           (if_then_else (eq_attr "mcu_mega" "yes")
3504                                         (const_int 2)
3505                                         (const_int 1))])])
3507 (define_insn "*call_value_insn"
3508   [(parallel[(set (match_operand 0 "register_operand"                   "=r,r,r,r")
3509                   (call (mem:HI (match_operand:HI 1 "nonmemory_operand"  "z,s,z,s"))
3510                         (match_operand:HI 2 "general_operand"            "X,X,X,X")))
3511              (use (match_operand:HI 3 "const_int_operand"                "L,L,P,P"))])]
3512   ;; Operand 2 not used on the AVR.
3513   ;; Operand 3 is 1 for tail-call, 0 otherwise.
3514   ""
3515   "@
3516     %!icall
3517     %~call %x1
3518     %!ijmp
3519     %~jmp %x1"
3520   [(set_attr "cc" "clobber")
3521    (set_attr_alternative "length"
3522                          [(const_int 1)
3523                           (if_then_else (eq_attr "mcu_mega" "yes")
3524                                         (const_int 2)
3525                                         (const_int 1))
3526                           (const_int 1)
3527                           (if_then_else (eq_attr "mcu_mega" "yes")
3528                                         (const_int 2)
3529                                         (const_int 1))])])
3531 (define_insn "nop"
3532   [(const_int 0)]
3533   ""
3534   "nop"
3535   [(set_attr "cc" "none")
3536    (set_attr "length" "1")])
3538 ; indirect jump
3540 (define_expand "indirect_jump"
3541   [(set (pc) (match_operand:HI 0 "nonmemory_operand" ""))]
3542   ""
3543   " if ((!AVR_HAVE_JMP_CALL) && !register_operand(operand0, HImode))
3544     {
3545       operands[0] = copy_to_mode_reg(HImode, operand0);
3546     }"
3549 ; indirect jump
3550 (define_insn "*jcindirect_jump"
3551   [(set (pc) (match_operand:HI 0 "immediate_operand" "i"))]
3552   ""
3553   "%~jmp %x0"
3554   [(set_attr "length" "2")
3555    (set_attr "cc" "none")])
3558 (define_insn "*njcindirect_jump"
3559   [(set (pc) (match_operand:HI 0 "register_operand" "!z,*r"))]
3560   "!AVR_HAVE_EIJMP_EICALL"
3561   "@
3562         ijmp
3563         push %A0\;push %B0\;ret"
3564   [(set_attr "length" "1,3")
3565    (set_attr "cc" "none,none")])
3567 (define_insn "*indirect_jump_avr6"
3568   [(set (pc) (match_operand:HI 0 "register_operand" "z"))]
3569   "AVR_HAVE_EIJMP_EICALL"
3570   "eijmp"
3571   [(set_attr "length" "1")
3572    (set_attr "cc" "none")])
3574 ;; table jump
3576 ;; Table made from "rjmp" instructions for <=8K devices.
3577 (define_insn "*tablejump_rjmp"
3578   [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r")]
3579                         UNSPEC_INDEX_JMP))
3580    (use (label_ref (match_operand 1 "" "")))
3581    (clobber (match_dup 0))]
3582   "(!AVR_HAVE_JMP_CALL) && (!AVR_HAVE_EIJMP_EICALL)"
3583   "@
3584         ijmp
3585         push %A0\;push %B0\;ret"
3586   [(set_attr "length" "1,3")
3587    (set_attr "cc" "none,none")])
3589 ;; Not a prologue, but similar idea - move the common piece of code to libgcc.
3590 (define_insn "*tablejump_lib"
3591   [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")]
3592                         UNSPEC_INDEX_JMP))
3593    (use (label_ref (match_operand 1 "" "")))
3594    (clobber (match_dup 0))]
3595   "AVR_HAVE_JMP_CALL && TARGET_CALL_PROLOGUES"
3596   "%~jmp __tablejump2__"
3597   [(set_attr "length" "2")
3598    (set_attr "cc" "clobber")])
3600 (define_insn "*tablejump_enh"
3601   [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")]
3602                         UNSPEC_INDEX_JMP))
3603    (use (label_ref (match_operand 1 "" "")))
3604    (clobber (match_dup 0))]
3605   "AVR_HAVE_JMP_CALL && AVR_HAVE_LPMX"
3606   "lsl r30
3607         rol r31
3608         lpm __tmp_reg__,Z+
3609         lpm r31,Z
3610         mov r30,__tmp_reg__
3611         %!ijmp"
3612   [(set_attr "length" "6")
3613    (set_attr "cc" "clobber")])
3615 (define_insn "*tablejump"
3616   [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")]
3617                         UNSPEC_INDEX_JMP))
3618    (use (label_ref (match_operand 1 "" "")))
3619    (clobber (match_dup 0))]
3620   "AVR_HAVE_JMP_CALL && !AVR_HAVE_EIJMP_EICALL"
3621   "lsl r30
3622         rol r31
3623         lpm
3624         inc r30
3625         push r0
3626         lpm
3627         push r0
3628         ret"
3629   [(set_attr "length" "8")
3630    (set_attr "cc" "clobber")])
3632 (define_expand "casesi"
3633   [(set (match_dup 6)
3634         (minus:HI (subreg:HI (match_operand:SI 0 "register_operand" "") 0)
3635                   (match_operand:HI 1 "register_operand" "")))
3636    (parallel [(set (cc0)
3637                    (compare (match_dup 6)
3638                             (match_operand:HI 2 "register_operand" "")))
3639               (clobber (match_scratch:QI 9 ""))])
3640    
3641    (set (pc)
3642         (if_then_else (gtu (cc0)
3643                            (const_int 0))
3644                       (label_ref (match_operand 4 "" ""))
3645                       (pc)))
3647    (set (match_dup 6)
3648         (plus:HI (match_dup 6) (label_ref (match_operand:HI 3 "" ""))))
3650    (parallel [(set (pc) (unspec:HI [(match_dup 6)] UNSPEC_INDEX_JMP))
3651               (use (label_ref (match_dup 3)))
3652               (clobber (match_dup 6))])]
3653   ""
3654   "
3656   operands[6] = gen_reg_rtx (HImode);
3660 ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3661 ;; This instruction sets Z flag
3663 (define_insn "sez"
3664   [(set (cc0) (const_int 0))]
3665   ""
3666   "sez"
3667   [(set_attr "length" "1")
3668    (set_attr "cc" "compare")])
3670 ;; Clear/set/test a single bit in I/O address space.
3672 (define_insn "*cbi"
3673   [(set (mem:QI (match_operand 0 "low_io_address_operand" "n"))
3674         (and:QI (mem:QI (match_dup 0))
3675                 (match_operand:QI 1 "single_zero_operand" "n")))]
3676   "(optimize > 0)"
3678   operands[2] = GEN_INT (exact_log2 (~INTVAL (operands[1]) & 0xff));
3679   return AS2 (cbi,%m0-0x20,%2);
3681   [(set_attr "length" "1")
3682    (set_attr "cc" "none")])
3684 (define_insn "*sbi"
3685   [(set (mem:QI (match_operand 0 "low_io_address_operand" "n"))
3686         (ior:QI (mem:QI (match_dup 0))
3687                 (match_operand:QI 1 "single_one_operand" "n")))]
3688   "(optimize > 0)"
3690   operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff));
3691   return AS2 (sbi,%m0-0x20,%2);
3693   [(set_attr "length" "1")
3694    (set_attr "cc" "none")])
3696 ;; Lower half of the I/O space - use sbic/sbis directly.
3697 (define_insn "*sbix_branch"
3698   [(set (pc)
3699         (if_then_else
3700          (match_operator 0 "eqne_operator"
3701                          [(zero_extract:HI
3702                            (mem:QI (match_operand 1 "low_io_address_operand" "n"))
3703                            (const_int 1)
3704                            (match_operand 2 "const_int_operand" "n"))
3705                           (const_int 0)])
3706          (label_ref (match_operand 3 "" ""))
3707          (pc)))]
3708   "(optimize > 0)"
3709   "* return avr_out_sbxx_branch (insn, operands);"
3710   [(set (attr "length")
3711         (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
3712                            (le (minus (pc) (match_dup 3)) (const_int 2046)))
3713                       (const_int 2)
3714                       (if_then_else (eq_attr "mcu_mega" "no")
3715                                     (const_int 2)
3716                                     (const_int 4))))
3717    (set_attr "cc" "clobber")])
3719 ;; Tests of bit 7 are pessimized to sign tests, so we need this too...
3720 (define_insn "*sbix_branch_bit7"
3721   [(set (pc)
3722         (if_then_else
3723          (match_operator 0 "gelt_operator"
3724                          [(mem:QI (match_operand 1 "low_io_address_operand" "n"))
3725                           (const_int 0)])
3726          (label_ref (match_operand 2 "" ""))
3727          (pc)))]
3728   "(optimize > 0)"
3730   operands[3] = operands[2];
3731   operands[2] = GEN_INT (7);
3732   return avr_out_sbxx_branch (insn, operands);
3734   [(set (attr "length")
3735         (if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046))
3736                            (le (minus (pc) (match_dup 2)) (const_int 2046)))
3737                       (const_int 2)
3738                       (if_then_else (eq_attr "mcu_mega" "no")
3739                                     (const_int 2)
3740                                     (const_int 4))))
3741    (set_attr "cc" "clobber")])
3743 ;; Upper half of the I/O space - read port to __tmp_reg__ and use sbrc/sbrs.
3744 (define_insn "*sbix_branch_tmp"
3745   [(set (pc)
3746         (if_then_else
3747          (match_operator 0 "eqne_operator"
3748                          [(zero_extract:HI
3749                            (mem:QI (match_operand 1 "high_io_address_operand" "n"))
3750                            (const_int 1)
3751                            (match_operand 2 "const_int_operand" "n"))
3752                           (const_int 0)])
3753          (label_ref (match_operand 3 "" ""))
3754          (pc)))]
3755   "(optimize > 0)"
3756   "* return avr_out_sbxx_branch (insn, operands);"
3757   [(set (attr "length")
3758         (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
3759                            (le (minus (pc) (match_dup 3)) (const_int 2045)))
3760                       (const_int 3)
3761                       (if_then_else (eq_attr "mcu_mega" "no")
3762                                     (const_int 3)
3763                                     (const_int 5))))
3764    (set_attr "cc" "clobber")])
3766 (define_insn "*sbix_branch_tmp_bit7"
3767   [(set (pc)
3768         (if_then_else
3769          (match_operator 0 "gelt_operator"
3770                          [(mem:QI (match_operand 1 "high_io_address_operand" "n"))
3771                           (const_int 0)])
3772          (label_ref (match_operand 2 "" ""))
3773          (pc)))]
3774   "(optimize > 0)"
3776   operands[3] = operands[2];
3777   operands[2] = GEN_INT (7);
3778   return avr_out_sbxx_branch (insn, operands);
3780   [(set (attr "length")
3781         (if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046))
3782                            (le (minus (pc) (match_dup 2)) (const_int 2045)))
3783                       (const_int 3)
3784                       (if_then_else (eq_attr "mcu_mega" "no")
3785                                     (const_int 3)
3786                                     (const_int 5))))
3787    (set_attr "cc" "clobber")])
3789 ;; ************************* Peepholes ********************************
3791 (define_peephole
3792   [(set (match_operand:SI 0 "d_register_operand" "")
3793         (plus:SI (match_dup 0)
3794                  (const_int -1)))
3795    (parallel
3796     [(set (cc0)
3797           (compare (match_dup 0)
3798                    (const_int -1)))
3799      (clobber (match_operand:QI 1 "d_register_operand" ""))])
3800    (set (pc)
3801         (if_then_else (ne (cc0) (const_int 0))
3802                       (label_ref (match_operand 2 "" ""))
3803                       (pc)))]
3804   ""
3805   "*
3807   CC_STATUS_INIT;
3808   if (test_hard_reg_class (ADDW_REGS, operands[0]))
3809     output_asm_insn (AS2 (sbiw,%0,1) CR_TAB
3810                      AS2 (sbc,%C0,__zero_reg__) CR_TAB
3811                      AS2 (sbc,%D0,__zero_reg__) \"\\n\", operands);
3812   else
3813     output_asm_insn (AS2 (subi,%A0,1) CR_TAB
3814                      AS2 (sbc,%B0,__zero_reg__) CR_TAB
3815                      AS2 (sbc,%C0,__zero_reg__) CR_TAB
3816                      AS2 (sbc,%D0,__zero_reg__) \"\\n\", operands);
3817   switch (avr_jump_mode (operands[2],insn))
3818   {
3819     case 1:
3820       return AS1 (brcc,%2);
3821     case 2:
3822       return (AS1 (brcs,.+2) CR_TAB
3823               AS1 (rjmp,%2));
3824   }
3825   return (AS1 (brcs,.+4) CR_TAB
3826           AS1 (jmp,%2));
3829 (define_peephole
3830   [(set (match_operand:HI 0 "d_register_operand" "")
3831         (plus:HI (match_dup 0)
3832                  (const_int -1)))
3833    (parallel
3834     [(set (cc0)
3835           (compare (match_dup 0)
3836                    (const_int 65535)))
3837      (clobber (match_operand:QI 1 "d_register_operand" ""))])
3838    (set (pc)
3839         (if_then_else (ne (cc0) (const_int 0))
3840                       (label_ref (match_operand 2 "" ""))
3841                       (pc)))]
3842   ""
3843   "*
3845   CC_STATUS_INIT;
3846   if (test_hard_reg_class (ADDW_REGS, operands[0]))
3847     output_asm_insn (AS2 (sbiw,%0,1), operands);
3848   else
3849     output_asm_insn (AS2 (subi,%A0,1) CR_TAB
3850                      AS2 (sbc,%B0,__zero_reg__) \"\\n\", operands);
3851   switch (avr_jump_mode (operands[2],insn))
3852   {
3853     case 1:
3854       return AS1 (brcc,%2);
3855     case 2:
3856       return (AS1 (brcs,.+2) CR_TAB
3857               AS1 (rjmp,%2));
3858   }
3859   return (AS1 (brcs,.+4) CR_TAB
3860           AS1 (jmp,%2));
3863 (define_peephole
3864   [(set (match_operand:QI 0 "d_register_operand" "")
3865         (plus:QI (match_dup 0)
3866                  (const_int -1)))
3867    (set (cc0)
3868         (compare (match_dup 0)
3869                  (const_int -1)))
3870    (set (pc)
3871         (if_then_else (ne (cc0) (const_int 0))
3872                       (label_ref (match_operand 1 "" ""))
3873                       (pc)))]
3874   ""
3875   "*
3877   CC_STATUS_INIT;
3878   cc_status.value1 = operands[0];
3879   cc_status.flags |= CC_OVERFLOW_UNUSABLE;
3880   output_asm_insn (AS2 (subi,%A0,1), operands);
3881   switch (avr_jump_mode (operands[1],insn))
3882   {
3883     case 1:
3884       return AS1 (brcc,%1);
3885     case 2:
3886       return (AS1 (brcs,.+2) CR_TAB
3887               AS1 (rjmp,%1));
3888   }
3889   return (AS1 (brcs,.+4) CR_TAB
3890           AS1 (jmp,%1));
3893 (define_peephole
3894   [(set (cc0)
3895         (compare (match_operand:QI 0 "register_operand" "")
3896                  (const_int 0)))
3897    (set (pc)
3898         (if_then_else (eq (cc0) (const_int 0))
3899                       (label_ref (match_operand 1 "" ""))
3900                       (pc)))]
3901   "jump_over_one_insn_p (insn, operands[1])"
3902   "cpse %0,__zero_reg__")
3904 (define_peephole
3905   [(set (cc0)
3906         (compare (match_operand:QI 0 "register_operand" "")
3907                  (match_operand:QI 1 "register_operand" "")))
3908    (set (pc)
3909         (if_then_else (eq (cc0) (const_int 0))
3910                       (label_ref (match_operand 2 "" ""))
3911                       (pc)))]
3912   "jump_over_one_insn_p (insn, operands[2])"
3913   "cpse %0,%1")
3915 ;;pppppppppppppppppppppppppppppppppppppppppppppppppppp
3916 ;;prologue/epilogue support instructions
3918 (define_insn "popqi"
3919   [(set (match_operand:QI 0 "register_operand" "=r")
3920         (mem:QI (pre_inc:HI (reg:HI REG_SP))))]
3921   ""
3922   "pop %0"
3923   [(set_attr "cc" "none")
3924    (set_attr "length" "1")])
3926 ;; Enable Interrupts
3927 (define_insn "enable_interrupt"
3928   [(unspec_volatile [(const_int 1)] UNSPECV_ENABLE_IRQS)]
3929   ""
3930   "sei"
3931   [(set_attr "length" "1")
3932    (set_attr "cc" "none")])
3934 ;; Disable Interrupts
3935 (define_insn "disable_interrupt"
3936   [(unspec_volatile [(const_int 0)] UNSPECV_ENABLE_IRQS)]
3937   ""
3938   "cli"
3939   [(set_attr "length" "1")
3940    (set_attr "cc" "none")])
3942 ;;  Library prologue saves
3943 (define_insn "call_prologue_saves"
3944   [(unspec_volatile:HI [(const_int 0)] UNSPECV_PROLOGUE_SAVES)
3945    (match_operand:HI 0 "immediate_operand" "")
3946    (set (reg:HI REG_SP) (minus:HI 
3947                            (reg:HI REG_SP)
3948                            (match_operand:HI 1 "immediate_operand" "")))
3949    (use (reg:HI REG_X))
3950    (clobber (reg:HI REG_Z))]
3951   ""
3952   "ldi r30,lo8(gs(1f))
3953         ldi r31,hi8(gs(1f))
3954         %~jmp __prologue_saves__+((18 - %0) * 2)
3956   [(set_attr_alternative "length"
3957                          [(if_then_else (eq_attr "mcu_mega" "yes")
3958                                         (const_int 6)
3959                                         (const_int 5))])
3960   (set_attr "cc" "clobber")
3961   ])
3962   
3963 ;  epilogue  restores using library
3964 (define_insn "epilogue_restores"
3965   [(unspec_volatile:QI [(const_int 0)] UNSPECV_EPILOGUE_RESTORES)
3966    (set (reg:HI REG_Y ) (plus:HI 
3967                            (reg:HI REG_Y)
3968                            (match_operand:HI 0 "immediate_operand" ""))) 
3969    (set (reg:HI REG_SP) (reg:HI REG_Y))
3970    (clobber  (reg:QI REG_Z))]
3971   ""
3972   "ldi r30, lo8(%0)
3973         %~jmp __epilogue_restores__ + ((18 - %0) * 2)"
3974   [(set_attr_alternative "length"
3975                          [(if_then_else (eq_attr "mcu_mega" "yes")
3976                                         (const_int 3)
3977                                         (const_int 2))])
3978   (set_attr "cc" "clobber")
3979   ])
3980   
3981 ; return
3982 (define_insn "return"
3983   [(return)]
3984   "reload_completed && avr_simple_epilogue ()"
3985   "ret"
3986   [(set_attr "cc" "none")
3987    (set_attr "length" "1")])
3989 (define_insn "return_from_epilogue"
3990   [(return)]
3991   "(reload_completed 
3992     && cfun->machine 
3993     && !(cfun->machine->is_interrupt || cfun->machine->is_signal)
3994     && !cfun->machine->is_naked)"
3995   "ret"
3996   [(set_attr "cc" "none")
3997    (set_attr "length" "1")])
3999 (define_insn "return_from_interrupt_epilogue"
4000   [(return)]
4001   "(reload_completed 
4002     && cfun->machine 
4003     && (cfun->machine->is_interrupt || cfun->machine->is_signal)
4004     && !cfun->machine->is_naked)"
4005   "reti"
4006   [(set_attr "cc" "none")
4007    (set_attr "length" "1")])
4009 (define_insn "return_from_naked_epilogue"
4010   [(return)]
4011   "(reload_completed 
4012     && cfun->machine 
4013     && cfun->machine->is_naked)"
4014   ""
4015   [(set_attr "cc" "none")
4016    (set_attr "length" "0")])
4018 (define_expand "prologue"
4019   [(const_int 0)]
4020   ""
4021   "
4022   {
4023     expand_prologue (); 
4024     DONE;
4025   }")
4027 (define_expand "epilogue"
4028   [(const_int 0)]
4029   ""
4030   {
4031     expand_epilogue (false /* sibcall_p */);
4032     DONE;
4033   })
4035 (define_expand "sibcall_epilogue"
4036   [(const_int 0)]
4037   ""
4038   {
4039     expand_epilogue (true /* sibcall_p */);
4040     DONE;
4041   })
4043 ;; Some instructions resp. instruction sequences available
4044 ;; via builtins.
4046 (define_insn "delay_cycles_1"
4047   [(unspec_volatile [(match_operand:QI 0 "const_int_operand" "n")
4048                      (const_int 1)]
4049                     UNSPECV_DELAY_CYCLES)
4050    (clobber (match_scratch:QI 1 "=&d"))]
4051   ""
4052   "ldi %1,lo8(%0)
4053         1: dec %1
4054         brne 1b"
4055   [(set_attr "length" "3")
4056    (set_attr "cc" "clobber")])
4058 (define_insn "delay_cycles_2"
4059   [(unspec_volatile [(match_operand:HI 0 "const_int_operand" "n")
4060                      (const_int 2)]
4061                     UNSPECV_DELAY_CYCLES)
4062    (clobber (match_scratch:HI 1 "=&w"))]
4063   ""
4064   "ldi %A1,lo8(%0)
4065         ldi %B1,hi8(%0)
4066         1: sbiw %A1,1
4067         brne 1b"
4068   [(set_attr "length" "4")
4069    (set_attr "cc" "clobber")])
4071 (define_insn "delay_cycles_3"
4072   [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n")
4073                      (const_int 3)]
4074                     UNSPECV_DELAY_CYCLES)
4075    (clobber (match_scratch:QI 1 "=&d"))
4076    (clobber (match_scratch:QI 2 "=&d"))
4077    (clobber (match_scratch:QI 3 "=&d"))]
4078   ""
4079   "ldi %1,lo8(%0)
4080         ldi %2,hi8(%0)
4081         ldi %3,hlo8(%0)
4082         1: subi %1,1
4083         sbci %2,0
4084         sbci %3,0
4085         brne 1b"
4086   [(set_attr "length" "7")
4087    (set_attr "cc" "clobber")])
4089 (define_insn "delay_cycles_4"
4090   [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n")
4091                      (const_int 4)]
4092                     UNSPECV_DELAY_CYCLES)
4093    (clobber (match_scratch:QI 1 "=&d"))
4094    (clobber (match_scratch:QI 2 "=&d"))
4095    (clobber (match_scratch:QI 3 "=&d"))
4096    (clobber (match_scratch:QI 4 "=&d"))]
4097   ""
4098   "ldi %1,lo8(%0)
4099         ldi %2,hi8(%0)
4100         ldi %3,hlo8(%0)
4101         ldi %4,hhi8(%0)
4102         1: subi %1,1
4103         sbci %2,0
4104         sbci %3,0
4105         sbci %4,0
4106         brne 1b"
4107   [(set_attr "length" "9")
4108    (set_attr "cc" "clobber")])
4111 ;; Parity
4113 (define_expand "parityhi2"
4114   [(set (reg:HI 24)
4115         (match_operand:HI 1 "register_operand" ""))
4116    (set (reg:HI 24)
4117         (parity:HI (reg:HI 24)))
4118    (set (match_operand:HI 0 "register_operand" "")
4119         (reg:HI 24))]
4120   ""
4121   "")
4123 (define_expand "paritysi2"
4124   [(set (reg:SI 22)
4125         (match_operand:SI 1 "register_operand" ""))
4126    (set (reg:HI 24)
4127         (truncate:HI (parity:SI (reg:SI 22))))
4128    (set (match_dup 2)
4129         (reg:HI 24))
4130    (set (match_operand:SI 0 "register_operand" "")
4131         (zero_extend:SI (match_dup 2)))]
4132   ""
4133   {
4134     operands[2] = gen_reg_rtx (HImode);
4135   })
4137 (define_insn "*parityhi2.libgcc"
4138   [(set (reg:HI 24)
4139         (parity:HI (reg:HI 24)))]
4140   ""
4141   "%~call __parityhi2"
4142   [(set_attr "type" "xcall")
4143    (set_attr "cc" "clobber")])
4145 (define_insn "*parityqihi2.libgcc"
4146   [(set (reg:HI 24)
4147         (zero_extend:HI (parity:QI (reg:QI 24))))]
4148   ""
4149   "%~call __parityqi2"
4150   [(set_attr "type" "xcall")
4151    (set_attr "cc" "clobber")])
4153 (define_insn "*paritysihi2.libgcc"
4154   [(set (reg:HI 24)
4155         (truncate:HI (parity:SI (reg:SI 22))))]
4156   ""
4157   "%~call __paritysi2"
4158   [(set_attr "type" "xcall")
4159    (set_attr "cc" "clobber")])
4162 ;; Popcount
4164 (define_expand "popcounthi2"
4165   [(set (reg:HI 24)
4166         (match_operand:HI 1 "register_operand" ""))
4167    (set (reg:HI 24)
4168         (popcount:HI (reg:HI 24)))
4169    (set (match_operand:HI 0 "register_operand" "")
4170         (reg:HI 24))]
4171   ""
4172   "")
4174 (define_expand "popcountsi2"
4175   [(set (reg:SI 22)
4176         (match_operand:SI 1 "register_operand" ""))
4177    (set (reg:HI 24)
4178         (truncate:HI (popcount:SI (reg:SI 22))))
4179    (set (match_dup 2)
4180         (reg:HI 24))
4181    (set (match_operand:SI 0 "register_operand" "")
4182         (zero_extend:SI (match_dup 2)))]
4183   ""
4184   {
4185     operands[2] = gen_reg_rtx (HImode);
4186   })
4188 (define_insn "*popcounthi2.libgcc"
4189   [(set (reg:HI 24)
4190         (popcount:HI (reg:HI 24)))]
4191   ""
4192   "%~call __popcounthi2"
4193   [(set_attr "type" "xcall")
4194    (set_attr "cc" "clobber")])
4196 (define_insn "*popcountsi2.libgcc"
4197   [(set (reg:HI 24)
4198         (truncate:HI (popcount:SI (reg:SI 22))))]
4199   ""
4200   "%~call __popcountsi2"
4201   [(set_attr "type" "xcall")
4202    (set_attr "cc" "clobber")])
4204 (define_insn "*popcountqi2.libgcc"
4205   [(set (reg:QI 24)
4206         (popcount:QI (reg:QI 24)))]
4207   ""
4208   "%~call __popcountqi2"
4209   [(set_attr "type" "xcall")
4210    (set_attr "cc" "clobber")])
4212 (define_insn_and_split "*popcountqihi2.libgcc"
4213   [(set (reg:HI 24)
4214         (zero_extend:HI (popcount:QI (reg:QI 24))))]
4215   ""
4216   "#"
4217   ""
4218   [(set (reg:QI 24)
4219         (popcount:QI (reg:QI 24)))
4220    (set (reg:QI 25)
4221         (const_int 0))]
4222   "")
4224 ;; Count Leading Zeros
4226 (define_expand "clzhi2"
4227   [(set (reg:HI 24)
4228         (match_operand:HI 1 "register_operand" ""))
4229    (parallel [(set (reg:HI 24)
4230                    (clz:HI (reg:HI 24)))
4231               (clobber (reg:QI 26))])
4232    (set (match_operand:HI 0 "register_operand" "")
4233         (reg:HI 24))]
4234   ""
4235   "")
4237 (define_expand "clzsi2"
4238   [(set (reg:SI 22)
4239         (match_operand:SI 1 "register_operand" ""))
4240    (parallel [(set (reg:HI 24)
4241                    (truncate:HI (clz:SI (reg:SI 22))))
4242               (clobber (reg:QI 26))])
4243    (set (match_dup 2)
4244         (reg:HI 24))
4245    (set (match_operand:SI 0 "register_operand" "")
4246         (zero_extend:SI (match_dup 2)))]
4247   ""
4248   {
4249     operands[2] = gen_reg_rtx (HImode);
4250   })
4252 (define_insn "*clzhi2.libgcc"
4253   [(set (reg:HI 24)
4254         (clz:HI (reg:HI 24)))
4255    (clobber (reg:QI 26))]
4256   ""
4257   "%~call __clzhi2"
4258   [(set_attr "type" "xcall")
4259    (set_attr "cc" "clobber")])
4261 (define_insn "*clzsihi2.libgcc"
4262   [(set (reg:HI 24)
4263         (truncate:HI (clz:SI (reg:SI 22))))
4264    (clobber (reg:QI 26))]
4265   ""
4266   "%~call __clzsi2"
4267   [(set_attr "type" "xcall")
4268    (set_attr "cc" "clobber")])
4270 ;; Count Trailing Zeros
4272 (define_expand "ctzhi2"
4273   [(set (reg:HI 24)
4274         (match_operand:HI 1 "register_operand" ""))
4275    (parallel [(set (reg:HI 24)
4276                    (ctz:HI (reg:HI 24)))
4277               (clobber (reg:QI 26))])
4278    (set (match_operand:HI 0 "register_operand" "")
4279         (reg:HI 24))]
4280   ""
4281   "")
4283 (define_expand "ctzsi2"
4284   [(set (reg:SI 22)
4285         (match_operand:SI 1 "register_operand" ""))
4286    (parallel [(set (reg:HI 24)
4287                    (truncate:HI (ctz:SI (reg:SI 22))))
4288               (clobber (reg:QI 22))
4289               (clobber (reg:QI 26))])
4290    (set (match_dup 2)
4291         (reg:HI 24))
4292    (set (match_operand:SI 0 "register_operand" "")
4293         (zero_extend:SI (match_dup 2)))]
4294   ""
4295   {
4296     operands[2] = gen_reg_rtx (HImode);
4297   })
4299 (define_insn "*ctzhi2.libgcc"
4300   [(set (reg:HI 24)
4301         (ctz:HI (reg:HI 24)))
4302    (clobber (reg:QI 26))]
4303   ""
4304   "%~call __ctzhi2"
4305   [(set_attr "type" "xcall")
4306    (set_attr "cc" "clobber")])
4308 (define_insn "*ctzsihi2.libgcc"
4309   [(set (reg:HI 24)
4310         (truncate:HI (ctz:SI (reg:SI 22))))
4311    (clobber (reg:QI 22))
4312    (clobber (reg:QI 26))]
4313   ""
4314   "%~call __ctzsi2"
4315   [(set_attr "type" "xcall")
4316    (set_attr "cc" "clobber")])
4318 ;; Find First Set
4320 (define_expand "ffshi2"
4321   [(set (reg:HI 24)
4322         (match_operand:HI 1 "register_operand" ""))
4323    (parallel [(set (reg:HI 24)
4324                    (ffs:HI (reg:HI 24)))
4325               (clobber (reg:QI 26))])
4326    (set (match_operand:HI 0 "register_operand" "")
4327         (reg:HI 24))]
4328   ""
4329   "")
4331 (define_expand "ffssi2"
4332   [(set (reg:SI 22)
4333         (match_operand:SI 1 "register_operand" ""))
4334    (parallel [(set (reg:HI 24)
4335                    (truncate:HI (ffs:SI (reg:SI 22))))
4336               (clobber (reg:QI 22))
4337               (clobber (reg:QI 26))])
4338    (set (match_dup 2)
4339         (reg:HI 24))
4340    (set (match_operand:SI 0 "register_operand" "")
4341         (zero_extend:SI (match_dup 2)))]
4342   ""
4343   {
4344     operands[2] = gen_reg_rtx (HImode);
4345   })
4347 (define_insn "*ffshi2.libgcc"
4348   [(set (reg:HI 24)
4349         (ffs:HI (reg:HI 24)))
4350    (clobber (reg:QI 26))]
4351   ""
4352   "%~call __ffshi2"
4353   [(set_attr "type" "xcall")
4354    (set_attr "cc" "clobber")])
4356 (define_insn "*ffssihi2.libgcc"
4357   [(set (reg:HI 24)
4358         (truncate:HI (ffs:SI (reg:SI 22))))
4359    (clobber (reg:QI 22))
4360    (clobber (reg:QI 26))]
4361   ""
4362   "%~call __ffssi2"
4363   [(set_attr "type" "xcall")
4364    (set_attr "cc" "clobber")])
4366 ;; Copysign
4368 (define_insn "copysignsf3"
4369   [(set (match_operand:SF 0 "register_operand"             "=r")
4370         (unspec:SF [(match_operand:SF 1 "register_operand"  "0")
4371                     (match_operand:SF 2 "register_operand"  "r")]
4372                    UNSPEC_COPYSIGN))]
4373   ""
4374   "bst %D2,7\;bld %D0,7"
4375   [(set_attr "length" "2")
4376    (set_attr "cc" "none")])
4377   
4378 ;; Swap Bytes (change byte-endianess)
4380 (define_expand "bswapsi2"
4381   [(set (reg:SI 22)
4382         (match_operand:SI 1 "register_operand" ""))
4383    (set (reg:SI 22)
4384         (bswap:SI (reg:SI 22)))
4385    (set (match_operand:SI 0 "register_operand" "")
4386         (reg:SI 22))]
4387   ""
4388   "")
4390 (define_insn "*bswapsi2.libgcc"
4391   [(set (reg:SI 22)
4392         (bswap:SI (reg:SI 22)))]
4393   ""
4394   "%~call __bswapsi2"
4395   [(set_attr "type" "xcall")
4396    (set_attr "cc" "clobber")])
4399 ;; CPU instructions
4401 ;; NOP taking 1 or 2 Ticks 
4402 (define_insn "nopv"
4403   [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "P,K")] 
4404                     UNSPECV_NOP)]
4405   ""
4406   "@
4407         nop
4408         rjmp ."
4409   [(set_attr "length" "1")
4410    (set_attr "cc" "none")])
4412 ;; SLEEP
4413 (define_insn "sleep"
4414   [(unspec_volatile [(const_int 0)] UNSPECV_SLEEP)]
4415   ""
4416   "sleep"
4417   [(set_attr "length" "1")
4418    (set_attr "cc" "none")])
4420 ;; WDR
4421 (define_insn "wdr"
4422   [(unspec_volatile [(const_int 0)] UNSPECV_WDR)]
4423   ""
4424   "wdr"
4425   [(set_attr "length" "1")
4426    (set_attr "cc" "none")])
4427   
4428 ;; FMUL
4429 (define_expand "fmul"
4430   [(set (reg:QI 24)
4431         (match_operand:QI 1 "register_operand" ""))
4432    (set (reg:QI 25)
4433         (match_operand:QI 2 "register_operand" ""))
4434    (parallel [(set (reg:HI 22)
4435                    (unspec:HI [(reg:QI 24)
4436                                (reg:QI 25)] UNSPEC_FMUL))
4437               (clobber (reg:HI 24))])
4438    (set (match_operand:HI 0 "register_operand" "")
4439         (reg:HI 22))]
4440   ""
4441   {
4442     if (AVR_HAVE_MUL)
4443       {
4444         emit_insn (gen_fmul_insn (operand0, operand1, operand2));
4445         DONE;
4446       }
4447   })
4449 (define_insn "fmul_insn"
4450   [(set (match_operand:HI 0 "register_operand" "=r")
4451         (unspec:HI [(match_operand:QI 1 "register_operand" "a")
4452                     (match_operand:QI 2 "register_operand" "a")]
4453                    UNSPEC_FMUL))]
4454   "AVR_HAVE_MUL"
4455   "fmul %1,%2
4456         movw %0,r0
4457         clr __zero_reg__"
4458   [(set_attr "length" "3")
4459    (set_attr "cc" "clobber")])
4461 (define_insn "*fmul.call"
4462   [(set (reg:HI 22)
4463         (unspec:HI [(reg:QI 24)
4464                     (reg:QI 25)] UNSPEC_FMUL))
4465    (clobber (reg:HI 24))]
4466   "!AVR_HAVE_MUL"
4467   "%~call __fmul"
4468   [(set_attr "type" "xcall")
4469    (set_attr "cc" "clobber")])
4471 ;; FMULS
4472 (define_expand "fmuls"
4473   [(set (reg:QI 24)
4474         (match_operand:QI 1 "register_operand" ""))
4475    (set (reg:QI 25)
4476         (match_operand:QI 2 "register_operand" ""))
4477    (parallel [(set (reg:HI 22)
4478                    (unspec:HI [(reg:QI 24)
4479                                (reg:QI 25)] UNSPEC_FMULS))
4480               (clobber (reg:HI 24))])
4481    (set (match_operand:HI 0 "register_operand" "")
4482         (reg:HI 22))]
4483   ""
4484   {
4485     if (AVR_HAVE_MUL)
4486       {
4487         emit_insn (gen_fmuls_insn (operand0, operand1, operand2));
4488         DONE;
4489       }
4490   })
4492 (define_insn "fmuls_insn"
4493   [(set (match_operand:HI 0 "register_operand" "=r")
4494         (unspec:HI [(match_operand:QI 1 "register_operand" "a")
4495                     (match_operand:QI 2 "register_operand" "a")]
4496                    UNSPEC_FMULS))]
4497   "AVR_HAVE_MUL"
4498   "fmuls %1,%2
4499         movw %0,r0
4500         clr __zero_reg__"
4501   [(set_attr "length" "3")
4502    (set_attr "cc" "clobber")])
4504 (define_insn "*fmuls.call"
4505   [(set (reg:HI 22)
4506         (unspec:HI [(reg:QI 24)
4507                     (reg:QI 25)] UNSPEC_FMULS))
4508    (clobber (reg:HI 24))]
4509   "!AVR_HAVE_MUL"
4510   "%~call __fmuls"
4511   [(set_attr "type" "xcall")
4512    (set_attr "cc" "clobber")])
4514 ;; FMULSU
4515 (define_expand "fmulsu"
4516   [(set (reg:QI 24)
4517         (match_operand:QI 1 "register_operand" ""))
4518    (set (reg:QI 25)
4519         (match_operand:QI 2 "register_operand" ""))
4520    (parallel [(set (reg:HI 22)
4521                    (unspec:HI [(reg:QI 24)
4522                                (reg:QI 25)] UNSPEC_FMULSU))
4523               (clobber (reg:HI 24))])
4524    (set (match_operand:HI 0 "register_operand" "")
4525         (reg:HI 22))]
4526   ""
4527   {
4528     if (AVR_HAVE_MUL)
4529       {
4530         emit_insn (gen_fmulsu_insn (operand0, operand1, operand2));
4531         DONE;
4532       }
4533   })
4535 (define_insn "fmulsu_insn"
4536   [(set (match_operand:HI 0 "register_operand" "=r")
4537         (unspec:HI [(match_operand:QI 1 "register_operand" "a")
4538                     (match_operand:QI 2 "register_operand" "a")]
4539                    UNSPEC_FMULSU))]
4540   "AVR_HAVE_MUL"
4541   "fmulsu %1,%2
4542         movw %0,r0
4543         clr __zero_reg__"
4544   [(set_attr "length" "3")
4545    (set_attr "cc" "clobber")])
4547 (define_insn "*fmulsu.call"
4548   [(set (reg:HI 22)
4549         (unspec:HI [(reg:QI 24)
4550                     (reg:QI 25)] UNSPEC_FMULSU))
4551    (clobber (reg:HI 24))]
4552   "!AVR_HAVE_MUL"
4553   "%~call __fmulsu"
4554   [(set_attr "type" "xcall")
4555    (set_attr "cc" "clobber")])
4558 ;; Some combiner patterns dealing with bits.
4559 ;; See PR42210
4561 ;; Move bit $3.0 into bit $0.$4
4562 (define_insn "*movbitqi.1-6.a"
4563   [(set (match_operand:QI 0 "register_operand"                               "=r")
4564         (ior:QI (and:QI (match_operand:QI 1 "register_operand"                "0")
4565                         (match_operand:QI 2 "single_zero_operand"             "n"))
4566                 (and:QI (ashift:QI (match_operand:QI 3 "register_operand"     "r")
4567                                    (match_operand:QI 4 "const_0_to_7_operand" "n"))
4568                         (match_operand:QI 5 "single_one_operand"              "n"))))]
4569   "INTVAL(operands[4]) == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))
4570    && INTVAL(operands[4]) == exact_log2 (INTVAL(operands[5]) & GET_MODE_MASK (QImode))"
4571   "bst %3,0\;bld %0,%4"
4572   [(set_attr "length" "2")
4573    (set_attr "cc" "none")])
4575 ;; Move bit $3.0 into bit $0.$4
4576 ;; Variation of above. Unfortunately, there is no canonicalized representation
4577 ;; of moving around bits.  So what we see here depends on how user writes down
4578 ;; bit manipulations.
4579 (define_insn "*movbitqi.1-6.b"
4580   [(set (match_operand:QI 0 "register_operand"                            "=r")
4581         (ior:QI (and:QI (match_operand:QI 1 "register_operand"             "0")
4582                         (match_operand:QI 2 "single_zero_operand"          "n"))
4583                 (ashift:QI (and:QI (match_operand:QI 3 "register_operand"  "r")
4584                                    (const_int 1))
4585                            (match_operand:QI 4 "const_0_to_7_operand"      "n"))))]
4586   "INTVAL(operands[4]) == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))"
4587   "bst %3,0\;bld %0,%4"
4588   [(set_attr "length" "2")
4589    (set_attr "cc" "none")])
4591 ;; Move bit $3.0 into bit $0.0.
4592 ;; For bit 0, combiner generates slightly different pattern.
4593 (define_insn "*movbitqi.0"
4594   [(set (match_operand:QI 0 "register_operand"                     "=r")
4595         (ior:QI (and:QI (match_operand:QI 1 "register_operand"      "0")
4596                         (match_operand:QI 2 "single_zero_operand"   "n"))
4597                 (and:QI (match_operand:QI 3 "register_operand"      "r")
4598                         (const_int 1))))]
4599   "0 == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))"
4600   "bst %3,0\;bld %0,0"
4601   [(set_attr "length" "2")
4602    (set_attr "cc" "none")])
4604 ;; Move bit $2.0 into bit $0.7.
4605 ;; For bit 7, combiner generates slightly different pattern
4606 (define_insn "*movbitqi.7"
4607   [(set (match_operand:QI 0 "register_operand"                      "=r")
4608         (ior:QI (and:QI (match_operand:QI 1 "register_operand"       "0")
4609                         (const_int 127))
4610                 (ashift:QI (match_operand:QI 2 "register_operand"    "r")
4611                            (const_int 7))))]
4612   ""
4613   "bst %2,0\;bld %0,7"
4614   [(set_attr "length" "2")
4615    (set_attr "cc" "none")])
4617 ;; Combiner transforms above four pattern into ZERO_EXTRACT if it sees MEM
4618 ;; and input/output match.  We provide a special pattern for this, because
4619 ;; in contrast to a IN/BST/BLD/OUT sequence we need less registers and the
4620 ;; operation on I/O is atomic.
4621 (define_insn "*insv.io"
4622   [(set (zero_extract:QI (mem:QI (match_operand 0 "low_io_address_operand" "n,n,n"))
4623                          (const_int 1)
4624                          (match_operand:QI 1 "const_0_to_7_operand"        "n,n,n"))
4625         (match_operand:QI 2 "nonmemory_operand"                            "L,P,r"))]
4626   ""
4627   "@
4628         cbi %m0-0x20,%1
4629         sbi %m0-0x20,%1
4630         sbrc %2,0\;sbi %m0-0x20,%1\;sbrs %2,0\;cbi %m0-0x20,%1"
4631   [(set_attr "length" "1,1,4")
4632    (set_attr "cc" "none")])
4634 (define_insn "*insv.not.io"
4635   [(set (zero_extract:QI (mem:QI (match_operand 0 "low_io_address_operand" "n"))
4636                          (const_int 1)
4637                          (match_operand:QI 1 "const_0_to_7_operand"        "n"))
4638         (not:QI (match_operand:QI 2 "register_operand"                     "r")))]
4639   ""
4640   "sbrs %2,0\;sbi %m0-0x20,%1\;sbrc %2,0\;cbi %m0-0x20,%1"
4641   [(set_attr "length" "4")
4642    (set_attr "cc" "none")])
4644 ;; The insv expander.
4645 ;; We only support 1-bit inserts
4646 (define_expand "insv"
4647   [(set (zero_extract:QI (match_operand:QI 0 "register_operand" "")
4648                          (match_operand:QI 1 "const1_operand" "")        ; width
4649                          (match_operand:QI 2 "const_0_to_7_operand" "")) ; pos
4650         (match_operand:QI 3 "nonmemory_operand" ""))]
4651   "optimize"
4652   "")
4654 ;; Insert bit $2.0 into $0.$1
4655 (define_insn "*insv.reg"
4656   [(set (zero_extract:QI (match_operand:QI 0 "register_operand"    "+r,d,d,l,l")
4657                          (const_int 1)
4658                          (match_operand:QI 1 "const_0_to_7_operand" "n,n,n,n,n"))
4659         (match_operand:QI 2 "nonmemory_operand"                     "r,L,P,L,P"))]
4660   ""
4661   "@
4662         bst %2,0\;bld %0,%1
4663         andi %0,lo8(~(1<<%1))
4664         ori %0,lo8(1<<%1)
4665         clt\;bld %0,%1
4666         set\;bld %0,%1"
4667   [(set_attr "length" "2,1,1,2,2")
4668    (set_attr "cc" "none,set_zn,set_zn,none,none")])
4671 ;; Some combine patterns that try to fix bad code when a value is composed
4672 ;; from byte parts like in PR27663.
4673 ;; The patterns give some release but the code still is not optimal,
4674 ;; in particular when subreg lowering (-fsplit-wide-types) is turned on.
4675 ;; That switch obfuscates things here and in many other places.
4677 (define_insn_and_split "*ior<mode>qi.byte0"
4678   [(set (match_operand:HISI 0 "register_operand"                 "=r")
4679         (ior:HISI
4680          (zero_extend:HISI (match_operand:QI 1 "register_operand" "r"))
4681          (match_operand:HISI 2 "register_operand"                 "0")))]
4682   ""
4683   "#"
4684   "reload_completed"
4685   [(set (match_dup 3)
4686         (ior:QI (match_dup 3)
4687                 (match_dup 1)))]
4688   {
4689     operands[3] = simplify_gen_subreg (QImode, operands[0], <MODE>mode, 0);
4690   })
4692 (define_insn_and_split "*ior<mode>qi.byte1-3"
4693   [(set (match_operand:HISI 0 "register_operand"                              "=r")
4694         (ior:HISI
4695          (ashift:HISI (zero_extend:HISI (match_operand:QI 1 "register_operand" "r"))
4696                       (match_operand:QI 2 "const_8_16_24_operand"              "n"))
4697          (match_operand:HISI 3 "register_operand"                              "0")))]
4698   "INTVAL(operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4699   "#"
4700   "&& reload_completed"
4701   [(set (match_dup 4)
4702         (ior:QI (match_dup 4)
4703                 (match_dup 1)))]
4704   {
4705     int byteno = INTVAL(operands[2]) / BITS_PER_UNIT;
4706     operands[4] = simplify_gen_subreg (QImode, operands[0], <MODE>mode, byteno);
4707   })
4709 (define_expand "extzv"
4710   [(set (match_operand:QI 0 "register_operand" "")
4711         (zero_extract:QI (match_operand:QI 1 "register_operand"  "")
4712                          (match_operand:QI 2 "const1_operand" "")
4713                          (match_operand:QI 3 "const_0_to_7_operand" "")))]
4714   ""
4715   "")
4717 (define_insn "*extzv"
4718   [(set (match_operand:QI 0 "register_operand"                   "=*d,*d,*d,*d,r")
4719         (zero_extract:QI (match_operand:QI 1 "register_operand"     "0,r,0,0,r")
4720                          (const_int 1)
4721                          (match_operand:QI 2 "const_0_to_7_operand" "L,L,P,C04,n")))]
4722   ""
4723   "@
4724         andi %0,1
4725         mov %0,%1\;andi %0,1
4726         lsr %0\;andi %0,1
4727         swap %0\;andi %0,1
4728         bst %1,%2\;clr %0\;bld %0,0"
4729   [(set_attr "length" "1,2,2,2,3")
4730    (set_attr "cc" "set_zn,set_zn,set_zn,set_zn,clobber")])
4732 (define_insn_and_split "*extzv.qihi1"
4733   [(set (match_operand:HI 0 "register_operand"                     "=r")
4734         (zero_extract:HI (match_operand:QI 1 "register_operand"     "r")
4735                          (const_int 1)
4736                          (match_operand:QI 2 "const_0_to_7_operand" "n")))]
4737   ""
4738   "#"
4739   ""
4740   [(set (match_dup 3)
4741         (zero_extract:QI (match_dup 1)
4742                          (const_int 1)
4743                          (match_dup 2)))
4744    (set (match_dup 4)
4745         (const_int 0))]
4746   {
4747     operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
4748     operands[4] = simplify_gen_subreg (QImode, operands[0], HImode, 1);
4749   })
4751 (define_insn_and_split "*extzv.qihi2"
4752   [(set (match_operand:HI 0 "register_operand"                      "=r")
4753         (zero_extend:HI 
4754          (zero_extract:QI (match_operand:QI 1 "register_operand"     "r")
4755                           (const_int 1)
4756                           (match_operand:QI 2 "const_0_to_7_operand" "n"))))]
4757   ""
4758   "#"
4759   ""
4760   [(set (match_dup 3)
4761         (zero_extract:QI (match_dup 1)
4762                          (const_int 1)
4763                          (match_dup 2)))
4764    (set (match_dup 4)
4765         (const_int 0))]
4766   {
4767     operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
4768     operands[4] = simplify_gen_subreg (QImode, operands[0], HImode, 1);
4769   })