OSDN Git Service

* config/avr/avr.md (SREG_ADDR): Remove constant definition.
[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
62 (define_c_enum "unspec"
63   [UNSPEC_STRLEN
64    UNSPEC_MOVMEM
65    UNSPEC_INDEX_JMP
66    UNSPEC_FMUL
67    UNSPEC_FMULS
68    UNSPEC_FMULSU
69    UNSPEC_COPYSIGN
70    UNSPEC_IDENTITY
71    UNSPEC_MAP_BITS
72    ])
73
74 (define_c_enum "unspecv"
75   [UNSPECV_PROLOGUE_SAVES
76    UNSPECV_EPILOGUE_RESTORES
77    UNSPECV_WRITE_SP
78    UNSPECV_GOTO_RECEIVER
79    UNSPECV_ENABLE_IRQS
80    UNSPECV_NOP
81    UNSPECV_SLEEP
82    UNSPECV_WDR
83    UNSPECV_DELAY_CYCLES
84    ])
85     
86
87 (include "predicates.md")
88 (include "constraints.md")
89   
90 ;; Condition code settings.
91 (define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber,
92                    out_plus, out_plus_noclobber,ldi"
93   (const_string "none"))
94
95 (define_attr "type" "branch,branch1,arith,xcall"
96   (const_string "arith"))
97
98 ;; The size of instructions in bytes.
99 ;; XXX may depend from "cc"
100
101 (define_attr "length" ""
102   (cond [(eq_attr "type" "branch")
103          (if_then_else (and (ge (minus (pc) (match_dup 0))
104                                 (const_int -63))
105                             (le (minus (pc) (match_dup 0))
106                                 (const_int 62)))
107                        (const_int 1)
108                        (if_then_else (and (ge (minus (pc) (match_dup 0))
109                                               (const_int -2045))
110                                           (le (minus (pc) (match_dup 0))
111                                               (const_int 2045)))
112                                      (const_int 2)
113                                      (const_int 3)))
114          (eq_attr "type" "branch1")
115          (if_then_else (and (ge (minus (pc) (match_dup 0))
116                                 (const_int -62))
117                             (le (minus (pc) (match_dup 0))
118                                 (const_int 61)))
119                        (const_int 2)
120                        (if_then_else (and (ge (minus (pc) (match_dup 0))
121                                               (const_int -2044))
122                                           (le (minus (pc) (match_dup 0))
123                                               (const_int 2043)))
124                                      (const_int 3)
125                                      (const_int 4)))
126          (eq_attr "type" "xcall")
127          (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
128                        (const_int 1)
129                        (const_int 2))]
130         (const_int 2)))
131
132 ;; Lengths of several insns are adjusted in avr.c:adjust_insn_length().
133 ;; Following insn attribute tells if and how the adjustment has to be
134 ;; done:
135 ;;     no     No adjustment needed; attribute "length" is fine.
136 ;; Otherwise do special processing depending on the attribute.
137
138 (define_attr "adjust_len"
139   "out_bitop, out_plus, out_plus_noclobber, plus64, addto_sp,
140    tsthi, tstpsi, tstsi, compare, compare64, call,
141    mov8, mov16, mov24, mov32, reload_in16, reload_in24, reload_in32,
142    xload, movmem,
143    ashlqi, ashrqi, lshrqi,
144    ashlhi, ashrhi, lshrhi,
145    ashlsi, ashrsi, lshrsi,
146    ashlpsi, ashrpsi, lshrpsi,
147    map_bits,
148    no"
149   (const_string "no"))
150
151 ;; Flavours of instruction set architecture (ISA), used in enabled attribute
152
153 ;; mov  : ISA has no MOVW                movw  : ISA has MOVW
154 ;; rjmp : ISA has no CALL/JMP            jmp   : ISA has CALL/JMP
155 ;; ijmp : ISA has no EICALL/EIJMP        eijmp : ISA has EICALL/EIJMP
156 ;; lpm  : ISA has no LPMX                lpmx  : ISA has LPMX
157 ;; elpm : ISA has ELPM but no ELPMX      elpmx : ISA has ELPMX
158
159 (define_attr "isa"
160   "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx,
161    standard"
162   (const_string "standard"))
163
164 (define_attr "enabled" ""
165   (cond [(eq_attr "isa" "standard")
166          (const_int 1)
167          
168          (and (eq_attr "isa" "mov")
169               (match_test "!AVR_HAVE_MOVW"))
170          (const_int 1)
171
172          (and (eq_attr "isa" "movw")
173               (match_test "AVR_HAVE_MOVW"))
174          (const_int 1)
175          
176          (and (eq_attr "isa" "rjmp")
177               (match_test "!AVR_HAVE_JMP_CALL"))
178          (const_int 1)
179
180          (and (eq_attr "isa" "jmp")
181               (match_test "AVR_HAVE_JMP_CALL"))
182          (const_int 1)
183          
184          (and (eq_attr "isa" "ijmp")
185               (match_test "!AVR_HAVE_EIJMP_EICALL"))
186          (const_int 1)
187
188          (and (eq_attr "isa" "eijmp")
189               (match_test "AVR_HAVE_EIJMP_EICALL"))
190          (const_int 1)
191
192          (and (eq_attr "isa" "lpm")
193               (match_test "!AVR_HAVE_LPMX"))
194          (const_int 1)
195
196          (and (eq_attr "isa" "lpmx")
197               (match_test "AVR_HAVE_LPMX"))
198          (const_int 1)
199
200          (and (eq_attr "isa" "elpm")
201               (match_test "AVR_HAVE_ELPM && !AVR_HAVE_ELPMX"))
202          (const_int 1)
203
204          (and (eq_attr "isa" "elpmx")
205               (match_test "AVR_HAVE_ELPMX"))
206          (const_int 1)
207          ] (const_int 0)))
208
209
210 ;; Define mode iterators
211 (define_mode_iterator QIHI  [(QI "") (HI "")])
212 (define_mode_iterator QIHI2 [(QI "") (HI "")])
213 (define_mode_iterator QISI [(QI "") (HI "") (PSI "") (SI "")])
214 (define_mode_iterator QIDI [(QI "") (HI "") (PSI "") (SI "") (DI "")])
215 (define_mode_iterator HISI [(HI "") (PSI "") (SI "")])
216
217 ;; All supported move-modes
218 (define_mode_iterator MOVMODE [(QI "") (HI "") (SI "") (SF "") (PSI "")])
219
220 ;; Define code iterators
221 ;; Define two incarnations so that we can build the cross product.
222 (define_code_iterator any_extend  [sign_extend zero_extend])
223 (define_code_iterator any_extend2 [sign_extend zero_extend])
224
225 ;; Define code attributes
226 (define_code_attr extend_su
227   [(sign_extend "s")
228    (zero_extend "u")])
229
230 (define_code_attr extend_u
231   [(sign_extend "")
232    (zero_extend "u")])
233
234 (define_code_attr extend_s
235   [(sign_extend "s")
236    (zero_extend "")])
237
238 ;; Constrain input operand of widening multiply, i.e. MUL resp. MULS.
239 (define_code_attr mul_r_d
240   [(zero_extend "r")
241    (sign_extend "d")])
242
243 ;; Map RTX code to its standard insn name
244 (define_code_attr code_stdname
245   [(ashift   "ashl")
246    (ashiftrt "ashr")
247    (lshiftrt "lshr")
248    (rotate   "rotl")])
249
250 ;;========================================================================
251 ;; The following is used by nonlocal_goto and setjmp.
252 ;; The receiver pattern will create no instructions since internally
253 ;; virtual_stack_vars = hard_frame_pointer + 1 so the RTL become R28=R28
254 ;; This avoids creating add/sub offsets in frame_pointer save/resore.
255 ;; The 'null' receiver also avoids  problems with optimisation
256 ;; not recognising incoming jmp and removing code that resets frame_pointer.
257 ;; The code derived from builtins.c.
258
259 (define_expand "nonlocal_goto_receiver"
260   [(set (reg:HI REG_Y) 
261         (unspec_volatile:HI [(const_int 0)] UNSPECV_GOTO_RECEIVER))]
262   ""
263   {
264     emit_move_insn (virtual_stack_vars_rtx, 
265                     gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, 
266                                   gen_int_mode (STARTING_FRAME_OFFSET,
267                                                 Pmode)));
268   /* This might change the hard frame pointer in ways that aren't
269     apparent to early optimization passes, so force a clobber.  */
270     emit_clobber (hard_frame_pointer_rtx);
271     DONE;
272   })
273   
274
275 ;; Defining nonlocal_goto_receiver means we must also define this.
276 ;; even though its function is identical to that in builtins.c
277
278 (define_expand "nonlocal_goto"
279   [(use (match_operand 0 "general_operand"))
280    (use (match_operand 1 "general_operand"))
281    (use (match_operand 2 "general_operand"))
282    (use (match_operand 3 "general_operand"))]
283   ""
284 {
285   rtx r_label = copy_to_reg (operands[1]);
286   rtx r_fp = operands[3];
287   rtx r_sp = operands[2];
288
289   emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
290
291   emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
292
293   emit_move_insn (hard_frame_pointer_rtx, r_fp);
294   emit_stack_restore (SAVE_NONLOCAL, r_sp);
295
296   emit_use (hard_frame_pointer_rtx);
297   emit_use (stack_pointer_rtx);
298
299   emit_indirect_jump (r_label);
300  
301   DONE;
302 })
303
304 (define_insn "pushqi1"
305   [(set (mem:QI (post_dec:HI (reg:HI REG_SP)))
306         (match_operand:QI 0 "reg_or_0_operand" "r,L"))]
307   ""
308   "@
309         push %0
310         push __zero_reg__"
311   [(set_attr "length" "1,1")])
312
313 ;; All modes for a multi-byte push.  We must include complex modes here too,
314 ;; lest emit_single_push_insn "helpfully " create the auto-inc itself.
315 (define_mode_iterator MPUSH
316   [(CQI "")
317    (HI "") (CHI "")
318    (PSI "")
319    (SI "") (CSI "")
320    (DI "") (CDI "")
321    (SF "") (SC "")])
322
323 (define_expand "push<mode>1"
324   [(match_operand:MPUSH 0 "" "")]
325   ""
326 {
327   int i;
328   for (i = GET_MODE_SIZE (<MODE>mode) - 1; i >= 0; --i)
329     {
330       rtx part = simplify_gen_subreg (QImode, operands[0], <MODE>mode, i);
331       if (part != const0_rtx)
332         part = force_reg (QImode, part);
333       emit_insn (gen_pushqi1 (part));
334     }
335   DONE;
336 })
337
338 ;; Notice a special-case when adding N to SP where N results in a
339 ;; zero REG_ARGS_SIZE.  This is equivalent to a move from FP.
340 (define_split
341   [(set (reg:HI REG_SP) (match_operand:HI 0 "register_operand" ""))]
342   "reload_completed
343    && frame_pointer_needed
344    && !cfun->calls_alloca
345    && find_reg_note (insn, REG_ARGS_SIZE, const0_rtx)"
346   [(set (reg:HI REG_SP) (reg:HI REG_Y))]
347   "")
348
349 ;;========================================================================
350 ;; Move stuff around
351
352 (define_expand "load<mode>_libgcc"
353   [(set (match_dup 3)
354         (match_dup 2))
355    (set (reg:MOVMODE 22)
356         (match_operand:MOVMODE 1 "memory_operand" ""))
357    (set (match_operand:MOVMODE 0 "register_operand" "")
358         (reg:MOVMODE 22))]
359   "avr_load_libgcc_p (operands[1])"
360   {
361     operands[3] = gen_rtx_REG (HImode, REG_Z);
362     operands[2] = force_operand (XEXP (operands[1], 0), NULL_RTX);
363     operands[1] = replace_equiv_address (operands[1], operands[3]);
364     set_mem_addr_space (operands[1], ADDR_SPACE_FLASH);
365   })
366     
367 (define_insn "load_<mode>_libgcc"
368   [(set (reg:MOVMODE 22)
369         (match_operand:MOVMODE 0 "memory_operand" "m,m"))]
370   "avr_load_libgcc_p (operands[0])
371    && REG_P (XEXP (operands[0], 0))
372    && REG_Z == REGNO (XEXP (operands[0], 0))"
373   {
374     operands[0] = GEN_INT (GET_MODE_SIZE (<MODE>mode));
375     return "%~call __load_%0";
376   }
377   [(set_attr "length" "1,2")
378    (set_attr "isa" "rjmp,jmp")
379    (set_attr "cc" "clobber")])
380
381
382 (define_insn_and_split "xload8_A"
383   [(set (match_operand:QI 0 "register_operand" "=r")
384         (match_operand:QI 1 "memory_operand"    "m"))
385    (clobber (reg:HI REG_Z))]
386   "can_create_pseudo_p()
387    && !avr_xload_libgcc_p (QImode)
388    && avr_mem_memx_p (operands[1])
389    && REG_P (XEXP (operands[1], 0))"
390   { gcc_unreachable(); }
391   "&& 1"
392   [(clobber (const_int 0))]
393   {
394     rtx insn, addr = XEXP (operands[1], 0);
395     rtx hi8 = gen_reg_rtx (QImode);
396     rtx reg_z = gen_rtx_REG (HImode, REG_Z);
397
398     emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0));
399     emit_move_insn (hi8, simplify_gen_subreg (QImode, addr, PSImode, 2));
400
401     insn = emit_insn (gen_xload_8 (operands[0], hi8));
402     set_mem_addr_space (SET_SRC (single_set (insn)),
403                                  MEM_ADDR_SPACE (operands[1]));
404     DONE;
405   })
406
407 (define_insn_and_split "xload<mode>_A"
408   [(set (match_operand:MOVMODE 0 "register_operand" "=r")
409         (match_operand:MOVMODE 1 "memory_operand"    "m"))
410    (clobber (reg:QI 21))
411    (clobber (reg:HI REG_Z))]
412   "can_create_pseudo_p()
413    && avr_mem_memx_p (operands[1])
414    && REG_P (XEXP (operands[1], 0))"
415   { gcc_unreachable(); }
416   "&& 1"
417   [(clobber (const_int 0))]
418   {
419     rtx addr = XEXP (operands[1], 0);
420     rtx reg_z = gen_rtx_REG (HImode, REG_Z);
421     rtx addr_hi8 = simplify_gen_subreg (QImode, addr, PSImode, 2);
422     addr_space_t as = MEM_ADDR_SPACE (operands[1]);
423     rtx insn;
424
425     /* Split the address to R21:Z */
426     emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0));
427     emit_move_insn (gen_rtx_REG (QImode, 21), addr_hi8);
428
429     /* Load with code from libgcc */
430     insn = emit_insn (gen_xload_<mode>_libgcc ());
431     set_mem_addr_space (SET_SRC (single_set (insn)), as);
432
433     /* Move to destination */
434     emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, 22));
435
436     DONE;
437   })
438
439 ;; Move value from address space memx to a register
440 ;; These insns must be prior to respective generic move insn.
441
442 (define_insn "xload_8"
443   [(set (match_operand:QI 0 "register_operand"                   "=&r,r")
444         (mem:QI (lo_sum:PSI (match_operand:QI 1 "register_operand" "r,r")
445                             (reg:HI REG_Z))))]
446   "!avr_xload_libgcc_p (QImode)"
447   {
448     return avr_out_xload (insn, operands, NULL);
449   }
450   [(set_attr "length" "3,4")
451    (set_attr "adjust_len" "*,xload")
452    (set_attr "isa" "lpmx,lpm")
453    (set_attr "cc" "none")])
454
455 ;; "xload_qi_libgcc"
456 ;; "xload_hi_libgcc"
457 ;; "xload_psi_libgcc"
458 ;; "xload_si_libgcc"
459 ;; "xload_sf_libgcc"
460 (define_insn "xload_<mode>_libgcc"
461   [(set (reg:MOVMODE 22)
462         (mem:MOVMODE (lo_sum:PSI (reg:QI 21)
463                                  (reg:HI REG_Z))))
464    (clobber (reg:QI 21))
465    (clobber (reg:HI REG_Z))]
466   "avr_xload_libgcc_p (<MODE>mode)"
467   {
468     rtx x_bytes = GEN_INT (GET_MODE_SIZE (<MODE>mode));
469
470     output_asm_insn ("%~call __xload_%0", &x_bytes);
471     return "";
472   }
473   [(set_attr "type" "xcall")
474    (set_attr "cc" "clobber")])
475
476
477 ;; General move expanders
478
479 ;; "movqi"
480 ;; "movhi"
481 ;; "movsi"
482 ;; "movsf"
483 ;; "movpsi"
484 (define_expand "mov<mode>"
485   [(set (match_operand:MOVMODE 0 "nonimmediate_operand" "")
486         (match_operand:MOVMODE 1 "general_operand" ""))]
487   ""
488   {
489     rtx dest = operands[0];
490     rtx src  = operands[1]; 
491     
492     if (avr_mem_flash_p (dest))
493       DONE;
494   
495     /* One of the operands has to be in a register.  */
496     if (!register_operand (dest, <MODE>mode)
497         && !(register_operand (src, <MODE>mode)
498              || src == CONST0_RTX (<MODE>mode)))
499       {
500         operands[1] = src = copy_to_mode_reg (<MODE>mode, src);
501       }
502
503   if (avr_mem_memx_p (src))
504     {
505       rtx addr = XEXP (src, 0);
506
507       if (!REG_P (addr))
508         src = replace_equiv_address (src, copy_to_mode_reg (PSImode, addr));
509
510       if (!avr_xload_libgcc_p (<MODE>mode))
511         emit_insn (gen_xload8_A (dest, src));
512       else
513         emit_insn (gen_xload<mode>_A (dest, src));
514
515       DONE;
516     }
517
518     if (avr_load_libgcc_p (src))
519       {
520         /* For the small devices, do loads per libgcc call.  */
521         emit_insn (gen_load<mode>_libgcc (dest, src));
522         DONE;
523       }
524   })
525
526 ;;========================================================================
527 ;; move byte
528 ;; The last alternative (any immediate constant to any register) is
529 ;; very expensive.  It should be optimized by peephole2 if a scratch
530 ;; register is available, but then that register could just as well be
531 ;; allocated for the variable we are loading.  But, most of NO_LD_REGS
532 ;; are call-saved registers, and most of LD_REGS are call-used registers,
533 ;; so this may still be a win for registers live across function calls.
534
535 (define_insn "movqi_insn"
536   [(set (match_operand:QI 0 "nonimmediate_operand" "=r ,d,Qm,r ,q,r,*r")
537         (match_operand:QI 1 "nox_general_operand"   "rL,i,rL,Qm,r,q,i"))]
538   "register_operand (operands[0], QImode)
539    || register_operand (operands[1], QImode)
540    || const0_rtx == operands[1]"
541   {
542     return output_movqi (insn, operands, NULL);
543   }
544   [(set_attr "length" "1,1,5,5,1,1,4")
545    (set_attr "adjust_len" "mov8")
546    (set_attr "cc" "ldi,none,clobber,clobber,none,none,clobber")])
547
548 ;; This is used in peephole2 to optimize loading immediate constants
549 ;; if a scratch register from LD_REGS happens to be available.
550
551 (define_insn "*reload_inqi"
552   [(set (match_operand:QI 0 "register_operand" "=l")
553         (match_operand:QI 1 "immediate_operand" "i"))
554    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
555   "reload_completed"
556   "ldi %2,lo8(%1)
557         mov %0,%2"
558   [(set_attr "length" "2")
559    (set_attr "cc" "none")])
560
561 (define_peephole2
562   [(match_scratch:QI 2 "d")
563    (set (match_operand:QI 0 "l_register_operand" "")
564         (match_operand:QI 1 "immediate_operand" ""))]
565   "(operands[1] != const0_rtx
566     && operands[1] != const1_rtx
567     && operands[1] != constm1_rtx)"
568   [(parallel [(set (match_dup 0) (match_dup 1))
569               (clobber (match_dup 2))])]
570   "")
571
572 ;;============================================================================
573 ;; move word (16 bit)
574
575 ;; Move register $1 to the Stack Pointer register SP.
576 ;; This insn is emit during function prologue/epilogue generation.
577 ;;    $2 = 0: We know that IRQs are off
578 ;;    $2 = 1: We know that IRQs are on
579 ;; Remaining cases when the state of the I-Flag is unknown are
580 ;; handled by generic movhi insn.
581
582 (define_insn "movhi_sp_r"
583   [(set (match_operand:HI 0 "stack_register_operand"                "=q,q")
584         (unspec_volatile:HI [(match_operand:HI 1 "register_operand"  "r,r")
585                              (match_operand:HI 2 "const_int_operand" "L,P")]
586                             UNSPECV_WRITE_SP))]
587   "!AVR_HAVE_8BIT_SP"
588   "@
589         out __SP_H__,%B1\;out __SP_L__,%A1
590         cli\;out __SP_H__,%B1\;sei\;out __SP_L__,%A1"
591   [(set_attr "length" "2,4")
592    (set_attr "cc" "none")])
593
594 (define_peephole2
595   [(match_scratch:QI 2 "d")
596    (set (match_operand:HI 0 "l_register_operand" "")
597         (match_operand:HI 1 "immediate_operand" ""))]
598   "(operands[1] != const0_rtx 
599     && operands[1] != constm1_rtx)"
600   [(parallel [(set (match_dup 0) (match_dup 1))
601               (clobber (match_dup 2))])]
602   "")
603
604 ;; '*' because it is not used in rtl generation, only in above peephole
605 (define_insn "*reload_inhi"
606   [(set (match_operand:HI 0 "register_operand" "=r")
607         (match_operand:HI 1 "immediate_operand" "i"))
608    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
609   "reload_completed"
610   {
611     return output_reload_inhi (operands, operands[2], NULL);
612   }
613   [(set_attr "length" "4")
614    (set_attr "adjust_len" "reload_in16")
615    (set_attr "cc" "none")])
616
617 (define_insn "*movhi"
618   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m ,d,*r,q,r")
619         (match_operand:HI 1 "nox_general_operand"   "r,L,m,rL,i,i ,r,q"))]
620   "register_operand (operands[0], HImode)
621    || register_operand (operands[1], HImode)
622    || const0_rtx == operands[1]"
623   {
624     return output_movhi (insn, operands, NULL);
625   }
626   [(set_attr "length" "2,2,6,7,2,6,5,2")
627    (set_attr "adjust_len" "mov16")
628    (set_attr "cc" "none,none,clobber,clobber,none,clobber,none,none")])
629
630 (define_peephole2 ; movw
631   [(set (match_operand:QI 0 "even_register_operand" "")
632         (match_operand:QI 1 "even_register_operand" ""))
633    (set (match_operand:QI 2 "odd_register_operand" "")
634         (match_operand:QI 3 "odd_register_operand" ""))]
635   "(AVR_HAVE_MOVW
636     && REGNO (operands[0]) == REGNO (operands[2]) - 1
637     && REGNO (operands[1]) == REGNO (operands[3]) - 1)"
638   [(set (match_dup 4) (match_dup 5))]
639   {
640     operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
641     operands[5] = gen_rtx_REG (HImode, REGNO (operands[1]));
642   })
643
644 (define_peephole2 ; movw_r
645   [(set (match_operand:QI 0 "odd_register_operand" "")
646         (match_operand:QI 1 "odd_register_operand" ""))
647    (set (match_operand:QI 2 "even_register_operand" "")
648         (match_operand:QI 3 "even_register_operand" ""))]
649   "(AVR_HAVE_MOVW
650     && REGNO (operands[2]) == REGNO (operands[0]) - 1
651     && REGNO (operands[3]) == REGNO (operands[1]) - 1)"
652   [(set (match_dup 4) (match_dup 5))]
653   {
654     operands[4] = gen_rtx_REG (HImode, REGNO (operands[2]));
655     operands[5] = gen_rtx_REG (HImode, REGNO (operands[3]));
656   })
657
658 ;; For LPM loads from AS1 we split 
659 ;;    R = *Z
660 ;; to
661 ;;    R = *Z++
662 ;;    Z = Z - sizeof (R)
663 ;;
664 ;; so that the second instruction can be optimized out.
665
666 (define_split ; "split-lpmx"
667   [(set (match_operand:HISI 0 "register_operand" "")
668         (match_operand:HISI 1 "memory_operand" ""))]
669   "reload_completed
670    && AVR_HAVE_LPMX"
671   [(set (match_dup 0)
672         (match_dup 2))
673    (set (match_dup 3)
674         (plus:HI (match_dup 3)
675                  (match_dup 4)))]
676   {
677      rtx addr = XEXP (operands[1], 0);
678
679      if (!avr_mem_flash_p (operands[1])
680          || !REG_P (addr)
681          || reg_overlap_mentioned_p (addr, operands[0]))
682        {
683          FAIL;
684        }
685
686     operands[2] = replace_equiv_address (operands[1],
687                                          gen_rtx_POST_INC (Pmode, addr));
688     operands[3] = addr;
689     operands[4] = gen_int_mode (-GET_MODE_SIZE (<MODE>mode), HImode);
690   })
691
692 ;;==========================================================================
693 ;; xpointer move (24 bit)
694   
695 (define_peephole2 ; *reload_inpsi
696   [(match_scratch:QI 2 "d")
697    (set (match_operand:PSI 0 "l_register_operand" "")
698         (match_operand:PSI 1 "immediate_operand" ""))
699    (match_dup 2)]
700   "operands[1] != const0_rtx
701    && operands[1] != constm1_rtx"
702   [(parallel [(set (match_dup 0)
703                    (match_dup 1))
704               (clobber (match_dup 2))])]
705   "")
706   
707 ;; '*' because it is not used in rtl generation.
708 (define_insn "*reload_inpsi"
709   [(set (match_operand:PSI 0 "register_operand" "=r")
710         (match_operand:PSI 1 "immediate_operand" "i"))
711    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
712   "reload_completed"
713   {
714     return avr_out_reload_inpsi (operands, operands[2], NULL);
715   }
716   [(set_attr "length" "6")
717    (set_attr "adjust_len" "reload_in24")
718    (set_attr "cc" "clobber")])
719
720 (define_insn "*movpsi"
721   [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
722         (match_operand:PSI 1 "nox_general_operand"   "r,L,Qm,rL,i ,i"))]
723   "register_operand (operands[0], PSImode)
724    || register_operand (operands[1], PSImode)
725    || const0_rtx == operands[1]"
726   {
727     return avr_out_movpsi (insn, operands, NULL);
728   }
729   [(set_attr "length" "3,3,8,9,4,10")
730    (set_attr "adjust_len" "mov24")
731    (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
732   
733 ;;==========================================================================
734 ;; move double word (32 bit)
735
736 (define_peephole2 ; *reload_insi
737   [(match_scratch:QI 2 "d")
738    (set (match_operand:SI 0 "l_register_operand" "")
739         (match_operand:SI 1 "const_int_operand" ""))
740    (match_dup 2)]
741   "(operands[1] != const0_rtx
742     && operands[1] != constm1_rtx)"
743   [(parallel [(set (match_dup 0) (match_dup 1))
744               (clobber (match_dup 2))])]
745   "")
746
747 ;; '*' because it is not used in rtl generation.
748 (define_insn "*reload_insi"
749   [(set (match_operand:SI 0 "register_operand" "=r")
750         (match_operand:SI 1 "const_int_operand" "n"))
751    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
752   "reload_completed"
753   {
754     return output_reload_insisf (operands, operands[2], NULL);
755   }
756   [(set_attr "length" "8")
757    (set_attr "adjust_len" "reload_in32")
758    (set_attr "cc" "clobber")])
759
760
761 (define_insn "*movsi"
762   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
763         (match_operand:SI 1 "nox_general_operand"   "r,L,Qm,rL,i ,i"))]
764   "register_operand (operands[0], SImode)
765    || register_operand (operands[1], SImode)
766    || const0_rtx == operands[1]"
767   {
768     return output_movsisf (insn, operands, NULL);
769   }
770   [(set_attr "length" "4,4,8,9,4,10")
771    (set_attr "adjust_len" "mov32")
772    (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
773
774 ;; fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
775 ;; move floating point numbers (32 bit)
776
777 (define_insn "*movsf"
778   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
779         (match_operand:SF 1 "nox_general_operand"   "r,G,Qm,rG,F ,F"))]
780   "register_operand (operands[0], SFmode)
781    || register_operand (operands[1], SFmode)
782    || operands[1] == CONST0_RTX (SFmode)"
783   {
784     return output_movsisf (insn, operands, NULL);
785   }
786   [(set_attr "length" "4,4,8,9,4,10")
787    (set_attr "adjust_len" "mov32")
788    (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
789
790 (define_peephole2 ; *reload_insf
791   [(match_scratch:QI 2 "d")
792    (set (match_operand:SF 0 "l_register_operand" "")
793         (match_operand:SF 1 "const_double_operand" ""))
794    (match_dup 2)]
795   "operands[1] != CONST0_RTX (SFmode)"
796   [(parallel [(set (match_dup 0) 
797                    (match_dup 1))
798               (clobber (match_dup 2))])]
799   "")
800
801 ;; '*' because it is not used in rtl generation.
802 (define_insn "*reload_insf"
803   [(set (match_operand:SF 0 "register_operand" "=r")
804         (match_operand:SF 1 "const_double_operand" "F"))
805    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
806   "reload_completed"
807   {
808     return output_reload_insisf (operands, operands[2], NULL);
809   }
810   [(set_attr "length" "8")
811    (set_attr "adjust_len" "reload_in32")
812    (set_attr "cc" "clobber")])
813
814 ;;=========================================================================
815 ;; move string (like memcpy)
816
817 (define_expand "movmemhi"
818   [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
819                    (match_operand:BLK 1 "memory_operand" ""))
820               (use (match_operand:HI 2 "const_int_operand" ""))
821               (use (match_operand:HI 3 "const_int_operand" ""))])]
822   ""
823   {
824     if (avr_emit_movmemhi (operands))
825       DONE;
826     
827     FAIL;
828   })
829
830 (define_mode_attr MOVMEM_r_d [(QI "r")
831                               (HI "wd")])
832
833 ;; $0, $4 : & dest (REG_X)
834 ;; $1, $5 : & src  (REG_Z)
835 ;; $2     : Address Space
836 ;; $3, $7 : Loop register
837 ;; $6     : Scratch register
838
839 ;; "movmem_qi"
840 ;; "movmem_hi"
841 (define_insn "movmem_<mode>"
842   [(set (mem:BLK (match_operand:HI 0 "register_operand" "x"))
843         (mem:BLK (match_operand:HI 1 "register_operand" "z")))
844    (unspec [(match_operand:QI 2 "const_int_operand"     "n")]
845            UNSPEC_MOVMEM)
846    (use (match_operand:QIHI 3 "register_operand"       "<MOVMEM_r_d>"))
847    (clobber (match_operand:HI 4 "register_operand"     "=0"))
848    (clobber (match_operand:HI 5 "register_operand"     "=1"))
849    (clobber (match_operand:QI 6 "register_operand"     "=&r"))
850    (clobber (match_operand:QIHI 7 "register_operand"   "=3"))]
851   ""
852   {
853     return avr_out_movmem (insn, operands, NULL);
854   }
855   [(set_attr "adjust_len" "movmem")
856    (set_attr "cc" "clobber")])
857
858 ;; Ditto and
859 ;; $3, $7 : Loop register = R24
860 ;; $8, $9 : hh8 (& src)   = R23
861 ;; $10    : RAMPZ_ADDR
862
863 ;; "movmemx_qi"
864 ;; "movmemx_hi"
865 (define_insn "movmemx_<mode>"
866   [(set (mem:BLK (match_operand:HI 0 "register_operand"             "x"))
867         (mem:BLK (lo_sum:PSI (match_operand:QI 8 "register_operand" "r")
868                              (match_operand:HI 1 "register_operand" "z"))))
869    (unspec [(match_operand:QI 2 "const_int_operand"                 "n")]
870            UNSPEC_MOVMEM)
871    (use (match_operand:QIHI 3 "register_operand"                   "w"))
872    (clobber (match_operand:HI 4 "register_operand"                 "=0"))
873    (clobber (match_operand:HI 5 "register_operand"                 "=1"))
874    (clobber (match_operand:QI 6 "register_operand"                 "=&r"))
875    (clobber (match_operand:HI 7 "register_operand"                 "=3"))
876    (clobber (match_operand:QI 9 "register_operand"                 "=8"))
877    (clobber (mem:QI (match_operand:QI 10 "io_address_operand"       "n")))]
878   ""
879   "%~call __movmemx_<mode>"
880   [(set_attr "type" "xcall")
881    (set_attr "cc" "clobber")])
882
883
884 ;; =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2
885 ;; memset (%0, %2, %1)
886
887 (define_expand "setmemhi"
888   [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
889                    (match_operand 2 "const_int_operand" ""))
890               (use (match_operand:HI 1 "const_int_operand" ""))
891               (use (match_operand:HI 3 "const_int_operand" ""))
892               (clobber (match_scratch:HI 4 ""))
893               (clobber (match_dup 5))])]
894   ""
895   {
896     rtx addr0;
897     enum machine_mode mode;
898
899     /* If value to set is not zero, use the library routine.  */
900     if (operands[2] != const0_rtx)
901       FAIL;
902
903     if (!CONST_INT_P (operands[1]))
904       FAIL;
905
906     mode = u8_operand (operands[1], VOIDmode) ? QImode : HImode;
907     operands[5] = gen_rtx_SCRATCH (mode);
908     operands[1] = copy_to_mode_reg (mode,
909                                     gen_int_mode (INTVAL (operands[1]), mode));
910     addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
911     operands[0] = gen_rtx_MEM (BLKmode, addr0);
912   })
913
914
915 (define_insn "*clrmemqi"
916   [(set (mem:BLK (match_operand:HI 0 "register_operand" "e"))
917         (const_int 0))
918    (use (match_operand:QI 1 "register_operand" "r"))
919    (use (match_operand:QI 2 "const_int_operand" "n"))
920    (clobber (match_scratch:HI 3 "=0"))
921    (clobber (match_scratch:QI 4 "=&1"))]
922   ""
923   "0:\;st %a0+,__zero_reg__\;dec %1\;brne 0b"
924   [(set_attr "length" "3")
925    (set_attr "cc" "clobber")])
926
927
928 (define_insn "*clrmemhi"
929   [(set (mem:BLK (match_operand:HI 0 "register_operand" "e,e"))
930         (const_int 0))
931    (use (match_operand:HI 1 "register_operand" "!w,d"))
932    (use (match_operand:HI 2 "const_int_operand" "n,n"))
933    (clobber (match_scratch:HI 3 "=0,0"))
934    (clobber (match_scratch:HI 4 "=&1,&1"))]
935   ""
936   "@
937         0:\;st %a0+,__zero_reg__\;sbiw %A1,1\;brne 0b
938         0:\;st %a0+,__zero_reg__\;subi %A1,1\;sbci %B1,0\;brne 0b"
939   [(set_attr "length" "3,4")
940    (set_attr "cc" "clobber,clobber")])
941
942 (define_expand "strlenhi"
943   [(set (match_dup 4)
944         (unspec:HI [(match_operand:BLK 1 "memory_operand" "")
945                     (match_operand:QI 2 "const_int_operand" "")
946                     (match_operand:HI 3 "immediate_operand" "")]
947                    UNSPEC_STRLEN))
948    (set (match_dup 4)
949         (plus:HI (match_dup 4)
950                  (const_int -1)))
951    (set (match_operand:HI 0 "register_operand" "")
952         (minus:HI (match_dup 4)
953                   (match_dup 5)))]
954   ""
955   {
956     rtx addr;
957     if (operands[2] != const0_rtx)
958       FAIL;
959     addr = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
960     operands[1] = gen_rtx_MEM (BLKmode, addr); 
961     operands[5] = addr;
962     operands[4] = gen_reg_rtx (HImode);
963   })
964
965 (define_insn "*strlenhi"
966   [(set (match_operand:HI 0 "register_operand"                      "=e")
967         (unspec:HI [(mem:BLK (match_operand:HI 1 "register_operand"  "0"))
968                     (const_int 0)
969                     (match_operand:HI 2 "immediate_operand"          "i")]
970                    UNSPEC_STRLEN))]
971   ""
972   "0:\;ld __tmp_reg__,%a0+\;tst __tmp_reg__\;brne 0b"
973   [(set_attr "length" "3")
974    (set_attr "cc" "clobber")])
975
976 ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
977 ; add bytes
978
979 (define_insn "addqi3"
980   [(set (match_operand:QI 0 "register_operand"          "=r,d,r,r,r,r")
981         (plus:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
982                  (match_operand:QI 2 "nonmemory_operand" "r,i,P,N,K,Cm2")))]
983   ""
984   "@
985         add %0,%2
986         subi %0,lo8(-(%2))
987         inc %0
988         dec %0
989         inc %0\;inc %0
990         dec %0\;dec %0"
991   [(set_attr "length" "1,1,1,1,2,2")
992    (set_attr "cc" "set_czn,set_czn,set_zn,set_zn,set_zn,set_zn")])
993
994
995 (define_expand "addhi3"
996   [(set (match_operand:HI 0 "register_operand" "")
997         (plus:HI (match_operand:HI 1 "register_operand" "")
998                  (match_operand:HI 2 "nonmemory_operand" "")))]
999   ""
1000   {
1001     if (CONST_INT_P (operands[2]))
1002       {
1003         operands[2] = gen_int_mode (INTVAL (operands[2]), HImode);
1004
1005         if (can_create_pseudo_p()
1006             && !stack_register_operand (operands[0], HImode)
1007             && !stack_register_operand (operands[1], HImode)
1008             && !d_register_operand (operands[0], HImode)
1009             && !d_register_operand (operands[1], HImode))
1010           {
1011             emit_insn (gen_addhi3_clobber (operands[0], operands[1], operands[2]));
1012             DONE;
1013           }
1014       }
1015   })
1016
1017
1018 (define_insn "*addhi3_zero_extend"
1019   [(set (match_operand:HI 0 "register_operand"                         "=r")
1020         (plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1021                  (match_operand:HI 2 "register_operand"                 "0")))]
1022   ""
1023   "add %A0,%1\;adc %B0,__zero_reg__"
1024   [(set_attr "length" "2")
1025    (set_attr "cc" "set_n")])
1026
1027 (define_insn "*addhi3_zero_extend1"
1028   [(set (match_operand:HI 0 "register_operand"                         "=r")
1029         (plus:HI (match_operand:HI 1 "register_operand"                 "0")
1030                  (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1031   ""
1032   "add %A0,%2\;adc %B0,__zero_reg__"
1033   [(set_attr "length" "2")
1034    (set_attr "cc" "set_n")])
1035
1036 (define_insn "*addhi3.sign_extend1"
1037   [(set (match_operand:HI 0 "register_operand"                         "=r")
1038         (plus:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "r"))
1039                  (match_operand:HI 2 "register_operand"                 "0")))]
1040   ""
1041   {
1042     return reg_overlap_mentioned_p (operands[0], operands[1])
1043       ? "mov __tmp_reg__,%1\;add %A0,%1\;adc %B0,__zero_reg__\;sbrc __tmp_reg__,7\;dec %B0"
1044       : "add %A0,%1\;adc %B0,__zero_reg__\;sbrc %1,7\;dec %B0";
1045   }
1046   [(set_attr "length" "5")
1047    (set_attr "cc" "clobber")])
1048
1049 (define_insn "*addhi3_sp"
1050   [(set (match_operand:HI 1 "stack_register_operand"           "=q")
1051         (plus:HI (match_operand:HI 2 "stack_register_operand"   "q")
1052                  (match_operand:HI 0 "avr_sp_immediate_operand" "Csp")))]
1053   ""
1054   {
1055     return avr_out_addto_sp (operands, NULL);
1056   }
1057   [(set_attr "length" "6")
1058    (set_attr "adjust_len" "addto_sp")])
1059
1060 (define_insn "*addhi3"
1061   [(set (match_operand:HI 0 "register_operand"          "=r,d,d")
1062         (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
1063                  (match_operand:HI 2 "nonmemory_operand" "r,s,n")))]
1064   ""
1065   {
1066     static const char * const asm_code[] =
1067       {
1068         "add %A0,%A2\;adc %B0,%B2",
1069         "subi %A0,lo8(-(%2))\;sbci %B0,hi8(-(%2))",
1070         ""
1071       };
1072
1073     if (*asm_code[which_alternative])
1074       return asm_code[which_alternative];
1075
1076     return avr_out_plus_noclobber (operands, NULL, NULL);
1077   }
1078   [(set_attr "length" "2,2,2")
1079    (set_attr "adjust_len" "*,*,out_plus_noclobber")
1080    (set_attr "cc" "set_n,set_czn,out_plus_noclobber")])
1081
1082 ;; Adding a constant to NO_LD_REGS might have lead to a reload of
1083 ;; that constant to LD_REGS.  We don't add a scratch to *addhi3
1084 ;; itself because that insn is special to reload.
1085
1086 (define_peephole2 ; addhi3_clobber
1087   [(set (match_operand:HI 0 "d_register_operand" "")
1088         (match_operand:HI 1 "const_int_operand" ""))
1089    (set (match_operand:HI 2 "l_register_operand" "")
1090         (plus:HI (match_dup 2)
1091                  (match_dup 0)))]
1092   "peep2_reg_dead_p (2, operands[0])"
1093   [(parallel [(set (match_dup 2)
1094                    (plus:HI (match_dup 2)
1095                             (match_dup 1)))
1096               (clobber (match_dup 3))])]
1097   {
1098     operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
1099   })
1100
1101 ;; Same, but with reload to NO_LD_REGS
1102 ;; Combine *reload_inhi with *addhi3
1103
1104 (define_peephole2 ; addhi3_clobber
1105   [(parallel [(set (match_operand:HI 0 "l_register_operand" "")
1106                    (match_operand:HI 1 "const_int_operand" ""))
1107               (clobber (match_operand:QI 2 "d_register_operand" ""))])
1108    (set (match_operand:HI 3 "l_register_operand" "")
1109         (plus:HI (match_dup 3)
1110                  (match_dup 0)))]
1111   "peep2_reg_dead_p (2, operands[0])"
1112   [(parallel [(set (match_dup 3)
1113                    (plus:HI (match_dup 3)
1114                             (match_dup 1)))
1115               (clobber (match_dup 2))])])
1116
1117 (define_insn "addhi3_clobber"
1118   [(set (match_operand:HI 0 "register_operand"           "=d,l")
1119         (plus:HI (match_operand:HI 1 "register_operand"  "%0,0")
1120                  (match_operand:HI 2 "const_int_operand"  "n,n")))
1121    (clobber (match_scratch:QI 3                          "=X,&d"))]
1122   ""
1123   {
1124     gcc_assert (REGNO (operands[0]) == REGNO (operands[1]));
1125     
1126     return avr_out_plus (operands, NULL, NULL);
1127   }
1128   [(set_attr "length" "4")
1129    (set_attr "adjust_len" "out_plus")
1130    (set_attr "cc" "out_plus")])
1131
1132
1133 (define_insn "addsi3"
1134   [(set (match_operand:SI 0 "register_operand"          "=r,d ,d,r")
1135         (plus:SI (match_operand:SI 1 "register_operand" "%0,0 ,0,0")
1136                  (match_operand:SI 2 "nonmemory_operand" "r,s ,n,n")))
1137    (clobber (match_scratch:QI 3                         "=X,X ,X,&d"))]
1138   ""
1139   {
1140     static const char * const asm_code[] =
1141       {
1142         "add %A0,%A2\;adc %B0,%B2\;adc %C0,%C2\;adc %D0,%D2",
1143         "subi %0,lo8(-(%2))\;sbci %B0,hi8(-(%2))\;sbci %C0,hlo8(-(%2))\;sbci %D0,hhi8(-(%2))",
1144         "",
1145         ""
1146       };
1147
1148     if (*asm_code[which_alternative])
1149       return asm_code[which_alternative];
1150
1151     return avr_out_plus (operands, NULL, NULL);
1152   }
1153   [(set_attr "length" "4,4,4,8")
1154    (set_attr "adjust_len" "*,*,out_plus,out_plus")
1155    (set_attr "cc" "set_n,set_czn,out_plus,out_plus")])
1156
1157 (define_insn "*addpsi3_zero_extend.qi"
1158   [(set (match_operand:PSI 0 "register_operand"                          "=r")
1159         (plus:PSI (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))
1160                   (match_operand:PSI 2 "register_operand"                 "0")))]
1161   ""
1162   "add %A0,%A1\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__"
1163   [(set_attr "length" "3")
1164    (set_attr "cc" "set_n")])
1165
1166 (define_insn "*addpsi3_zero_extend.hi"
1167   [(set (match_operand:PSI 0 "register_operand"                          "=r")
1168         (plus:PSI (zero_extend:PSI (match_operand:HI 1 "register_operand" "r"))
1169                   (match_operand:PSI 2 "register_operand"                 "0")))]
1170   ""
1171   "add %A0,%A1\;adc %B0,%B1\;adc %C0,__zero_reg__"
1172   [(set_attr "length" "3")
1173    (set_attr "cc" "set_n")])
1174
1175 (define_insn "*addpsi3_sign_extend.hi"
1176   [(set (match_operand:PSI 0 "register_operand"                          "=r")
1177         (plus:PSI (sign_extend:PSI (match_operand:HI 1 "register_operand" "r"))
1178                   (match_operand:PSI 2 "register_operand"                 "0")))]
1179   ""
1180   "add %A0,%1\;adc %B0,%B1\;adc %C0,__zero_reg__\;sbrc %B1,7\;dec %C0"
1181   [(set_attr "length" "5")
1182    (set_attr "cc" "set_n")])
1183
1184 (define_insn "*addsi3_zero_extend"
1185   [(set (match_operand:SI 0 "register_operand"                         "=r")
1186         (plus:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
1187                  (match_operand:SI 2 "register_operand"                 "0")))]
1188   ""
1189   "add %A0,%1\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__"
1190   [(set_attr "length" "4")
1191    (set_attr "cc" "set_n")])
1192
1193 (define_insn "*addsi3_zero_extend.hi"
1194   [(set (match_operand:SI 0 "register_operand"                         "=r")
1195         (plus:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
1196                  (match_operand:SI 2 "register_operand"                 "0")))]
1197   ""
1198   "add %A0,%1\;adc %B0,%B1\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__"
1199   [(set_attr "length" "4")
1200    (set_attr "cc" "set_n")])
1201
1202 (define_insn "addpsi3"
1203   [(set (match_operand:PSI 0 "register_operand"           "=r,d ,d,r")
1204         (plus:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0,0")
1205                   (match_operand:PSI 2 "nonmemory_operand" "r,s ,n,n")))
1206    (clobber (match_scratch:QI 3                           "=X,X ,X,&d"))]
1207   ""
1208   {
1209     static const char * const asm_code[] =
1210       {
1211         "add %A0,%A2\;adc %B0,%B2\;adc %C0,%C2",
1212         "subi %0,lo8(-(%2))\;sbci %B0,hi8(-(%2))\;sbci %C0,hlo8(-(%2))",
1213         "",
1214         ""
1215       };
1216
1217     if (*asm_code[which_alternative])
1218       return asm_code[which_alternative];
1219
1220     return avr_out_plus (operands, NULL, NULL);
1221   }
1222   [(set_attr "length" "3,3,3,6")
1223    (set_attr "adjust_len" "*,*,out_plus,out_plus")
1224    (set_attr "cc" "set_n,set_czn,out_plus,out_plus")])
1225
1226 (define_insn "subpsi3"
1227   [(set (match_operand:PSI 0 "register_operand"           "=r")
1228         (minus:PSI (match_operand:PSI 1 "register_operand" "0")
1229                    (match_operand:PSI 2 "register_operand" "r")))]
1230   ""
1231   "sub %0,%2\;sbc %B0,%B2\;sbc %C0,%C2"
1232   [(set_attr "length" "3")
1233    (set_attr "cc" "set_czn")])
1234
1235 (define_insn "*subpsi3_zero_extend.qi"
1236   [(set (match_operand:PSI 0 "register_operand"                           "=r")
1237         (minus:PSI (match_operand:SI 1 "register_operand"                  "0")
1238                    (zero_extend:PSI (match_operand:QI 2 "register_operand" "r"))))]
1239   ""
1240   "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__"
1241   [(set_attr "length" "3")
1242    (set_attr "cc" "set_czn")])
1243
1244 (define_insn "*subpsi3_zero_extend.hi"
1245   [(set (match_operand:PSI 0 "register_operand"                           "=r")
1246         (minus:PSI (match_operand:PSI 1 "register_operand"                 "0")
1247                    (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
1248   ""
1249   "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__"
1250   [(set_attr "length" "3")
1251    (set_attr "cc" "set_czn")])
1252
1253 (define_insn "*subpsi3_sign_extend.hi"
1254   [(set (match_operand:PSI 0 "register_operand"                           "=r")
1255         (minus:PSI (match_operand:PSI 1 "register_operand"                 "0")
1256                    (sign_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
1257   ""
1258   "sub %A0,%A2\;sbc %B0,%B2\;sbc %C0,__zero_reg__\;sbrc %B2,7\;inc %C0"
1259   [(set_attr "length" "5")
1260    (set_attr "cc" "set_czn")])
1261
1262 ;-----------------------------------------------------------------------------
1263 ; sub bytes
1264 (define_insn "subqi3"
1265   [(set (match_operand:QI 0 "register_operand" "=r,d")
1266         (minus:QI (match_operand:QI 1 "register_operand" "0,0")
1267                   (match_operand:QI 2 "nonmemory_operand" "r,i")))]
1268   ""
1269   "@
1270         sub %0,%2
1271         subi %0,lo8(%2)"
1272   [(set_attr "length" "1,1")
1273    (set_attr "cc" "set_czn,set_czn")])
1274
1275 (define_insn "subhi3"
1276   [(set (match_operand:HI 0 "register_operand" "=r,d")
1277         (minus:HI (match_operand:HI 1 "register_operand" "0,0")
1278                   (match_operand:HI 2 "nonmemory_operand" "r,i")))]
1279   ""
1280   "@
1281         sub %A0,%A2\;sbc %B0,%B2
1282         subi %A0,lo8(%2)\;sbci %B0,hi8(%2)"
1283   [(set_attr "length" "2,2")
1284    (set_attr "cc" "set_czn,set_czn")])
1285
1286 (define_insn "*subhi3_zero_extend1"
1287   [(set (match_operand:HI 0 "register_operand"                          "=r")
1288         (minus:HI (match_operand:HI 1 "register_operand"                 "0")
1289                   (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1290   ""
1291   "sub %A0,%2\;sbc %B0,__zero_reg__"
1292   [(set_attr "length" "2")
1293    (set_attr "cc" "set_czn")])
1294
1295 (define_insn "*subhi3.sign_extend2"
1296   [(set (match_operand:HI 0 "register_operand"                          "=r")
1297         (minus:HI (match_operand:HI 1 "register_operand"                 "0")
1298                   (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1299   ""
1300   {
1301     return reg_overlap_mentioned_p (operands[0], operands[2])
1302       ? "mov __tmp_reg__,%2\;sub %A0,%2\;sbc %B0,__zero_reg__\;sbrc __tmp_reg__,7\;inc %B0"
1303       : "sub %A0,%2\;sbc %B0,__zero_reg__\;sbrc %2,7\;inc %B0";
1304   }
1305   [(set_attr "length" "5")
1306    (set_attr "cc" "clobber")])
1307
1308 (define_insn "subsi3"
1309   [(set (match_operand:SI 0 "register_operand"          "=r")
1310         (minus:SI (match_operand:SI 1 "register_operand" "0")
1311                   (match_operand:SI 2 "register_operand" "r")))]
1312   ""
1313   "sub %0,%2\;sbc %B0,%B2\;sbc %C0,%C2\;sbc %D0,%D2"
1314   [(set_attr "length" "4")
1315    (set_attr "cc" "set_czn")])
1316
1317 (define_insn "*subsi3_zero_extend"
1318   [(set (match_operand:SI 0 "register_operand"                          "=r")
1319         (minus:SI (match_operand:SI 1 "register_operand"                 "0")
1320                   (zero_extend:SI (match_operand:QI 2 "register_operand" "r"))))]
1321   ""
1322   "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
1323   [(set_attr "length" "4")
1324    (set_attr "cc" "set_czn")])
1325
1326 (define_insn "*subsi3_zero_extend.hi"
1327   [(set (match_operand:SI 0 "register_operand"                          "=r")
1328         (minus:SI (match_operand:SI 1 "register_operand"                 "0")
1329                   (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1330   ""
1331   "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
1332   [(set_attr "length" "4")
1333    (set_attr "cc" "set_czn")])
1334
1335 ;******************************************************************************
1336 ; mul
1337
1338 (define_expand "mulqi3"
1339   [(set (match_operand:QI 0 "register_operand" "")
1340         (mult:QI (match_operand:QI 1 "register_operand" "")
1341                  (match_operand:QI 2 "register_operand" "")))]
1342   ""
1343   {
1344     if (!AVR_HAVE_MUL)
1345       {
1346         emit_insn (gen_mulqi3_call (operands[0], operands[1], operands[2]));
1347         DONE;
1348       }
1349   })
1350
1351 (define_insn "*mulqi3_enh"
1352   [(set (match_operand:QI 0 "register_operand" "=r")
1353         (mult:QI (match_operand:QI 1 "register_operand" "r")
1354                  (match_operand:QI 2 "register_operand" "r")))]
1355   "AVR_HAVE_MUL"
1356   "mul %1,%2
1357         mov %0,r0
1358         clr r1"
1359   [(set_attr "length" "3")
1360    (set_attr "cc" "clobber")])
1361
1362 (define_expand "mulqi3_call"
1363   [(set (reg:QI 24) (match_operand:QI 1 "register_operand" ""))
1364    (set (reg:QI 22) (match_operand:QI 2 "register_operand" ""))
1365    (parallel [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22)))
1366               (clobber (reg:QI 22))])
1367    (set (match_operand:QI 0 "register_operand" "") (reg:QI 24))]
1368   ""
1369   "")
1370
1371 (define_insn "*mulqi3_call"
1372   [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22)))
1373    (clobber (reg:QI 22))]
1374   "!AVR_HAVE_MUL"
1375   "%~call __mulqi3"
1376   [(set_attr "type" "xcall")
1377    (set_attr "cc" "clobber")])
1378
1379 ;; "umulqi3_highpart"
1380 ;; "smulqi3_highpart"
1381 (define_insn "<extend_su>mulqi3_highpart"
1382   [(set (match_operand:QI 0 "register_operand"                                       "=r")
1383         (truncate:QI
1384          (lshiftrt:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1385                                (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))
1386                       (const_int 8))))]
1387   "AVR_HAVE_MUL"
1388   "mul<extend_s> %1,%2
1389         mov %0,r1
1390         clr __zero_reg__"
1391   [(set_attr "length" "3")
1392    (set_attr "cc" "clobber")])
1393   
1394
1395 ;; Used when expanding div or mod inline for some special values
1396 (define_insn "*subqi3.ashiftrt7"
1397   [(set (match_operand:QI 0 "register_operand"                       "=r")
1398         (minus:QI (match_operand:QI 1 "register_operand"              "0")
1399                   (ashiftrt:QI (match_operand:QI 2 "register_operand" "r")
1400                                (const_int 7))))]
1401   ""
1402   "sbrc %2,7\;inc %0"
1403   [(set_attr "length" "2")
1404    (set_attr "cc" "clobber")])
1405
1406 (define_insn "*addqi3.lt0"
1407   [(set (match_operand:QI 0 "register_operand"                 "=r")
1408         (plus:QI (lt:QI (match_operand:QI 1 "register_operand"  "r")
1409                         (const_int 0))
1410                  (match_operand:QI 2 "register_operand"         "0")))]
1411   ""
1412   "sbrc %1,7\;inc %0"
1413   [(set_attr "length" "2")
1414    (set_attr "cc" "clobber")])
1415
1416 (define_insn "*addhi3.lt0"
1417   [(set (match_operand:HI 0 "register_operand"                   "=w,r")
1418         (plus:HI (lt:HI (match_operand:QI 1 "register_operand"    "r,r")
1419                         (const_int 0))
1420                  (match_operand:HI 2 "register_operand"           "0,0")))
1421    (clobber (match_scratch:QI 3                                  "=X,&1"))]
1422   ""
1423   "@
1424         sbrc %1,7\;adiw %0,1
1425         lsl %1\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__"
1426   [(set_attr "length" "2,3")
1427    (set_attr "cc" "clobber")])
1428
1429 (define_insn "*addpsi3.lt0"
1430   [(set (match_operand:PSI 0 "register_operand"                         "=r")
1431         (plus:PSI (lshiftrt:PSI (match_operand:PSI 1 "register_operand"  "r")
1432                                 (const_int 23))
1433                  (match_operand:PSI 2 "register_operand"                 "0")))]
1434   ""
1435   "mov __tmp_reg__,%C1\;lsl __tmp_reg__
1436         adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__"
1437   [(set_attr "length" "5")
1438    (set_attr "cc" "clobber")])
1439
1440 (define_insn "*addsi3.lt0"
1441   [(set (match_operand:SI 0 "register_operand"                       "=r")
1442         (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"  "r")
1443                               (const_int 31))
1444                  (match_operand:SI 2 "register_operand"               "0")))]
1445   ""
1446   "mov __tmp_reg__,%D1\;lsl __tmp_reg__
1447         adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__"
1448   [(set_attr "length" "6")
1449    (set_attr "cc" "clobber")])
1450   
1451
1452 ;; "umulqihi3"
1453 ;; "mulqihi3"
1454 (define_insn "<extend_u>mulqihi3"
1455   [(set (match_operand:HI 0 "register_operand"                         "=r")
1456         (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1457                  (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>"))))]
1458   "AVR_HAVE_MUL"
1459   "mul<extend_s> %1,%2
1460         movw %0,r0
1461         clr __zero_reg__"
1462   [(set_attr "length" "3")
1463    (set_attr "cc" "clobber")])
1464
1465 (define_insn "usmulqihi3"
1466   [(set (match_operand:HI 0 "register_operand"                         "=r")
1467         (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "a"))
1468                  (sign_extend:HI (match_operand:QI 2 "register_operand" "a"))))]
1469   "AVR_HAVE_MUL"
1470   "mulsu %2,%1
1471         movw %0,r0
1472         clr __zero_reg__"
1473   [(set_attr "length" "3")
1474    (set_attr "cc" "clobber")])
1475
1476 ;; Above insn is not canonicalized by insn combine, so here is a version with
1477 ;; operands swapped.
1478
1479 (define_insn "*sumulqihi3"
1480   [(set (match_operand:HI 0 "register_operand"                         "=r")
1481         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1482                  (zero_extend:HI (match_operand:QI 2 "register_operand" "a"))))]
1483   "AVR_HAVE_MUL"
1484   "mulsu %1,%2
1485         movw %0,r0
1486         clr __zero_reg__"
1487   [(set_attr "length" "3")
1488    (set_attr "cc" "clobber")])
1489
1490 ;; One-extend operand 1
1491
1492 (define_insn "*osmulqihi3"
1493   [(set (match_operand:HI 0 "register_operand"                                        "=&r")
1494         (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "a"))))
1495                  (sign_extend:HI (match_operand:QI 2 "register_operand"                 "a"))))]
1496   "AVR_HAVE_MUL"
1497   "mulsu %2,%1
1498         movw %0,r0
1499         sub %B0,%2
1500         clr __zero_reg__"
1501   [(set_attr "length" "4")
1502    (set_attr "cc" "clobber")])
1503
1504 (define_insn "*oumulqihi3"
1505   [(set (match_operand:HI 0 "register_operand"                                        "=&r")
1506         (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "r"))))
1507                  (zero_extend:HI (match_operand:QI 2 "register_operand"                 "r"))))]
1508   "AVR_HAVE_MUL"
1509   "mul %2,%1
1510         movw %0,r0
1511         sub %B0,%2
1512         clr __zero_reg__"
1513   [(set_attr "length" "4")
1514    (set_attr "cc" "clobber")])
1515
1516 ;******************************************************************************
1517 ; multiply-add/sub QI: $0 = $3 +/- $1*$2
1518 ;******************************************************************************
1519
1520 (define_insn "*maddqi4"
1521   [(set (match_operand:QI 0 "register_operand"                  "=r")
1522         (plus:QI (mult:QI (match_operand:QI 1 "register_operand" "r")
1523                           (match_operand:QI 2 "register_operand" "r"))
1524                  (match_operand:QI 3 "register_operand"          "0")))]
1525   
1526   "AVR_HAVE_MUL"
1527   "mul %1,%2
1528         add %A0,r0
1529         clr __zero_reg__"
1530   [(set_attr "length" "4")
1531    (set_attr "cc" "clobber")])
1532
1533 (define_insn "*msubqi4"
1534   [(set (match_operand:QI 0 "register_operand"                   "=r")
1535         (minus:QI (match_operand:QI 3 "register_operand"          "0")
1536                   (mult:QI (match_operand:QI 1 "register_operand" "r")
1537                            (match_operand:QI 2 "register_operand" "r"))))]
1538   "AVR_HAVE_MUL"
1539   "mul %1,%2
1540         sub %A0,r0
1541         clr __zero_reg__"
1542   [(set_attr "length" "4")
1543    (set_attr "cc" "clobber")])
1544
1545 (define_insn_and_split "*maddqi4.const"
1546   [(set (match_operand:QI 0 "register_operand"                   "=r")
1547         (plus:QI (mult:QI (match_operand:QI 1 "register_operand"  "r")
1548                           (match_operand:QI 2 "const_int_operand" "n"))
1549                  (match_operand:QI 3 "register_operand"           "0")))
1550    (clobber (match_scratch:QI 4                                 "=&d"))]
1551   "AVR_HAVE_MUL"
1552   "#"
1553   "&& reload_completed"
1554   [(set (match_dup 4)
1555         (match_dup 2))
1556    ; *maddqi4
1557    (set (match_dup 0)
1558         (plus:QI (mult:QI (match_dup 1)
1559                           (match_dup 4))
1560                  (match_dup 3)))]
1561   "")
1562
1563 (define_insn_and_split "*msubqi4.const"
1564   [(set (match_operand:QI 0 "register_operand"                    "=r")
1565         (minus:QI (match_operand:QI 3 "register_operand"           "0")
1566                   (mult:QI (match_operand:QI 1 "register_operand"  "r")
1567                            (match_operand:QI 2 "const_int_operand" "n"))))
1568    (clobber (match_scratch:QI 4                                  "=&d"))]
1569   "AVR_HAVE_MUL"
1570   "#"
1571   "&& reload_completed"
1572   [(set (match_dup 4)
1573         (match_dup 2))
1574    ; *msubqi4
1575    (set (match_dup 0)
1576         (minus:QI (match_dup 3)
1577                   (mult:QI (match_dup 1)
1578                            (match_dup 4))))]
1579   "")
1580
1581
1582 ;******************************************************************************
1583 ; multiply-add/sub HI: $0 = $3 +/- $1*$2  with 8-bit values $1, $2
1584 ;******************************************************************************
1585
1586 ;; We don't use standard insns/expanders as they lead to cumbersome code for,
1587 ;; e.g,
1588 ;;
1589 ;;     int foo (unsigned char z)
1590 ;;     {
1591 ;;       extern int aInt[];
1592 ;;       return aInt[3*z+2];
1593 ;;     }
1594 ;;
1595 ;; because the constant +4 then is added explicitely instead of consuming it
1596 ;; with the aInt symbol.  Therefore, we rely on insn combine which takes costs
1597 ;; into account more accurately and doesn't do burte-force multiply-add/sub.
1598 ;; The implementational effort is the same so we are fine with that approach.
1599
1600
1601 ;; "*maddqihi4"
1602 ;; "*umaddqihi4"
1603 (define_insn "*<extend_u>maddqihi4"
1604   [(set (match_operand:HI 0 "register_operand"                                  "=r")
1605         (plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1606                           (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))
1607                  (match_operand:HI 3 "register_operand"                         "0")))]
1608   
1609   "AVR_HAVE_MUL"
1610   "mul<extend_s> %1,%2
1611         add %A0,r0
1612         adc %B0,r1
1613         clr __zero_reg__"
1614   [(set_attr "length" "4")
1615    (set_attr "cc" "clobber")])
1616
1617 ;; "*msubqihi4"
1618 ;; "*umsubqihi4"
1619 (define_insn "*<extend_u>msubqihi4"
1620   [(set (match_operand:HI 0 "register_operand"                                  "=r")
1621         (minus:HI (match_operand:HI 3 "register_operand"                         "0")
1622                   (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1623                            (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))))]
1624   "AVR_HAVE_MUL"
1625   "mul<extend_s> %1,%2
1626         sub %A0,r0
1627         sbc %B0,r1
1628         clr __zero_reg__"
1629   [(set_attr "length" "4")
1630    (set_attr "cc" "clobber")])
1631
1632 ;; "*usmaddqihi4"
1633 ;; "*sumaddqihi4"
1634 (define_insn "*<any_extend:extend_su><any_extend2:extend_su>msubqihi4"
1635   [(set (match_operand:HI 0 "register_operand"                                  "=r")
1636         (plus:HI (mult:HI (any_extend:HI  (match_operand:QI 1 "register_operand" "a"))
1637                           (any_extend2:HI (match_operand:QI 2 "register_operand" "a")))
1638                  (match_operand:HI 3 "register_operand"                          "0")))]
1639   "AVR_HAVE_MUL
1640    && reload_completed
1641    && <any_extend:CODE> != <any_extend2:CODE>"
1642   {
1643     output_asm_insn (<any_extend:CODE> == SIGN_EXTEND
1644                      ? "mulsu %1,%2" : "mulsu %2,%1", operands);
1645
1646     return "add %A0,r0\;adc %B0,r1\;clr __zero_reg__";
1647   }
1648   [(set_attr "length" "4")
1649    (set_attr "cc" "clobber")])
1650
1651 ;; "*usmsubqihi4"
1652 ;; "*sumsubqihi4"
1653 (define_insn "*<any_extend:extend_su><any_extend2:extend_su>msubqihi4"
1654   [(set (match_operand:HI 0 "register_operand"                                   "=r")
1655         (minus:HI (match_operand:HI 3 "register_operand"                          "0")
1656                   (mult:HI (any_extend:HI  (match_operand:QI 1 "register_operand" "a"))
1657                            (any_extend2:HI (match_operand:QI 2 "register_operand" "a")))))]
1658   "AVR_HAVE_MUL
1659    && reload_completed
1660    && <any_extend:CODE> != <any_extend2:CODE>"
1661   {
1662     output_asm_insn (<any_extend:CODE> == SIGN_EXTEND
1663                      ? "mulsu %1,%2" : "mulsu %2,%1", operands);
1664
1665     return "sub %A0,r0\;sbc %B0,r1\;clr __zero_reg__";
1666   }
1667   [(set_attr "length" "4")
1668    (set_attr "cc" "clobber")])
1669
1670 ;; Handle small constants
1671
1672 ;; "umaddqihi4.uconst"
1673 ;; "maddqihi4.sconst"
1674 (define_insn_and_split "*<extend_u>maddqihi4.<extend_su>const"
1675   [(set (match_operand:HI 0 "register_operand"                                  "=r")
1676         (plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1677                           (match_operand:HI 2 "<extend_su>8_operand"             "n"))
1678                  (match_operand:HI 3 "register_operand"                          "0")))
1679    (clobber (match_scratch:QI 4                                                 "=&d"))]
1680   "AVR_HAVE_MUL"
1681   "#"
1682   "&& reload_completed"
1683   [(set (match_dup 4)
1684         (match_dup 2))
1685    ; *umaddqihi4 resp. *maddqihi4
1686    (set (match_dup 0)
1687         (plus:HI (mult:HI (any_extend:HI (match_dup 1))
1688                           (any_extend:HI (match_dup 4)))
1689                  (match_dup 3)))]
1690   {
1691     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1692   })
1693
1694 ;; "*umsubqihi4.uconst"
1695 ;; "*msubqihi4.sconst"
1696 (define_insn_and_split "*<extend_u>msubqihi4.<extend_su>const"
1697   [(set (match_operand:HI 0 "register_operand"                                  "=r")
1698         (minus:HI (match_operand:HI 3 "register_operand"                         "0")
1699                   (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1700                            (match_operand:HI 2 "<extend_su>8_operand"            "n"))))
1701    (clobber (match_scratch:QI 4                                                 "=&d"))]
1702   "AVR_HAVE_MUL"
1703   "#"
1704   "&& reload_completed"
1705   [(set (match_dup 4)
1706         (match_dup 2))
1707    ; *umsubqihi4 resp. *msubqihi4
1708    (set (match_dup 0)
1709         (minus:HI (match_dup 3)
1710                   (mult:HI (any_extend:HI (match_dup 1))
1711                            (any_extend:HI (match_dup 4)))))]
1712   {
1713     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1714   })
1715
1716 ;; Same as the insn above, but combiner tries versions canonicalized to ASHIFT
1717 ;; for MULT with power of 2 and skips trying MULT insn above.
1718
1719 (define_insn_and_split "*umsubqihi4.uconst.ashift"
1720   [(set (match_operand:HI 0 "register_operand"                                     "=r")
1721         (minus:HI (match_operand:HI 3 "register_operand"                            "0")
1722                   (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1723                              (match_operand:HI 2 "const_2_to_7_operand"             "n"))))
1724    (clobber (match_scratch:QI 4                                                   "=&d"))]
1725   "AVR_HAVE_MUL"
1726   "#"
1727   "&& reload_completed"
1728   [(set (match_dup 4)
1729         (match_dup 2))
1730    ; *umsubqihi4
1731    (set (match_dup 0)
1732         (minus:HI (match_dup 3)
1733                   (mult:HI (zero_extend:HI (match_dup 1))
1734                            (zero_extend:HI (match_dup 4)))))]
1735   {
1736     operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
1737   })
1738
1739 ;; Same as the insn above, but combiner tries versions canonicalized to ASHIFT
1740 ;; for MULT with power of 2 and skips trying MULT insn above.  We omit 128
1741 ;; because this would require an extra pattern for just one value.
1742
1743 (define_insn_and_split "*msubqihi4.sconst.ashift"
1744   [(set (match_operand:HI 0 "register_operand"                                     "=r")
1745         (minus:HI (match_operand:HI 3 "register_operand"                            "0")
1746                   (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
1747                              (match_operand:HI 2 "const_1_to_6_operand"             "M"))))
1748    (clobber (match_scratch:QI 4                                                   "=&d"))]
1749   "AVR_HAVE_MUL"
1750   "#"
1751   "&& reload_completed"
1752   [(set (match_dup 4)
1753         (match_dup 2))
1754    ; *smsubqihi4
1755    (set (match_dup 0)
1756         (minus:HI (match_dup 3)
1757                   (mult:HI (sign_extend:HI (match_dup 1))
1758                            (sign_extend:HI (match_dup 4)))))]
1759   {
1760     operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
1761   })
1762
1763 ;; For signed/unsigned combinations that require narrow constraint "a"
1764 ;; just provide a pattern if signed/unsigned combination is actually needed.
1765
1766 (define_insn_and_split "*sumaddqihi4.uconst"
1767   [(set (match_operand:HI 0 "register_operand"                                  "=r")
1768         (plus:HI (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1769                           (match_operand:HI 2 "u8_operand"                       "M"))
1770                  (match_operand:HI 3 "register_operand"                          "0")))
1771    (clobber (match_scratch:QI 4                                                "=&a"))]
1772   "AVR_HAVE_MUL
1773    && !s8_operand (operands[2], VOIDmode)"
1774   "#"
1775   "&& reload_completed"
1776   [(set (match_dup 4)
1777         (match_dup 2))
1778    ; *sumaddqihi4
1779    (set (match_dup 0)
1780         (plus:HI (mult:HI (sign_extend:HI (match_dup 1))
1781                           (zero_extend:HI (match_dup 4)))
1782                  (match_dup 3)))]
1783   {
1784     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1785   })
1786
1787 (define_insn_and_split "*sumsubqihi4.uconst"
1788   [(set (match_operand:HI 0 "register_operand"                                   "=r")
1789         (minus:HI (match_operand:HI 3 "register_operand"                          "0")
1790                   (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1791                            (match_operand:HI 2 "u8_operand"                       "M"))))
1792    (clobber (match_scratch:QI 4                                                 "=&a"))]
1793   "AVR_HAVE_MUL
1794    && !s8_operand (operands[2], VOIDmode)"
1795   "#"
1796   "&& reload_completed"
1797   [(set (match_dup 4)
1798         (match_dup 2))
1799    ; *sumsubqihi4
1800    (set (match_dup 0)
1801         (minus:HI (match_dup 3)
1802                   (mult:HI (sign_extend:HI (match_dup 1))
1803                            (zero_extend:HI (match_dup 4)))))]
1804   {
1805     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1806   })
1807
1808 ;******************************************************************************
1809 ; mul HI: $1 = sign/zero-extend, $2 = small constant
1810 ;******************************************************************************
1811
1812 ;; "*muluqihi3.uconst"
1813 ;; "*mulsqihi3.sconst"
1814 (define_insn_and_split "*mul<extend_su>qihi3.<extend_su>const"
1815   [(set (match_operand:HI 0 "register_operand"                         "=r")
1816         (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1817                  (match_operand:HI 2 "<extend_su>8_operand"            "n")))
1818    (clobber (match_scratch:QI 3                                       "=&d"))]
1819   "AVR_HAVE_MUL"
1820   "#"
1821   "&& reload_completed"
1822   [(set (match_dup 3)
1823         (match_dup 2))
1824    ; umulqihi3 resp. mulqihi3
1825    (set (match_dup 0)
1826         (mult:HI (any_extend:HI (match_dup 1))
1827                  (any_extend:HI (match_dup 3))))]
1828   {
1829     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1830   })
1831
1832 (define_insn_and_split "*muluqihi3.sconst"
1833   [(set (match_operand:HI 0 "register_operand"                         "=r")
1834         (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "a"))
1835                  (match_operand:HI 2 "s8_operand"                       "n")))
1836    (clobber (match_scratch:QI 3                                       "=&a"))]
1837   "AVR_HAVE_MUL"
1838   "#"
1839   "&& reload_completed"
1840   [(set (match_dup 3)
1841         (match_dup 2))
1842    ; usmulqihi3
1843    (set (match_dup 0)
1844         (mult:HI (zero_extend:HI (match_dup 1))
1845                  (sign_extend:HI (match_dup 3))))]
1846   {
1847     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1848   })
1849
1850 (define_insn_and_split "*mulsqihi3.uconst"
1851   [(set (match_operand:HI 0 "register_operand"                         "=r")
1852         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1853                  (match_operand:HI 2 "u8_operand"                       "M")))
1854    (clobber (match_scratch:QI 3                                       "=&a"))]
1855   "AVR_HAVE_MUL"
1856   "#"
1857   "&& reload_completed"
1858   [(set (match_dup 3)
1859         (match_dup 2))
1860    ; usmulqihi3
1861    (set (match_dup 0)
1862         (mult:HI (zero_extend:HI (match_dup 3))
1863                  (sign_extend:HI (match_dup 1))))]
1864   {
1865     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1866   })
1867
1868 (define_insn_and_split "*mulsqihi3.oconst"
1869   [(set (match_operand:HI 0 "register_operand"                        "=&r")
1870         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1871                  (match_operand:HI 2 "o8_operand"                       "n")))
1872    (clobber (match_scratch:QI 3                                       "=&a"))]
1873   "AVR_HAVE_MUL"
1874   "#"
1875   "&& reload_completed"
1876   [(set (match_dup 3)
1877         (match_dup 2))
1878    ; *osmulqihi3
1879    (set (match_dup 0)
1880         (mult:HI (not:HI (zero_extend:HI (not:QI (match_dup 3))))
1881                  (sign_extend:HI (match_dup 1))))]
1882   {
1883     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1884   })
1885
1886 ;; The EXTEND of $1 only appears in combine, we don't see it in expand so that
1887 ;; expand decides to use ASHIFT instead of MUL because ASHIFT costs are cheaper
1888 ;; at that time.  Fix that.
1889
1890 (define_insn "*ashiftqihi2.signx.1"
1891   [(set (match_operand:HI 0 "register_operand"                           "=r,*r")
1892         (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "0,r"))
1893                    (const_int 1)))]
1894   ""
1895   "@
1896         lsl %A0\;sbc %B0,%B0
1897         mov %A0,%1\;lsl %A0\;sbc %B0,%B0"
1898   [(set_attr "length" "2,3")
1899    (set_attr "cc" "clobber")])
1900
1901 (define_insn_and_split "*ashifthi3.signx.const"
1902   [(set (match_operand:HI 0 "register_operand"                           "=r")
1903         (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
1904                    (match_operand:HI 2 "const_2_to_6_operand"             "I")))
1905    (clobber (match_scratch:QI 3                                         "=&d"))]
1906   "AVR_HAVE_MUL"
1907   "#"
1908   "&& reload_completed"
1909   [(set (match_dup 3)
1910         (match_dup 2))
1911    ; mulqihi3
1912    (set (match_dup 0)
1913         (mult:HI (sign_extend:HI (match_dup 1))
1914                  (sign_extend:HI (match_dup 3))))]
1915   {
1916     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
1917   })
1918
1919 (define_insn_and_split "*ashifthi3.signx.const7"
1920   [(set (match_operand:HI 0 "register_operand"                           "=r")
1921         (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1922                    (const_int 7)))
1923    (clobber (match_scratch:QI 2                                         "=&a"))]
1924   "AVR_HAVE_MUL"
1925   "#"
1926   "&& reload_completed"
1927   [(set (match_dup 2)
1928         (match_dup 3))
1929    ; usmulqihi3
1930    (set (match_dup 0)
1931         (mult:HI (zero_extend:HI (match_dup 2))
1932                  (sign_extend:HI (match_dup 1))))]
1933   {
1934     operands[3] = gen_int_mode (1 << 7, QImode);
1935   })
1936
1937 (define_insn_and_split "*ashifthi3.zerox.const"
1938   [(set (match_operand:HI 0 "register_operand"                           "=r")
1939         (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1940                    (match_operand:HI 2 "const_2_to_7_operand"             "I")))
1941    (clobber (match_scratch:QI 3                                         "=&d"))]
1942   "AVR_HAVE_MUL"
1943   "#"
1944   "&& reload_completed"
1945   [(set (match_dup 3)
1946         (match_dup 2))
1947    ; umulqihi3
1948    (set (match_dup 0)
1949         (mult:HI (zero_extend:HI (match_dup 1))
1950                  (zero_extend:HI (match_dup 3))))]
1951   {
1952     operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
1953   })
1954
1955 ;******************************************************************************
1956 ; mul HI: $1 = sign-/zero-/one-extend, $2 = reg
1957 ;******************************************************************************
1958
1959 (define_insn "mulsqihi3"
1960   [(set (match_operand:HI 0 "register_operand"                        "=&r")
1961         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1962                  (match_operand:HI 2 "register_operand"                 "a")))]
1963   "AVR_HAVE_MUL"
1964   "mulsu %1,%A2
1965         movw %0,r0
1966         mul %1,%B2
1967         add %B0,r0
1968         clr __zero_reg__"
1969   [(set_attr "length" "5")
1970    (set_attr "cc" "clobber")])
1971
1972 (define_insn "muluqihi3"
1973   [(set (match_operand:HI 0 "register_operand"                        "=&r")
1974         (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1975                  (match_operand:HI 2 "register_operand"                 "r")))]
1976   "AVR_HAVE_MUL"
1977   "mul %1,%A2
1978         movw %0,r0
1979         mul %1,%B2
1980         add %B0,r0
1981         clr __zero_reg__"
1982   [(set_attr "length" "5")
1983    (set_attr "cc" "clobber")])
1984
1985 ;; one-extend operand 1
1986
1987 (define_insn "muloqihi3"
1988   [(set (match_operand:HI 0 "register_operand"                                        "=&r")
1989         (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "r"))))
1990                  (match_operand:HI 2 "register_operand"                                 "r")))]
1991   "AVR_HAVE_MUL"
1992   "mul %1,%A2
1993         movw %0,r0
1994         mul %1,%B2
1995         add %B0,r0
1996         sub %B0,%A2
1997         clr __zero_reg__"
1998   [(set_attr "length" "6")
1999    (set_attr "cc" "clobber")])
2000
2001 ;******************************************************************************
2002
2003 (define_expand "mulhi3"
2004   [(set (match_operand:HI 0 "register_operand" "")
2005         (mult:HI (match_operand:HI 1 "register_operand" "")
2006                  (match_operand:HI 2 "register_or_s9_operand" "")))]
2007   ""
2008   {
2009     if (!AVR_HAVE_MUL)
2010       {
2011         if (!register_operand (operands[2], HImode))
2012           operands[2] = force_reg (HImode, operands[2]);
2013
2014         emit_insn (gen_mulhi3_call (operands[0], operands[1], operands[2]));
2015         DONE;
2016       }
2017
2018     /* For small constants we can do better by extending them on the fly.
2019        The constant can be loaded in one instruction and the widening
2020        multiplication is shorter.  First try the unsigned variant because it
2021        allows constraint "d" instead of "a" for the signed version.  */
2022
2023     if (s9_operand (operands[2], HImode))
2024       {
2025         rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
2026
2027         if (u8_operand (operands[2], HImode))
2028           {
2029             emit_insn (gen_muluqihi3 (operands[0], reg, operands[1]));
2030           } 
2031         else if (s8_operand (operands[2], HImode))
2032           {
2033             emit_insn (gen_mulsqihi3 (operands[0], reg, operands[1]));
2034           }
2035         else
2036           {
2037             emit_insn (gen_muloqihi3 (operands[0], reg, operands[1]));
2038           }
2039
2040         DONE;
2041       }
2042
2043     if (!register_operand (operands[2], HImode))
2044       operands[2] = force_reg (HImode, operands[2]);
2045   })
2046
2047 (define_insn "*mulhi3_enh"
2048   [(set (match_operand:HI 0 "register_operand" "=&r")
2049         (mult:HI (match_operand:HI 1 "register_operand" "r")
2050                  (match_operand:HI 2 "register_operand" "r")))]
2051   "AVR_HAVE_MUL"
2052   {
2053     return REGNO (operands[1]) == REGNO (operands[2])
2054            ? "mul %A1,%A1\;movw %0,r0\;mul %A1,%B1\;add %B0,r0\;add %B0,r0\;clr r1"
2055            : "mul %A1,%A2\;movw %0,r0\;mul %A1,%B2\;add %B0,r0\;mul %B1,%A2\;add %B0,r0\;clr r1";
2056   }
2057   [(set_attr "length" "7")
2058    (set_attr "cc" "clobber")])
2059
2060 (define_expand "mulhi3_call"
2061   [(set (reg:HI 24) (match_operand:HI 1 "register_operand" ""))
2062    (set (reg:HI 22) (match_operand:HI 2 "register_operand" ""))
2063    (parallel [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22)))
2064               (clobber (reg:HI 22))
2065               (clobber (reg:QI 21))])
2066    (set (match_operand:HI 0 "register_operand" "") (reg:HI 24))]
2067   ""
2068   "")
2069
2070 (define_insn "*mulhi3_call"
2071   [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22)))
2072    (clobber (reg:HI 22))
2073    (clobber (reg:QI 21))]
2074   "!AVR_HAVE_MUL"
2075   "%~call __mulhi3"
2076   [(set_attr "type" "xcall")
2077    (set_attr "cc" "clobber")])
2078
2079 ;; To support widening multiplication with constant we postpone
2080 ;; expanding to the implicit library call until post combine and
2081 ;; prior to register allocation.  Clobber all hard registers that
2082 ;; might be used by the (widening) multiply until it is split and
2083 ;; it's final register footprint is worked out.
2084
2085 (define_expand "mulsi3"
2086   [(parallel [(set (match_operand:SI 0 "register_operand" "")
2087                    (mult:SI (match_operand:SI 1 "register_operand" "")
2088                             (match_operand:SI 2 "nonmemory_operand" "")))
2089               (clobber (reg:HI 26))
2090               (clobber (reg:DI 18))])]
2091   "AVR_HAVE_MUL"
2092   {
2093     if (u16_operand (operands[2], SImode))
2094       {
2095         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2096         emit_insn (gen_muluhisi3 (operands[0], operands[2], operands[1]));
2097         DONE;
2098       }
2099
2100     if (o16_operand (operands[2], SImode))
2101       {
2102         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2103         emit_insn (gen_mulohisi3 (operands[0], operands[2], operands[1]));
2104         DONE;
2105       }
2106   })
2107
2108 (define_insn_and_split "*mulsi3"
2109   [(set (match_operand:SI 0 "pseudo_register_operand"                      "=r")
2110         (mult:SI (match_operand:SI 1 "pseudo_register_operand"              "r")
2111                  (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn")))
2112    (clobber (reg:HI 26))
2113    (clobber (reg:DI 18))]
2114   "AVR_HAVE_MUL && !reload_completed"
2115   { gcc_unreachable(); }
2116   "&& 1"
2117   [(set (reg:SI 18)
2118         (match_dup 1))
2119    (set (reg:SI 22) 
2120         (match_dup 2))
2121    (parallel [(set (reg:SI 22)
2122                    (mult:SI (reg:SI 22)
2123                             (reg:SI 18)))
2124               (clobber (reg:HI 26))])
2125    (set (match_dup 0)
2126         (reg:SI 22))]
2127   {
2128     if (u16_operand (operands[2], SImode))
2129       {
2130         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2131         emit_insn (gen_muluhisi3 (operands[0], operands[2], operands[1]));
2132         DONE;
2133       }
2134
2135     if (o16_operand (operands[2], SImode))
2136       {
2137         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2138         emit_insn (gen_mulohisi3 (operands[0], operands[2], operands[1]));
2139         DONE;
2140       }
2141   })
2142
2143 ;; "muluqisi3"
2144 ;; "muluhisi3"
2145 (define_insn_and_split "mulu<mode>si3"
2146   [(set (match_operand:SI 0 "pseudo_register_operand"                           "=r")
2147         (mult:SI (zero_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r"))
2148                  (match_operand:SI 2 "pseudo_register_or_const_int_operand"      "rn")))
2149    (clobber (reg:HI 26))
2150    (clobber (reg:DI 18))]
2151   "AVR_HAVE_MUL && !reload_completed"
2152   { gcc_unreachable(); }
2153   "&& 1"
2154   [(set (reg:HI 26)
2155         (match_dup 1))
2156    (set (reg:SI 18)
2157         (match_dup 2))
2158    (set (reg:SI 22)
2159         (mult:SI (zero_extend:SI (reg:HI 26))
2160                  (reg:SI 18)))
2161    (set (match_dup 0)
2162         (reg:SI 22))]
2163   {
2164     /* Do the QI -> HI extension explicitely before the multiplication.  */
2165     /* Do the HI -> SI extension implicitely and after the multiplication.  */
2166        
2167     if (QImode == <MODE>mode)
2168       operands[1] = gen_rtx_ZERO_EXTEND (HImode, operands[1]);
2169
2170     if (u16_operand (operands[2], SImode))
2171       {
2172         operands[1] = force_reg (HImode, operands[1]);
2173         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2174         emit_insn (gen_umulhisi3 (operands[0], operands[1], operands[2]));
2175         DONE;
2176       }
2177   })
2178
2179 ;; "mulsqisi3"
2180 ;; "mulshisi3"
2181 (define_insn_and_split "muls<mode>si3"
2182   [(set (match_operand:SI 0 "pseudo_register_operand"                           "=r")
2183         (mult:SI (sign_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r"))
2184                  (match_operand:SI 2 "pseudo_register_or_const_int_operand"      "rn")))
2185    (clobber (reg:HI 26))
2186    (clobber (reg:DI 18))]
2187   "AVR_HAVE_MUL && !reload_completed"
2188   { gcc_unreachable(); }
2189   "&& 1"
2190   [(set (reg:HI 26)
2191         (match_dup 1))
2192    (set (reg:SI 18)
2193         (match_dup 2))
2194    (set (reg:SI 22)
2195         (mult:SI (sign_extend:SI (reg:HI 26))
2196                  (reg:SI 18)))
2197    (set (match_dup 0)
2198         (reg:SI 22))]
2199   {
2200     /* Do the QI -> HI extension explicitely before the multiplication.  */
2201     /* Do the HI -> SI extension implicitely and after the multiplication.  */
2202        
2203     if (QImode == <MODE>mode)
2204       operands[1] = gen_rtx_SIGN_EXTEND (HImode, operands[1]);
2205
2206     if (u16_operand (operands[2], SImode)
2207         || s16_operand (operands[2], SImode))
2208       {
2209         rtx xop2 = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2210
2211         operands[1] = force_reg (HImode, operands[1]);
2212
2213         if (u16_operand (operands[2], SImode))
2214           emit_insn (gen_usmulhisi3 (operands[0], xop2, operands[1]));
2215         else
2216           emit_insn (gen_mulhisi3 (operands[0], operands[1], xop2));
2217
2218         DONE;
2219       }
2220   })
2221
2222 ;; One-extend operand 1
2223
2224 (define_insn_and_split "mulohisi3"
2225   [(set (match_operand:SI 0 "pseudo_register_operand"                          "=r")
2226         (mult:SI (not:SI (zero_extend:SI 
2227                           (not:HI (match_operand:HI 1 "pseudo_register_operand" "r"))))
2228                  (match_operand:SI 2 "pseudo_register_or_const_int_operand"     "rn")))
2229    (clobber (reg:HI 26))
2230    (clobber (reg:DI 18))]
2231   "AVR_HAVE_MUL && !reload_completed"
2232   { gcc_unreachable(); }
2233   "&& 1"
2234   [(set (reg:HI 26)
2235         (match_dup 1))
2236    (set (reg:SI 18)
2237         (match_dup 2))
2238    (set (reg:SI 22)
2239         (mult:SI (not:SI (zero_extend:SI (not:HI (reg:HI 26))))
2240                  (reg:SI 18)))
2241    (set (match_dup 0)
2242         (reg:SI 22))]
2243   "")
2244
2245 ;; "mulhisi3"
2246 ;; "umulhisi3"
2247 (define_expand "<extend_u>mulhisi3"
2248   [(parallel [(set (match_operand:SI 0 "register_operand" "")
2249                    (mult:SI (any_extend:SI (match_operand:HI 1 "register_operand" ""))
2250                             (any_extend:SI (match_operand:HI 2 "register_operand" ""))))
2251               (clobber (reg:HI 26))
2252               (clobber (reg:DI 18))])]
2253   "AVR_HAVE_MUL"
2254   "")
2255
2256 (define_expand "usmulhisi3"
2257   [(parallel [(set (match_operand:SI 0 "register_operand" "")
2258                    (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" ""))
2259                             (sign_extend:SI (match_operand:HI 2 "register_operand" ""))))
2260               (clobber (reg:HI 26))
2261               (clobber (reg:DI 18))])]
2262   "AVR_HAVE_MUL"
2263   "")
2264
2265 ;; "*uumulqihisi3" "*uumulhiqisi3" "*uumulhihisi3" "*uumulqiqisi3"
2266 ;; "*usmulqihisi3" "*usmulhiqisi3" "*usmulhihisi3" "*usmulqiqisi3"
2267 ;; "*sumulqihisi3" "*sumulhiqisi3" "*sumulhihisi3" "*sumulqiqisi3"
2268 ;; "*ssmulqihisi3" "*ssmulhiqisi3" "*ssmulhihisi3" "*ssmulqiqisi3"
2269 (define_insn_and_split
2270   "*<any_extend:extend_su><any_extend2:extend_su>mul<QIHI:mode><QIHI2:mode>si3"
2271   [(set (match_operand:SI 0 "pseudo_register_operand"                            "=r")
2272         (mult:SI (any_extend:SI (match_operand:QIHI 1 "pseudo_register_operand"   "r"))
2273                  (any_extend2:SI (match_operand:QIHI2 2 "pseudo_register_operand" "r"))))
2274    (clobber (reg:HI 26))
2275    (clobber (reg:DI 18))]
2276   "AVR_HAVE_MUL && !reload_completed"
2277   { gcc_unreachable(); }
2278   "&& 1"
2279   [(set (reg:HI 18)
2280         (match_dup 1))
2281    (set (reg:HI 26)
2282         (match_dup 2))
2283    (set (reg:SI 22)
2284         (mult:SI (match_dup 3)
2285                  (match_dup 4)))
2286    (set (match_dup 0)
2287         (reg:SI 22))]
2288   {
2289     rtx xop1 = operands[1];
2290     rtx xop2 = operands[2];
2291
2292     /* Do the QI -> HI extension explicitely before the multiplication.  */
2293     /* Do the HI -> SI extension implicitely and after the multiplication.  */
2294        
2295     if (QImode == <QIHI:MODE>mode)
2296       xop1 = gen_rtx_fmt_e (<any_extend:CODE>, HImode, xop1);
2297
2298     if (QImode == <QIHI2:MODE>mode)
2299       xop2 = gen_rtx_fmt_e (<any_extend2:CODE>, HImode, xop2);
2300
2301     if (<any_extend:CODE> == <any_extend2:CODE>
2302         || <any_extend:CODE> == ZERO_EXTEND)
2303       {
2304         operands[1] = xop1;
2305         operands[2] = xop2;
2306         operands[3] = gen_rtx_fmt_e (<any_extend:CODE>, SImode, gen_rtx_REG (HImode, 18));
2307         operands[4] = gen_rtx_fmt_e (<any_extend2:CODE>, SImode, gen_rtx_REG (HImode, 26));
2308       }
2309     else
2310       {
2311         /* <any_extend:CODE>  = SIGN_EXTEND */
2312         /* <any_extend2:CODE> = ZERO_EXTEND */
2313
2314         operands[1] = xop2;
2315         operands[2] = xop1;
2316         operands[3] = gen_rtx_ZERO_EXTEND (SImode, gen_rtx_REG (HImode, 18));
2317         operands[4] = gen_rtx_SIGN_EXTEND (SImode, gen_rtx_REG (HImode, 26));
2318       }
2319   })
2320
2321 ;; "smulhi3_highpart"
2322 ;; "umulhi3_highpart"
2323 (define_expand "<extend_su>mulhi3_highpart"
2324   [(set (reg:HI 18)
2325         (match_operand:HI 1 "nonmemory_operand" ""))
2326    (set (reg:HI 26)
2327         (match_operand:HI 2 "nonmemory_operand" ""))
2328    (parallel [(set (reg:HI 24)
2329                    (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
2330                                                       (any_extend:SI (reg:HI 26)))
2331                                              (const_int 16))))
2332               (clobber (reg:HI 22))])
2333    (set (match_operand:HI 0 "register_operand" "")
2334         (reg:HI 24))]
2335   "AVR_HAVE_MUL"
2336   "")
2337
2338
2339 (define_insn "*mulsi3_call"
2340   [(set (reg:SI 22)
2341         (mult:SI (reg:SI 22)
2342                  (reg:SI 18)))
2343    (clobber (reg:HI 26))]
2344   "AVR_HAVE_MUL"
2345   "%~call __mulsi3"
2346   [(set_attr "type" "xcall")
2347    (set_attr "cc" "clobber")])
2348
2349 ;; "*mulhisi3_call"
2350 ;; "*umulhisi3_call"
2351 (define_insn "*<extend_u>mulhisi3_call"
2352   [(set (reg:SI 22)
2353         (mult:SI (any_extend:SI (reg:HI 18))
2354                  (any_extend:SI (reg:HI 26))))]
2355   "AVR_HAVE_MUL"
2356   "%~call __<extend_u>mulhisi3"
2357   [(set_attr "type" "xcall")
2358    (set_attr "cc" "clobber")])
2359
2360 ;; "*umulhi3_highpart_call"
2361 ;; "*smulhi3_highpart_call"
2362 (define_insn "*<extend_su>mulhi3_highpart_call"
2363   [(set (reg:HI 24)
2364         (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
2365                                            (any_extend:SI (reg:HI 26)))
2366                                   (const_int 16))))
2367    (clobber (reg:HI 22))]
2368   "AVR_HAVE_MUL"
2369   "%~call __<extend_u>mulhisi3"
2370   [(set_attr "type" "xcall")
2371    (set_attr "cc" "clobber")])
2372
2373 (define_insn "*usmulhisi3_call"
2374   [(set (reg:SI 22)
2375         (mult:SI (zero_extend:SI (reg:HI 18))
2376                  (sign_extend:SI (reg:HI 26))))]
2377   "AVR_HAVE_MUL"
2378   "%~call __usmulhisi3"
2379   [(set_attr "type" "xcall")
2380    (set_attr "cc" "clobber")])
2381
2382 (define_insn "*mul<extend_su>hisi3_call"
2383   [(set (reg:SI 22)
2384         (mult:SI (any_extend:SI (reg:HI 26))
2385                  (reg:SI 18)))]
2386   "AVR_HAVE_MUL"
2387   "%~call __mul<extend_su>hisi3"
2388   [(set_attr "type" "xcall")
2389    (set_attr "cc" "clobber")])
2390
2391 (define_insn "*mulohisi3_call"
2392   [(set (reg:SI 22)
2393         (mult:SI (not:SI (zero_extend:SI (not:HI (reg:HI 26))))
2394                  (reg:SI 18)))]
2395   "AVR_HAVE_MUL"
2396   "%~call __mulohisi3"
2397   [(set_attr "type" "xcall")
2398    (set_attr "cc" "clobber")])
2399
2400 ; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / %
2401 ; divmod
2402
2403 ;; Generate lib1funcs.S calls ourselves, because:
2404 ;;  - we know exactly which registers are clobbered (for QI and HI
2405 ;;    modes, some of the call-used registers are preserved)
2406 ;;  - we get both the quotient and the remainder at no extra cost
2407 ;;  - we split the patterns only after the first CSE passes because
2408 ;;    CSE has problems to operate on hard regs.
2409 ;; 
2410 (define_insn_and_split "divmodqi4"
2411   [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "") 
2412                    (div:QI (match_operand:QI 1 "pseudo_register_operand" "") 
2413                            (match_operand:QI 2 "pseudo_register_operand" "")))
2414               (set (match_operand:QI 3 "pseudo_register_operand" "") 
2415                    (mod:QI (match_dup 1) (match_dup 2)))
2416               (clobber (reg:QI 22)) 
2417               (clobber (reg:QI 23)) 
2418               (clobber (reg:QI 24)) 
2419               (clobber (reg:QI 25))])]
2420   ""
2421   "this divmodqi4 pattern should have been splitted;"
2422   ""
2423   [(set (reg:QI 24) (match_dup 1))
2424    (set (reg:QI 22) (match_dup 2))
2425    (parallel [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
2426               (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
2427               (clobber (reg:QI 22))
2428               (clobber (reg:QI 23))])
2429    (set (match_dup 0) (reg:QI 24))
2430    (set (match_dup 3) (reg:QI 25))]
2431   "")
2432
2433 (define_insn "*divmodqi4_call"
2434   [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
2435    (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
2436    (clobber (reg:QI 22))
2437    (clobber (reg:QI 23))]
2438   ""
2439   "%~call __divmodqi4"
2440   [(set_attr "type" "xcall")
2441    (set_attr "cc" "clobber")])
2442
2443 (define_insn_and_split "udivmodqi4"
2444  [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "") 
2445                   (udiv:QI (match_operand:QI 1 "pseudo_register_operand" "") 
2446                            (match_operand:QI 2 "pseudo_register_operand" "")))
2447              (set (match_operand:QI 3 "pseudo_register_operand" "") 
2448                   (umod:QI (match_dup 1) (match_dup 2)))
2449              (clobber (reg:QI 22))
2450              (clobber (reg:QI 23))
2451              (clobber (reg:QI 24))
2452              (clobber (reg:QI 25))])]
2453   ""
2454   "this udivmodqi4 pattern should have been splitted;"
2455   "" 
2456   [(set (reg:QI 24) (match_dup 1))
2457    (set (reg:QI 22) (match_dup 2))
2458    (parallel [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
2459               (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
2460               (clobber (reg:QI 23))])
2461    (set (match_dup 0) (reg:QI 24))
2462    (set (match_dup 3) (reg:QI 25))]
2463   "")
2464
2465 (define_insn "*udivmodqi4_call"
2466   [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
2467    (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
2468    (clobber (reg:QI 23))]
2469   ""
2470   "%~call __udivmodqi4"
2471   [(set_attr "type" "xcall")
2472    (set_attr "cc" "clobber")])
2473
2474 (define_insn_and_split "divmodhi4"
2475   [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "") 
2476                    (div:HI (match_operand:HI 1 "pseudo_register_operand" "") 
2477                            (match_operand:HI 2 "pseudo_register_operand" "")))
2478               (set (match_operand:HI 3 "pseudo_register_operand" "") 
2479                    (mod:HI (match_dup 1) (match_dup 2)))
2480               (clobber (reg:QI 21))
2481               (clobber (reg:HI 22))
2482               (clobber (reg:HI 24))
2483               (clobber (reg:HI 26))])]
2484   ""
2485   "this should have been splitted;"
2486   ""
2487   [(set (reg:HI 24) (match_dup 1))
2488    (set (reg:HI 22) (match_dup 2))
2489    (parallel [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
2490               (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
2491               (clobber (reg:HI 26))
2492               (clobber (reg:QI 21))])
2493    (set (match_dup 0) (reg:HI 22))
2494    (set (match_dup 3) (reg:HI 24))]
2495   "") 
2496
2497 (define_insn "*divmodhi4_call"
2498   [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
2499    (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
2500    (clobber (reg:HI 26))
2501    (clobber (reg:QI 21))]
2502   ""
2503   "%~call __divmodhi4"
2504   [(set_attr "type" "xcall")
2505    (set_attr "cc" "clobber")])
2506
2507 (define_insn_and_split "udivmodhi4"
2508   [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "") 
2509                    (udiv:HI (match_operand:HI 1 "pseudo_register_operand" "")
2510                             (match_operand:HI 2 "pseudo_register_operand" "")))
2511               (set (match_operand:HI 3 "pseudo_register_operand" "") 
2512                    (umod:HI (match_dup 1) (match_dup 2)))
2513               (clobber (reg:QI 21))
2514               (clobber (reg:HI 22))
2515               (clobber (reg:HI 24))
2516               (clobber (reg:HI 26))])]
2517   ""
2518   "this udivmodhi4 pattern should have been splitted.;"
2519   ""
2520   [(set (reg:HI 24) (match_dup 1))
2521    (set (reg:HI 22) (match_dup 2))
2522    (parallel [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
2523               (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
2524               (clobber (reg:HI 26))
2525               (clobber (reg:QI 21))])
2526    (set (match_dup 0) (reg:HI 22))
2527    (set (match_dup 3) (reg:HI 24))]
2528   "")
2529
2530 (define_insn "*udivmodhi4_call"
2531   [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
2532    (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
2533    (clobber (reg:HI 26))
2534    (clobber (reg:QI 21))]
2535   ""
2536   "%~call __udivmodhi4"
2537   [(set_attr "type" "xcall")
2538    (set_attr "cc" "clobber")])
2539
2540 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2541 ;; 24-bit multiply
2542
2543 ;; To support widening multiplication with constant we postpone
2544 ;; expanding to the implicit library call until post combine and
2545 ;; prior to register allocation.  Clobber all hard registers that
2546 ;; might be used by the (widening) multiply until it is split and
2547 ;; it's final register footprint is worked out.
2548
2549 (define_expand "mulpsi3"
2550   [(parallel [(set (match_operand:PSI 0 "register_operand" "")
2551                    (mult:PSI (match_operand:PSI 1 "register_operand" "")
2552                              (match_operand:PSI 2 "nonmemory_operand" "")))
2553               (clobber (reg:HI 26))
2554               (clobber (reg:DI 18))])]
2555   "AVR_HAVE_MUL"
2556   {
2557     if (s8_operand (operands[2], PSImode))
2558       {
2559         rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
2560         emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1]));
2561         DONE;
2562       }
2563   })
2564
2565 (define_insn "*umulqihipsi3"
2566   [(set (match_operand:PSI 0 "register_operand"                         "=&r")
2567         (mult:PSI (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))
2568                   (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
2569   "AVR_HAVE_MUL"
2570   "mul %1,%A2
2571         movw %A0,r0
2572         mul %1,%B2
2573         clr %C0
2574         add %B0,r0
2575         adc %C0,r1
2576         clr __zero_reg__"
2577   [(set_attr "length" "7")
2578    (set_attr "cc" "clobber")])
2579
2580 (define_insn "*umulhiqipsi3"
2581   [(set (match_operand:PSI 0 "register_operand"                         "=&r")
2582         (mult:PSI (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))
2583                   (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))))]
2584   "AVR_HAVE_MUL"
2585   "mul %1,%A2
2586         movw %A0,r0
2587         mul %1,%B2
2588         add %B0,r0
2589         mov %C0,r1
2590         clr __zero_reg__
2591         adc %C0,__zero_reg__"
2592   [(set_attr "length" "7")
2593    (set_attr "cc" "clobber")])
2594
2595 (define_insn_and_split "mulsqipsi3"
2596   [(set (match_operand:PSI 0 "pseudo_register_operand"                          "=r")
2597         (mult:PSI (sign_extend:PSI (match_operand:QI 1 "pseudo_register_operand" "r"))
2598                   (match_operand:PSI 2 "pseudo_register_or_const_int_operand"    "rn")))
2599    (clobber (reg:HI 26))
2600    (clobber (reg:DI 18))]
2601   "AVR_HAVE_MUL && !reload_completed"
2602   { gcc_unreachable(); }
2603   "&& 1"
2604   [(set (reg:QI 25)
2605         (match_dup 1))
2606    (set (reg:PSI 22)
2607         (match_dup 2))
2608    (set (reg:PSI 18)
2609         (mult:PSI (sign_extend:PSI (reg:QI 25))
2610                   (reg:PSI 22)))
2611    (set (match_dup 0)
2612         (reg:PSI 18))])
2613
2614 (define_insn_and_split "*mulpsi3"
2615   [(set (match_operand:PSI 0 "pseudo_register_operand"                       "=r")
2616         (mult:PSI (match_operand:PSI 1 "pseudo_register_operand"              "r")
2617                   (match_operand:PSI 2 "pseudo_register_or_const_int_operand" "rn")))
2618    (clobber (reg:HI 26))
2619    (clobber (reg:DI 18))]
2620   "AVR_HAVE_MUL && !reload_completed"
2621   { gcc_unreachable(); }
2622   "&& 1"
2623   [(set (reg:PSI 18)
2624         (match_dup 1))
2625    (set (reg:PSI 22) 
2626         (match_dup 2))
2627    (parallel [(set (reg:PSI 22)
2628                    (mult:PSI (reg:PSI 22)
2629                              (reg:PSI 18)))
2630               (clobber (reg:QI 21))
2631               (clobber (reg:QI 25))
2632               (clobber (reg:HI 26))])
2633    (set (match_dup 0)
2634         (reg:PSI 22))]
2635   {
2636     if (s8_operand (operands[2], PSImode))
2637       {
2638         rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
2639         emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1]));
2640         DONE;
2641       }
2642   })
2643
2644 (define_insn "*mulsqipsi3.libgcc"
2645   [(set (reg:PSI 18)
2646         (mult:PSI (sign_extend:PSI (reg:QI 25))
2647                   (reg:PSI 22)))]
2648   "AVR_HAVE_MUL"
2649   "%~call __mulsqipsi3"
2650   [(set_attr "type" "xcall")
2651    (set_attr "cc" "clobber")])
2652
2653 (define_insn "*mulpsi3.libgcc"
2654   [(set (reg:PSI 22)
2655         (mult:PSI (reg:PSI 22)
2656                   (reg:PSI 18)))
2657    (clobber (reg:QI 21))
2658    (clobber (reg:QI 25))
2659    (clobber (reg:HI 26))]
2660   "AVR_HAVE_MUL"
2661   "%~call __mulpsi3"
2662   [(set_attr "type" "xcall")
2663    (set_attr "cc" "clobber")])
2664
2665
2666 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2667 ;; 24-bit signed/unsigned division and modulo.
2668 ;; Notice that the libgcc implementation return the quotient in R22
2669 ;; and the remainder in R18 whereas the 32-bit [u]divmodsi4
2670 ;; implementation works the other way round.
2671
2672 (define_insn_and_split "divmodpsi4"
2673   [(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "")
2674                    (div:PSI (match_operand:PSI 1 "pseudo_register_operand" "")
2675                             (match_operand:PSI 2 "pseudo_register_operand" "")))
2676               (set (match_operand:PSI 3 "pseudo_register_operand" "")
2677                    (mod:PSI (match_dup 1)
2678                             (match_dup 2)))
2679               (clobber (reg:DI 18))
2680               (clobber (reg:QI 26))])]
2681   ""
2682   { gcc_unreachable(); }
2683   ""
2684   [(set (reg:PSI 22) (match_dup 1))
2685    (set (reg:PSI 18) (match_dup 2))
2686    (parallel [(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18)))
2687               (set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18)))
2688               (clobber (reg:QI 21))
2689               (clobber (reg:QI 25))
2690               (clobber (reg:QI 26))])
2691    (set (match_dup 0) (reg:PSI 22))
2692    (set (match_dup 3) (reg:PSI 18))])
2693
2694 (define_insn "*divmodpsi4_call"
2695   [(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18)))
2696    (set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18)))
2697    (clobber (reg:QI 21))
2698    (clobber (reg:QI 25))
2699    (clobber (reg:QI 26))]
2700   ""
2701   "%~call __divmodpsi4"
2702   [(set_attr "type" "xcall")
2703    (set_attr "cc" "clobber")])
2704
2705 (define_insn_and_split "udivmodpsi4"
2706   [(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "")
2707                    (udiv:PSI (match_operand:PSI 1 "pseudo_register_operand" "")
2708                              (match_operand:PSI 2 "pseudo_register_operand" "")))
2709               (set (match_operand:PSI 3 "pseudo_register_operand" "")
2710                    (umod:PSI (match_dup 1)
2711                              (match_dup 2)))
2712               (clobber (reg:DI 18))
2713               (clobber (reg:QI 26))])]
2714   ""
2715   { gcc_unreachable(); }
2716   ""
2717   [(set (reg:PSI 22) (match_dup 1))
2718    (set (reg:PSI 18) (match_dup 2))
2719    (parallel [(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18)))
2720               (set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18)))
2721               (clobber (reg:QI 21))
2722               (clobber (reg:QI 25))
2723               (clobber (reg:QI 26))])
2724    (set (match_dup 0) (reg:PSI 22))
2725    (set (match_dup 3) (reg:PSI 18))])
2726
2727 (define_insn "*udivmodpsi4_call"
2728   [(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18)))
2729    (set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18)))
2730    (clobber (reg:QI 21))
2731    (clobber (reg:QI 25))
2732    (clobber (reg:QI 26))]
2733   ""
2734   "%~call __udivmodpsi4"
2735   [(set_attr "type" "xcall")
2736    (set_attr "cc" "clobber")])
2737
2738 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2739
2740 (define_insn_and_split "divmodsi4"
2741   [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") 
2742                    (div:SI (match_operand:SI 1 "pseudo_register_operand" "") 
2743                            (match_operand:SI 2 "pseudo_register_operand" "")))
2744               (set (match_operand:SI 3 "pseudo_register_operand" "") 
2745                    (mod:SI (match_dup 1) (match_dup 2)))
2746               (clobber (reg:SI 18))
2747               (clobber (reg:SI 22))
2748               (clobber (reg:HI 26))
2749               (clobber (reg:HI 30))])]
2750   ""
2751   "this divmodsi4 pattern should have been splitted;" 
2752   ""
2753   [(set (reg:SI 22) (match_dup 1))
2754    (set (reg:SI 18) (match_dup 2))
2755    (parallel [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
2756               (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
2757               (clobber (reg:HI 26))
2758               (clobber (reg:HI 30))])
2759    (set (match_dup 0) (reg:SI 18))
2760    (set (match_dup 3) (reg:SI 22))]
2761   "")
2762
2763 (define_insn "*divmodsi4_call"
2764   [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
2765    (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
2766    (clobber (reg:HI 26))
2767    (clobber (reg:HI 30))]
2768   ""
2769   "%~call __divmodsi4"
2770   [(set_attr "type" "xcall")
2771    (set_attr "cc" "clobber")])
2772
2773 (define_insn_and_split "udivmodsi4"
2774   [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") 
2775                    (udiv:SI (match_operand:SI 1 "pseudo_register_operand" "") 
2776                            (match_operand:SI 2 "pseudo_register_operand" "")))
2777               (set (match_operand:SI 3 "pseudo_register_operand" "") 
2778                    (umod:SI (match_dup 1) (match_dup 2)))
2779               (clobber (reg:SI 18))
2780               (clobber (reg:SI 22))
2781               (clobber (reg:HI 26))
2782               (clobber (reg:HI 30))])]
2783   ""
2784   "this udivmodsi4 pattern should have been splitted;"
2785   ""
2786   [(set (reg:SI 22) (match_dup 1))
2787    (set (reg:SI 18) (match_dup 2))
2788    (parallel [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
2789               (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
2790               (clobber (reg:HI 26))
2791               (clobber (reg:HI 30))])
2792    (set (match_dup 0) (reg:SI 18))
2793    (set (match_dup 3) (reg:SI 22))]
2794   "")
2795
2796 (define_insn "*udivmodsi4_call"
2797   [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
2798    (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
2799    (clobber (reg:HI 26))
2800    (clobber (reg:HI 30))]
2801   ""
2802   "%~call __udivmodsi4"
2803   [(set_attr "type" "xcall")
2804    (set_attr "cc" "clobber")])
2805
2806 ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2807 ; and
2808
2809 (define_insn "andqi3"
2810   [(set (match_operand:QI 0 "register_operand" "=r,d")
2811         (and:QI (match_operand:QI 1 "register_operand" "%0,0")
2812                 (match_operand:QI 2 "nonmemory_operand" "r,i")))]
2813   ""
2814   "@
2815         and %0,%2
2816         andi %0,lo8(%2)"
2817   [(set_attr "length" "1,1")
2818    (set_attr "cc" "set_zn,set_zn")])
2819
2820 (define_insn "andhi3"
2821   [(set (match_operand:HI 0 "register_operand"         "=r,d,d,r  ,r")
2822         (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0  ,0")
2823                 (match_operand:HI 2 "nonmemory_operand" "r,s,n,Ca2,n")))
2824    (clobber (match_scratch:QI 3                        "=X,X,X,X  ,&d"))]
2825   ""
2826   {
2827     if (which_alternative == 0)
2828       return "and %A0,%A2\;and %B0,%B2";
2829     else if (which_alternative == 1)
2830       return "andi %A0,lo8(%2)\;andi %B0,hi8(%2)";
2831
2832     return avr_out_bitop (insn, operands, NULL);
2833   }
2834   [(set_attr "length" "2,2,2,4,4")
2835    (set_attr "adjust_len" "*,*,out_bitop,out_bitop,out_bitop")
2836    (set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
2837
2838 (define_insn "andpsi3"
2839   [(set (match_operand:PSI 0 "register_operand"          "=r,d,r  ,r")
2840         (and:PSI (match_operand:PSI 1 "register_operand" "%0,0,0  ,0")
2841                  (match_operand:PSI 2 "nonmemory_operand" "r,n,Ca3,n")))
2842    (clobber (match_scratch:QI 3                          "=X,X,X  ,&d"))]
2843   ""
2844   {
2845     if (which_alternative == 0)
2846       return "and %A0,%A2" CR_TAB
2847              "and %B0,%B2" CR_TAB
2848              "and %C0,%C2";
2849
2850     return avr_out_bitop (insn, operands, NULL);
2851   }
2852   [(set_attr "length" "3,3,6,6")
2853    (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
2854    (set_attr "cc" "set_n,clobber,clobber,clobber")])
2855
2856 (define_insn "andsi3"
2857   [(set (match_operand:SI 0 "register_operand"         "=r,d,r  ,r")
2858         (and:SI (match_operand:SI 1 "register_operand" "%0,0,0  ,0")
2859                 (match_operand:SI 2 "nonmemory_operand" "r,n,Ca4,n")))
2860    (clobber (match_scratch:QI 3                        "=X,X,X  ,&d"))]
2861   ""
2862   {
2863     if (which_alternative == 0)
2864       return "and %0,%2"   CR_TAB
2865              "and %B0,%B2" CR_TAB
2866              "and %C0,%C2" CR_TAB
2867              "and %D0,%D2";
2868
2869     return avr_out_bitop (insn, operands, NULL);
2870   }
2871   [(set_attr "length" "4,4,8,8")
2872    (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
2873    (set_attr "cc" "set_n,clobber,clobber,clobber")])
2874
2875 (define_peephole2 ; andi
2876   [(set (match_operand:QI 0 "d_register_operand" "")
2877         (and:QI (match_dup 0)
2878                 (match_operand:QI 1 "const_int_operand" "")))
2879    (set (match_dup 0)
2880         (and:QI (match_dup 0)
2881                 (match_operand:QI 2 "const_int_operand" "")))]
2882   ""
2883   [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
2884   {
2885     operands[1] = GEN_INT (INTVAL (operands[1]) & INTVAL (operands[2]));
2886   })
2887
2888 ;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2889 ;; ior
2890
2891 (define_insn "iorqi3"
2892   [(set (match_operand:QI 0 "register_operand" "=r,d")
2893         (ior:QI (match_operand:QI 1 "register_operand" "%0,0")
2894                 (match_operand:QI 2 "nonmemory_operand" "r,i")))]
2895   ""
2896   "@
2897         or %0,%2
2898         ori %0,lo8(%2)"
2899   [(set_attr "length" "1,1")
2900    (set_attr "cc" "set_zn,set_zn")])
2901
2902 (define_insn "iorhi3"
2903   [(set (match_operand:HI 0 "register_operand"         "=r,d,d,r  ,r")
2904         (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0  ,0")
2905                 (match_operand:HI 2 "nonmemory_operand" "r,s,n,Co2,n")))
2906    (clobber (match_scratch:QI 3                        "=X,X,X,X  ,&d"))]
2907   ""
2908   {
2909     if (which_alternative == 0)
2910       return "or %A0,%A2\;or %B0,%B2";
2911     else if (which_alternative == 1)
2912       return "ori %A0,lo8(%2)\;ori %B0,hi8(%2)";
2913
2914     return avr_out_bitop (insn, operands, NULL);
2915   }
2916   [(set_attr "length" "2,2,2,4,4")
2917    (set_attr "adjust_len" "*,*,out_bitop,out_bitop,out_bitop")
2918    (set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
2919
2920 (define_insn "iorpsi3"
2921   [(set (match_operand:PSI 0 "register_operand"          "=r,d,r  ,r")
2922         (ior:PSI (match_operand:PSI 1 "register_operand" "%0,0,0  ,0")
2923                  (match_operand:PSI 2 "nonmemory_operand" "r,n,Co3,n")))
2924    (clobber (match_scratch:QI 3                          "=X,X,X  ,&d"))]
2925   ""
2926   {
2927     if (which_alternative == 0)
2928       return "or %A0,%A2" CR_TAB
2929              "or %B0,%B2" CR_TAB
2930              "or %C0,%C2";
2931
2932     return avr_out_bitop (insn, operands, NULL);
2933   }
2934   [(set_attr "length" "3,3,6,6")
2935    (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
2936    (set_attr "cc" "set_n,clobber,clobber,clobber")])
2937
2938 (define_insn "iorsi3"
2939   [(set (match_operand:SI 0 "register_operand"         "=r,d,r  ,r")
2940         (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0  ,0")
2941                 (match_operand:SI 2 "nonmemory_operand" "r,n,Co4,n")))
2942    (clobber (match_scratch:QI 3                        "=X,X,X  ,&d"))]
2943   ""
2944   {
2945     if (which_alternative == 0)
2946       return "or %0,%2"   CR_TAB
2947              "or %B0,%B2" CR_TAB
2948              "or %C0,%C2" CR_TAB
2949              "or %D0,%D2";
2950
2951     return avr_out_bitop (insn, operands, NULL);
2952   }
2953   [(set_attr "length" "4,4,8,8")
2954    (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
2955    (set_attr "cc" "set_n,clobber,clobber,clobber")])
2956
2957 ;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2958 ;; xor
2959
2960 (define_insn "xorqi3"
2961   [(set (match_operand:QI 0 "register_operand" "=r")
2962         (xor:QI (match_operand:QI 1 "register_operand" "%0")
2963                 (match_operand:QI 2 "register_operand" "r")))]
2964   ""
2965   "eor %0,%2"
2966   [(set_attr "length" "1")
2967    (set_attr "cc" "set_zn")])
2968
2969 (define_insn "xorhi3"
2970   [(set (match_operand:HI 0 "register_operand"         "=r,r  ,r")
2971         (xor:HI (match_operand:HI 1 "register_operand" "%0,0  ,0")
2972                 (match_operand:HI 2 "nonmemory_operand" "r,Cx2,n")))
2973    (clobber (match_scratch:QI 3                        "=X,X  ,&d"))]
2974   ""
2975   {
2976     if (which_alternative == 0)
2977       return "eor %A0,%A2\;eor %B0,%B2";
2978
2979     return avr_out_bitop (insn, operands, NULL);
2980   }
2981   [(set_attr "length" "2,2,4")
2982    (set_attr "adjust_len" "*,out_bitop,out_bitop")
2983    (set_attr "cc" "set_n,clobber,clobber")])
2984
2985 (define_insn "xorpsi3"
2986   [(set (match_operand:PSI 0 "register_operand"          "=r,r  ,r")
2987         (xor:PSI (match_operand:PSI 1 "register_operand" "%0,0  ,0")
2988                  (match_operand:PSI 2 "nonmemory_operand" "r,Cx3,n")))
2989    (clobber (match_scratch:QI 3                          "=X,X  ,&d"))]
2990   ""
2991   {
2992     if (which_alternative == 0)
2993       return "eor %A0,%A2" CR_TAB
2994              "eor %B0,%B2" CR_TAB
2995              "eor %C0,%C2";
2996
2997     return avr_out_bitop (insn, operands, NULL);
2998   }
2999   [(set_attr "length" "3,6,6")
3000    (set_attr "adjust_len" "*,out_bitop,out_bitop")
3001    (set_attr "cc" "set_n,clobber,clobber")])
3002
3003 (define_insn "xorsi3"
3004   [(set (match_operand:SI 0 "register_operand"         "=r,r  ,r")
3005         (xor:SI (match_operand:SI 1 "register_operand" "%0,0  ,0")
3006                 (match_operand:SI 2 "nonmemory_operand" "r,Cx4,n")))
3007    (clobber (match_scratch:QI 3                        "=X,X  ,&d"))]
3008   ""
3009   {
3010     if (which_alternative == 0)
3011       return "eor %0,%2"   CR_TAB
3012              "eor %B0,%B2" CR_TAB
3013              "eor %C0,%C2" CR_TAB
3014              "eor %D0,%D2";
3015
3016     return avr_out_bitop (insn, operands, NULL);
3017   }
3018   [(set_attr "length" "4,8,8")
3019    (set_attr "adjust_len" "*,out_bitop,out_bitop")
3020    (set_attr "cc" "set_n,clobber,clobber")])
3021
3022 ;; swap swap swap swap swap swap swap swap swap swap swap swap swap swap swap
3023 ;; swap
3024
3025 (define_expand "rotlqi3"
3026   [(set (match_operand:QI 0 "register_operand" "")
3027         (rotate:QI (match_operand:QI 1 "register_operand" "")
3028                    (match_operand:QI 2 "const_0_to_7_operand" "")))]
3029   ""
3030   {
3031     if (!CONST_INT_P (operands[2]))
3032       FAIL;
3033
3034     operands[2] = gen_int_mode (INTVAL (operands[2]) & 7, QImode);
3035   })
3036
3037 ;; Expander used by __builtin_avr_swap
3038 (define_expand "rotlqi3_4"
3039   [(set (match_operand:QI 0 "register_operand" "")
3040         (rotate:QI (match_operand:QI 1 "register_operand" "")
3041                    (const_int 4)))])
3042
3043 (define_insn "*rotlqi3"
3044   [(set (match_operand:QI 0 "register_operand"               "=r,r,r  ,r  ,r  ,r  ,r  ,r")
3045         (rotate:QI (match_operand:QI 1 "register_operand"     "0,0,0  ,0  ,0  ,0  ,0  ,0")
3046                    (match_operand:QI 2 "const_0_to_7_operand" "P,K,C03,C04,C05,C06,C07,L")))]
3047   ""
3048   "@
3049         lsl %0\;adc %0,__zero_reg__
3050         lsl %0\;adc %0,__zero_reg__\;lsl %0\;adc %0,__zero_reg__
3051         swap %0\;bst %0,0\;ror %0\;bld %0,7
3052         swap %0
3053         swap %0\;lsl %0\;adc %0,__zero_reg__
3054         swap %0\;lsl %0\;adc %0,__zero_reg__\;lsl %0\;adc %0,__zero_reg__
3055         bst %0,0\;ror %0\;bld %0,7
3056         "
3057   [(set_attr "length" "2,4,4,1,3,5,3,0")
3058    (set_attr "cc" "set_n,set_n,clobber,none,set_n,set_n,clobber,none")])
3059
3060 ;; Split all rotates of HI,SI and PSImode registers where rotation is by
3061 ;; a whole number of bytes.  The split creates the appropriate moves and
3062 ;; considers all overlap situations.
3063
3064 ;; HImode does not need scratch.  Use attribute for this constraint.
3065
3066 (define_mode_attr rotx [(SI "&r,&r,X") (PSI "&r,&r,X") (HI "X,X,X")])
3067 (define_mode_attr rotsmode [(SI "HI") (PSI "QI") (HI "QI")])
3068
3069 ;; "rotlhi3"
3070 ;; "rotlpsi3"
3071 ;; "rotlsi3"
3072 (define_expand "rotl<mode>3"
3073   [(parallel [(set (match_operand:HISI 0 "register_operand" "")
3074                    (rotate:HISI (match_operand:HISI 1 "register_operand" "")
3075                                 (match_operand:VOID 2 "const_int_operand" "")))
3076               (clobber (match_dup 3))])]
3077   ""
3078   {
3079     int offset;
3080
3081     if (!CONST_INT_P (operands[2]))
3082       FAIL;
3083
3084     offset = INTVAL (operands[2]);
3085  
3086     if (0 == offset % 8)
3087       {
3088         if (AVR_HAVE_MOVW && 0 == offset % 16)
3089           operands[3] = gen_rtx_SCRATCH (<rotsmode>mode);
3090         else
3091           operands[3] = gen_rtx_SCRATCH (QImode);
3092       }
3093     else if (offset == 1
3094              || offset == GET_MODE_BITSIZE (<MODE>mode) -1)
3095       {
3096         /*; Support rotate left/right by 1  */
3097
3098         emit_move_insn (operands[0],
3099                         gen_rtx_ROTATE (<MODE>mode, operands[1], operands[2]));
3100         DONE;
3101       }
3102     else
3103       FAIL;
3104   })
3105
3106 (define_insn "*rotlhi2.1"
3107   [(set (match_operand:HI 0 "register_operand"           "=r")
3108         (rotate:HI (match_operand:HI 1 "register_operand" "0")
3109                    (const_int 1)))]
3110   ""
3111   "lsl %A0\;rol %B0\;adc %A0,__zero_reg__"
3112   [(set_attr "length" "3")
3113    (set_attr "cc" "clobber")])
3114
3115 (define_insn "*rotlhi2.15"
3116   [(set (match_operand:HI 0 "register_operand"           "=r")
3117         (rotate:HI (match_operand:HI 1 "register_operand" "0")
3118                    (const_int 15)))]
3119   ""
3120   "bst %A0,0\;ror %B0\;ror %A0\;bld %B0,7"
3121   [(set_attr "length" "4")
3122    (set_attr "cc" "clobber")])
3123
3124 (define_insn "*rotlpsi2.1"
3125   [(set (match_operand:PSI 0 "register_operand"            "=r")
3126         (rotate:PSI (match_operand:PSI 1 "register_operand" "0")
3127                     (const_int 1)))]
3128   ""
3129   "lsl %A0\;rol %B0\;rol %C0\;adc %A0,__zero_reg__"
3130   [(set_attr "length" "4")
3131    (set_attr "cc" "clobber")])
3132
3133 (define_insn "*rotlpsi2.23"
3134   [(set (match_operand:PSI 0 "register_operand"            "=r")
3135         (rotate:PSI (match_operand:PSI 1 "register_operand" "0")
3136                     (const_int 23)))]
3137   ""
3138   "bst %A0,0\;ror %C0\;ror %B0\;ror %A0\;bld %C0,7"
3139   [(set_attr "length" "5")
3140    (set_attr "cc" "clobber")])
3141
3142 (define_insn "*rotlsi2.1"
3143   [(set (match_operand:SI 0 "register_operand"           "=r")
3144         (rotate:SI (match_operand:SI 1 "register_operand" "0")
3145                    (const_int 1)))]
3146   ""
3147   "lsl %A0\;rol %B0\;rol %C0\;rol %D0\;adc %A0,__zero_reg__"
3148   [(set_attr "length" "5")
3149    (set_attr "cc" "clobber")])
3150
3151 (define_insn "*rotlsi2.31"
3152   [(set (match_operand:SI 0 "register_operand"           "=r")
3153         (rotate:SI (match_operand:SI 1 "register_operand" "0")
3154                    (const_int 31)))]
3155   ""
3156   "bst %A0,0\;ror %D0\;ror %C0\;ror %B0\;ror %A0\;bld %D0,7"
3157   [(set_attr "length" "6")
3158    (set_attr "cc" "clobber")])
3159
3160 ;; Overlapping non-HImode registers often (but not always) need a scratch.
3161 ;; The best we can do is use early clobber alternative "#&r" so that
3162 ;; completely non-overlapping operands dont get a scratch but # so register
3163 ;; allocation does not prefer non-overlapping.
3164
3165
3166 ;; Split word aligned rotates using scratch that is mode dependent.
3167
3168 ;; "*rotwhi"
3169 ;; "*rotwsi"
3170 (define_insn_and_split "*rotw<mode>"
3171   [(set (match_operand:HISI 0 "register_operand"             "=r,r,#&r")
3172         (rotate:HISI (match_operand:HISI 1 "register_operand" "0,r,r")
3173                      (match_operand 2 "const_int_operand"     "n,n,n")))
3174    (clobber (match_scratch:<rotsmode> 3 "=<rotx>"))]
3175   "AVR_HAVE_MOVW
3176    && CONST_INT_P (operands[2])
3177    && GET_MODE_SIZE (<MODE>mode) % 2 == 0
3178    && 0 == INTVAL (operands[2]) % 16"
3179   "#"
3180   "&& reload_completed"
3181   [(const_int 0)]
3182   {
3183     avr_rotate_bytes (operands);
3184     DONE;
3185   })
3186
3187
3188 ;; Split byte aligned rotates using scratch that is always QI mode.
3189
3190 ;; "*rotbhi"
3191 ;; "*rotbpsi"
3192 ;; "*rotbsi"
3193 (define_insn_and_split "*rotb<mode>"
3194   [(set (match_operand:HISI 0 "register_operand"             "=r,r,#&r")
3195         (rotate:HISI (match_operand:HISI 1 "register_operand" "0,r,r")
3196                      (match_operand 2 "const_int_operand"     "n,n,n")))
3197    (clobber (match_scratch:QI 3 "=<rotx>"))]
3198   "CONST_INT_P (operands[2])
3199    && (8 == INTVAL (operands[2]) % 16
3200        || ((!AVR_HAVE_MOVW
3201             || GET_MODE_SIZE (<MODE>mode) % 2 != 0)
3202            && 0 == INTVAL (operands[2]) % 16))"
3203   "#"
3204   "&& reload_completed"
3205   [(const_int 0)]
3206   {
3207     avr_rotate_bytes (operands);
3208     DONE;
3209   })
3210
3211
3212 ;;<< << << << << << << << << << << << << << << << << << << << << << << << << <<
3213 ;; arithmetic shift left
3214
3215 (define_expand "ashlqi3"
3216   [(set (match_operand:QI 0 "register_operand"            "")
3217         (ashift:QI (match_operand:QI 1 "register_operand" "")
3218                    (match_operand:QI 2 "nop_general_operand" "")))])
3219
3220 (define_split ; ashlqi3_const4
3221   [(set (match_operand:QI 0 "d_register_operand" "")
3222         (ashift:QI (match_dup 0)
3223                    (const_int 4)))]
3224   ""
3225   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
3226    (set (match_dup 0) (and:QI (match_dup 0) (const_int -16)))]
3227   "")
3228
3229 (define_split ; ashlqi3_const5
3230   [(set (match_operand:QI 0 "d_register_operand" "")
3231         (ashift:QI (match_dup 0)
3232                    (const_int 5)))]
3233   ""
3234   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
3235    (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))
3236    (set (match_dup 0) (and:QI (match_dup 0) (const_int -32)))]
3237   "")
3238
3239 (define_split ; ashlqi3_const6
3240   [(set (match_operand:QI 0 "d_register_operand" "")
3241         (ashift:QI (match_dup 0)
3242                    (const_int 6)))]
3243   ""
3244   [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
3245    (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 2)))
3246    (set (match_dup 0) (and:QI (match_dup 0) (const_int -64)))]
3247   "")
3248
3249 (define_insn "*ashlqi3"
3250   [(set (match_operand:QI 0 "register_operand"              "=r,r,r,r,!d,r,r")
3251         (ashift:QI (match_operand:QI 1 "register_operand"    "0,0,0,0,0 ,0,0")
3252                    (match_operand:QI 2 "nop_general_operand" "r,L,P,K,n ,n,Qm")))]
3253   ""
3254   {
3255     return ashlqi3_out (insn, operands, NULL);
3256   }
3257   [(set_attr "length" "5,0,1,2,4,6,9")
3258    (set_attr "adjust_len" "ashlqi")
3259    (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")])
3260
3261 (define_insn "ashlhi3"
3262   [(set (match_operand:HI 0 "register_operand"              "=r,r,r,r,r,r,r")
3263         (ashift:HI (match_operand:HI 1 "register_operand"    "0,0,0,r,0,0,0")
3264                    (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
3265   ""
3266   {
3267     return ashlhi3_out (insn, operands, NULL);
3268   }
3269   [(set_attr "length" "6,0,2,2,4,10,10")
3270    (set_attr "adjust_len" "ashlhi")
3271    (set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")])
3272
3273
3274 ;; Insns like the following are generated when (implicitly) extending 8-bit shifts
3275 ;; like char1 = char2 << char3.  Only the low-byte is needed in that situation.
3276
3277 ;; "*ashluqihiqi3"
3278 ;; "*ashlsqihiqi3"
3279 (define_insn_and_split "*ashl<extend_su>qihiqi3"
3280   [(set (match_operand:QI 0 "register_operand"                                     "=r")
3281         (subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "0"))
3282                               (match_operand:QI 2 "register_operand"                "r"))
3283                    0))]
3284   ""
3285   "#"
3286   ""
3287   [(set (match_dup 0)
3288         (ashift:QI (match_dup 1)
3289                    (match_dup 2)))]
3290   "")
3291
3292 ;; ??? Combiner does not recognize that it could split the following insn;
3293 ;;     presumably because he has no register handy?
3294
3295 ;; "*ashluqihiqi3.mem"
3296 ;; "*ashlsqihiqi3.mem"
3297 (define_insn_and_split "*ashl<extend_su>qihiqi3.mem"
3298   [(set (match_operand:QI 0 "memory_operand" "=m")
3299         (subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "r"))
3300                               (match_operand:QI 2 "register_operand" "r"))
3301                    0))]
3302   "!reload_completed"
3303   { gcc_unreachable(); }
3304   "&& 1"
3305   [(set (match_dup 3)
3306         (ashift:QI (match_dup 1)
3307                    (match_dup 2)))
3308    (set (match_dup 0)
3309         (match_dup 3))]
3310   {
3311     operands[3] = gen_reg_rtx (QImode);
3312   })
3313
3314 ;; Similar.
3315
3316 (define_insn_and_split "*ashlhiqi3"
3317   [(set (match_operand:QI 0 "nonimmediate_operand" "=r")
3318         (subreg:QI (ashift:HI (match_operand:HI 1 "register_operand" "0")
3319                               (match_operand:QI 2 "register_operand" "r")) 0))]
3320   "!reload_completed"
3321   { gcc_unreachable(); }
3322   "&& 1"
3323   [(set (match_dup 4)
3324         (ashift:QI (match_dup 3)
3325                    (match_dup 2)))
3326    (set (match_dup 0)
3327         (match_dup 4))]
3328   {
3329     operands[3] = simplify_gen_subreg (QImode, operands[1], HImode, 0);
3330     operands[4] = gen_reg_rtx (QImode);
3331   })
3332
3333 ;; High part of 16-bit shift is unused after the instruction:
3334 ;; No need to compute it, map to 8-bit shift.
3335
3336 (define_peephole2
3337   [(set (match_operand:HI 0 "register_operand" "")
3338         (ashift:HI (match_dup 0)
3339                    (match_operand:QI 1 "register_operand" "")))]
3340   ""
3341   [(set (match_dup 2)
3342         (ashift:QI (match_dup 2)
3343                    (match_dup 1)))
3344    (clobber (match_dup 3))]
3345   {
3346     operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 1);
3347
3348     if (!peep2_reg_dead_p (1, operands[3]))
3349       FAIL;
3350
3351     operands[2] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
3352   })
3353
3354
3355 (define_insn "ashlsi3"
3356   [(set (match_operand:SI 0 "register_operand"              "=r,r,r,r,r,r,r")
3357         (ashift:SI (match_operand:SI 1 "register_operand"    "0,0,0,r,0,0,0")
3358                    (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
3359   ""
3360   {
3361     return ashlsi3_out (insn, operands, NULL);
3362   }
3363   [(set_attr "length" "8,0,4,4,8,10,12")
3364