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