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