OSDN Git Service

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