OSDN Git Service

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