OSDN Git Service

Fix clearing ZERO_REG
[pf3gnuchains/gcc-fork.git] / gcc / config / avr / avr.md
1 ;;   Machine description for GNU compiler,
2 ;;   for ATMEL AVR micro controllers.
3 ;;   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008,
4 ;;   2009, 2010, 2011 Free Software Foundation, Inc.
5 ;;   Contributed by Denis Chertykov (chertykov@gmail.com)
6
7 ;; This file is part of GCC.
8
9 ;; GCC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 3, or (at your option)
12 ;; any later version.
13
14 ;; GCC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GCC; see the file COPYING3.  If not see
21 ;; <http://www.gnu.org/licenses/>.
22
23 ;; Special characters after '%':
24 ;;  A  No effect (add 0).
25 ;;  B  Add 1 to REG number, MEM address or CONST_INT.
26 ;;  C  Add 2.
27 ;;  D  Add 3.
28 ;;  j  Branch condition.
29 ;;  k  Reverse branch condition.
30 ;;..m..Constant Direct Data memory address.
31 ;;  i  Print the SFR address quivalent of a CONST_INT or a CONST_INT
32 ;;     RAM address.  The resulting 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.
49
50
51 (define_constants
52   [(REG_X       26)
53    (REG_Y       28)
54    (REG_Z       30)
55    (REG_W       24)
56    (REG_SP      32)
57    (LPM_REGNO   0)      ; implicit target register of LPM
58    (TMP_REGNO   0)      ; temporary register r0
59    (ZERO_REGNO  1)      ; zero register r1
60
61    ;; RAM addresses of some SFRs common to all Devices.
62
63    (SREG_ADDR   0x5F)   ; Status Register
64    (SP_ADDR     0x5D)   ; Stack Pointer
65    (RAMPZ_ADDR  0x5B)   ; Address' high part when loading via ELPM
66    ])
67
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    ])
79
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     
92
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,ldi"
99   (const_string "none"))
100
101 (define_attr "type" "branch,branch1,arith,xcall"
102   (const_string "arith"))
103
104 ;; The size of instructions in bytes.
105 ;; XXX may depend from "cc"
106
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)))
137
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.
143
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"))
156
157 ;; Flavours of instruction set architecture (ISA), used in enabled attribute
158
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
164
165 (define_attr "isa"
166   "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx,
167    standard"
168   (const_string "standard"))
169
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)
177
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)
185
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)
193
194          (and (eq_attr "isa" "eijmp")
195               (match_test "AVR_HAVE_EIJMP_EICALL"))
196          (const_int 1)
197
198          (and (eq_attr "isa" "lpm")
199               (match_test "!AVR_HAVE_LPMX"))
200          (const_int 1)
201
202          (and (eq_attr "isa" "lpmx")
203               (match_test "AVR_HAVE_LPMX"))
204          (const_int 1)
205
206          (and (eq_attr "isa" "elpm")
207               (match_test "AVR_HAVE_ELPM && !AVR_HAVE_ELPMX"))
208          (const_int 1)
209
210          (and (eq_attr "isa" "elpmx")
211               (match_test "AVR_HAVE_ELPMX"))
212          (const_int 1)
213          ] (const_int 0)))
214
215
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 "")])
222
223 ;; All supported move-modes
224 (define_mode_iterator MOVMODE [(QI "") (HI "") (SI "") (SF "") (PSI "")])
225
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])
230
231 ;; Define code attributes
232 (define_code_attr extend_su
233   [(sign_extend "s")
234    (zero_extend "u")])
235
236 (define_code_attr extend_u
237   [(sign_extend "")
238    (zero_extend "u")])
239
240 (define_code_attr extend_s
241   [(sign_extend "s")
242    (zero_extend "")])
243
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")])
248
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")])
255
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.
264
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   
280
281 ;; Defining nonlocal_goto_receiver means we must also define this.
282 ;; even though its function is identical to that in builtins.c
283
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   ""
290 {
291   rtx r_label = copy_to_reg (operands[1]);
292   rtx r_fp = operands[3];
293   rtx r_sp = operands[2];
294
295   emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
296
297   emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
298
299   emit_move_insn (hard_frame_pointer_rtx, r_fp);
300   emit_stack_restore (SAVE_NONLOCAL, r_sp);
301
302   emit_use (hard_frame_pointer_rtx);
303   emit_use (stack_pointer_rtx);
304
305   emit_indirect_jump (r_label);
306  
307   DONE;
308 })
309
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")])
318
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 "")])
328
329 (define_expand "push<mode>1"
330   [(match_operand:MPUSH 0 "" "")]
331   ""
332 {
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;
342 })
343
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   "")
354
355 ;;========================================================================
356 ;; Move stuff around
357
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")])
386
387
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);
402
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));
405
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   })
411
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;
430
431     emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0));
432
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);
444
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       }
455
456     set_mem_addr_space (SET_SRC (single_set (insn)), as);
457
458     DONE;
459   })
460
461 ;; Move value from address space pgmx to a register
462 ;; These insns must be prior to respective generic move insn.
463
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")])
474
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));
489
490     /* Devices with ELPM* also have CALL.  */
491
492     output_asm_insn ("call __xload_%0", &x_bytes);
493     return "";
494   }
495   [(set_attr "length" "2")
496    (set_attr "cc" "clobber")])
497
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")])
515
516
517 ;; General move expanders
518
519 ;; "movqi"
520 ;; "movhi"
521 ;; "movsi"
522 ;; "movsf"
523 ;; "movpsi"
524
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       }
543
544   if (avr_mem_pgmx_p (src))
545     {
546       rtx addr = XEXP (src, 0);
547
548       if (!REG_P (addr))
549         src = replace_equiv_address (src, copy_to_mode_reg (PSImode, addr));
550
551       if (QImode == <MODE>mode)
552         emit_insn (gen_xload8_A (dest, src));
553       else
554         emit_insn (gen_xload<mode>_A (dest, src));
555
556       DONE;
557     }
558
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   })
566
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.
575
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" "ldi,none,clobber,clobber,none,none,clobber")])
588
589 ;; This is used in peephole2 to optimize loading immediate constants
590 ;; if a scratch register from LD_REGS happens to be available.
591
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")])
601
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   "")
612
613 ;;============================================================================
614 ;; move word (16 bit)
615
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.
622
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")])
634
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   "")
644
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")])
657
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")])
670
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   })
684
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   })
698
699 ;; For LPM loads from AS1 we split 
700 ;;    R = *Z
701 ;; to
702 ;;    R = *Z++
703 ;;    Z = Z - sizeof (R)
704 ;;
705 ;; so that the second instruction can be optimized out.
706
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);
719
720      if (!avr_mem_pgm_p (operands[1])
721          || !REG_P (addr)
722          || reg_overlap_mentioned_p (addr, operands[0]))
723        {
724          FAIL;
725        }
726
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   })
732
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")])
760
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)
776
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   "")
787
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")])
800
801
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")])
814
815 ;; fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
816 ;; move floating point numbers (32 bit)
817
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")])
830
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   "")
841
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")])
854
855 ;;=========================================================================
856 ;; move string (like memcpy)
857
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   })
870
871 (define_mode_attr MOVMEM_r_d [(QI "r")
872                               (HI "d")])
873
874 ;; $0, $4 : & dest
875 ;; $1, $5 : & src
876 ;; $2     : Address Space
877 ;; $3, $7 : Loop register
878 ;; $6     : Scratch register
879
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")])
898
899 ;; Ditto and
900 ;; $8, $9 : hh8 (& src)
901 ;; $10    : RAMPZ_ADDR
902
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")])
924
925
926 ;; =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2
927 ;; memset (%0, %2, %1)
928
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;
940
941     /* If value to set is not zero, use the library routine.  */
942     if (operands[2] != const0_rtx)
943       FAIL;
944
945     if (!CONST_INT_P (operands[1]))
946       FAIL;
947
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   })
955
956
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")])
968
969
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")])
983
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   })
1006
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")])
1017
1018 ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1019 ; add bytes
1020
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")])
1035
1036
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);
1046
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   })
1058
1059
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")])
1068
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")])
1077
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")])
1090
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")])
1101
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       };
1114
1115     if (*asm_code[which_alternative])
1116       return asm_code[which_alternative];
1117
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")])
1123
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.
1127
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   })
1142
1143 ;; Same, but with reload to NO_LD_REGS
1144 ;; Combine *reload_inhi with *addhi3
1145
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))])])
1158
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")])
1173
1174
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       };
1189
1190     if (*asm_code[which_alternative])
1191       return asm_code [which_alternative];
1192
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")])
1198
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")])
1207
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")])
1216
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")])
1225
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")])
1234
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")])
1243
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       };
1258
1259     if (*asm_code[which_alternative])
1260       return asm_code [which_alternative];
1261
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")])
1267
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")])
1276
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")])
1285
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")])
1294
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")])
1303
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")])
1316
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")])
1327
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")])
1336
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")])
1349
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")])
1358
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")])
1367
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")])
1376
1377 ;******************************************************************************
1378 ; mul
1379
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     }
1391 }")
1392
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")])
1403
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   "")
1412
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")])
1420
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   
1436
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")])
1447
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")])
1457
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")])
1470
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")])
1481
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   
1493
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")])
1506
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")])
1517
1518 ;; Above insn is not canonicalized by insn combine, so here is a version with
1519 ;; operands swapped.
1520
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")])
1531
1532 ;; One-extend operand 1
1533
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")])
1545
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")])
1557
1558 ;******************************************************************************
1559 ; multiply-add/sub QI: $0 = $3 +/- $1*$2
1560 ;******************************************************************************
1561
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")])
1574
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")])
1586
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   "")
1604
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   "")
1622
1623
1624 ;******************************************************************************
1625 ; multiply-add/sub HI: $0 = $3 +/- $1*$2  with 8-bit values $1, $2
1626 ;******************************************************************************
1627
1628 ;; We don't use standard insns/expanders as they lead to cumbersome code for,
1629 ;; e.g,
1630 ;;
1631 ;;     int foo (unsigned char z)
1632 ;;     {
1633 ;;       extern int aInt[];
1634 ;;       return aInt[3*z+2];
1635 ;;     }
1636 ;;
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.
1641
1642
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")])
1658
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")])
1673
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);
1687
1688     return "add %A0,r0\;adc %B0,r1\;clr __zero_reg__";
1689   }
1690   [(set_attr "length" "4")
1691    (set_attr "cc" "clobber")])
1692
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);
1706
1707     return "sub %A0,r0\;sbc %B0,r1\;clr __zero_reg__";
1708   }
1709   [(set_attr "length" "4")
1710    (set_attr "cc" "clobber")])
1711
1712 ;; Handle small constants
1713
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   })
1735
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   })
1757
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.
1760
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   })
1780
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.
1784
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   })
1804
1805 ;; For signed/unsigned combinations that require narrow constraint "a"
1806 ;; just provide a pattern if signed/unsigned combination is actually needed.
1807
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   })
1828
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   })
1849
1850 ;******************************************************************************
1851 ; mul HI: $1 = sign/zero-extend, $2 = small constant
1852 ;******************************************************************************
1853
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   })
1873
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   })
1891
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   })
1909
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   })
1927
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.
1931
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")])
1942
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   })
1960
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   })
1978
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   })
1996
1997 ;******************************************************************************
1998 ; mul HI: $1 = sign-/zero-/one-extend, $2 = reg
1999 ;******************************************************************************
2000
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")])
2013
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")])
2026
2027 ;; one-extend operand 1
2028
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")])
2042
2043 ;******************************************************************************
2044
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]);
2055
2056         emit_insn (gen_mulhi3_call (operands[0], operands[1], operands[2]));
2057         DONE;
2058       }
2059
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.  */
2064
2065     if (s9_operand (operands[2], HImode))
2066       {
2067         rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
2068
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           }
2081
2082         DONE;
2083       }
2084
2085     if (!register_operand (operands[2], HImode))
2086       operands[2] = force_reg (HImode, operands[2]);
2087   })
2088
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")])
2101
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   "")
2111
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")])
2120
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.
2126
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       }
2141
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   })
2149
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       }
2176
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   })
2184
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]);
2211
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   })
2220
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]);
2247
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));
2252
2253         operands[1] = force_reg (HImode, operands[1]);
2254
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));
2259
2260         DONE;
2261       }
2262   })
2263
2264 ;; One-extend operand 1
2265
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   "")
2286
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   "")
2297
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   "")
2306
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];
2333
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);
2339
2340     if (QImode == <QIHI2:MODE>mode)
2341       xop2 = gen_rtx_fmt_e (<any_extend2:CODE>, HImode, xop2);
2342
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 */
2355
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   })
2362
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   "")
2379
2380
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")])
2390
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")])
2401
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")])
2414
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")])
2423
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")])
2432
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")])
2441
2442 ; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / %
2443 ; divmod
2444
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   "")
2474
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")])
2484
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   "")
2506
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")])
2515
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   "") 
2538
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")])
2548
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   "")
2571
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")])
2581
2582 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2583 ;; 24-bit multiply
2584
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.
2590
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   })
2606
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")])
2621
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")])
2636
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))])
2655
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   })
2685
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")])
2694
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")])
2706
2707
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.
2713
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))])
2735
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")])
2746
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))])
2768
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")])
2779
2780 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2781
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   "")
2804
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")])
2814
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   "")
2837
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")])
2847
2848 ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2849 ; and
2850
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")])
2861
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)";
2873
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")])
2879
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";
2891
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")])
2897
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";
2910
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")])
2916
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   })
2929
2930 ;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2931 ;; ior
2932
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")])
2943
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)";
2955
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")])
2961
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";
2973
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")])
2979
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";
2992
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")])
2998
2999 ;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3000 ;; xor
3001
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")])
3010
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";
3020
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")])
3026
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";
3038
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")])
3044
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";
3057
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")])
3063
3064 ;; swap swap swap swap swap swap swap swap swap swap swap swap swap swap swap
3065 ;; swap
3066
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;
3075
3076     operands[2] = gen_int_mode (INTVAL (operands[2]) & 7, QImode);
3077   })
3078
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)))])
3084
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")])
3101
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.
3105
3106 ;; HImode does not need scratch.  Use attribute for this constraint.
3107
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")])
3110
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;
3122
3123     if (!CONST_INT_P (operands[2]))
3124       FAIL;
3125
3126     offset = INTVAL (operands[2]);
3127  
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  */
3139
3140         emit_move_insn (operands[0],
3141                         gen_rtx_ROTATE (<MODE>mode, operands[1], operands[2]));
3142         DONE;
3143       }
3144     else
3145       FAIL;
3146   })
3147
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")])
3156
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")])
3165
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")])
3174
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")])
3183
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")])
3192
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")])
3201
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.
3206
3207
3208 ;; Split word aligned rotates using scratch that is mode dependent.
3209
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   })
3228
3229
3230 ;; Split byte aligned rotates using scratch that is always QI mode.
3231
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   })
3252
3253
3254 ;;<< << << << << << << << << << << << << << << << << << << << << << << << << <<
3255 ;; arithmetic shift left
3256
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" "")))])
3261
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   "")
3270
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   "")
3280
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   "")
3290
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")])
3302
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")])
3314
3315
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.
3318
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   "")
3333
3334 ;; ??? Combiner does not recognize that it could split the following insn;
3335 ;;     presumably because he has no register handy?
3336
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   })
3355
3356 ;; Similar.
3357
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(); }