PR middle-end/54635
[official-gcc.git] / gcc / config / avr / avr.md
blobb86f9b639df49253837a44a6ffa11bcead5abb90
1 ;;   Machine description for GNU compiler,
2 ;;   for ATMEL AVR micro controllers.
3 ;;   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008,
4 ;;   2009, 2010, 2011 Free Software Foundation, Inc.
5 ;;   Contributed by Denis Chertykov (chertykov@gmail.com)
7 ;; This file is part of GCC.
9 ;; GCC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 3, or (at your option)
12 ;; any later version.
14 ;; GCC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GCC; see the file COPYING3.  If not see
21 ;; <http://www.gnu.org/licenses/>.
23 ;; Special characters after '%':
24 ;;  A  No effect (add 0).
25 ;;  B  Add 1 to REG number, MEM address or CONST_INT.
26 ;;  C  Add 2.
27 ;;  D  Add 3.
28 ;;  j  Branch condition.
29 ;;  k  Reverse branch condition.
30 ;;..m..Constant Direct Data memory address.
31 ;;  i  Print the SFR address quivalent of a CONST_INT or a CONST_INT
32 ;;     RAM address.  The resulting address is suitable to be used in IN/OUT.
33 ;;  o  Displacement for (mem (plus (reg) (const_int))) operands.
34 ;;  p  POST_INC or PRE_DEC address as a pointer (X, Y, Z)
35 ;;  r  POST_INC or PRE_DEC address as a register (r26, r28, r30)
36 ;; T/T Print operand suitable for BLD/BST instruction, i.e. register and
37 ;;     bit number.  This gets 2 operands: The first %T gets a REG_P and
38 ;;     just cashes the operand for the next %T.  The second %T gets
39 ;;     a CONST_INT that represents a bit position.
40 ;;     Example: With %0 = (reg:HI 18)  and  %1 = (const_int 13)
41 ;;              "%T0%T1" it will print "r19,5".
42 ;;     Notice that you must not write a comma between %T0 and %T1.
43 ;; T/t Similar to above, but don't print the comma and the bit number.
44 ;;     Example: With %0 = (reg:HI 18)  and  %1 = (const_int 13)
45 ;;              "%T0%t1" it will print "r19".
46 ;;..x..Constant Direct Program memory address.
47 ;;  ~  Output 'r' if not AVR_HAVE_JMP_CALL.
48 ;;  !  Output 'e' if AVR_HAVE_EIJMP_EICALL.
51 (define_constants
52   [(REG_X       26)
53    (REG_Y       28)
54    (REG_Z       30)
55    (REG_W       24)
56    (REG_SP      32)
57    (LPM_REGNO   0)      ; implicit target register of LPM
58    (TMP_REGNO   0)      ; temporary register r0
59    (ZERO_REGNO  1)      ; zero register r1
60    ])
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    ])
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     
89 (include "predicates.md")
90 (include "constraints.md")
92 ;; Condition code settings.
93 (define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber,
94                    plus,ldi"
95   (const_string "none"))
97 (define_attr "type" "branch,branch1,arith,xcall"
98   (const_string "arith"))
100 ;; The size of instructions in bytes.
101 ;; XXX may depend from "cc"
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)))
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.
140 (define_attr "adjust_len"
141   "out_bitop, plus, addto_sp,
142    tsthi, tstpsi, tstsi, compare, compare64, call,
143    mov8, mov16, mov24, mov32, reload_in16, reload_in24, reload_in32,
144    ufract, sfract,
145    xload, movmem, load_lpm,
146    ashlqi, ashrqi, lshrqi,
147    ashlhi, ashrhi, lshrhi,
148    ashlsi, ashrsi, lshrsi,
149    ashlpsi, ashrpsi, lshrpsi,
150    insert_bits,
151    no"
152   (const_string "no"))
154 ;; Flavours of instruction set architecture (ISA), used in enabled attribute
156 ;; mov  : ISA has no MOVW                movw  : ISA has MOVW
157 ;; rjmp : ISA has no CALL/JMP            jmp   : ISA has CALL/JMP
158 ;; ijmp : ISA has no EICALL/EIJMP        eijmp : ISA has EICALL/EIJMP
159 ;; lpm  : ISA has no LPMX                lpmx  : ISA has LPMX
160 ;; elpm : ISA has ELPM but no ELPMX      elpmx : ISA has ELPMX
161 ;; no_xmega: non-XMEGA core              xmega : XMEGA core
163 (define_attr "isa"
164   "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx, no_xmega,xmega,
165    standard"
166   (const_string "standard"))
168 (define_attr "enabled" ""
169   (cond [(eq_attr "isa" "standard")
170          (const_int 1)
171          
172          (and (eq_attr "isa" "mov")
173               (match_test "!AVR_HAVE_MOVW"))
174          (const_int 1)
176          (and (eq_attr "isa" "movw")
177               (match_test "AVR_HAVE_MOVW"))
178          (const_int 1)
179          
180          (and (eq_attr "isa" "rjmp")
181               (match_test "!AVR_HAVE_JMP_CALL"))
182          (const_int 1)
184          (and (eq_attr "isa" "jmp")
185               (match_test "AVR_HAVE_JMP_CALL"))
186          (const_int 1)
187          
188          (and (eq_attr "isa" "ijmp")
189               (match_test "!AVR_HAVE_EIJMP_EICALL"))
190          (const_int 1)
192          (and (eq_attr "isa" "eijmp")
193               (match_test "AVR_HAVE_EIJMP_EICALL"))
194          (const_int 1)
196          (and (eq_attr "isa" "lpm")
197               (match_test "!AVR_HAVE_LPMX"))
198          (const_int 1)
200          (and (eq_attr "isa" "lpmx")
201               (match_test "AVR_HAVE_LPMX"))
202          (const_int 1)
204          (and (eq_attr "isa" "elpm")
205               (match_test "AVR_HAVE_ELPM && !AVR_HAVE_ELPMX"))
206          (const_int 1)
208          (and (eq_attr "isa" "elpmx")
209               (match_test "AVR_HAVE_ELPMX"))
210          (const_int 1)
212          (and (eq_attr "isa" "xmega")
213               (match_test "AVR_XMEGA"))
214          (const_int 1)
216          (and (eq_attr "isa" "no_xmega")
217               (match_test "!AVR_XMEGA"))
218          (const_int 1)
219          ] (const_int 0)))
222 ;; Define mode iterators
223 (define_mode_iterator QIHI  [QI HI])
224 (define_mode_iterator QIHI2 [QI HI])
225 (define_mode_iterator QISI  [QI HI PSI SI])
226 (define_mode_iterator QIDI  [QI HI PSI SI DI])
227 (define_mode_iterator HISI  [HI PSI SI])
229 (define_mode_iterator ALL1 [QI QQ UQQ])
230 (define_mode_iterator ALL2 [HI HQ UHQ HA UHA])
231 (define_mode_iterator ALL4 [SI SQ USQ SA USA])
233 ;; All supported move-modes
234 (define_mode_iterator MOVMODE [QI QQ UQQ
235                                HI HQ UHQ HA UHA
236                                SI SQ USQ SA USA
237                                SF PSI])
239 ;; Supported ordered modes that are 2, 3, 4 bytes wide
240 (define_mode_iterator ORDERED234 [HI SI PSI
241                                   HQ UHQ HA UHA
242                                   SQ USQ SA USA])
244 ;; Define code iterators
245 ;; Define two incarnations so that we can build the cross product.
246 (define_code_iterator any_extend  [sign_extend zero_extend])
247 (define_code_iterator any_extend2 [sign_extend zero_extend])
249 (define_code_iterator xior [xor ior])
250 (define_code_iterator eqne [eq ne])
252 (define_code_iterator ss_addsub [ss_plus ss_minus])
253 (define_code_iterator us_addsub [us_plus us_minus])
254 (define_code_iterator ss_abs_neg [ss_abs ss_neg])
256 ;; Define code attributes
257 (define_code_attr extend_su
258   [(sign_extend "s")
259    (zero_extend "u")])
261 (define_code_attr extend_u
262   [(sign_extend "")
263    (zero_extend "u")])
265 (define_code_attr extend_s
266   [(sign_extend "s")
267    (zero_extend "")])
269 ;; Constrain input operand of widening multiply, i.e. MUL resp. MULS.
270 (define_code_attr mul_r_d
271   [(zero_extend "r")
272    (sign_extend "d")])
274 (define_code_attr abelian
275   [(ss_minus "") (us_minus "")
276    (ss_plus "%") (us_plus "%")])
278 ;; Map RTX code to its standard insn name
279 (define_code_attr code_stdname
280   [(ashift   "ashl")
281    (ashiftrt "ashr")
282    (lshiftrt "lshr")
283    (ior      "ior")
284    (xor      "xor")
285    (rotate   "rotl")
286    (ss_plus  "ssadd")  (ss_minus "sssub")  (ss_neg "ssneg")  (ss_abs "ssabs")
287    (us_plus  "usadd")  (us_minus "ussub")  (us_neg "usneg")
288    ])
290 ;;========================================================================
291 ;; The following is used by nonlocal_goto and setjmp.
292 ;; The receiver pattern will create no instructions since internally
293 ;; virtual_stack_vars = hard_frame_pointer + 1 so the RTL become R28=R28
294 ;; This avoids creating add/sub offsets in frame_pointer save/resore.
295 ;; The 'null' receiver also avoids  problems with optimisation
296 ;; not recognising incoming jmp and removing code that resets frame_pointer.
297 ;; The code derived from builtins.c.
299 (define_expand "nonlocal_goto_receiver"
300   [(set (reg:HI REG_Y) 
301         (unspec_volatile:HI [(const_int 0)] UNSPECV_GOTO_RECEIVER))]
302   ""
303   {
304     emit_move_insn (virtual_stack_vars_rtx, 
305                     gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, 
306                                   gen_int_mode (STARTING_FRAME_OFFSET,
307                                                 Pmode)));
308     /* ; This might change the hard frame pointer in ways that aren't
309        ; apparent to early optimization passes, so force a clobber.  */
310     emit_clobber (hard_frame_pointer_rtx);
311     DONE;
312   })
313   
315 ;; Defining nonlocal_goto_receiver means we must also define this.
316 ;; even though its function is identical to that in builtins.c
318 (define_expand "nonlocal_goto"
319   [(use (match_operand 0 "general_operand"))
320    (use (match_operand 1 "general_operand"))
321    (use (match_operand 2 "general_operand"))
322    (use (match_operand 3 "general_operand"))]
323   ""
324   {
325     rtx r_label = copy_to_reg (operands[1]);
326     rtx r_fp = operands[3];
327     rtx r_sp = operands[2];
329     emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
331     emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
333     emit_move_insn (hard_frame_pointer_rtx, r_fp);
334     emit_stack_restore (SAVE_NONLOCAL, r_sp);
336     emit_use (hard_frame_pointer_rtx);
337     emit_use (stack_pointer_rtx);
339     emit_indirect_jump (r_label);
341     DONE;
342   })
344 ;; "pushqi1"
345 ;; "pushqq1"  "pushuqq1"
346 (define_insn "push<mode>1"
347   [(set (mem:ALL1 (post_dec:HI (reg:HI REG_SP)))
348         (match_operand:ALL1 0 "reg_or_0_operand" "r,Y00"))]
349   ""
350   "@
351         push %0
352         push __zero_reg__"
353   [(set_attr "length" "1,1")])
355 ;; All modes for a multi-byte push.  We must include complex modes here too,
356 ;; lest emit_single_push_insn "helpfully" create the auto-inc itself.
357 (define_mode_iterator MPUSH
358   [CQI
359    HI CHI HA UHA HQ UHQ
360    SI CSI SA USA SQ USQ
361    DI CDI DA UDA DQ UDQ
362    TA UTA
363    SF SC
364    PSI])
366 (define_expand "push<mode>1"
367   [(match_operand:MPUSH 0 "" "")]
368   ""
369   {
370     int i;
371     for (i = GET_MODE_SIZE (<MODE>mode) - 1; i >= 0; --i)
372       {
373         rtx part = simplify_gen_subreg (QImode, operands[0], <MODE>mode, i);
374         if (part != const0_rtx)
375           part = force_reg (QImode, part);
376         emit_insn (gen_pushqi1 (part));
377       }
378     DONE;
379   })
381 ;; Notice a special-case when adding N to SP where N results in a
382 ;; zero REG_ARGS_SIZE.  This is equivalent to a move from FP.
383 (define_split
384   [(set (reg:HI REG_SP)
385         (match_operand:HI 0 "register_operand" ""))]
386   "reload_completed
387    && frame_pointer_needed
388    && !cfun->calls_alloca
389    && find_reg_note (insn, REG_ARGS_SIZE, const0_rtx)"
390   [(set (reg:HI REG_SP)
391         (reg:HI REG_Y))])
393 ;;========================================================================
394 ;; Move stuff around
396 ;; Represent a load from __flash that needs libgcc support as UNSPEC.
397 ;; This is legal because we read from non-changing memory.
398 ;; For rationale see the FIXME below.
400 ;; "load_psi_libgcc"    
401 ;; "load_si_libgcc"    
402 ;; "load_sf_libgcc"    
403 (define_insn "load_<mode>_libgcc"
404   [(set (reg:MOVMODE 22)
405         (unspec:MOVMODE [(reg:HI REG_Z)]
406                         UNSPEC_LPM))]
407   ""
408   {
409     rtx n_bytes = GEN_INT (GET_MODE_SIZE (<MODE>mode));
410     output_asm_insn ("%~call __load_%0", &n_bytes);
411     return "";
412   }
413   [(set_attr "type" "xcall")
414    (set_attr "cc" "clobber")])
417 ;; Similar for inline reads from flash.  We use UNSPEC instead
418 ;; of MEM for the same reason as above: PR52543.
419 ;; $1 contains the memory segment.
421 (define_insn "load_<mode>"
422   [(set (match_operand:MOVMODE 0 "register_operand" "=r")
423         (unspec:MOVMODE [(reg:HI REG_Z)
424                          (match_operand:QI 1 "reg_or_0_operand" "rL")]
425                         UNSPEC_LPM))]
426   "(CONST_INT_P (operands[1]) && AVR_HAVE_LPMX)
427    || (REG_P (operands[1]) && AVR_HAVE_ELPMX)"
428   {
429     return avr_load_lpm (insn, operands, NULL);
430   }
431   [(set_attr "adjust_len" "load_lpm")
432    (set_attr "cc" "clobber")])
435 ;; Similar to above for the complementary situation when there is no [E]LPMx.
436 ;; Clobber Z in that case.
438 (define_insn "load_<mode>_clobber"
439   [(set (match_operand:MOVMODE 0 "register_operand" "=r")
440         (unspec:MOVMODE [(reg:HI REG_Z)
441                          (match_operand:QI 1 "reg_or_0_operand" "rL")]
442                         UNSPEC_LPM))
443    (clobber (reg:HI REG_Z))]
444   "!((CONST_INT_P (operands[1]) && AVR_HAVE_LPMX)
445      || (REG_P (operands[1]) && AVR_HAVE_ELPMX))"
446   {
447     return avr_load_lpm (insn, operands, NULL);
448   }
449   [(set_attr "adjust_len" "load_lpm")
450    (set_attr "cc" "clobber")])
453 ;; "xload8qi_A"
454 ;; "xload8qq_A" "xload8uqq_A"
455 (define_insn_and_split "xload8<mode>_A"
456   [(set (match_operand:ALL1 0 "register_operand" "=r")
457         (match_operand:ALL1 1 "memory_operand"    "m"))
458    (clobber (reg:HI REG_Z))]
459   "can_create_pseudo_p()
460    && !avr_xload_libgcc_p (<MODE>mode)
461    && avr_mem_memx_p (operands[1])
462    && REG_P (XEXP (operands[1], 0))"
463   { gcc_unreachable(); }
464   "&& 1"
465   [(clobber (const_int 0))]
466   {
467     rtx insn, addr = XEXP (operands[1], 0);
468     rtx hi8 = gen_reg_rtx (QImode);
469     rtx reg_z = gen_rtx_REG (HImode, REG_Z);
471     emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0));
472     emit_move_insn (hi8, simplify_gen_subreg (QImode, addr, PSImode, 2));
474     insn = emit_insn (gen_xload<mode>_8 (operands[0], hi8));
475     set_mem_addr_space (SET_SRC (single_set (insn)),
476                                  MEM_ADDR_SPACE (operands[1]));
477     DONE;
478   })
480 ;; "xloadqi_A" "xloadqq_A" "xloaduqq_A"
481 ;; "xloadhi_A" "xloadhq_A" "xloaduhq_A" "xloadha_A" "xloaduha_A"
482 ;; "xloadsi_A" "xloadsq_A" "xloadusq_A" "xloadsa_A" "xloadusa_A"
483 ;; "xloadpsi_A"
484 ;; "xloadsf_A"
485 (define_insn_and_split "xload<mode>_A"
486   [(set (match_operand:MOVMODE 0 "register_operand" "=r")
487         (match_operand:MOVMODE 1 "memory_operand"    "m"))
488    (clobber (reg:MOVMODE 22))
489    (clobber (reg:QI 21))
490    (clobber (reg:HI REG_Z))]
491   "can_create_pseudo_p()
492    && avr_mem_memx_p (operands[1])
493    && REG_P (XEXP (operands[1], 0))"
494   { gcc_unreachable(); }
495   "&& 1"
496   [(clobber (const_int 0))]
497   {
498     rtx addr = XEXP (operands[1], 0);
499     rtx reg_z = gen_rtx_REG (HImode, REG_Z);
500     rtx addr_hi8 = simplify_gen_subreg (QImode, addr, PSImode, 2);
501     addr_space_t as = MEM_ADDR_SPACE (operands[1]);
502     rtx insn;
504     /* Split the address to R21:Z */
505     emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0));
506     emit_move_insn (gen_rtx_REG (QImode, 21), addr_hi8);
508     /* Load with code from libgcc */
509     insn = emit_insn (gen_xload_<mode>_libgcc ());
510     set_mem_addr_space (SET_SRC (single_set (insn)), as);
512     /* Move to destination */
513     emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, 22));
515     DONE;
516   })
518 ;; Move value from address space memx to a register
519 ;; These insns must be prior to respective generic move insn.
521 ;; "xloadqi_8"
522 ;; "xloadqq_8" "xloaduqq_8"
523 (define_insn "xload<mode>_8"
524   [(set (match_operand:ALL1 0 "register_operand"                   "=&r,r")
525         (mem:ALL1 (lo_sum:PSI (match_operand:QI 1 "register_operand" "r,r")
526                               (reg:HI REG_Z))))]
527   "!avr_xload_libgcc_p (<MODE>mode)"
528   {
529     return avr_out_xload (insn, operands, NULL);
530   }
531   [(set_attr "length" "4,4")
532    (set_attr "adjust_len" "*,xload")
533    (set_attr "isa" "lpmx,lpm")
534    (set_attr "cc" "none")])
536 ;; R21:Z : 24-bit source address
537 ;; R22   : 1-4 byte output
539 ;; "xload_qi_libgcc" "xload_qq_libgcc" "xload_uqq_libgcc"
540 ;; "xload_hi_libgcc" "xload_hq_libgcc" "xload_uhq_libgcc" "xload_ha_libgcc" "xload_uha_libgcc"
541 ;; "xload_si_libgcc" "xload_sq_libgcc" "xload_usq_libgcc" "xload_sa_libgcc" "xload_usa_libgcc"
542 ;; "xload_sf_libgcc"
543 ;; "xload_psi_libgcc"
544 (define_insn "xload_<mode>_libgcc"
545   [(set (reg:MOVMODE 22)
546         (mem:MOVMODE (lo_sum:PSI (reg:QI 21)
547                                  (reg:HI REG_Z))))
548    (clobber (reg:QI 21))
549    (clobber (reg:HI REG_Z))]
550   "avr_xload_libgcc_p (<MODE>mode)"
551   {
552     rtx x_bytes = GEN_INT (GET_MODE_SIZE (<MODE>mode));
554     output_asm_insn ("%~call __xload_%0", &x_bytes);
555     return "";
556   }
557   [(set_attr "type" "xcall")
558    (set_attr "cc" "clobber")])
561 ;; General move expanders
563 ;; "movqi" "movqq" "movuqq"
564 ;; "movhi" "movhq" "movuhq" "movha" "movuha"
565 ;; "movsi" "movsq" "movusq" "movsa" "movusa"
566 ;; "movsf"
567 ;; "movpsi"
568 (define_expand "mov<mode>"
569   [(set (match_operand:MOVMODE 0 "nonimmediate_operand" "")
570         (match_operand:MOVMODE 1 "general_operand" ""))]
571   ""
572   {
573     rtx dest = operands[0];
574     rtx src  = operands[1]; 
575     
576     if (avr_mem_flash_p (dest))
577       DONE;
578   
579     /* One of the operands has to be in a register.  */
580     if (!register_operand (dest, <MODE>mode)
581         && !reg_or_0_operand (src, <MODE>mode))
582       {
583         operands[1] = src = copy_to_mode_reg (<MODE>mode, src);
584       }
586   if (avr_mem_memx_p (src))
587     {
588       rtx addr = XEXP (src, 0);
590       if (!REG_P (addr))
591         src = replace_equiv_address (src, copy_to_mode_reg (PSImode, addr));
593       if (!avr_xload_libgcc_p (<MODE>mode))
594         /* ; No <mode> here because gen_xload8<mode>_A only iterates over ALL1.
595            ; insn-emit does not depend on the mode, it' all about operands.  */
596         emit_insn (gen_xload8qi_A (dest, src));
597       else
598         emit_insn (gen_xload<mode>_A (dest, src));
600       DONE;
601     }
603     /* For old devices without LPMx, prefer __flash loads per libcall.  */
605     if (avr_load_libgcc_p (src))
606       {
607         emit_move_insn (gen_rtx_REG (Pmode, REG_Z),
608                         force_reg (Pmode, XEXP (src, 0)));
610         emit_insn (gen_load_<mode>_libgcc ());
611         emit_move_insn (dest, gen_rtx_REG (<MODE>mode, 22));
612         DONE;
613       }
615     /* ; FIXME:  Hack around PR rtl-optimization/52543.
616        ; lower-subreg.c splits loads from the 16-bit address spaces which
617        ; causes code bloat because each load need his setting of RAMPZ.
618        ; Moreover, the split will happen in such a way that the loads don't
619        ; take advantage of POST_INC addressing.  Thus, we use UNSPEC to
620        ; represent these loads instead.  Notice that this is legitimate
621        ; because the memory content does not change:  Loads from the same
622        ; address will yield the same value.
623        ; POST_INC addressing would make the addresses mode_dependent and could
624        ; work around that PR, too.  However, notice that it is *not* legitimate
625        ; to expand to POST_INC at expand time:  The following passes assert
626        ; that pre-/post-modify addressing is introduced by .auto_inc_dec and
627        ; does not exist before that pass.  */
629     if (avr_mem_flash_p (src)
630         && (GET_MODE_SIZE (<MODE>mode) > 1
631             || MEM_ADDR_SPACE (src) != ADDR_SPACE_FLASH))
632       {
633         rtx xsegment = GEN_INT (avr_addrspace[MEM_ADDR_SPACE (src)].segment);
634         if (!AVR_HAVE_ELPM)
635           xsegment = const0_rtx;
636         if (xsegment != const0_rtx)
637           xsegment = force_reg (QImode, xsegment);
639         emit_move_insn (gen_rtx_REG (Pmode, REG_Z),
640                         force_reg (Pmode, XEXP (src, 0)));
642         if ((CONST_INT_P (xsegment) && AVR_HAVE_LPMX)
643             || (REG_P (xsegment) && AVR_HAVE_ELPMX))
644           emit_insn (gen_load_<mode> (dest, xsegment));
645         else
646           emit_insn (gen_load_<mode>_clobber (dest, xsegment));
647         DONE;
648       }
650     /* ; The only address-space for which we use plain MEM and reload
651        ; machinery are 1-byte loads from __flash.  */
652   })
654 ;;========================================================================
655 ;; move byte
656 ;; The last alternative (any immediate constant to any register) is
657 ;; very expensive.  It should be optimized by peephole2 if a scratch
658 ;; register is available, but then that register could just as well be
659 ;; allocated for the variable we are loading.  But, most of NO_LD_REGS
660 ;; are call-saved registers, and most of LD_REGS are call-used registers,
661 ;; so this may still be a win for registers live across function calls.
663 ;; "movqi_insn"
664 ;; "movqq_insn" "movuqq_insn"
665 (define_insn "mov<mode>_insn"
666   [(set (match_operand:ALL1 0 "nonimmediate_operand" "=r    ,d    ,Qm   ,r ,q,r,*r")
667         (match_operand:ALL1 1 "nox_general_operand"   "r Y00,n Ynn,r Y00,Qm,r,q,i"))]
668   "register_operand (operands[0], <MODE>mode)
669    || reg_or_0_operand (operands[1], <MODE>mode)"
670   {
671     return output_movqi (insn, operands, NULL);
672   }
673   [(set_attr "length" "1,1,5,5,1,1,4")
674    (set_attr "adjust_len" "mov8")
675    (set_attr "cc" "ldi,none,clobber,clobber,none,none,clobber")])
677 ;; This is used in peephole2 to optimize loading immediate constants
678 ;; if a scratch register from LD_REGS happens to be available.
680 ;; "*reload_inqi"
681 ;; "*reload_inqq" "*reload_inuqq"
682 (define_insn "*reload_in<mode>"
683   [(set (match_operand:ALL1 0 "register_operand"    "=l")
684         (match_operand:ALL1 1 "const_operand"        "i"))
685    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
686   "reload_completed"
687   "ldi %2,lo8(%1)
688         mov %0,%2"
689   [(set_attr "length" "2")
690    (set_attr "cc" "none")])
692 (define_peephole2
693   [(match_scratch:QI 2 "d")
694    (set (match_operand:ALL1 0 "l_register_operand" "")
695         (match_operand:ALL1 1 "const_operand" ""))]
696   ; No need for a clobber reg for 0x0, 0x01 or 0xff
697   "!satisfies_constraint_Y00 (operands[1])
698    && !satisfies_constraint_Y01 (operands[1])
699    && !satisfies_constraint_Ym1 (operands[1])"
700   [(parallel [(set (match_dup 0)
701                    (match_dup 1))
702               (clobber (match_dup 2))])])
704 ;;============================================================================
705 ;; move word (16 bit)
707 ;; Move register $1 to the Stack Pointer register SP.
708 ;; This insn is emit during function prologue/epilogue generation.
709 ;;    $2 =  0: We know that IRQs are off
710 ;;    $2 =  1: We know that IRQs are on
711 ;;    $2 =  2: SP has 8 bits only, IRQ state does not matter
712 ;;    $2 = -1: We don't know anything about IRQ on/off
713 ;; Always write SP via unspec, see PR50063
715 (define_insn "movhi_sp_r"
716   [(set (match_operand:HI 0 "stack_register_operand"                "=q,q,q,q,q")
717         (unspec_volatile:HI [(match_operand:HI 1 "register_operand"  "r,r,r,r,r")
718                              (match_operand:HI 2 "const_int_operand" "L,P,N,K,LPN")]
719                             UNSPECV_WRITE_SP))]
720   ""
721   "@
722         out %B0,%B1\;out %A0,%A1
723         cli\;out %B0,%B1\;sei\;out %A0,%A1
724         in __tmp_reg__,__SREG__\;cli\;out %B0,%B1\;out __SREG__,__tmp_reg__\;out %A0,%A1
725         out %A0,%A1
726         out %A0,%A1\;out %B0,%B1"
727   [(set_attr "length" "2,4,5,1,2")
728    (set_attr "isa" "no_xmega,no_xmega,no_xmega,*,xmega")
729    (set_attr "cc" "none")])
731 (define_peephole2
732   [(match_scratch:QI 2 "d")
733    (set (match_operand:ALL2 0 "l_register_operand" "")
734         (match_operand:ALL2 1 "const_or_immediate_operand" ""))]
735   "operands[1] != CONST0_RTX (<MODE>mode)"
736   [(parallel [(set (match_dup 0)
737                    (match_dup 1))
738               (clobber (match_dup 2))])])
740 ;; '*' because it is not used in rtl generation, only in above peephole
741 ;; "*reload_inhi"
742 ;; "*reload_inhq" "*reload_inuhq"
743 ;; "*reload_inha" "*reload_inuha"
744 (define_insn "*reload_in<mode>"
745   [(set (match_operand:ALL2 0 "l_register_operand"  "=l")
746         (match_operand:ALL2 1 "immediate_operand"    "i"))
747    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
748   "reload_completed"
749   {
750     return output_reload_inhi (operands, operands[2], NULL);
751   }
752   [(set_attr "length" "4")
753    (set_attr "adjust_len" "reload_in16")
754    (set_attr "cc" "clobber")])
756 ;; "*movhi"
757 ;; "*movhq" "*movuhq"
758 ;; "*movha" "*movuha"
759 (define_insn "*mov<mode>"
760   [(set (match_operand:ALL2 0 "nonimmediate_operand" "=r,r  ,r,m    ,d,*r,q,r")
761         (match_operand:ALL2 1 "nox_general_operand"   "r,Y00,m,r Y00,i,i ,r,q"))]
762   "register_operand (operands[0], <MODE>mode)
763    || reg_or_0_operand (operands[1], <MODE>mode)"
764   {
765     return output_movhi (insn, operands, NULL);
766   }
767   [(set_attr "length" "2,2,6,7,2,6,5,2")
768    (set_attr "adjust_len" "mov16")
769    (set_attr "cc" "none,none,clobber,clobber,none,clobber,none,none")])
771 (define_peephole2 ; movw
772   [(set (match_operand:ALL1 0 "even_register_operand" "")
773         (match_operand:ALL1 1 "even_register_operand" ""))
774    (set (match_operand:ALL1 2 "odd_register_operand" "")
775         (match_operand:ALL1 3 "odd_register_operand" ""))]
776   "AVR_HAVE_MOVW
777    && REGNO (operands[0]) == REGNO (operands[2]) - 1
778    && REGNO (operands[1]) == REGNO (operands[3]) - 1"
779   [(set (match_dup 4)
780         (match_dup 5))]
781   {
782     operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
783     operands[5] = gen_rtx_REG (HImode, REGNO (operands[1]));
784   })
786 (define_peephole2 ; movw_r
787   [(set (match_operand:ALL1 0 "odd_register_operand" "")
788         (match_operand:ALL1 1 "odd_register_operand" ""))
789    (set (match_operand:ALL1 2 "even_register_operand" "")
790         (match_operand:ALL1 3 "even_register_operand" ""))]
791   "AVR_HAVE_MOVW
792    && REGNO (operands[2]) == REGNO (operands[0]) - 1
793    && REGNO (operands[3]) == REGNO (operands[1]) - 1"
794   [(set (match_dup 4)
795         (match_dup 5))]
796   {
797     operands[4] = gen_rtx_REG (HImode, REGNO (operands[2]));
798     operands[5] = gen_rtx_REG (HImode, REGNO (operands[3]));
799   })
801 ;;==========================================================================
802 ;; xpointer move (24 bit)
803   
804 (define_peephole2 ; *reload_inpsi
805   [(match_scratch:QI 2 "d")
806    (set (match_operand:PSI 0 "l_register_operand" "")
807         (match_operand:PSI 1 "immediate_operand" ""))
808    (match_dup 2)]
809   "operands[1] != const0_rtx
810    && operands[1] != constm1_rtx"
811   [(parallel [(set (match_dup 0)
812                    (match_dup 1))
813               (clobber (match_dup 2))])])
814   
815 ;; '*' because it is not used in rtl generation.
816 (define_insn "*reload_inpsi"
817   [(set (match_operand:PSI 0 "register_operand" "=r")
818         (match_operand:PSI 1 "immediate_operand" "i"))
819    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
820   "reload_completed"
821   {
822     return avr_out_reload_inpsi (operands, operands[2], NULL);
823   }
824   [(set_attr "length" "6")
825    (set_attr "adjust_len" "reload_in24")
826    (set_attr "cc" "clobber")])
828 (define_insn "*movpsi"
829   [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
830         (match_operand:PSI 1 "nox_general_operand"   "r,L,Qm,rL,i ,i"))]
831   "register_operand (operands[0], PSImode)
832    || register_operand (operands[1], PSImode)
833    || const0_rtx == operands[1]"
834   {
835     return avr_out_movpsi (insn, operands, NULL);
836   }
837   [(set_attr "length" "3,3,8,9,4,10")
838    (set_attr "adjust_len" "mov24")
839    (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
840   
841 ;;==========================================================================
842 ;; move double word (32 bit)
844 (define_peephole2 ; *reload_insi
845   [(match_scratch:QI 2 "d")
846    (set (match_operand:ALL4 0 "l_register_operand" "")
847         (match_operand:ALL4 1 "immediate_operand" ""))
848    (match_dup 2)]
849   "operands[1] != CONST0_RTX (<MODE>mode)"
850   [(parallel [(set (match_dup 0)
851                    (match_dup 1))
852               (clobber (match_dup 2))])])
854 ;; '*' because it is not used in rtl generation.
855 ;; "*reload_insi"
856 ;; "*reload_insq" "*reload_inusq"
857 ;; "*reload_insa" "*reload_inusa"
858 (define_insn "*reload_insi"
859   [(set (match_operand:ALL4 0 "register_operand"   "=r")
860         (match_operand:ALL4 1 "immediate_operand"   "n Ynn"))
861    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
862   "reload_completed"
863   {
864     return output_reload_insisf (operands, operands[2], NULL);
865   }
866   [(set_attr "length" "8")
867    (set_attr "adjust_len" "reload_in32")
868    (set_attr "cc" "clobber")])
871 ;; "*movsi"
872 ;; "*movsq" "*movusq"
873 ;; "*movsa" "*movusa"
874 (define_insn "*mov<mode>"
875   [(set (match_operand:ALL4 0 "nonimmediate_operand" "=r,r  ,r ,Qm   ,!d,r")
876         (match_operand:ALL4 1 "nox_general_operand"   "r,Y00,Qm,r Y00,i ,i"))]
877   "register_operand (operands[0], <MODE>mode)
878    || reg_or_0_operand (operands[1], <MODE>mode)"
879   {
880     return output_movsisf (insn, operands, NULL);
881   }
882   [(set_attr "length" "4,4,8,9,4,10")
883    (set_attr "adjust_len" "mov32")
884    (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
886 ;; fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
887 ;; move floating point numbers (32 bit)
889 (define_insn "*movsf"
890   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
891         (match_operand:SF 1 "nox_general_operand"   "r,G,Qm,rG,F ,F"))]
892   "register_operand (operands[0], SFmode)
893    || reg_or_0_operand (operands[1], SFmode)"
894   {
895     return output_movsisf (insn, operands, NULL);
896   }
897   [(set_attr "length" "4,4,8,9,4,10")
898    (set_attr "adjust_len" "mov32")
899    (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
901 (define_peephole2 ; *reload_insf
902   [(match_scratch:QI 2 "d")
903    (set (match_operand:SF 0 "l_register_operand" "")
904         (match_operand:SF 1 "const_double_operand" ""))
905    (match_dup 2)]
906   "operands[1] != CONST0_RTX (SFmode)"
907   [(parallel [(set (match_dup 0) 
908                    (match_dup 1))
909               (clobber (match_dup 2))])])
911 ;; '*' because it is not used in rtl generation.
912 (define_insn "*reload_insf"
913   [(set (match_operand:SF 0 "register_operand" "=r")
914         (match_operand:SF 1 "const_double_operand" "F"))
915    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
916   "reload_completed"
917   {
918     return output_reload_insisf (operands, operands[2], NULL);
919   }
920   [(set_attr "length" "8")
921    (set_attr "adjust_len" "reload_in32")
922    (set_attr "cc" "clobber")])
924 ;;=========================================================================
925 ;; move string (like memcpy)
927 (define_expand "movmemhi"
928   [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
929                    (match_operand:BLK 1 "memory_operand" ""))
930               (use (match_operand:HI 2 "const_int_operand" ""))
931               (use (match_operand:HI 3 "const_int_operand" ""))])]
932   ""
933   {
934     if (avr_emit_movmemhi (operands))
935       DONE;
936     
937     FAIL;
938   })
940 (define_mode_attr MOVMEM_r_d [(QI "r")
941                               (HI "wd")])
943 ;; $0     : Address Space
944 ;; $1, $2 : Loop register
945 ;; R30    : source address
946 ;; R26    : destination address
948 ;; "movmem_qi"
949 ;; "movmem_hi"
950 (define_insn "movmem_<mode>"
951   [(set (mem:BLK (reg:HI REG_X))
952         (mem:BLK (reg:HI REG_Z)))
953    (unspec [(match_operand:QI 0 "const_int_operand" "n")]
954            UNSPEC_MOVMEM)
955    (use (match_operand:QIHI 1 "register_operand" "<MOVMEM_r_d>"))
956    (clobber (reg:HI REG_X))
957    (clobber (reg:HI REG_Z))
958    (clobber (reg:QI LPM_REGNO))
959    (clobber (match_operand:QIHI 2 "register_operand" "=1"))]
960   ""
961   {
962     return avr_out_movmem (insn, operands, NULL);
963   }
964   [(set_attr "adjust_len" "movmem")
965    (set_attr "cc" "clobber")])
968 ;; $0    : Address Space
969 ;; $1    : RAMPZ RAM address
970 ;; R24   : #bytes and loop register
971 ;; R23:Z : 24-bit source address
972 ;; R26   : 16-bit destination address
974 ;; "movmemx_qi"
975 ;; "movmemx_hi"
976 (define_insn "movmemx_<mode>"
977   [(set (mem:BLK (reg:HI REG_X))
978         (mem:BLK (lo_sum:PSI (reg:QI 23)
979                              (reg:HI REG_Z))))
980    (unspec [(match_operand:QI 0 "const_int_operand" "n")]
981            UNSPEC_MOVMEM)
982    (use (reg:QIHI 24))
983    (clobber (reg:HI REG_X))
984    (clobber (reg:HI REG_Z))
985    (clobber (reg:QI LPM_REGNO))
986    (clobber (reg:HI 24))
987    (clobber (reg:QI 23))
988    (clobber (mem:QI (match_operand:QI 1 "io_address_operand" "n")))]
989   ""
990   "%~call __movmemx_<mode>"
991   [(set_attr "type" "xcall")
992    (set_attr "cc" "clobber")])
995 ;; =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2
996 ;; memset (%0, %2, %1)
998 (define_expand "setmemhi"
999   [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
1000                    (match_operand 2 "const_int_operand" ""))
1001               (use (match_operand:HI 1 "const_int_operand" ""))
1002               (use (match_operand:HI 3 "const_int_operand" ""))
1003               (clobber (match_scratch:HI 4 ""))
1004               (clobber (match_dup 5))])]
1005   ""
1006   {
1007     rtx addr0;
1008     enum machine_mode mode;
1010     /* If value to set is not zero, use the library routine.  */
1011     if (operands[2] != const0_rtx)
1012       FAIL;
1014     if (!CONST_INT_P (operands[1]))
1015       FAIL;
1017     mode = u8_operand (operands[1], VOIDmode) ? QImode : HImode;
1018     operands[5] = gen_rtx_SCRATCH (mode);
1019     operands[1] = copy_to_mode_reg (mode,
1020                                     gen_int_mode (INTVAL (operands[1]), mode));
1021     addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
1022     operands[0] = gen_rtx_MEM (BLKmode, addr0);
1023   })
1026 (define_insn "*clrmemqi"
1027   [(set (mem:BLK (match_operand:HI 0 "register_operand" "e"))
1028         (const_int 0))
1029    (use (match_operand:QI 1 "register_operand" "r"))
1030    (use (match_operand:QI 2 "const_int_operand" "n"))
1031    (clobber (match_scratch:HI 3 "=0"))
1032    (clobber (match_scratch:QI 4 "=&1"))]
1033   ""
1034   "0:\;st %a0+,__zero_reg__\;dec %1\;brne 0b"
1035   [(set_attr "length" "3")
1036    (set_attr "cc" "clobber")])
1039 (define_insn "*clrmemhi"
1040   [(set (mem:BLK (match_operand:HI 0 "register_operand" "e,e"))
1041         (const_int 0))
1042    (use (match_operand:HI 1 "register_operand" "!w,d"))
1043    (use (match_operand:HI 2 "const_int_operand" "n,n"))
1044    (clobber (match_scratch:HI 3 "=0,0"))
1045    (clobber (match_scratch:HI 4 "=&1,&1"))]
1046   ""
1047   "@
1048         0:\;st %a0+,__zero_reg__\;sbiw %A1,1\;brne 0b
1049         0:\;st %a0+,__zero_reg__\;subi %A1,1\;sbci %B1,0\;brne 0b"
1050   [(set_attr "length" "3,4")
1051    (set_attr "cc" "clobber,clobber")])
1053 (define_expand "strlenhi"
1054   [(set (match_dup 4)
1055         (unspec:HI [(match_operand:BLK 1 "memory_operand" "")
1056                     (match_operand:QI 2 "const_int_operand" "")
1057                     (match_operand:HI 3 "immediate_operand" "")]
1058                    UNSPEC_STRLEN))
1059    (set (match_dup 4)
1060         (plus:HI (match_dup 4)
1061                  (const_int -1)))
1062    (parallel [(set (match_operand:HI 0 "register_operand" "")
1063                    (minus:HI (match_dup 4)
1064                              (match_dup 5)))
1065               (clobber (scratch:QI))])]
1066   ""
1067   {
1068     rtx addr;
1069     if (operands[2] != const0_rtx)
1070       FAIL;
1071     addr = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
1072     operands[1] = gen_rtx_MEM (BLKmode, addr); 
1073     operands[5] = addr;
1074     operands[4] = gen_reg_rtx (HImode);
1075   })
1077 (define_insn "*strlenhi"
1078   [(set (match_operand:HI 0 "register_operand"                      "=e")
1079         (unspec:HI [(mem:BLK (match_operand:HI 1 "register_operand"  "0"))
1080                     (const_int 0)
1081                     (match_operand:HI 2 "immediate_operand"          "i")]
1082                    UNSPEC_STRLEN))]
1083   ""
1084   "0:\;ld __tmp_reg__,%a0+\;tst __tmp_reg__\;brne 0b"
1085   [(set_attr "length" "3")
1086    (set_attr "cc" "clobber")])
1088 ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1089 ; add bytes
1091 ;; "addqi3"
1092 ;; "addqq3" "adduqq3"
1093 (define_insn "add<mode>3"
1094   [(set (match_operand:ALL1 0 "register_operand"            "=r,d    ,r  ,r  ,r  ,r")
1095         (plus:ALL1 (match_operand:ALL1 1 "register_operand" "%0,0    ,0  ,0  ,0  ,0")
1096                    (match_operand:ALL1 2 "nonmemory_operand" "r,n Ynn,Y01,Ym1,Y02,Ym2")))]
1097   ""
1098   "@
1099         add %0,%2
1100         subi %0,lo8(-(%2))
1101         inc %0
1102         dec %0
1103         inc %0\;inc %0
1104         dec %0\;dec %0"
1105   [(set_attr "length" "1,1,1,1,2,2")
1106    (set_attr "cc" "set_czn,set_czn,set_zn,set_zn,set_zn,set_zn")])
1108 ;; "addhi3"
1109 ;; "addhq3" "adduhq3"
1110 ;; "addha3" "adduha3"
1111 (define_expand "add<mode>3"
1112   [(set (match_operand:ALL2 0 "register_operand" "")
1113         (plus:ALL2 (match_operand:ALL2 1 "register_operand" "")
1114                    (match_operand:ALL2 2 "nonmemory_or_const_operand" "")))]
1115   ""
1116   {
1117     if (CONST_INT_P (operands[2]))
1118       {
1119         operands[2] = gen_int_mode (INTVAL (operands[2]), HImode);
1121         if (can_create_pseudo_p()
1122             && !stack_register_operand (operands[0], HImode)
1123             && !stack_register_operand (operands[1], HImode)
1124             && !d_register_operand (operands[0], HImode)
1125             && !d_register_operand (operands[1], HImode))
1126           {
1127             emit_insn (gen_addhi3_clobber (operands[0], operands[1], operands[2]));
1128             DONE;
1129           }
1130       }
1132     if (CONST_FIXED_P (operands[2]))
1133       {
1134         emit_insn (gen_add<mode>3_clobber (operands[0], operands[1], operands[2]));
1135         DONE;
1136       }
1137   })
1140 (define_insn "*addhi3_zero_extend"
1141   [(set (match_operand:HI 0 "register_operand"                         "=r")
1142         (plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1143                  (match_operand:HI 2 "register_operand"                 "0")))]
1144   ""
1145   "add %A0,%1\;adc %B0,__zero_reg__"
1146   [(set_attr "length" "2")
1147    (set_attr "cc" "set_n")])
1149 (define_insn "*addhi3_zero_extend1"
1150   [(set (match_operand:HI 0 "register_operand"                         "=r")
1151         (plus:HI (match_operand:HI 1 "register_operand"                 "0")
1152                  (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1153   ""
1154   "add %A0,%2\;adc %B0,__zero_reg__"
1155   [(set_attr "length" "2")
1156    (set_attr "cc" "set_n")])
1158 (define_insn "*addhi3.sign_extend1"
1159   [(set (match_operand:HI 0 "register_operand"                         "=r")
1160         (plus:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "r"))
1161                  (match_operand:HI 2 "register_operand"                 "0")))]
1162   ""
1163   {
1164     return reg_overlap_mentioned_p (operands[0], operands[1])
1165       ? "mov __tmp_reg__,%1\;add %A0,%1\;adc %B0,__zero_reg__\;sbrc __tmp_reg__,7\;dec %B0"
1166       : "add %A0,%1\;adc %B0,__zero_reg__\;sbrc %1,7\;dec %B0";
1167   }
1168   [(set_attr "length" "5")
1169    (set_attr "cc" "clobber")])
1171 (define_insn "*addhi3_sp"
1172   [(set (match_operand:HI 1 "stack_register_operand"           "=q")
1173         (plus:HI (match_operand:HI 2 "stack_register_operand"   "q")
1174                  (match_operand:HI 0 "avr_sp_immediate_operand" "Csp")))]
1175   ""
1176   {
1177     return avr_out_addto_sp (operands, NULL);
1178   }
1179   [(set_attr "length" "6")
1180    (set_attr "adjust_len" "addto_sp")])
1182 ;; "*addhi3"
1183 ;; "*addhq3" "*adduhq3"
1184 ;; "*addha3" "*adduha3"
1185 (define_insn "*add<mode>3"
1186   [(set (match_operand:ALL2 0 "register_operand"                    "=?r,d,!w    ,d")
1187         (plus:ALL2 (match_operand:ALL2 1 "register_operand"          "%0,0,0     ,0")
1188                    (match_operand:ALL2 2 "nonmemory_or_const_operand" "r,s,IJ YIJ,n Ynn")))]
1189   ""
1190   {
1191     return avr_out_plus (insn, operands);
1192   }
1193   [(set_attr "length" "2")
1194    (set_attr "adjust_len" "plus")
1195    (set_attr "cc" "plus")])
1197 ;; Adding a constant to NO_LD_REGS might have lead to a reload of
1198 ;; that constant to LD_REGS.  We don't add a scratch to *addhi3
1199 ;; itself because that insn is special to reload.
1201 (define_peephole2 ; addhi3_clobber
1202   [(set (match_operand:ALL2 0 "d_register_operand" "")
1203         (match_operand:ALL2 1 "const_operand" ""))
1204    (set (match_operand:ALL2 2 "l_register_operand" "")
1205         (plus:ALL2 (match_dup 2)
1206                    (match_dup 0)))]
1207   "peep2_reg_dead_p (2, operands[0])"
1208   [(parallel [(set (match_dup 2)
1209                    (plus:ALL2 (match_dup 2)
1210                               (match_dup 1)))
1211               (clobber (match_dup 3))])]
1212   {
1213     operands[3] = simplify_gen_subreg (QImode, operands[0], <MODE>mode, 0);
1214   })
1216 ;; Same, but with reload to NO_LD_REGS
1217 ;; Combine *reload_inhi with *addhi3
1219 (define_peephole2 ; addhi3_clobber
1220   [(parallel [(set (match_operand:ALL2 0 "l_register_operand" "")
1221                    (match_operand:ALL2 1 "const_operand" ""))
1222               (clobber (match_operand:QI 2 "d_register_operand" ""))])
1223    (set (match_operand:ALL2 3 "l_register_operand" "")
1224         (plus:ALL2 (match_dup 3)
1225                    (match_dup 0)))]
1226   "peep2_reg_dead_p (2, operands[0])"
1227   [(parallel [(set (match_dup 3)
1228                    (plus:ALL2 (match_dup 3)
1229                               (match_dup 1)))
1230               (clobber (match_dup 2))])])
1232 ;; "addhi3_clobber"
1233 ;; "addhq3_clobber" "adduhq3_clobber"
1234 ;; "addha3_clobber" "adduha3_clobber"
1235 (define_insn "add<mode>3_clobber"
1236   [(set (match_operand:ALL2 0 "register_operand"            "=!w    ,d    ,r")
1237         (plus:ALL2 (match_operand:ALL2 1 "register_operand"  "%0    ,0    ,0")
1238                    (match_operand:ALL2 2 "const_operand"     "IJ YIJ,n Ynn,n Ynn")))
1239    (clobber (match_scratch:QI 3                             "=X     ,X    ,&d"))]
1240   ""
1241   {
1242     return avr_out_plus (insn, operands);
1243   }
1244   [(set_attr "length" "4")
1245    (set_attr "adjust_len" "plus")
1246    (set_attr "cc" "plus")])
1249 ;; "addsi3"
1250 ;; "addsq3" "addusq3"
1251 ;; "addsa3" "addusa3"
1252 (define_insn "add<mode>3"
1253   [(set (match_operand:ALL4 0 "register_operand"            "=r,d ,r")
1254         (plus:ALL4 (match_operand:ALL4 1 "register_operand" "%0,0 ,0")
1255                    (match_operand:ALL4 2 "nonmemory_operand" "r,i ,n Ynn")))
1256    (clobber (match_scratch:QI 3                             "=X,X ,&d"))]
1257   ""
1258   {
1259     return avr_out_plus (insn, operands);
1260   }
1261   [(set_attr "length" "4")
1262    (set_attr "adjust_len" "plus")
1263    (set_attr "cc" "plus")])
1265 (define_insn "*addpsi3_zero_extend.qi"
1266   [(set (match_operand:PSI 0 "register_operand"                          "=r")
1267         (plus:PSI (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))
1268                   (match_operand:PSI 2 "register_operand"                 "0")))]
1269   ""
1270   "add %A0,%A1\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__"
1271   [(set_attr "length" "3")
1272    (set_attr "cc" "set_n")])
1274 (define_insn "*addpsi3_zero_extend.hi"
1275   [(set (match_operand:PSI 0 "register_operand"                          "=r")
1276         (plus:PSI (zero_extend:PSI (match_operand:HI 1 "register_operand" "r"))
1277                   (match_operand:PSI 2 "register_operand"                 "0")))]
1278   ""
1279   "add %A0,%A1\;adc %B0,%B1\;adc %C0,__zero_reg__"
1280   [(set_attr "length" "3")
1281    (set_attr "cc" "set_n")])
1283 (define_insn "*addpsi3_sign_extend.hi"
1284   [(set (match_operand:PSI 0 "register_operand"                          "=r")
1285         (plus:PSI (sign_extend:PSI (match_operand:HI 1 "register_operand" "r"))
1286                   (match_operand:PSI 2 "register_operand"                 "0")))]
1287   ""
1288   "add %A0,%1\;adc %B0,%B1\;adc %C0,__zero_reg__\;sbrc %B1,7\;dec %C0"
1289   [(set_attr "length" "5")
1290    (set_attr "cc" "set_n")])
1292 (define_insn "*addsi3_zero_extend"
1293   [(set (match_operand:SI 0 "register_operand"                         "=r")
1294         (plus:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
1295                  (match_operand:SI 2 "register_operand"                 "0")))]
1296   ""
1297   "add %A0,%1\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__"
1298   [(set_attr "length" "4")
1299    (set_attr "cc" "set_n")])
1301 (define_insn "*addsi3_zero_extend.hi"
1302   [(set (match_operand:SI 0 "register_operand"                         "=r")
1303         (plus:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
1304                  (match_operand:SI 2 "register_operand"                 "0")))]
1305   ""
1306   "add %A0,%1\;adc %B0,%B1\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__"
1307   [(set_attr "length" "4")
1308    (set_attr "cc" "set_n")])
1310 (define_insn "addpsi3"
1311   [(set (match_operand:PSI 0 "register_operand"           "=r,d ,d,r")
1312         (plus:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0,0")
1313                   (match_operand:PSI 2 "nonmemory_operand" "r,s ,n,n")))
1314    (clobber (match_scratch:QI 3                           "=X,X ,X,&d"))]
1315   ""
1316   {
1317     return avr_out_plus (insn, operands);
1318   }
1319   [(set_attr "length" "3")
1320    (set_attr "adjust_len" "plus")
1321    (set_attr "cc" "plus")])
1323 (define_insn "subpsi3"
1324   [(set (match_operand:PSI 0 "register_operand"           "=r")
1325         (minus:PSI (match_operand:PSI 1 "register_operand" "0")
1326                    (match_operand:PSI 2 "register_operand" "r")))]
1327   ""
1328   "sub %0,%2\;sbc %B0,%B2\;sbc %C0,%C2"
1329   [(set_attr "length" "3")
1330    (set_attr "cc" "set_czn")])
1332 (define_insn "*subpsi3_zero_extend.qi"
1333   [(set (match_operand:PSI 0 "register_operand"                           "=r")
1334         (minus:PSI (match_operand:SI 1 "register_operand"                  "0")
1335                    (zero_extend:PSI (match_operand:QI 2 "register_operand" "r"))))]
1336   ""
1337   "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__"
1338   [(set_attr "length" "3")
1339    (set_attr "cc" "set_czn")])
1341 (define_insn "*subpsi3_zero_extend.hi"
1342   [(set (match_operand:PSI 0 "register_operand"                           "=r")
1343         (minus:PSI (match_operand:PSI 1 "register_operand"                 "0")
1344                    (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
1345   ""
1346   "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__"
1347   [(set_attr "length" "3")
1348    (set_attr "cc" "set_czn")])
1350 (define_insn "*subpsi3_sign_extend.hi"
1351   [(set (match_operand:PSI 0 "register_operand"                           "=r")
1352         (minus:PSI (match_operand:PSI 1 "register_operand"                 "0")
1353                    (sign_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
1354   ""
1355   "sub %A0,%A2\;sbc %B0,%B2\;sbc %C0,__zero_reg__\;sbrc %B2,7\;inc %C0"
1356   [(set_attr "length" "5")
1357    (set_attr "cc" "set_czn")])
1359 ;-----------------------------------------------------------------------------
1360 ; sub bytes
1362 ;; "subqi3"
1363 ;; "subqq3" "subuqq3"
1364 (define_insn "sub<mode>3"
1365   [(set (match_operand:ALL1 0 "register_operand"                      "=r,d    ,r  ,r  ,r  ,r")
1366         (minus:ALL1 (match_operand:ALL1 1 "register_operand"           "0,0    ,0  ,0  ,0  ,0")
1367                     (match_operand:ALL1 2 "nonmemory_or_const_operand" "r,n Ynn,Y01,Ym1,Y02,Ym2")))]
1368   ""
1369   "@
1370         sub %0,%2
1371         subi %0,lo8(%2)
1372         dec %0
1373         inc %0
1374         dec %0\;dec %0
1375         inc %0\;inc %0"
1376   [(set_attr "length" "1,1,1,1,2,2")
1377    (set_attr "cc" "set_czn,set_czn,set_zn,set_zn,set_zn,set_zn")])
1379 ;; "subhi3"
1380 ;; "subhq3" "subuhq3"
1381 ;; "subha3" "subuha3"
1382 (define_insn "sub<mode>3"
1383   [(set (match_operand:ALL2 0 "register_operand"                      "=r,d    ,*r")
1384         (minus:ALL2 (match_operand:ALL2 1 "register_operand"           "0,0    ,0")
1385                     (match_operand:ALL2 2 "nonmemory_or_const_operand" "r,i Ynn,Ynn")))
1386    (clobber (match_scratch:QI 3                                       "=X,X    ,&d"))]
1387   ""
1388   {
1389     return avr_out_plus (insn, operands);
1390   }
1391   [(set_attr "adjust_len" "plus")
1392    (set_attr "cc" "plus")])
1394 (define_insn "*subhi3_zero_extend1"
1395   [(set (match_operand:HI 0 "register_operand"                          "=r")
1396         (minus:HI (match_operand:HI 1 "register_operand"                 "0")
1397                   (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1398   ""
1399   "sub %A0,%2\;sbc %B0,__zero_reg__"
1400   [(set_attr "length" "2")
1401    (set_attr "cc" "set_czn")])
1403 (define_insn "*subhi3.sign_extend2"
1404   [(set (match_operand:HI 0 "register_operand"                          "=r")
1405         (minus:HI (match_operand:HI 1 "register_operand"                 "0")
1406                   (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1407   ""
1408   {
1409     return reg_overlap_mentioned_p (operands[0], operands[2])
1410       ? "mov __tmp_reg__,%2\;sub %A0,%2\;sbc %B0,__zero_reg__\;sbrc __tmp_reg__,7\;inc %B0"
1411       : "sub %A0,%2\;sbc %B0,__zero_reg__\;sbrc %2,7\;inc %B0";
1412   }
1413   [(set_attr "length" "5")
1414    (set_attr "cc" "clobber")])
1416 ;; "subsi3"
1417 ;; "subsq3" "subusq3"
1418 ;; "subsa3" "subusa3"
1419 (define_insn "sub<mode>3"
1420   [(set (match_operand:ALL4 0 "register_operand"                      "=r,d    ,r")
1421         (minus:ALL4 (match_operand:ALL4 1 "register_operand"           "0,0    ,0")
1422                     (match_operand:ALL4 2 "nonmemory_or_const_operand" "r,n Ynn,Ynn")))
1423    (clobber (match_scratch:QI 3                                       "=X,X    ,&d"))]
1424   ""
1425   {
1426     return avr_out_plus (insn, operands);
1427   }
1428   [(set_attr "adjust_len" "plus")
1429    (set_attr "cc" "plus")])
1431 (define_insn "*subsi3_zero_extend"
1432   [(set (match_operand:SI 0 "register_operand"                          "=r")
1433         (minus:SI (match_operand:SI 1 "register_operand"                 "0")
1434                   (zero_extend:SI (match_operand:QI 2 "register_operand" "r"))))]
1435   ""
1436   "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
1437   [(set_attr "length" "4")
1438    (set_attr "cc" "set_czn")])
1440 (define_insn "*subsi3_zero_extend.hi"
1441   [(set (match_operand:SI 0 "register_operand"                          "=r")
1442         (minus:SI (match_operand:SI 1 "register_operand"                 "0")
1443                   (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1444   ""
1445   "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
1446   [(set_attr "length" "4")
1447    (set_attr "cc" "set_czn")])
1449 ;******************************************************************************
1450 ; mul
1452 (define_expand "mulqi3"
1453   [(set (match_operand:QI 0 "register_operand" "")
1454         (mult:QI (match_operand:QI 1 "register_operand" "")
1455                  (match_operand:QI 2 "register_operand" "")))]
1456   ""
1457   {
1458     if (!AVR_HAVE_MUL)
1459       {
1460         emit_insn (gen_mulqi3_call (operands[0], operands[1], operands[2]));
1461         DONE;
1462       }
1463   })
1465 (define_insn "*mulqi3_enh"
1466   [(set (match_operand:QI 0 "register_operand" "=r")
1467         (mult:QI (match_operand:QI 1 "register_operand" "r")
1468                  (match_operand:QI 2 "register_operand" "r")))]
1469   "AVR_HAVE_MUL"
1470   "mul %1,%2
1471         mov %0,r0
1472         clr r1"
1473   [(set_attr "length" "3")
1474    (set_attr "cc" "clobber")])
1476 (define_expand "mulqi3_call"
1477   [(set (reg:QI 24) (match_operand:QI 1 "register_operand" ""))
1478    (set (reg:QI 22) (match_operand:QI 2 "register_operand" ""))
1479    (parallel [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22)))
1480               (clobber (reg:QI 22))])
1481    (set (match_operand:QI 0 "register_operand" "") (reg:QI 24))])
1483 (define_insn "*mulqi3_call"
1484   [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22)))
1485    (clobber (reg:QI 22))]
1486   "!AVR_HAVE_MUL"
1487   "%~call __mulqi3"
1488   [(set_attr "type" "xcall")
1489    (set_attr "cc" "clobber")])
1491 ;; "umulqi3_highpart"
1492 ;; "smulqi3_highpart"
1493 (define_insn "<extend_su>mulqi3_highpart"
1494   [(set (match_operand:QI 0 "register_operand"                                       "=r")
1495         (truncate:QI
1496          (lshiftrt:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1497                                (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))
1498                       (const_int 8))))]
1499   "AVR_HAVE_MUL"
1500   "mul<extend_s> %1,%2
1501         mov %0,r1
1502         clr __zero_reg__"
1503   [(set_attr "length" "3")
1504    (set_attr "cc" "clobber")])
1505   
1507 ;; Used when expanding div or mod inline for some special values
1508 (define_insn "*subqi3.ashiftrt7"
1509   [(set (match_operand:QI 0 "register_operand"                       "=r")
1510         (minus:QI (match_operand:QI 1 "register_operand"              "0")
1511                   (ashiftrt:QI (match_operand:QI 2 "register_operand" "r")
1512                                (const_int 7))))]
1513   ""
1514   "sbrc %2,7\;inc %0"
1515   [(set_attr "length" "2")
1516    (set_attr "cc" "clobber")])
1518 (define_insn "*addqi3.lt0"
1519   [(set (match_operand:QI 0 "register_operand"                 "=r")
1520         (plus:QI (lt:QI (match_operand:QI 1 "register_operand"  "r")
1521                         (const_int 0))
1522                  (match_operand:QI 2 "register_operand"         "0")))]
1523   ""
1524   "sbrc %1,7\;inc %0"
1525   [(set_attr "length" "2")
1526    (set_attr "cc" "clobber")])
1528 (define_insn "*addhi3.lt0"
1529   [(set (match_operand:HI 0 "register_operand"                   "=w,r")
1530         (plus:HI (lt:HI (match_operand:QI 1 "register_operand"    "r,r")
1531                         (const_int 0))
1532                  (match_operand:HI 2 "register_operand"           "0,0")))
1533    (clobber (match_scratch:QI 3                                  "=X,&1"))]
1534   ""
1535   "@
1536         sbrc %1,7\;adiw %0,1
1537         lsl %1\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__"
1538   [(set_attr "length" "2,3")
1539    (set_attr "cc" "clobber")])
1541 (define_insn "*addpsi3.lt0"
1542   [(set (match_operand:PSI 0 "register_operand"                         "=r")
1543         (plus:PSI (lshiftrt:PSI (match_operand:PSI 1 "register_operand"  "r")
1544                                 (const_int 23))
1545                  (match_operand:PSI 2 "register_operand"                 "0")))]
1546   ""
1547   "mov __tmp_reg__,%C1\;lsl __tmp_reg__
1548         adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__"
1549   [(set_attr "length" "5")
1550    (set_attr "cc" "clobber")])
1552 (define_insn "*addsi3.lt0"
1553   [(set (match_operand:SI 0 "register_operand"                       "=r")
1554         (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"  "r")
1555                               (const_int 31))
1556                  (match_operand:SI 2 "register_operand"               "0")))]
1557   ""
1558   "mov __tmp_reg__,%D1\;lsl __tmp_reg__
1559         adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__"
1560   [(set_attr "length" "6")
1561    (set_attr "cc" "clobber")])
1563 (define_insn "*umulqihi3.call"
1564   [(set (reg:HI 24)
1565         (mult:HI (zero_extend:HI (reg:QI 22))
1566                  (zero_extend:HI (reg:QI 24))))
1567    (clobber (reg:QI 21))
1568    (clobber (reg:HI 22))]
1569   "!AVR_HAVE_MUL"
1570   "%~call __umulqihi3"
1571   [(set_attr "type" "xcall")
1572    (set_attr "cc" "clobber")])
1573   
1574 ;; "umulqihi3"
1575 ;; "mulqihi3"
1576 (define_insn "<extend_u>mulqihi3"
1577   [(set (match_operand:HI 0 "register_operand"                         "=r")
1578         (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1579                  (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>"))))]
1580   "AVR_HAVE_MUL"
1581   "mul<extend_s> %1,%2
1582         movw %0,r0
1583         clr __zero_reg__"
1584   [(set_attr "length" "3")
1585    (set_attr "cc" "clobber")])
1587 (define_insn "usmulqihi3"
1588   [(set (match_operand:HI 0 "register_operand"                         "=r")
1589         (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "a"))
1590                  (sign_extend:HI (match_operand:QI 2 "register_operand" "a"))))]
1591   "AVR_HAVE_MUL"
1592   "mulsu %2,%1
1593         movw %0,r0
1594         clr __zero_reg__"
1595   [(set_attr "length" "3")
1596    (set_attr "cc" "clobber")])
1598 ;; Above insn is not canonicalized by insn combine, so here is a version with
1599 ;; operands swapped.
1601 (define_insn "*sumulqihi3"
1602   [(set (match_operand:HI 0 "register_operand"                         "=r")
1603         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1604                  (zero_extend:HI (match_operand:QI 2 "register_operand" "a"))))]
1605   "AVR_HAVE_MUL"
1606   "mulsu %1,%2
1607         movw %0,r0
1608         clr __zero_reg__"
1609   [(set_attr "length" "3")
1610    (set_attr "cc" "clobber")])
1612 ;; One-extend operand 1
1614 (define_insn "*osmulqihi3"
1615   [(set (match_operand:HI 0 "register_operand"                                        "=&r")
1616         (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "a"))))
1617                  (sign_extend:HI (match_operand:QI 2 "register_operand"                 "a"))))]
1618   "AVR_HAVE_MUL"
1619   "mulsu %2,%1
1620         movw %0,r0
1621         sub %B0,%2
1622         clr __zero_reg__"
1623   [(set_attr "length" "4")
1624    (set_attr "cc" "clobber")])
1626 (define_insn "*oumulqihi3"
1627   [(set (match_operand:HI 0 "register_operand"                                        "=&r")
1628         (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "r"))))
1629                  (zero_extend:HI (match_operand:QI 2 "register_operand"                 "r"))))]
1630   "AVR_HAVE_MUL"
1631   "mul %2,%1
1632         movw %0,r0
1633         sub %B0,%2
1634         clr __zero_reg__"
1635   [(set_attr "length" "4")
1636    (set_attr "cc" "clobber")])
1638 ;******************************************************************************
1639 ; multiply-add/sub QI: $0 = $3 +/- $1*$2
1640 ;******************************************************************************
1642 (define_insn "*maddqi4"
1643   [(set (match_operand:QI 0 "register_operand"                  "=r")
1644         (plus:QI (mult:QI (match_operand:QI 1 "register_operand" "r")
1645                           (match_operand:QI 2 "register_operand" "r"))
1646                  (match_operand:QI 3 "register_operand"          "0")))]
1647   
1648   "AVR_HAVE_MUL"
1649   "mul %1,%2
1650         add %A0,r0
1651         clr __zero_reg__"
1652   [(set_attr "length" "4")
1653    (set_attr "cc" "clobber")])
1655 (define_insn "*msubqi4"
1656   [(set (match_operand:QI 0 "register_operand"                   "=r")
1657         (minus:QI (match_operand:QI 3 "register_operand"          "0")
1658                   (mult:QI (match_operand:QI 1 "register_operand" "r")
1659                            (match_operand:QI 2 "register_operand" "r"))))]
1660   "AVR_HAVE_MUL"
1661   "mul %1,%2
1662         sub %A0,r0
1663         clr __zero_reg__"
1664   [(set_attr "length" "4")
1665    (set_attr "cc" "clobber")])
1667 (define_insn_and_split "*maddqi4.const"
1668   [(set (match_operand:QI 0 "register_operand"                   "=r")
1669         (plus:QI (mult:QI (match_operand:QI 1 "register_operand"  "r")
1670                           (match_operand:QI 2 "const_int_operand" "n"))
1671                  (match_operand:QI 3 "register_operand"           "0")))
1672    (clobber (match_scratch:QI 4                                 "=&d"))]
1673   "AVR_HAVE_MUL"
1674   "#"
1675   "&& reload_completed"
1676   [(set (match_dup 4)
1677         (match_dup 2))
1678    ; *maddqi4
1679    (set (match_dup 0)
1680         (plus:QI (mult:QI (match_dup 1)
1681                           (match_dup 4))
1682                  (match_dup 3)))])
1684 (define_insn_and_split "*msubqi4.const"
1685   [(set (match_operand:QI 0 "register_operand"                    "=r")
1686         (minus:QI (match_operand:QI 3 "register_operand"           "0")
1687                   (mult:QI (match_operand:QI 1 "register_operand"  "r")
1688                            (match_operand:QI 2 "const_int_operand" "n"))))
1689    (clobber (match_scratch:QI 4                                  "=&d"))]
1690   "AVR_HAVE_MUL"
1691   "#"
1692   "&& reload_completed"
1693   [(set (match_dup 4)
1694         (match_dup 2))
1695    ; *msubqi4
1696    (set (match_dup 0)
1697         (minus:QI (match_dup 3)
1698                   (mult:QI (match_dup 1)
1699                            (match_dup 4))))])
1702 ;******************************************************************************
1703 ; multiply-add/sub HI: $0 = $3 +/- $1*$2  with 8-bit values $1, $2
1704 ;******************************************************************************
1706 ;; We don't use standard insns/expanders as they lead to cumbersome code for,
1707 ;; e.g,
1709 ;;     int foo (unsigned char z)
1710 ;;     {
1711 ;;       extern int aInt[];
1712 ;;       return aInt[3*z+2];
1713 ;;     }
1715 ;; because the constant +4 then is added explicitely instead of consuming it
1716 ;; with the aInt symbol.  Therefore, we rely on insn combine which takes costs
1717 ;; into account more accurately and doesn't do burte-force multiply-add/sub.
1718 ;; The implementational effort is the same so we are fine with that approach.
1721 ;; "*maddqihi4"
1722 ;; "*umaddqihi4"
1723 (define_insn "*<extend_u>maddqihi4"
1724   [(set (match_operand:HI 0 "register_operand"                                  "=r")
1725         (plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1726                           (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))
1727                  (match_operand:HI 3 "register_operand"                         "0")))]
1728   
1729   "AVR_HAVE_MUL"
1730   "mul<extend_s> %1,%2
1731         add %A0,r0
1732         adc %B0,r1
1733         clr __zero_reg__"
1734   [(set_attr "length" "4")
1735    (set_attr "cc" "clobber")])
1737 ;; "*msubqihi4"
1738 ;; "*umsubqihi4"
1739 (define_insn "*<extend_u>msubqihi4"
1740   [(set (match_operand:HI 0 "register_operand"                                  "=r")
1741         (minus:HI (match_operand:HI 3 "register_operand"                         "0")
1742                   (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1743                            (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))))]
1744   "AVR_HAVE_MUL"
1745   "mul<extend_s> %1,%2
1746         sub %A0,r0
1747         sbc %B0,r1
1748         clr __zero_reg__"
1749   [(set_attr "length" "4")
1750    (set_attr "cc" "clobber")])
1752 ;; "*usmaddqihi4"
1753 ;; "*sumaddqihi4"
1754 (define_insn "*<any_extend:extend_su><any_extend2:extend_su>msubqihi4"
1755   [(set (match_operand:HI 0 "register_operand"                                  "=r")
1756         (plus:HI (mult:HI (any_extend:HI  (match_operand:QI 1 "register_operand" "a"))
1757                           (any_extend2:HI (match_operand:QI 2 "register_operand" "a")))
1758                  (match_operand:HI 3 "register_operand"                          "0")))]
1759   "AVR_HAVE_MUL
1760    && reload_completed
1761    && <any_extend:CODE> != <any_extend2:CODE>"
1762   {
1763     output_asm_insn (<any_extend:CODE> == SIGN_EXTEND
1764                      ? "mulsu %1,%2" : "mulsu %2,%1", operands);
1766     return "add %A0,r0\;adc %B0,r1\;clr __zero_reg__";
1767   }
1768   [(set_attr "length" "4")
1769    (set_attr "cc" "clobber")])
1771 ;; "*usmsubqihi4"
1772 ;; "*sumsubqihi4"
1773 (define_insn "*<any_extend:extend_su><any_extend2:extend_su>msubqihi4"
1774   [(set (match_operand:HI 0 "register_operand"                                   "=r")
1775         (minus:HI (match_operand:HI 3 "register_operand"                          "0")
1776                   (mult:HI (any_extend:HI  (match_operand:QI 1 "register_operand" "a"))
1777                            (any_extend2:HI (match_operand:QI 2 "register_operand" "a")))))]
1778   "AVR_HAVE_MUL
1779    && reload_completed
1780    && <any_extend:CODE> != <any_extend2:CODE>"
1781   {
1782     output_asm_insn (<any_extend:CODE> == SIGN_EXTEND
1783                      ? "mulsu %1,%2" : "mulsu %2,%1", operands);
1785     return "sub %A0,r0\;sbc %B0,r1\;clr __zero_reg__";
1786   }
1787   [(set_attr "length" "4")
1788    (set_attr "cc" "clobber")])
1790 ;; Handle small constants
1792 ;; Special case of a += 2*b as frequently seen with accesses to int arrays.
1793 ;; This is shorter, faster than MUL and has lower register pressure.
1795 (define_insn_and_split "*umaddqihi4.2"
1796   [(set (match_operand:HI 0 "register_operand"                                  "=r")
1797         (plus:HI (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1798                           (const_int 2))
1799                  (match_operand:HI 2 "register_operand"                          "r")))]
1800   "!reload_completed
1801    && !reg_overlap_mentioned_p (operands[0], operands[1])"
1802   { gcc_unreachable(); }
1803   "&& 1"
1804   [(set (match_dup 0)
1805         (match_dup 2))
1806    ; *addhi3_zero_extend
1807    (set (match_dup 0)
1808         (plus:HI (zero_extend:HI (match_dup 1))
1809                  (match_dup 0)))
1810    ; *addhi3_zero_extend
1811    (set (match_dup 0)
1812         (plus:HI (zero_extend:HI (match_dup 1))
1813                  (match_dup 0)))])
1815 ;; "umaddqihi4.uconst"
1816 ;; "maddqihi4.sconst"
1817 (define_insn_and_split "*<extend_u>maddqihi4.<extend_su>const"
1818   [(set (match_operand:HI 0 "register_operand"                                  "=r")
1819         (plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1820                           (match_operand:HI 2 "<extend_su>8_operand"             "n"))
1821                  (match_operand:HI 3 "register_operand"                          "0")))
1822    (clobber (match_scratch:QI 4                                                 "=&d"))]
1823   "AVR_HAVE_MUL"
1824   "#"
1825   "&& reload_completed"
1826   [(set (match_dup 4)
1827         (match_dup 2))
1828    ; *umaddqihi4 resp. *maddqihi4
1829    (set (match_dup 0)
1830         (plus:HI (mult:HI (any_extend:HI (match_dup 1))
1831                           (any_extend:HI (match_dup 4)))
1832                  (match_dup 3)))]
1833   {
1834     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1835   })
1837 ;; "*umsubqihi4.uconst"
1838 ;; "*msubqihi4.sconst"
1839 (define_insn_and_split "*<extend_u>msubqihi4.<extend_su>const"
1840   [(set (match_operand:HI 0 "register_operand"                                  "=r")
1841         (minus:HI (match_operand:HI 3 "register_operand"                         "0")
1842                   (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1843                            (match_operand:HI 2 "<extend_su>8_operand"            "n"))))
1844    (clobber (match_scratch:QI 4                                                 "=&d"))]
1845   "AVR_HAVE_MUL"
1846   "#"
1847   "&& reload_completed"
1848   [(set (match_dup 4)
1849         (match_dup 2))
1850    ; *umsubqihi4 resp. *msubqihi4
1851    (set (match_dup 0)
1852         (minus:HI (match_dup 3)
1853                   (mult:HI (any_extend:HI (match_dup 1))
1854                            (any_extend:HI (match_dup 4)))))]
1855   {
1856     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1857   })
1859 ;; Same as the insn above, but combiner tries versions canonicalized to ASHIFT
1860 ;; for MULT with power of 2 and skips trying MULT insn above.
1862 (define_insn_and_split "*umsubqihi4.uconst.ashift"
1863   [(set (match_operand:HI 0 "register_operand"                                     "=r")
1864         (minus:HI (match_operand:HI 3 "register_operand"                            "0")
1865                   (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1866                              (match_operand:HI 2 "const_2_to_7_operand"             "n"))))
1867    (clobber (match_scratch:QI 4                                                   "=&d"))]
1868   "AVR_HAVE_MUL"
1869   "#"
1870   "&& reload_completed"
1871   [(set (match_dup 4)
1872         (match_dup 2))
1873    ; *umsubqihi4
1874    (set (match_dup 0)
1875         (minus:HI (match_dup 3)
1876                   (mult:HI (zero_extend:HI (match_dup 1))
1877                            (zero_extend:HI (match_dup 4)))))]
1878   {
1879     operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
1880   })
1882 ;; Same as the insn above, but combiner tries versions canonicalized to ASHIFT
1883 ;; for MULT with power of 2 and skips trying MULT insn above.  We omit 128
1884 ;; because this would require an extra pattern for just one value.
1886 (define_insn_and_split "*msubqihi4.sconst.ashift"
1887   [(set (match_operand:HI 0 "register_operand"                                     "=r")
1888         (minus:HI (match_operand:HI 3 "register_operand"                            "0")
1889                   (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
1890                              (match_operand:HI 2 "const_1_to_6_operand"             "M"))))
1891    (clobber (match_scratch:QI 4                                                   "=&d"))]
1892   "AVR_HAVE_MUL"
1893   "#"
1894   "&& reload_completed"
1895   [(set (match_dup 4)
1896         (match_dup 2))
1897    ; *smsubqihi4
1898    (set (match_dup 0)
1899         (minus:HI (match_dup 3)
1900                   (mult:HI (sign_extend:HI (match_dup 1))
1901                            (sign_extend:HI (match_dup 4)))))]
1902   {
1903     operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
1904   })
1906 ;; For signed/unsigned combinations that require narrow constraint "a"
1907 ;; just provide a pattern if signed/unsigned combination is actually needed.
1909 (define_insn_and_split "*sumaddqihi4.uconst"
1910   [(set (match_operand:HI 0 "register_operand"                                  "=r")
1911         (plus:HI (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1912                           (match_operand:HI 2 "u8_operand"                       "M"))
1913                  (match_operand:HI 3 "register_operand"                          "0")))
1914    (clobber (match_scratch:QI 4                                                "=&a"))]
1915   "AVR_HAVE_MUL
1916    && !s8_operand (operands[2], VOIDmode)"
1917   "#"
1918   "&& reload_completed"
1919   [(set (match_dup 4)
1920         (match_dup 2))
1921    ; *sumaddqihi4
1922    (set (match_dup 0)
1923         (plus:HI (mult:HI (sign_extend:HI (match_dup 1))
1924                           (zero_extend:HI (match_dup 4)))
1925                  (match_dup 3)))]
1926   {
1927     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1928   })
1930 (define_insn_and_split "*sumsubqihi4.uconst"
1931   [(set (match_operand:HI 0 "register_operand"                                   "=r")
1932         (minus:HI (match_operand:HI 3 "register_operand"                          "0")
1933                   (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1934                            (match_operand:HI 2 "u8_operand"                       "M"))))
1935    (clobber (match_scratch:QI 4                                                 "=&a"))]
1936   "AVR_HAVE_MUL
1937    && !s8_operand (operands[2], VOIDmode)"
1938   "#"
1939   "&& reload_completed"
1940   [(set (match_dup 4)
1941         (match_dup 2))
1942    ; *sumsubqihi4
1943    (set (match_dup 0)
1944         (minus:HI (match_dup 3)
1945                   (mult:HI (sign_extend:HI (match_dup 1))
1946                            (zero_extend:HI (match_dup 4)))))]
1947   {
1948     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1949   })
1951 ;******************************************************************************
1952 ; mul HI: $1 = sign/zero-extend, $2 = small constant
1953 ;******************************************************************************
1955 ;; "*muluqihi3.uconst"
1956 ;; "*mulsqihi3.sconst"
1957 (define_insn_and_split "*mul<extend_su>qihi3.<extend_su>const"
1958   [(set (match_operand:HI 0 "register_operand"                         "=r")
1959         (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1960                  (match_operand:HI 2 "<extend_su>8_operand"            "n")))
1961    (clobber (match_scratch:QI 3                                       "=&d"))]
1962   "AVR_HAVE_MUL"
1963   "#"
1964   "&& reload_completed"
1965   [(set (match_dup 3)
1966         (match_dup 2))
1967    ; umulqihi3 resp. mulqihi3
1968    (set (match_dup 0)
1969         (mult:HI (any_extend:HI (match_dup 1))
1970                  (any_extend:HI (match_dup 3))))]
1971   {
1972     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1973   })
1975 (define_insn_and_split "*muluqihi3.sconst"
1976   [(set (match_operand:HI 0 "register_operand"                         "=r")
1977         (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "a"))
1978                  (match_operand:HI 2 "s8_operand"                       "n")))
1979    (clobber (match_scratch:QI 3                                       "=&a"))]
1980   "AVR_HAVE_MUL"
1981   "#"
1982   "&& reload_completed"
1983   [(set (match_dup 3)
1984         (match_dup 2))
1985    ; usmulqihi3
1986    (set (match_dup 0)
1987         (mult:HI (zero_extend:HI (match_dup 1))
1988                  (sign_extend:HI (match_dup 3))))]
1989   {
1990     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1991   })
1993 (define_insn_and_split "*mulsqihi3.uconst"
1994   [(set (match_operand:HI 0 "register_operand"                         "=r")
1995         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1996                  (match_operand:HI 2 "u8_operand"                       "M")))
1997    (clobber (match_scratch:QI 3                                       "=&a"))]
1998   "AVR_HAVE_MUL"
1999   "#"
2000   "&& reload_completed"
2001   [(set (match_dup 3)
2002         (match_dup 2))
2003    ; usmulqihi3
2004    (set (match_dup 0)
2005         (mult:HI (zero_extend:HI (match_dup 3))
2006                  (sign_extend:HI (match_dup 1))))]
2007   {
2008     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
2009   })
2011 (define_insn_and_split "*mulsqihi3.oconst"
2012   [(set (match_operand:HI 0 "register_operand"                        "=&r")
2013         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
2014                  (match_operand:HI 2 "o8_operand"                       "n")))
2015    (clobber (match_scratch:QI 3                                       "=&a"))]
2016   "AVR_HAVE_MUL"
2017   "#"
2018   "&& reload_completed"
2019   [(set (match_dup 3)
2020         (match_dup 2))
2021    ; *osmulqihi3
2022    (set (match_dup 0)
2023         (mult:HI (not:HI (zero_extend:HI (not:QI (match_dup 3))))
2024                  (sign_extend:HI (match_dup 1))))]
2025   {
2026     operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
2027   })
2029 ;; The EXTEND of $1 only appears in combine, we don't see it in expand so that
2030 ;; expand decides to use ASHIFT instead of MUL because ASHIFT costs are cheaper
2031 ;; at that time.  Fix that.
2033 (define_insn "*ashiftqihi2.signx.1"
2034   [(set (match_operand:HI 0 "register_operand"                           "=r,*r")
2035         (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "0,r"))
2036                    (const_int 1)))]
2037   ""
2038   "@
2039         lsl %A0\;sbc %B0,%B0
2040         mov %A0,%1\;lsl %A0\;sbc %B0,%B0"
2041   [(set_attr "length" "2,3")
2042    (set_attr "cc" "clobber")])
2044 (define_insn_and_split "*ashifthi3.signx.const"
2045   [(set (match_operand:HI 0 "register_operand"                           "=r")
2046         (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
2047                    (match_operand:HI 2 "const_2_to_6_operand"             "I")))
2048    (clobber (match_scratch:QI 3                                         "=&d"))]
2049   "AVR_HAVE_MUL"
2050   "#"
2051   "&& reload_completed"
2052   [(set (match_dup 3)
2053         (match_dup 2))
2054    ; mulqihi3
2055    (set (match_dup 0)
2056         (mult:HI (sign_extend:HI (match_dup 1))
2057                  (sign_extend:HI (match_dup 3))))]
2058   {
2059     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
2060   })
2062 (define_insn_and_split "*ashifthi3.signx.const7"
2063   [(set (match_operand:HI 0 "register_operand"                           "=r")
2064         (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
2065                    (const_int 7)))
2066    (clobber (match_scratch:QI 2                                         "=&a"))]
2067   "AVR_HAVE_MUL"
2068   "#"
2069   "&& reload_completed"
2070   [(set (match_dup 2)
2071         (match_dup 3))
2072    ; usmulqihi3
2073    (set (match_dup 0)
2074         (mult:HI (zero_extend:HI (match_dup 2))
2075                  (sign_extend:HI (match_dup 1))))]
2076   {
2077     operands[3] = gen_int_mode (1 << 7, QImode);
2078   })
2080 (define_insn_and_split "*ashifthi3.zerox.const"
2081   [(set (match_operand:HI 0 "register_operand"                           "=r")
2082         (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
2083                    (match_operand:HI 2 "const_2_to_7_operand"             "I")))
2084    (clobber (match_scratch:QI 3                                         "=&d"))]
2085   "AVR_HAVE_MUL"
2086   "#"
2087   "&& reload_completed"
2088   [(set (match_dup 3)
2089         (match_dup 2))
2090    ; umulqihi3
2091    (set (match_dup 0)
2092         (mult:HI (zero_extend:HI (match_dup 1))
2093                  (zero_extend:HI (match_dup 3))))]
2094   {
2095     operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
2096   })
2098 ;******************************************************************************
2099 ; mul HI: $1 = sign-/zero-/one-extend, $2 = reg
2100 ;******************************************************************************
2102 (define_insn "mulsqihi3"
2103   [(set (match_operand:HI 0 "register_operand"                        "=&r")
2104         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
2105                  (match_operand:HI 2 "register_operand"                 "a")))]
2106   "AVR_HAVE_MUL"
2107   "mulsu %1,%A2
2108         movw %0,r0
2109         mul %1,%B2
2110         add %B0,r0
2111         clr __zero_reg__"
2112   [(set_attr "length" "5")
2113    (set_attr "cc" "clobber")])
2115 (define_insn "muluqihi3"
2116   [(set (match_operand:HI 0 "register_operand"                        "=&r")
2117         (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
2118                  (match_operand:HI 2 "register_operand"                 "r")))]
2119   "AVR_HAVE_MUL"
2120   "mul %1,%A2
2121         movw %0,r0
2122         mul %1,%B2
2123         add %B0,r0
2124         clr __zero_reg__"
2125   [(set_attr "length" "5")
2126    (set_attr "cc" "clobber")])
2128 ;; one-extend operand 1
2130 (define_insn "muloqihi3"
2131   [(set (match_operand:HI 0 "register_operand"                                        "=&r")
2132         (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "r"))))
2133                  (match_operand:HI 2 "register_operand"                                 "r")))]
2134   "AVR_HAVE_MUL"
2135   "mul %1,%A2
2136         movw %0,r0
2137         mul %1,%B2
2138         add %B0,r0
2139         sub %B0,%A2
2140         clr __zero_reg__"
2141   [(set_attr "length" "6")
2142    (set_attr "cc" "clobber")])
2144 ;******************************************************************************
2146 (define_expand "mulhi3"
2147   [(set (match_operand:HI 0 "register_operand" "")
2148         (mult:HI (match_operand:HI 1 "register_operand" "")
2149                  (match_operand:HI 2 "register_or_s9_operand" "")))]
2150   ""
2151   {
2152     if (!AVR_HAVE_MUL)
2153       {
2154         if (!register_operand (operands[2], HImode))
2155           operands[2] = force_reg (HImode, operands[2]);
2157         emit_insn (gen_mulhi3_call (operands[0], operands[1], operands[2]));
2158         DONE;
2159       }
2161     /* For small constants we can do better by extending them on the fly.
2162        The constant can be loaded in one instruction and the widening
2163        multiplication is shorter.  First try the unsigned variant because it
2164        allows constraint "d" instead of "a" for the signed version.  */
2166     if (s9_operand (operands[2], HImode))
2167       {
2168         rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
2170         if (u8_operand (operands[2], HImode))
2171           {
2172             emit_insn (gen_muluqihi3 (operands[0], reg, operands[1]));
2173           } 
2174         else if (s8_operand (operands[2], HImode))
2175           {
2176             emit_insn (gen_mulsqihi3 (operands[0], reg, operands[1]));
2177           }
2178         else
2179           {
2180             emit_insn (gen_muloqihi3 (operands[0], reg, operands[1]));
2181           }
2183         DONE;
2184       }
2186     if (!register_operand (operands[2], HImode))
2187       operands[2] = force_reg (HImode, operands[2]);
2188   })
2190 (define_insn "*mulhi3_enh"
2191   [(set (match_operand:HI 0 "register_operand" "=&r")
2192         (mult:HI (match_operand:HI 1 "register_operand" "r")
2193                  (match_operand:HI 2 "register_operand" "r")))]
2194   "AVR_HAVE_MUL"
2195   {
2196     return REGNO (operands[1]) == REGNO (operands[2])
2197            ? "mul %A1,%A1\;movw %0,r0\;mul %A1,%B1\;add %B0,r0\;add %B0,r0\;clr r1"
2198            : "mul %A1,%A2\;movw %0,r0\;mul %A1,%B2\;add %B0,r0\;mul %B1,%A2\;add %B0,r0\;clr r1";
2199   }
2200   [(set_attr "length" "7")
2201    (set_attr "cc" "clobber")])
2203 (define_expand "mulhi3_call"
2204   [(set (reg:HI 24) (match_operand:HI 1 "register_operand" ""))
2205    (set (reg:HI 22) (match_operand:HI 2 "register_operand" ""))
2206    (parallel [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22)))
2207               (clobber (reg:HI 22))
2208               (clobber (reg:QI 21))])
2209    (set (match_operand:HI 0 "register_operand" "") (reg:HI 24))])
2211 (define_insn "*mulhi3_call"
2212   [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22)))
2213    (clobber (reg:HI 22))
2214    (clobber (reg:QI 21))]
2215   "!AVR_HAVE_MUL"
2216   "%~call __mulhi3"
2217   [(set_attr "type" "xcall")
2218    (set_attr "cc" "clobber")])
2220 ;; To support widening multiplication with constant we postpone
2221 ;; expanding to the implicit library call until post combine and
2222 ;; prior to register allocation.  Clobber all hard registers that
2223 ;; might be used by the (widening) multiply until it is split and
2224 ;; it's final register footprint is worked out.
2226 (define_expand "mulsi3"
2227   [(parallel [(set (match_operand:SI 0 "register_operand" "")
2228                    (mult:SI (match_operand:SI 1 "register_operand" "")
2229                             (match_operand:SI 2 "nonmemory_operand" "")))
2230               (clobber (reg:HI 26))
2231               (clobber (reg:DI 18))])]
2232   "AVR_HAVE_MUL"
2233   {
2234     if (u16_operand (operands[2], SImode))
2235       {
2236         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2237         emit_insn (gen_muluhisi3 (operands[0], operands[2], operands[1]));
2238         DONE;
2239       }
2241     if (o16_operand (operands[2], SImode))
2242       {
2243         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2244         emit_insn (gen_mulohisi3 (operands[0], operands[2], operands[1]));
2245         DONE;
2246       }
2247   })
2249 (define_insn_and_split "*mulsi3"
2250   [(set (match_operand:SI 0 "pseudo_register_operand"                      "=r")
2251         (mult:SI (match_operand:SI 1 "pseudo_register_operand"              "r")
2252                  (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn")))
2253    (clobber (reg:HI 26))
2254    (clobber (reg:DI 18))]
2255   "AVR_HAVE_MUL && !reload_completed"
2256   { gcc_unreachable(); }
2257   "&& 1"
2258   [(set (reg:SI 18)
2259         (match_dup 1))
2260    (set (reg:SI 22) 
2261         (match_dup 2))
2262    (parallel [(set (reg:SI 22)
2263                    (mult:SI (reg:SI 22)
2264                             (reg:SI 18)))
2265               (clobber (reg:HI 26))])
2266    (set (match_dup 0)
2267         (reg:SI 22))]
2268   {
2269     if (u16_operand (operands[2], SImode))
2270       {
2271         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2272         emit_insn (gen_muluhisi3 (operands[0], operands[2], operands[1]));
2273         DONE;
2274       }
2276     if (o16_operand (operands[2], SImode))
2277       {
2278         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2279         emit_insn (gen_mulohisi3 (operands[0], operands[2], operands[1]));
2280         DONE;
2281       }
2282   })
2284 ;; "muluqisi3"
2285 ;; "muluhisi3"
2286 (define_insn_and_split "mulu<mode>si3"
2287   [(set (match_operand:SI 0 "pseudo_register_operand"                           "=r")
2288         (mult:SI (zero_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r"))
2289                  (match_operand:SI 2 "pseudo_register_or_const_int_operand"      "rn")))
2290    (clobber (reg:HI 26))
2291    (clobber (reg:DI 18))]
2292   "AVR_HAVE_MUL && !reload_completed"
2293   { gcc_unreachable(); }
2294   "&& 1"
2295   [(set (reg:HI 26)
2296         (match_dup 1))
2297    (set (reg:SI 18)
2298         (match_dup 2))
2299    (set (reg:SI 22)
2300         (mult:SI (zero_extend:SI (reg:HI 26))
2301                  (reg:SI 18)))
2302    (set (match_dup 0)
2303         (reg:SI 22))]
2304   {
2305     /* Do the QI -> HI extension explicitely before the multiplication.  */
2306     /* Do the HI -> SI extension implicitely and after the multiplication.  */
2307        
2308     if (QImode == <MODE>mode)
2309       operands[1] = gen_rtx_ZERO_EXTEND (HImode, operands[1]);
2311     if (u16_operand (operands[2], SImode))
2312       {
2313         operands[1] = force_reg (HImode, operands[1]);
2314         operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2315         emit_insn (gen_umulhisi3 (operands[0], operands[1], operands[2]));
2316         DONE;
2317       }
2318   })
2320 ;; "mulsqisi3"
2321 ;; "mulshisi3"
2322 (define_insn_and_split "muls<mode>si3"
2323   [(set (match_operand:SI 0 "pseudo_register_operand"                           "=r")
2324         (mult:SI (sign_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r"))
2325                  (match_operand:SI 2 "pseudo_register_or_const_int_operand"      "rn")))
2326    (clobber (reg:HI 26))
2327    (clobber (reg:DI 18))]
2328   "AVR_HAVE_MUL && !reload_completed"
2329   { gcc_unreachable(); }
2330   "&& 1"
2331   [(set (reg:HI 26)
2332         (match_dup 1))
2333    (set (reg:SI 18)
2334         (match_dup 2))
2335    (set (reg:SI 22)
2336         (mult:SI (sign_extend:SI (reg:HI 26))
2337                  (reg:SI 18)))
2338    (set (match_dup 0)
2339         (reg:SI 22))]
2340   {
2341     /* Do the QI -> HI extension explicitely before the multiplication.  */
2342     /* Do the HI -> SI extension implicitely and after the multiplication.  */
2343        
2344     if (QImode == <MODE>mode)
2345       operands[1] = gen_rtx_SIGN_EXTEND (HImode, operands[1]);
2347     if (u16_operand (operands[2], SImode)
2348         || s16_operand (operands[2], SImode))
2349       {
2350         rtx xop2 = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2352         operands[1] = force_reg (HImode, operands[1]);
2354         if (u16_operand (operands[2], SImode))
2355           emit_insn (gen_usmulhisi3 (operands[0], xop2, operands[1]));
2356         else
2357           emit_insn (gen_mulhisi3 (operands[0], operands[1], xop2));
2359         DONE;
2360       }
2361   })
2363 ;; One-extend operand 1
2365 (define_insn_and_split "mulohisi3"
2366   [(set (match_operand:SI 0 "pseudo_register_operand"                          "=r")
2367         (mult:SI (not:SI (zero_extend:SI 
2368                           (not:HI (match_operand:HI 1 "pseudo_register_operand" "r"))))
2369                  (match_operand:SI 2 "pseudo_register_or_const_int_operand"     "rn")))
2370    (clobber (reg:HI 26))
2371    (clobber (reg:DI 18))]
2372   "AVR_HAVE_MUL && !reload_completed"
2373   { gcc_unreachable(); }
2374   "&& 1"
2375   [(set (reg:HI 26)
2376         (match_dup 1))
2377    (set (reg:SI 18)
2378         (match_dup 2))
2379    (set (reg:SI 22)
2380         (mult:SI (not:SI (zero_extend:SI (not:HI (reg:HI 26))))
2381                  (reg:SI 18)))
2382    (set (match_dup 0)
2383         (reg:SI 22))])
2385 ;; "mulhisi3"
2386 ;; "umulhisi3"
2387 (define_expand "<extend_u>mulhisi3"
2388   [(parallel [(set (match_operand:SI 0 "register_operand" "")
2389                    (mult:SI (any_extend:SI (match_operand:HI 1 "register_operand" ""))
2390                             (any_extend:SI (match_operand:HI 2 "register_operand" ""))))
2391               (clobber (reg:HI 26))
2392               (clobber (reg:DI 18))])]
2393   "AVR_HAVE_MUL")
2395 (define_expand "usmulhisi3"
2396   [(parallel [(set (match_operand:SI 0 "register_operand" "")
2397                    (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" ""))
2398                             (sign_extend:SI (match_operand:HI 2 "register_operand" ""))))
2399               (clobber (reg:HI 26))
2400               (clobber (reg:DI 18))])]
2401   "AVR_HAVE_MUL")
2403 ;; "*uumulqihisi3" "*uumulhiqisi3" "*uumulhihisi3" "*uumulqiqisi3"
2404 ;; "*usmulqihisi3" "*usmulhiqisi3" "*usmulhihisi3" "*usmulqiqisi3"
2405 ;; "*sumulqihisi3" "*sumulhiqisi3" "*sumulhihisi3" "*sumulqiqisi3"
2406 ;; "*ssmulqihisi3" "*ssmulhiqisi3" "*ssmulhihisi3" "*ssmulqiqisi3"
2407 (define_insn_and_split
2408   "*<any_extend:extend_su><any_extend2:extend_su>mul<QIHI:mode><QIHI2:mode>si3"
2409   [(set (match_operand:SI 0 "pseudo_register_operand"                            "=r")
2410         (mult:SI (any_extend:SI (match_operand:QIHI 1 "pseudo_register_operand"   "r"))
2411                  (any_extend2:SI (match_operand:QIHI2 2 "pseudo_register_operand" "r"))))
2412    (clobber (reg:HI 26))
2413    (clobber (reg:DI 18))]
2414   "AVR_HAVE_MUL && !reload_completed"
2415   { gcc_unreachable(); }
2416   "&& 1"
2417   [(set (reg:HI 18)
2418         (match_dup 1))
2419    (set (reg:HI 26)
2420         (match_dup 2))
2421    (set (reg:SI 22)
2422         (mult:SI (match_dup 3)
2423                  (match_dup 4)))
2424    (set (match_dup 0)
2425         (reg:SI 22))]
2426   {
2427     rtx xop1 = operands[1];
2428     rtx xop2 = operands[2];
2430     /* Do the QI -> HI extension explicitely before the multiplication.  */
2431     /* Do the HI -> SI extension implicitely and after the multiplication.  */
2432        
2433     if (QImode == <QIHI:MODE>mode)
2434       xop1 = gen_rtx_fmt_e (<any_extend:CODE>, HImode, xop1);
2436     if (QImode == <QIHI2:MODE>mode)
2437       xop2 = gen_rtx_fmt_e (<any_extend2:CODE>, HImode, xop2);
2439     if (<any_extend:CODE> == <any_extend2:CODE>
2440         || <any_extend:CODE> == ZERO_EXTEND)
2441       {
2442         operands[1] = xop1;
2443         operands[2] = xop2;
2444         operands[3] = gen_rtx_fmt_e (<any_extend:CODE>, SImode, gen_rtx_REG (HImode, 18));
2445         operands[4] = gen_rtx_fmt_e (<any_extend2:CODE>, SImode, gen_rtx_REG (HImode, 26));
2446       }
2447     else
2448       {
2449         /* <any_extend:CODE>  = SIGN_EXTEND */
2450         /* <any_extend2:CODE> = ZERO_EXTEND */
2452         operands[1] = xop2;
2453         operands[2] = xop1;
2454         operands[3] = gen_rtx_ZERO_EXTEND (SImode, gen_rtx_REG (HImode, 18));
2455         operands[4] = gen_rtx_SIGN_EXTEND (SImode, gen_rtx_REG (HImode, 26));
2456       }
2457   })
2459 ;; "smulhi3_highpart"
2460 ;; "umulhi3_highpart"
2461 (define_expand "<extend_su>mulhi3_highpart"
2462   [(set (reg:HI 18)
2463         (match_operand:HI 1 "nonmemory_operand" ""))
2464    (set (reg:HI 26)
2465         (match_operand:HI 2 "nonmemory_operand" ""))
2466    (parallel [(set (reg:HI 24)
2467                    (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
2468                                                       (any_extend:SI (reg:HI 26)))
2469                                              (const_int 16))))
2470               (clobber (reg:HI 22))])
2471    (set (match_operand:HI 0 "register_operand" "")
2472         (reg:HI 24))]
2473   "AVR_HAVE_MUL")
2476 (define_insn "*mulsi3_call"
2477   [(set (reg:SI 22)
2478         (mult:SI (reg:SI 22)
2479                  (reg:SI 18)))
2480    (clobber (reg:HI 26))]
2481   "AVR_HAVE_MUL"
2482   "%~call __mulsi3"
2483   [(set_attr "type" "xcall")
2484    (set_attr "cc" "clobber")])
2486 ;; "*mulhisi3_call"
2487 ;; "*umulhisi3_call"
2488 (define_insn "*<extend_u>mulhisi3_call"
2489   [(set (reg:SI 22)
2490         (mult:SI (any_extend:SI (reg:HI 18))
2491                  (any_extend:SI (reg:HI 26))))]
2492   "AVR_HAVE_MUL"
2493   "%~call __<extend_u>mulhisi3"
2494   [(set_attr "type" "xcall")
2495    (set_attr "cc" "clobber")])
2497 ;; "*umulhi3_highpart_call"
2498 ;; "*smulhi3_highpart_call"
2499 (define_insn "*<extend_su>mulhi3_highpart_call"
2500   [(set (reg:HI 24)
2501         (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
2502                                            (any_extend:SI (reg:HI 26)))
2503                                   (const_int 16))))
2504    (clobber (reg:HI 22))]
2505   "AVR_HAVE_MUL"
2506   "%~call __<extend_u>mulhisi3"
2507   [(set_attr "type" "xcall")
2508    (set_attr "cc" "clobber")])
2510 (define_insn "*usmulhisi3_call"
2511   [(set (reg:SI 22)
2512         (mult:SI (zero_extend:SI (reg:HI 18))
2513                  (sign_extend:SI (reg:HI 26))))]
2514   "AVR_HAVE_MUL"
2515   "%~call __usmulhisi3"
2516   [(set_attr "type" "xcall")
2517    (set_attr "cc" "clobber")])
2519 (define_insn "*mul<extend_su>hisi3_call"
2520   [(set (reg:SI 22)
2521         (mult:SI (any_extend:SI (reg:HI 26))
2522                  (reg:SI 18)))]
2523   "AVR_HAVE_MUL"
2524   "%~call __mul<extend_su>hisi3"
2525   [(set_attr "type" "xcall")
2526    (set_attr "cc" "clobber")])
2528 (define_insn "*mulohisi3_call"
2529   [(set (reg:SI 22)
2530         (mult:SI (not:SI (zero_extend:SI (not:HI (reg:HI 26))))
2531                  (reg:SI 18)))]
2532   "AVR_HAVE_MUL"
2533   "%~call __mulohisi3"
2534   [(set_attr "type" "xcall")
2535    (set_attr "cc" "clobber")])
2537 ; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / %
2538 ; divmod
2540 ;; Generate lib1funcs.S calls ourselves, because:
2541 ;;  - we know exactly which registers are clobbered (for QI and HI
2542 ;;    modes, some of the call-used registers are preserved)
2543 ;;  - we get both the quotient and the remainder at no extra cost
2544 ;;  - we split the patterns only after the first CSE passes because
2545 ;;    CSE has problems to operate on hard regs.
2546 ;; 
2547 (define_insn_and_split "divmodqi4"
2548   [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "") 
2549                    (div:QI (match_operand:QI 1 "pseudo_register_operand" "") 
2550                            (match_operand:QI 2 "pseudo_register_operand" "")))
2551               (set (match_operand:QI 3 "pseudo_register_operand" "") 
2552                    (mod:QI (match_dup 1) (match_dup 2)))
2553               (clobber (reg:QI 22)) 
2554               (clobber (reg:QI 23)) 
2555               (clobber (reg:QI 24)) 
2556               (clobber (reg:QI 25))])]
2557   ""
2558   "this divmodqi4 pattern should have been splitted;"
2559   ""
2560   [(set (reg:QI 24) (match_dup 1))
2561    (set (reg:QI 22) (match_dup 2))
2562    (parallel [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
2563               (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
2564               (clobber (reg:QI 22))
2565               (clobber (reg:QI 23))])
2566    (set (match_dup 0) (reg:QI 24))
2567    (set (match_dup 3) (reg:QI 25))])
2569 (define_insn "*divmodqi4_call"
2570   [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
2571    (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
2572    (clobber (reg:QI 22))
2573    (clobber (reg:QI 23))]
2574   ""
2575   "%~call __divmodqi4"
2576   [(set_attr "type" "xcall")
2577    (set_attr "cc" "clobber")])
2579 (define_insn_and_split "udivmodqi4"
2580  [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "") 
2581                   (udiv:QI (match_operand:QI 1 "pseudo_register_operand" "") 
2582                            (match_operand:QI 2 "pseudo_register_operand" "")))
2583              (set (match_operand:QI 3 "pseudo_register_operand" "") 
2584                   (umod:QI (match_dup 1) (match_dup 2)))
2585              (clobber (reg:QI 22))
2586              (clobber (reg:QI 23))
2587              (clobber (reg:QI 24))
2588              (clobber (reg:QI 25))])]
2589   ""
2590   "this udivmodqi4 pattern should have been splitted;"
2591   "" 
2592   [(set (reg:QI 24) (match_dup 1))
2593    (set (reg:QI 22) (match_dup 2))
2594    (parallel [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
2595               (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
2596               (clobber (reg:QI 23))])
2597    (set (match_dup 0) (reg:QI 24))
2598    (set (match_dup 3) (reg:QI 25))])
2600 (define_insn "*udivmodqi4_call"
2601   [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
2602    (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
2603    (clobber (reg:QI 23))]
2604   ""
2605   "%~call __udivmodqi4"
2606   [(set_attr "type" "xcall")
2607    (set_attr "cc" "clobber")])
2609 (define_insn_and_split "divmodhi4"
2610   [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "") 
2611                    (div:HI (match_operand:HI 1 "pseudo_register_operand" "") 
2612                            (match_operand:HI 2 "pseudo_register_operand" "")))
2613               (set (match_operand:HI 3 "pseudo_register_operand" "") 
2614                    (mod:HI (match_dup 1) (match_dup 2)))
2615               (clobber (reg:QI 21))
2616               (clobber (reg:HI 22))
2617               (clobber (reg:HI 24))
2618               (clobber (reg:HI 26))])]
2619   ""
2620   "this should have been splitted;"
2621   ""
2622   [(set (reg:HI 24) (match_dup 1))
2623    (set (reg:HI 22) (match_dup 2))
2624    (parallel [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
2625               (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
2626               (clobber (reg:HI 26))
2627               (clobber (reg:QI 21))])
2628    (set (match_dup 0) (reg:HI 22))
2629    (set (match_dup 3) (reg:HI 24))])
2631 (define_insn "*divmodhi4_call"
2632   [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
2633    (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
2634    (clobber (reg:HI 26))
2635    (clobber (reg:QI 21))]
2636   ""
2637   "%~call __divmodhi4"
2638   [(set_attr "type" "xcall")
2639    (set_attr "cc" "clobber")])
2641 (define_insn_and_split "udivmodhi4"
2642   [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "") 
2643                    (udiv:HI (match_operand:HI 1 "pseudo_register_operand" "")
2644                             (match_operand:HI 2 "pseudo_register_operand" "")))
2645               (set (match_operand:HI 3 "pseudo_register_operand" "") 
2646                    (umod:HI (match_dup 1) (match_dup 2)))
2647               (clobber (reg:QI 21))
2648               (clobber (reg:HI 22))
2649               (clobber (reg:HI 24))
2650               (clobber (reg:HI 26))])]
2651   ""
2652   "this udivmodhi4 pattern should have been splitted.;"
2653   ""
2654   [(set (reg:HI 24) (match_dup 1))
2655    (set (reg:HI 22) (match_dup 2))
2656    (parallel [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
2657               (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
2658               (clobber (reg:HI 26))
2659               (clobber (reg:QI 21))])
2660    (set (match_dup 0) (reg:HI 22))
2661    (set (match_dup 3) (reg:HI 24))])
2663 (define_insn "*udivmodhi4_call"
2664   [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
2665    (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
2666    (clobber (reg:HI 26))
2667    (clobber (reg:QI 21))]
2668   ""
2669   "%~call __udivmodhi4"
2670   [(set_attr "type" "xcall")
2671    (set_attr "cc" "clobber")])
2673 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2674 ;; 24-bit multiply
2676 ;; To support widening multiplication with constant we postpone
2677 ;; expanding to the implicit library call until post combine and
2678 ;; prior to register allocation.  Clobber all hard registers that
2679 ;; might be used by the (widening) multiply until it is split and
2680 ;; it's final register footprint is worked out.
2682 (define_expand "mulpsi3"
2683   [(parallel [(set (match_operand:PSI 0 "register_operand" "")
2684                    (mult:PSI (match_operand:PSI 1 "register_operand" "")
2685                              (match_operand:PSI 2 "nonmemory_operand" "")))
2686               (clobber (reg:HI 26))
2687               (clobber (reg:DI 18))])]
2688   "AVR_HAVE_MUL"
2689   {
2690     if (s8_operand (operands[2], PSImode))
2691       {
2692         rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
2693         emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1]));
2694         DONE;
2695       }
2696   })
2698 (define_insn "*umulqihipsi3"
2699   [(set (match_operand:PSI 0 "register_operand"                         "=&r")
2700         (mult:PSI (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))
2701                   (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
2702   "AVR_HAVE_MUL"
2703   "mul %1,%A2
2704         movw %A0,r0
2705         mul %1,%B2
2706         clr %C0
2707         add %B0,r0
2708         adc %C0,r1
2709         clr __zero_reg__"
2710   [(set_attr "length" "7")
2711    (set_attr "cc" "clobber")])
2713 (define_insn "*umulhiqipsi3"
2714   [(set (match_operand:PSI 0 "register_operand"                         "=&r")
2715         (mult:PSI (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))
2716                   (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))))]
2717   "AVR_HAVE_MUL"
2718   "mul %1,%A2
2719         movw %A0,r0
2720         mul %1,%B2
2721         add %B0,r0
2722         mov %C0,r1
2723         clr __zero_reg__
2724         adc %C0,__zero_reg__"
2725   [(set_attr "length" "7")
2726    (set_attr "cc" "clobber")])
2728 (define_insn_and_split "mulsqipsi3"
2729   [(set (match_operand:PSI 0 "pseudo_register_operand"                          "=r")
2730         (mult:PSI (sign_extend:PSI (match_operand:QI 1 "pseudo_register_operand" "r"))
2731                   (match_operand:PSI 2 "pseudo_register_or_const_int_operand"    "rn")))
2732    (clobber (reg:HI 26))
2733    (clobber (reg:DI 18))]
2734   "AVR_HAVE_MUL && !reload_completed"
2735   { gcc_unreachable(); }
2736   "&& 1"
2737   [(set (reg:QI 25)
2738         (match_dup 1))
2739    (set (reg:PSI 22)
2740         (match_dup 2))
2741    (set (reg:PSI 18)
2742         (mult:PSI (sign_extend:PSI (reg:QI 25))
2743                   (reg:PSI 22)))
2744    (set (match_dup 0)
2745         (reg:PSI 18))])
2747 (define_insn_and_split "*mulpsi3"
2748   [(set (match_operand:PSI 0 "pseudo_register_operand"                       "=r")
2749         (mult:PSI (match_operand:PSI 1 "pseudo_register_operand"              "r")
2750                   (match_operand:PSI 2 "pseudo_register_or_const_int_operand" "rn")))
2751    (clobber (reg:HI 26))
2752    (clobber (reg:DI 18))]
2753   "AVR_HAVE_MUL && !reload_completed"
2754   { gcc_unreachable(); }
2755   "&& 1"
2756   [(set (reg:PSI 18)
2757         (match_dup 1))
2758    (set (reg:PSI 22) 
2759         (match_dup 2))
2760    (parallel [(set (reg:PSI 22)
2761                    (mult:PSI (reg:PSI 22)
2762                              (reg:PSI 18)))
2763               (clobber (reg:QI 21))
2764               (clobber (reg:QI 25))
2765               (clobber (reg:HI 26))])
2766    (set (match_dup 0)
2767         (reg:PSI 22))]
2768   {
2769     if (s8_operand (operands[2], PSImode))
2770       {
2771         rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
2772         emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1]));
2773         DONE;
2774       }
2775   })
2777 (define_insn "*mulsqipsi3.libgcc"
2778   [(set (reg:PSI 18)
2779         (mult:PSI (sign_extend:PSI (reg:QI 25))
2780                   (reg:PSI 22)))]
2781   "AVR_HAVE_MUL"
2782   "%~call __mulsqipsi3"
2783   [(set_attr "type" "xcall")
2784    (set_attr "cc" "clobber")])
2786 (define_insn "*mulpsi3.libgcc"
2787   [(set (reg:PSI 22)
2788         (mult:PSI (reg:PSI 22)
2789                   (reg:PSI 18)))
2790    (clobber (reg:QI 21))
2791    (clobber (reg:QI 25))
2792    (clobber (reg:HI 26))]
2793   "AVR_HAVE_MUL"
2794   "%~call __mulpsi3"
2795   [(set_attr "type" "xcall")
2796    (set_attr "cc" "clobber")])
2799 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2800 ;; 24-bit signed/unsigned division and modulo.
2801 ;; Notice that the libgcc implementation return the quotient in R22
2802 ;; and the remainder in R18 whereas the 32-bit [u]divmodsi4
2803 ;; implementation works the other way round.
2805 (define_insn_and_split "divmodpsi4"
2806   [(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "")
2807                    (div:PSI (match_operand:PSI 1 "pseudo_register_operand" "")
2808                             (match_operand:PSI 2 "pseudo_register_operand" "")))
2809               (set (match_operand:PSI 3 "pseudo_register_operand" "")
2810                    (mod:PSI (match_dup 1)
2811                             (match_dup 2)))
2812               (clobber (reg:DI 18))
2813               (clobber (reg:QI 26))])]
2814   ""
2815   { gcc_unreachable(); }
2816   ""
2817   [(set (reg:PSI 22) (match_dup 1))
2818    (set (reg:PSI 18) (match_dup 2))
2819    (parallel [(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18)))
2820               (set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18)))
2821               (clobber (reg:QI 21))
2822               (clobber (reg:QI 25))
2823               (clobber (reg:QI 26))])
2824    (set (match_dup 0) (reg:PSI 22))
2825    (set (match_dup 3) (reg:PSI 18))])
2827 (define_insn "*divmodpsi4_call"
2828   [(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18)))
2829    (set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18)))
2830    (clobber (reg:QI 21))
2831    (clobber (reg:QI 25))
2832    (clobber (reg:QI 26))]
2833   ""
2834   "%~call __divmodpsi4"
2835   [(set_attr "type" "xcall")
2836    (set_attr "cc" "clobber")])
2838 (define_insn_and_split "udivmodpsi4"
2839   [(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "")
2840                    (udiv:PSI (match_operand:PSI 1 "pseudo_register_operand" "")
2841                              (match_operand:PSI 2 "pseudo_register_operand" "")))
2842               (set (match_operand:PSI 3 "pseudo_register_operand" "")
2843                    (umod:PSI (match_dup 1)
2844                              (match_dup 2)))
2845               (clobber (reg:DI 18))
2846               (clobber (reg:QI 26))])]
2847   ""
2848   { gcc_unreachable(); }
2849   ""
2850   [(set (reg:PSI 22) (match_dup 1))
2851    (set (reg:PSI 18) (match_dup 2))
2852    (parallel [(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18)))
2853               (set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18)))
2854               (clobber (reg:QI 21))
2855               (clobber (reg:QI 25))
2856               (clobber (reg:QI 26))])
2857    (set (match_dup 0) (reg:PSI 22))
2858    (set (match_dup 3) (reg:PSI 18))])
2860 (define_insn "*udivmodpsi4_call"
2861   [(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18)))
2862    (set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18)))
2863    (clobber (reg:QI 21))
2864    (clobber (reg:QI 25))
2865    (clobber (reg:QI 26))]
2866   ""
2867   "%~call __udivmodpsi4"
2868   [(set_attr "type" "xcall")
2869    (set_attr "cc" "clobber")])
2871 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2873 (define_insn_and_split "divmodsi4"
2874   [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") 
2875                    (div:SI (match_operand:SI 1 "pseudo_register_operand" "") 
2876                            (match_operand:SI 2 "pseudo_register_operand" "")))
2877               (set (match_operand:SI 3 "pseudo_register_operand" "") 
2878                    (mod:SI (match_dup 1) (match_dup 2)))
2879               (clobber (reg:SI 18))
2880               (clobber (reg:SI 22))
2881               (clobber (reg:HI 26))
2882               (clobber (reg:HI 30))])]
2883   ""
2884   "this divmodsi4 pattern should have been splitted;" 
2885   ""
2886   [(set (reg:SI 22) (match_dup 1))
2887    (set (reg:SI 18) (match_dup 2))
2888    (parallel [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
2889               (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
2890               (clobber (reg:HI 26))
2891               (clobber (reg:HI 30))])
2892    (set (match_dup 0) (reg:SI 18))
2893    (set (match_dup 3) (reg:SI 22))])
2895 (define_insn "*divmodsi4_call"
2896   [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
2897    (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
2898    (clobber (reg:HI 26))
2899    (clobber (reg:HI 30))]
2900   ""
2901   "%~call __divmodsi4"
2902   [(set_attr "type" "xcall")
2903    (set_attr "cc" "clobber")])
2905 (define_insn_and_split "udivmodsi4"
2906   [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") 
2907                    (udiv:SI (match_operand:SI 1 "pseudo_register_operand" "") 
2908                            (match_operand:SI 2 "pseudo_register_operand" "")))
2909               (set (match_operand:SI 3 "pseudo_register_operand" "") 
2910                    (umod:SI (match_dup 1) (match_dup 2)))
2911               (clobber (reg:SI 18))
2912               (clobber (reg:SI 22))
2913               (clobber (reg:HI 26))
2914               (clobber (reg:HI 30))])]
2915   ""
2916   "this udivmodsi4 pattern should have been splitted;"
2917   ""
2918   [(set (reg:SI 22) (match_dup 1))
2919    (set (reg:SI 18) (match_dup 2))
2920    (parallel [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
2921               (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
2922               (clobber (reg:HI 26))
2923               (clobber (reg:HI 30))])
2924    (set (match_dup 0) (reg:SI 18))
2925    (set (match_dup 3) (reg:SI 22))])
2927 (define_insn "*udivmodsi4_call"
2928   [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
2929    (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
2930    (clobber (reg:HI 26))
2931    (clobber (reg:HI 30))]
2932   ""
2933   "%~call __udivmodsi4"
2934   [(set_attr "type" "xcall")
2935    (set_attr "cc" "clobber")])
2937 ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2938 ; and
2940 (define_insn "andqi3"
2941   [(set (match_operand:QI 0 "register_operand" "=r,d")
2942         (and:QI (match_operand:QI 1 "register_operand" "%0,0")
2943                 (match_operand:QI 2 "nonmemory_operand" "r,i")))]
2944   ""
2945   "@
2946         and %0,%2
2947         andi %0,lo8(%2)"
2948   [(set_attr "length" "1,1")
2949    (set_attr "cc" "set_zn,set_zn")])
2951 (define_insn "andhi3"
2952   [(set (match_operand:HI 0 "register_operand"         "=r,d,d,r  ,r")
2953         (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0  ,0")
2954                 (match_operand:HI 2 "nonmemory_operand" "r,s,n,Ca2,n")))
2955    (clobber (match_scratch:QI 3                        "=X,X,X,X  ,&d"))]
2956   ""
2957   {
2958     if (which_alternative == 0)
2959       return "and %A0,%A2\;and %B0,%B2";
2960     else if (which_alternative == 1)
2961       return "andi %A0,lo8(%2)\;andi %B0,hi8(%2)";
2963     return avr_out_bitop (insn, operands, NULL);
2964   }
2965   [(set_attr "length" "2,2,2,4,4")
2966    (set_attr "adjust_len" "*,*,out_bitop,out_bitop,out_bitop")
2967    (set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
2969 (define_insn "andpsi3"
2970   [(set (match_operand:PSI 0 "register_operand"          "=r,d,r  ,r")
2971         (and:PSI (match_operand:PSI 1 "register_operand" "%0,0,0  ,0")
2972                  (match_operand:PSI 2 "nonmemory_operand" "r,n,Ca3,n")))
2973    (clobber (match_scratch:QI 3                          "=X,X,X  ,&d"))]
2974   ""
2975   {
2976     if (which_alternative == 0)
2977       return "and %A0,%A2" CR_TAB
2978              "and %B0,%B2" CR_TAB
2979              "and %C0,%C2";
2981     return avr_out_bitop (insn, operands, NULL);
2982   }
2983   [(set_attr "length" "3,3,6,6")
2984    (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
2985    (set_attr "cc" "set_n,clobber,clobber,clobber")])
2987 (define_insn "andsi3"
2988   [(set (match_operand:SI 0 "register_operand"         "=r,d,r  ,r")
2989         (and:SI (match_operand:SI 1 "register_operand" "%0,0,0  ,0")
2990                 (match_operand:SI 2 "nonmemory_operand" "r,n,Ca4,n")))
2991    (clobber (match_scratch:QI 3                        "=X,X,X  ,&d"))]
2992   ""
2993   {
2994     if (which_alternative == 0)
2995       return "and %0,%2"   CR_TAB
2996              "and %B0,%B2" CR_TAB
2997              "and %C0,%C2" CR_TAB
2998              "and %D0,%D2";
3000     return avr_out_bitop (insn, operands, NULL);
3001   }
3002   [(set_attr "length" "4,4,8,8")
3003    (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
3004    (set_attr "cc" "set_n,clobber,clobber,clobber")])
3006 (define_peephole2 ; andi
3007   [(set (match_operand:QI 0 "d_register_operand" "")
3008         (and:QI (match_dup 0)
3009                 (match_operand:QI 1 "const_int_operand" "")))
3010    (set (match_dup 0)
3011         (and:QI (match_dup 0)
3012                 (match_operand:QI 2 "const_int_operand" "")))]
3013   ""
3014   [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
3015   {
3016     operands[1] = GEN_INT (INTVAL (operands[1]) & INTVAL (operands[2]));
3017   })
3019 ;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
3020 ;; ior
3022 (define_insn "iorqi3"
3023   [(set (match_operand:QI 0 "register_operand" "=r,d")
3024         (ior:QI (match_operand:QI 1 "register_operand" "%0,0")
3025                 (match_operand:QI 2 "nonmemory_operand" "r,i")))]
3026   ""
3027   "@
3028         or %0,%2
3029         ori %0,lo8(%2)"
3030   [(set_attr "length" "1,1")
3031    (set_attr "cc" "set_zn,set_zn")])
3033 (define_insn "iorhi3"
3034   [(set (match_operand:HI 0 "register_operand"         "=r,d,d,r  ,r")
3035         (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0  ,0")
3036                 (match_operand:HI 2 "nonmemory_operand" "r,s,n,Co2,n")))
3037    (clobber (match_scratch:QI 3                        "=X,X,X,X  ,&d"))]
3038   ""
3039   {
3040     if (which_alternative == 0)
3041       return "or %A0,%A2\;or %B0,%B2";
3042     else if (which_alternative == 1)
3043       return "ori %A0,lo8(%2)\;ori %B0,hi8(%2)";
3045     return avr_out_bitop (insn, operands, NULL);
3046   }
3047   [(set_attr "length" "2,2,2,4,4")
3048    (set_attr "adjust_len" "*,*,out_bitop,out_bitop,out_bitop")
3049    (set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
3051 (define_insn "iorpsi3"
3052   [(set (match_operand:PSI 0 "register_operand"          "=r,d,r  ,r")
3053         (ior:PSI (match_operand:PSI 1 "register_operand" "%0,0,0  ,0")
3054                  (match_operand:PSI 2 "nonmemory_operand" "r,n,Co3,n")))
3055    (clobber (match_scratch:QI 3                          "=X,X,X  ,&d"))]
3056   ""
3057   {
3058     if (which_alternative == 0)
3059       return "or %A0,%A2" CR_TAB
3060              "or %B0,%B2" CR_TAB
3061              "or %C0,%C2";
3063     return avr_out_bitop (insn, operands, NULL);
3064   }
3065   [(set_attr "length" "3,3,6,6")
3066    (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
3067    (set_attr "cc" "set_n,clobber,clobber,clobber")])
3069 (define_insn "iorsi3"
3070   [(set (match_operand:SI 0 "register_operand"         "=r,d,r  ,r")
3071         (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0  ,0")
3072                 (match_operand:SI 2 "nonmemory_operand" "r,n,Co4,n")))
3073    (clobber (match_scratch:QI 3                        "=X,X,X  ,&d"))]
3074   ""
3075   {
3076     if (which_alternative == 0)
3077       return "or %0,%2"   CR_TAB
3078              "or %B0,%B2" CR_TAB
3079              "or %C0,%C2" CR_TAB
3080              "or %D0,%D2";
3082     return avr_out_bitop (insn, operands, NULL);
3083   }
3084   [(set_attr "length" "4,4,8,8")
3085    (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
3086    (set_attr "cc" "set_n,clobber,clobber,clobber")])
3088 ;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3089 ;; xor
3091 (define_insn "xorqi3"
3092   [(set (match_operand:QI 0 "register_operand" "=r")
3093         (xor:QI (match_operand:QI 1 "register_operand" "%0")
3094                 (match_operand:QI 2 "register_operand" "r")))]
3095   ""
3096   "eor %0,%2"
3097   [(set_attr "length" "1")
3098    (set_attr "cc" "set_zn")])
3100 (define_insn "xorhi3"
3101   [(set (match_operand:HI 0 "register_operand"         "=r,r  ,r")
3102         (xor:HI (match_operand:HI 1 "register_operand" "%0,0  ,0")
3103                 (match_operand:HI 2 "nonmemory_operand" "r,Cx2,n")))
3104    (clobber (match_scratch:QI 3                        "=X,X  ,&d"))]
3105   ""
3106   {
3107     if (which_alternative == 0)
3108       return "eor %A0,%A2\;eor %B0,%B2";
3110     return avr_out_bitop (insn, operands, NULL);
3111   }
3112   [(set_attr "length" "2,2,4")
3113    (set_attr "adjust_len" "*,out_bitop,out_bitop")
3114    (set_attr "cc" "set_n,clobber,clobber")])
3116 (define_insn "xorpsi3"
3117   [(set (match_operand:PSI 0 "register_operand"          "=r,r  ,r")
3118         (xor:PSI (match_operand:PSI 1 "register_operand" "%0,0  ,0")
3119                  (match_operand:PSI 2 "nonmemory_operand" "r,Cx3,n")))
3120    (clobber (match_scratch:QI 3                          "=X,X  ,&d"))]
3121   ""
3122   {
3123     if (which_alternative == 0)
3124       return "eor %A0,%A2" CR_TAB
3125              "eor %B0,%B2" CR_TAB
3126              "eor %C0,%C2";
3128     return avr_out_bitop (insn, operands, NULL);
3129   }
3130   [(set_attr "length" "3,6,6")
3131    (set_attr "adjust_len" "*,out_bitop,out_bitop")
3132    (set_attr "cc" "set_n,clobber,clobber")])
3134 (define_insn "xorsi3"
3135   [(set (match_operand:SI 0 "register_operand"         "=r,r  ,r")
3136         (xor:SI (match_operand:SI 1 "register_operand" "%0,0  ,0")
3137                 (match_operand:SI 2 "nonmemory_operand" "r,Cx4,n")))
3138    (clobber (match_scratch:QI 3                        "=X,X  ,&d"))]
3139   ""
3140   {
3141     if (which_alternative == 0)
3142       return "eor %0,%2"   CR_TAB
3143              "eor %B0,%B2" CR_TAB
3144              "eor %C0,%C2" CR_TAB
3145              "eor %D0,%D2";
3147     return avr_out_bitop (insn, operands, NULL);
3148   }
3149   [(set_attr "length" "4,8,8")
3150    (set_attr "adjust_len" "*,out_bitop,out_bitop")
3151    (set_attr "cc" "set_n,clobber,clobber")])
3153 ;; swap swap swap swap swap swap swap swap swap swap swap swap swap swap swap
3154 ;; swap
3156 (define_expand "rotlqi3"
3157   [(set (match_operand:QI 0 "register_operand" "")
3158         (rotate:QI (match_operand:QI 1 "register_operand" "")
3159                    (match_operand:QI 2 "const_0_to_7_operand" "")))]
3160   ""
3161   {
3162     if (!CONST_INT_P (operands[2]))
3163       FAIL;
3165     operands[2] = gen_int_mode (INTVAL (operands[2]) & 7, QImode);
3166   })
3168 ;; Expander used by __builtin_avr_swap
3169 (define_expand "rotlqi3_4"
3170   [(set (match_operand:QI 0 "register_operand" "")
3171         (rotate:QI (match_operand:QI 1 "register_operand" "")
3172                    (const_int 4)))])
3174 (define_insn "*rotlqi3"
3175   [(set (match_operand:QI 0 "register_operand"               "=r,r,r  ,r  ,r  ,r  ,r  ,r")
3176         (rotate:QI (match_operand:QI 1 "register_operand"     "0,0,0  ,0  ,0  ,0  ,0  ,0")
3177                    (match_operand:QI 2 "const_0_to_7_operand" "P,K,C03,C04,C05,C06,C07,L")))]
3178   ""
3179   "@
3180         lsl %0\;adc %0,__zero_reg__
3181         lsl %0\;adc %0,__zero_reg__\;lsl %0\;adc %0,__zero_reg__
3182         swap %0\;bst %0,0\;ror %0\;bld %0,7
3183         swap %0
3184         swap %0\;lsl %0\;adc %0,__zero_reg__
3185         swap %0\;lsl %0\;adc %0,__zero_reg__\;lsl %0\;adc %0,__zero_reg__
3186         bst %0,0\;ror %0\;bld %0,7
3187         "
3188   [(set_attr "length" "2,4,4,1,3,5,3,0")
3189    (set_attr "cc" "set_n,set_n,clobber,none,set_n,set_n,clobber,none")])
3191 ;; Split all rotates of HI,SI and PSImode registers where rotation is by
3192 ;; a whole number of bytes.  The split creates the appropriate moves and
3193 ;; considers all overlap situations.
3195 ;; HImode does not need scratch.  Use attribute for this constraint.
3197 (define_mode_attr rotx [(SI "&r,&r,X") (PSI "&r,&r,X") (HI "X,X,X")])
3198 (define_mode_attr rotsmode [(SI "HI") (PSI "QI") (HI "QI")])
3200 ;; "rotlhi3"
3201 ;; "rotlpsi3"
3202 ;; "rotlsi3"
3203 (define_expand "rotl<mode>3"
3204   [(parallel [(set (match_operand:HISI 0 "register_operand" "")
3205                    (rotate:HISI (match_operand:HISI 1 "register_operand" "")
3206                                 (match_operand:VOID 2 "const_int_operand" "")))
3207               (clobber (match_dup 3))])]
3208   ""
3209   {
3210     int offset;
3212     if (!CONST_INT_P (operands[2]))
3213       FAIL;
3215     offset = INTVAL (operands[2]);
3217     if (0 == offset % 8)
3218       {
3219         if (AVR_HAVE_MOVW && 0 == offset % 16)
3220           operands[3] = gen_rtx_SCRATCH (<rotsmode>mode);
3221         else
3222           operands[3] = gen_rtx_SCRATCH (QImode);
3223       }
3224     else if (offset == 1
3225              || offset == GET_MODE_BITSIZE (<MODE>mode) -1)
3226       {
3227         /*; Support rotate left/right by 1  */
3229         emit_move_insn (operands[0],
3230                         gen_rtx_ROTATE (<MODE>mode, operands[1], operands[2]));
3231         DONE;
3232       }
3233     else
3234       FAIL;
3235   })
3237 (define_insn "*rotlhi2.1"
3238   [(set (match_operand:HI 0 "register_operand"           "=r")
3239         (rotate:HI (match_operand:HI 1 "register_operand" "0")
3240                    (const_int 1)))]
3241   ""
3242   "lsl %A0\;rol %B0\;adc %A0,__zero_reg__"
3243   [(set_attr "length" "3")
3244    (set_attr "cc" "clobber")])
3246 (define_insn "*rotlhi2.15"
3247   [(set (match_operand:HI 0 "register_operand"           "=r")
3248         (rotate:HI (match_operand:HI 1 "register_operand" "0")
3249                    (const_int 15)))]
3250   ""
3251   "bst %A0,0\;ror %B0\;ror %A0\;bld %B0,7"
3252   [(set_attr "length" "4")
3253    (set_attr "cc" "clobber")])
3255 (define_insn "*rotlpsi2.1"
3256   [(set (match_operand:PSI 0 "register_operand"            "=r")
3257         (rotate:PSI (match_operand:PSI 1 "register_operand" "0")
3258                     (const_int 1)))]
3259   ""
3260   "lsl %A0\;rol %B0\;rol %C0\;adc %A0,__zero_reg__"
3261   [(set_attr "length" "4")
3262    (set_attr "cc" "clobber")])
3264 (define_insn "*rotlpsi2.23"
3265   [(set (match_operand:PSI 0 "register_operand"            "=r")
3266         (rotate:PSI (match_operand:PSI 1 "register_operand" "0")
3267                     (const_int 23)))]
3268   ""
3269   "bst %A0,0\;ror %C0\;ror %B0\;ror %A0\;bld %C0,7"
3270   [(set_attr "length" "5")
3271    (set_attr "cc" "clobber")])
3273 (define_insn "*rotlsi2.1"
3274   [(set (match_operand:SI 0 "register_operand"           "=r")
3275         (rotate:SI (match_operand:SI 1 "register_operand" "0")
3276                    (const_int 1)))]
3277   ""
3278   "lsl %A0\;rol %B0\;rol %C0\;rol %D0\;adc %A0,__zero_reg__"
3279   [(set_attr "length" "5")
3280    (set_attr "cc" "clobber")])
3282 (define_insn "*rotlsi2.31"
3283   [(set (match_operand:SI 0 "register_operand"           "=r")
3284         (rotate:SI (match_operand:SI 1 "register_operand" "0")
3285                    (const_int 31)))]
3286   ""
3287   "bst %A0,0\;ror %D0\;ror %C0\;ror %B0\;ror %A0\;bld %D0,7"
3288   [(set_attr "length" "6")
3289    (set_attr "cc" "clobber")])
3291 ;; Overlapping non-HImode registers often (but not always) need a scratch.
3292 ;; The best we can do is use early clobber alternative "#&r" so that
3293 ;; completely non-overlapping operands dont get a scratch but # so register
3294 ;; allocation does not prefer non-overlapping.
3297 ;; Split word aligned rotates using scratch that is mode dependent.
3299 ;; "*rotwhi"
3300 ;; "*rotwsi"
3301 (define_insn_and_split "*rotw<mode>"
3302   [(set (match_operand:HISI 0 "register_operand"             "=r,r,#&r")
3303         (rotate:HISI (match_operand:HISI 1 "register_operand" "0,r,r")
3304                      (match_operand 2 "const_int_operand"     "n,n,n")))
3305    (clobber (match_scratch:<rotsmode> 3 "=<rotx>"))]
3306   "AVR_HAVE_MOVW
3307    && CONST_INT_P (operands[2])
3308    && GET_MODE_SIZE (<MODE>mode) % 2 == 0
3309    && 0 == INTVAL (operands[2]) % 16"
3310   "#"
3311   "&& reload_completed"
3312   [(const_int 0)]
3313   {
3314     avr_rotate_bytes (operands);
3315     DONE;
3316   })
3319 ;; Split byte aligned rotates using scratch that is always QI mode.
3321 ;; "*rotbhi"
3322 ;; "*rotbpsi"
3323 ;; "*rotbsi"
3324 (define_insn_and_split "*rotb<mode>"
3325   [(set (match_operand:HISI 0 "register_operand"             "=r,r,#&r")
3326         (rotate:HISI (match_operand:HISI 1 "register_operand" "0,r,r")
3327                      (match_operand 2 "const_int_operand"     "n,n,n")))
3328    (clobber (match_scratch:QI 3 "=<rotx>"))]
3329   "CONST_INT_P (operands[2])
3330    && (8 == INTVAL (operands[2]) % 16
3331        || ((!AVR_HAVE_MOVW
3332             || GET_MODE_SIZE (<MODE>mode) % 2 != 0)
3333            && 0 == INTVAL (operands[2]) % 16))"
3334   "#"
3335   "&& reload_completed"
3336   [(const_int 0)]
3337   {
3338     avr_rotate_bytes (operands);
3339     DONE;
3340   })
3343 ;;<< << << << << << << << << << << << << << << << << << << << << << << << << <<
3344 ;; arithmetic shift left
3346 ;; "ashlqi3"
3347 ;; "ashlqq3"  "ashluqq3"
3348 (define_expand "ashl<mode>3"
3349   [(set (match_operand:ALL1 0 "register_operand" "")
3350         (ashift:ALL1 (match_operand:ALL1 1 "register_operand" "")
3351                      (match_operand:QI 2 "nop_general_operand" "")))])
3353 (define_split ; ashlqi3_const4
3354   [(set (match_operand:ALL1 0 "d_register_operand" "")
3355         (ashift:ALL1 (match_dup 0)
3356                      (const_int 4)))]
3357   ""
3358   [(set (match_dup 1)
3359         (rotate:QI (match_dup 1)
3360                    (const_int 4)))
3361    (set (match_dup 1)
3362         (and:QI (match_dup 1)
3363                 (const_int -16)))]
3364   {
3365     operands[1] = avr_to_int_mode (operands[0]);
3366   })
3368 (define_split ; ashlqi3_const5
3369   [(set (match_operand:ALL1 0 "d_register_operand" "")
3370         (ashift:ALL1 (match_dup 0)
3371                      (const_int 5)))]
3372   ""
3373   [(set (match_dup 1) (rotate:QI (match_dup 1) (const_int 4)))
3374    (set (match_dup 1) (ashift:QI (match_dup 1) (const_int 1)))
3375    (set (match_dup 1) (and:QI (match_dup 1) (const_int -32)))]
3376   {
3377     operands[1] = avr_to_int_mode (operands[0]);
3378   })
3380 (define_split ; ashlqi3_const6
3381   [(set (match_operand:ALL1 0 "d_register_operand" "")
3382         (ashift:ALL1 (match_dup 0)
3383                      (const_int 6)))]
3384   ""
3385   [(set (match_dup 1) (rotate:QI (match_dup 1) (const_int 4)))
3386    (set (match_dup 1) (ashift:QI (match_dup 1) (const_int 2)))
3387    (set (match_dup 1) (and:QI (match_dup 1) (const_int -64)))]
3388   {
3389     operands[1] = avr_to_int_mode (operands[0]);
3390   })
3392 ;; "*ashlqi3"
3393 ;; "*ashlqq3"  "*ashluqq3"
3394 (define_insn "*ashl<mode>3"
3395   [(set (match_operand:ALL1 0 "register_operand"              "=r,r,r,r,!d,r,r")
3396         (ashift:ALL1 (match_operand:ALL1 1 "register_operand"  "0,0,0,0,0 ,0,0")
3397                      (match_operand:QI 2 "nop_general_operand" "r,L,P,K,n ,n,Qm")))]
3398   ""
3399   {
3400     return ashlqi3_out (insn, operands, NULL);
3401   }
3402   [(set_attr "length" "5,0,1,2,4,6,9")
3403    (set_attr "adjust_len" "ashlqi")
3404    (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")])
3406 (define_insn "ashl<mode>3"
3407   [(set (match_operand:ALL2 0 "register_operand"              "=r,r,r,r,r,r,r")
3408         (ashift:ALL2 (match_operand:ALL2 1 "register_operand"  "0,0,0,r,0,0,0")
3409                      (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
3410   ""
3411   {
3412     return ashlhi3_out (insn, operands, NULL);
3413   }
3414   [(set_attr "length" "6,0,2,2,4,10,10")
3415    (set_attr "adjust_len" "ashlhi")
3416    (set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")])
3419 ;; Insns like the following are generated when (implicitly) extending 8-bit shifts
3420 ;; like char1 = char2 << char3.  Only the low-byte is needed in that situation.
3422 ;; "*ashluqihiqi3"
3423 ;; "*ashlsqihiqi3"
3424 (define_insn_and_split "*ashl<extend_su>qihiqi3"
3425   [(set (match_operand:QI 0 "register_operand"                                     "=r")
3426         (subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "0"))
3427                               (match_operand:QI 2 "register_operand"                "r"))
3428                    0))]
3429   ""
3430   "#"
3431   ""
3432   [(set (match_dup 0)
3433         (ashift:QI (match_dup 1)
3434                    (match_dup 2)))])
3436 ;; ??? Combiner does not recognize that it could split the following insn;
3437 ;;     presumably because he has no register handy?
3439 ;; "*ashluqihiqi3.mem"
3440 ;; "*ashlsqihiqi3.mem"
3441 (define_insn_and_split "*ashl<extend_su>qihiqi3.mem"
3442   [(set (match_operand:QI 0 "memory_operand" "=m")
3443         (subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "r"))
3444                               (match_operand:QI 2 "register_operand" "r"))
3445                    0))]
3446   "!reload_completed"
3447   { gcc_unreachable(); }
3448   "&& 1"
3449   [(set (match_dup 3)
3450         (ashift:QI (match_dup 1)
3451                    (match_dup 2)))
3452    (set (match_dup 0)
3453         (match_dup 3))]
3454   {
3455     operands[3] = gen_reg_rtx (QImode);
3456   })
3458 ;; Similar.
3460 (define_insn_and_split "*ashlhiqi3"
3461   [(set (match_operand:QI 0 "nonimmediate_operand" "=r")
3462         (subreg:QI (ashift:HI (match_operand:HI 1 "register_operand" "0")
3463                               (match_operand:QI 2 "register_operand" "r")) 0))]
3464   "!reload_completed"
3465   { gcc_unreachable(); }
3466   "&& 1"
3467   [(set (match_dup 4)
3468         (ashift:QI (match_dup 3)
3469                    (match_dup 2)))
3470    (set (match_dup 0)
3471         (match_dup 4))]
3472   {
3473     operands[3] = simplify_gen_subreg (QImode, operands[1], HImode, 0);
3474     operands[4] = gen_reg_rtx (QImode);
3475   })
3477 ;; High part of 16-bit shift is unused after the instruction:
3478 ;; No need to compute it, map to 8-bit shift.
3480 (define_peephole2
3481   [(set (match_operand:HI 0 "register_operand" "")
3482         (ashift:HI (match_dup 0)
3483                    (match_operand:QI 1 "register_operand" "")))]
3484   ""
3485   [(set (match_dup 2)
3486         (ashift:QI (match_dup 2)
3487                    (match_dup 1)))
3488    (clobber (match_dup 3))]
3489   {
3490     operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 1);
3492     if (!peep2_reg_dead_p (1, operands[3]))
3493       FAIL;
3495     operands[2] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
3496   })
3499 ;; "ashlsi3"
3500 ;; "ashlsq3"  "ashlusq3"
3501 ;; "ashlsa3"  "ashlusa3"
3502 (define_insn "ashl<mode>3"
3503   [(set (match_operand:ALL4 0 "register_operand"                "=r,r,r,r,r,r,r")
3504         (ashift:ALL4 (match_operand:ALL4 1 "register_operand"    "0,0,0,r,0,0,0")
3505                      (match_operand:QI 2 "nop_general_operand"   "r,L,P,O,K,n,Qm")))]
3506   ""
3507   {
3508     return ashlsi3_out (insn, operands, NULL);
3509   }
3510   [(set_attr "length" "8,0,4,4,8,10,12")
3511    (set_attr "adjust_len" "ashlsi")
3512    (set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")])
3514 ;; Optimize if a scratch register from LD_REGS happens to be available.
3516 (define_peephole2 ; ashlqi3_l_const4
3517   [(set (match_operand:ALL1 0 "l_register_operand" "")
3518         (ashift:ALL1 (match_dup 0)
3519                      (const_int 4)))
3520    (match_scratch:QI 1 "d")]
3521   ""
3522   [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4)))
3523    (set (match_dup 1) (const_int -16))
3524    (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))]
3525   {
3526     operands[2] = avr_to_int_mode (operands[0]);
3527   })
3529 (define_peephole2 ; ashlqi3_l_const5
3530   [(set (match_operand:ALL1 0 "l_register_operand" "")
3531         (ashift:ALL1 (match_dup 0)
3532                      (const_int 5)))
3533    (match_scratch:QI 1 "d")]
3534   ""
3535   [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4)))
3536    (set (match_dup 2) (ashift:QI (match_dup 2) (const_int 1)))
3537    (set (match_dup 1) (const_int -32))
3538    (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))]
3539   {
3540     operands[2] = avr_to_int_mode (operands[0]);
3541   })
3543 (define_peephole2 ; ashlqi3_l_const6
3544   [(set (match_operand:ALL1 0 "l_register_operand" "")
3545         (ashift:ALL1 (match_dup 0)
3546                      (const_int 6)))
3547    (match_scratch:QI 1 "d")]
3548   ""
3549   [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4)))
3550    (set (match_dup 2) (ashift:QI (match_dup 2) (const_int 2)))
3551    (set (match_dup 1) (const_int -64))
3552    (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))]
3553   {
3554     operands[2] = avr_to_int_mode (operands[0]);
3555   })
3557 (define_peephole2
3558   [(match_scratch:QI 3 "d")
3559    (set (match_operand:ALL2 0 "register_operand" "")
3560         (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "")
3561                      (match_operand:QI 2 "const_int_operand" "")))]
3562   ""
3563   [(parallel [(set (match_dup 0)
3564                    (ashift:ALL2 (match_dup 1)
3565                                 (match_dup 2)))
3566               (clobber (match_dup 3))])])
3568 ;; "*ashlhi3_const"
3569 ;; "*ashlhq3_const"  "*ashluhq3_const"
3570 ;; "*ashlha3_const"  "*ashluha3_const"
3571 (define_insn "*ashl<mode>3_const"
3572   [(set (match_operand:ALL2 0 "register_operand"              "=r,r,r,r,r")
3573         (ashift:ALL2 (match_operand:ALL2 1 "register_operand"  "0,0,r,0,0")
3574                      (match_operand:QI 2 "const_int_operand"   "L,P,O,K,n")))
3575    (clobber (match_scratch:QI 3                               "=X,X,X,X,&d"))]
3576   "reload_completed"
3577   {
3578     return ashlhi3_out (insn, operands, NULL);
3579   }
3580   [(set_attr "length" "0,2,2,4,10")
3581    (set_attr "adjust_len" "ashlhi")
3582    (set_attr "cc" "none,set_n,clobber,set_n,clobber")])
3584 (define_peephole2
3585   [(match_scratch:QI 3 "d")
3586    (set (match_operand:ALL4 0 "register_operand" "")
3587         (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "")
3588                      (match_operand:QI 2 "const_int_operand" "")))]
3589   ""
3590   [(parallel [(set (match_dup 0)
3591                    (ashift:ALL4 (match_dup 1)
3592                                 (match_dup 2)))
3593               (clobber (match_dup 3))])])
3595 ;; "*ashlsi3_const"
3596 ;; "*ashlsq3_const"  "*ashlusq3_const"
3597 ;; "*ashlsa3_const"  "*ashlusa3_const"
3598 (define_insn "*ashl<mode>3_const"
3599   [(set (match_operand:ALL4 0 "register_operand"              "=r,r,r,r")
3600         (ashift:ALL4 (match_operand:ALL4 1 "register_operand"  "0,0,r,0")
3601                      (match_operand:QI 2 "const_int_operand"   "L,P,O,n")))
3602    (clobber (match_scratch:QI 3                               "=X,X,X,&d"))]
3603   "reload_completed"
3604   {
3605     return ashlsi3_out (insn, operands, NULL);
3606   }
3607   [(set_attr "length" "0,4,4,10")
3608    (set_attr "adjust_len" "ashlsi")
3609    (set_attr "cc" "none,set_n,clobber,clobber")])
3611 (define_expand "ashlpsi3"
3612   [(parallel [(set (match_operand:PSI 0 "register_operand"             "")
3613                    (ashift:PSI (match_operand:PSI 1 "register_operand" "")
3614                                (match_operand:QI 2 "nonmemory_operand" "")))
3615               (clobber (scratch:QI))])]
3616   ""
3617   {
3618     if (AVR_HAVE_MUL
3619         && CONST_INT_P (operands[2]))
3620       {
3621         if (IN_RANGE (INTVAL (operands[2]), 3, 6))
3622           {
3623             rtx xoffset = force_reg (QImode, gen_int_mode (1 << INTVAL (operands[2]), QImode));
3624             emit_insn (gen_mulsqipsi3 (operands[0], xoffset, operands[1])); 
3625             DONE;
3626           }
3627         else if (optimize_insn_for_speed_p ()
3628                  && INTVAL (operands[2]) != 16
3629                  && IN_RANGE (INTVAL (operands[2]), 9, 22))
3630           {
3631             rtx xoffset = force_reg (PSImode, gen_int_mode (1 << INTVAL (operands[2]), PSImode));
3632             emit_insn (gen_mulpsi3 (operands[0], operands[1], xoffset)); 
3633             DONE;
3634           }
3635       }
3636   })
3638 (define_insn "*ashlpsi3"
3639   [(set (match_operand:PSI 0 "register_operand"             "=r,r,r,r")
3640         (ashift:PSI (match_operand:PSI 1 "register_operand"  "0,0,r,0")
3641                     (match_operand:QI 2 "nonmemory_operand"  "r,P,O,n")))
3642    (clobber (match_scratch:QI 3                             "=X,X,X,&d"))]
3643   ""
3644   {
3645     return avr_out_ashlpsi3 (insn, operands, NULL);
3646   }
3647   [(set_attr "adjust_len" "ashlpsi")
3648    (set_attr "cc" "clobber")])
3650 ;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>
3651 ;; arithmetic shift right
3653 ;; "ashrqi3"
3654 ;; "ashrqq3"  "ashruqq3"
3655 (define_insn "ashr<mode>3"
3656   [(set (match_operand:ALL1 0 "register_operand"                  "=r,r,r,r,r          ,r      ,r")
3657         (ashiftrt:ALL1 (match_operand:ALL1 1 "register_operand"    "0,0,0,0,0          ,0      ,0")
3658                        (match_operand:QI 2 "nop_general_operand"   "r,L,P,K,C03 C04 C05,C06 C07,Qm")))]
3659   ""
3660   {
3661     return ashrqi3_out (insn, operands, NULL);
3662   }
3663   [(set_attr "length" "5,0,1,2,5,4,9")
3664    (set_attr "adjust_len" "ashrqi")
3665    (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,clobber,clobber")])
3667 ;; "ashrhi3"
3668 ;; "ashrhq3"  "ashruhq3"
3669 ;; "ashrha3"  "ashruha3"
3670 (define_insn "ashr<mode>3"
3671   [(set (match_operand:ALL2 0 "register_operand"                "=r,r,r,r,r,r,r")
3672         (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand"  "0,0,0,r,0,0,0")
3673                        (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
3674   ""
3675   {
3676     return ashrhi3_out (insn, operands, NULL);
3677   }
3678   [(set_attr "length" "6,0,2,4,4,10,10")
3679    (set_attr "adjust_len" "ashrhi")
3680    (set_attr "cc" "clobber,none,clobber,set_n,clobber,clobber,clobber")])
3682 (define_insn "ashrpsi3"
3683   [(set (match_operand:PSI 0 "register_operand"                 "=r,r,r,r,r")
3684         (ashiftrt:PSI (match_operand:PSI 1 "register_operand"    "0,0,0,r,0")
3685                       (match_operand:QI 2 "nonmemory_operand"    "r,P,K,O,n")))
3686    (clobber (match_scratch:QI 3                                 "=X,X,X,X,&d"))]
3687   ""
3688   {
3689     return avr_out_ashrpsi3 (insn, operands, NULL);
3690   }
3691   [(set_attr "adjust_len" "ashrpsi")
3692    (set_attr "cc" "clobber")])
3694 ;; "ashrsi3"
3695 ;; "ashrsq3"  "ashrusq3"
3696 ;; "ashrsa3"  "ashrusa3"
3697 (define_insn "ashr<mode>3"
3698   [(set (match_operand:ALL4 0 "register_operand"                  "=r,r,r,r,r,r,r")
3699         (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand"    "0,0,0,r,0,0,0")
3700                        (match_operand:QI 2 "nop_general_operand"   "r,L,P,O,K,n,Qm")))]
3701   ""
3702   {
3703     return ashrsi3_out (insn, operands, NULL);
3704   }
3705   [(set_attr "length" "8,0,4,6,8,10,12")
3706    (set_attr "adjust_len" "ashrsi")
3707    (set_attr "cc" "clobber,none,clobber,set_n,clobber,clobber,clobber")])
3709 ;; Optimize if a scratch register from LD_REGS happens to be available.
3711 (define_peephole2
3712   [(match_scratch:QI 3 "d")
3713    (set (match_operand:ALL2 0 "register_operand" "")
3714         (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "")
3715                        (match_operand:QI 2 "const_int_operand" "")))]
3716   ""
3717   [(parallel [(set (match_dup 0)
3718                    (ashiftrt:ALL2 (match_dup 1)
3719                                   (match_dup 2)))
3720               (clobber (match_dup 3))])])
3722 ;; "*ashrhi3_const"
3723 ;; "*ashrhq3_const"  "*ashruhq3_const"
3724 ;; "*ashrha3_const"  "*ashruha3_const"
3725 (define_insn "*ashr<mode>3_const"
3726   [(set (match_operand:ALL2 0 "register_operand"                "=r,r,r,r,r")
3727         (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand"  "0,0,r,0,0")
3728                        (match_operand:QI 2 "const_int_operand"   "L,P,O,K,n")))
3729    (clobber (match_scratch:QI 3                                 "=X,X,X,X,&d"))]
3730   "reload_completed"
3731   {
3732     return ashrhi3_out (insn, operands, NULL);
3733   }
3734   [(set_attr "length" "0,2,4,4,10")
3735    (set_attr "adjust_len" "ashrhi")
3736    (set_attr "cc" "none,clobber,set_n,clobber,clobber")])
3738 (define_peephole2
3739   [(match_scratch:QI 3 "d")
3740    (set (match_operand:ALL4 0 "register_operand" "")
3741         (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "")
3742                        (match_operand:QI 2 "const_int_operand" "")))]
3743   ""
3744   [(parallel [(set (match_dup 0)
3745                    (ashiftrt:ALL4 (match_dup 1)
3746                                   (match_dup 2)))
3747               (clobber (match_dup 3))])])
3749 ;; "*ashrsi3_const"
3750 ;; "*ashrsq3_const"  "*ashrusq3_const"
3751 ;; "*ashrsa3_const"  "*ashrusa3_const"
3752 (define_insn "*ashr<mode>3_const"
3753   [(set (match_operand:ALL4 0 "register_operand"                "=r,r,r,r")
3754         (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand"  "0,0,r,0")
3755                        (match_operand:QI 2 "const_int_operand"   "L,P,O,n")))
3756    (clobber (match_scratch:QI 3                                 "=X,X,X,&d"))]
3757   "reload_completed"
3758   {
3759     return ashrsi3_out (insn, operands, NULL);
3760   }
3761   [(set_attr "length" "0,4,4,10")
3762    (set_attr "adjust_len" "ashrsi")
3763    (set_attr "cc" "none,clobber,set_n,clobber")])
3765 ;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>
3766 ;; logical shift right
3768 ;; "lshrqi3"
3769 ;; "lshrqq3 "lshruqq3"
3770 (define_expand "lshr<mode>3"
3771   [(set (match_operand:ALL1 0 "register_operand" "")
3772         (lshiftrt:ALL1 (match_operand:ALL1 1 "register_operand" "")
3773                        (match_operand:QI 2 "nop_general_operand" "")))])
3775 (define_split   ; lshrqi3_const4
3776   [(set (match_operand:ALL1 0 "d_register_operand" "")
3777         (lshiftrt:ALL1 (match_dup 0)
3778                        (const_int 4)))]
3779   ""
3780   [(set (match_dup 1)
3781         (rotate:QI (match_dup 1)
3782                    (const_int 4)))
3783    (set (match_dup 1)
3784         (and:QI (match_dup 1)
3785                 (const_int 15)))]
3786   {
3787     operands[1] = avr_to_int_mode (operands[0]);
3788   })
3790 (define_split   ; lshrqi3_const5
3791   [(set (match_operand:ALL1 0 "d_register_operand" "")
3792         (lshiftrt:ALL1 (match_dup 0)
3793                        (const_int 5)))]
3794   ""
3795   [(set (match_dup 1) (rotate:QI (match_dup 1) (const_int 4)))
3796    (set (match_dup 1) (lshiftrt:QI (match_dup 1) (const_int 1)))
3797    (set (match_dup 1) (and:QI (match_dup 1) (const_int 7)))]
3798   {
3799     operands[1] = avr_to_int_mode (operands[0]);
3800   })
3802 (define_split   ; lshrqi3_const6
3803   [(set (match_operand:QI 0 "d_register_operand" "")
3804         (lshiftrt:QI (match_dup 0)
3805                      (const_int 6)))]
3806   ""
3807   [(set (match_dup 1) (rotate:QI (match_dup 1) (const_int 4)))
3808    (set (match_dup 1) (lshiftrt:QI (match_dup 1) (const_int 2)))
3809    (set (match_dup 1) (and:QI (match_dup 1) (const_int 3)))]
3810   {
3811     operands[1] = avr_to_int_mode (operands[0]);
3812   })
3814 ;; "*lshrqi3"
3815 ;; "*lshrqq3"
3816 ;; "*lshruqq3"
3817 (define_insn "*lshr<mode>3"
3818   [(set (match_operand:ALL1 0 "register_operand"                  "=r,r,r,r,!d,r,r")
3819         (lshiftrt:ALL1 (match_operand:ALL1 1 "register_operand"    "0,0,0,0,0 ,0,0")
3820                        (match_operand:QI 2 "nop_general_operand"   "r,L,P,K,n ,n,Qm")))]
3821   ""
3822   {
3823     return lshrqi3_out (insn, operands, NULL);
3824   }
3825   [(set_attr "length" "5,0,1,2,4,6,9")
3826    (set_attr "adjust_len" "lshrqi")
3827    (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")])
3829 ;; "lshrhi3"
3830 ;; "lshrhq3"  "lshruhq3"
3831 ;; "lshrha3"  "lshruha3"
3832 (define_insn "lshr<mode>3"
3833   [(set (match_operand:ALL2 0 "register_operand"                "=r,r,r,r,r,r,r")
3834         (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand"    "0,0,0,r,0,0,0")
3835                        (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
3836   ""
3837   {
3838     return lshrhi3_out (insn, operands, NULL);
3839   }
3840   [(set_attr "length" "6,0,2,2,4,10,10")
3841    (set_attr "adjust_len" "lshrhi")
3842    (set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber,clobber")])
3844 (define_insn "lshrpsi3"
3845   [(set (match_operand:PSI 0 "register_operand"                 "=r,r,r,r,r")
3846         (lshiftrt:PSI (match_operand:PSI 1 "register_operand"    "0,0,r,0,0")
3847                       (match_operand:QI 2 "nonmemory_operand"    "r,P,O,K,n")))
3848    (clobber (match_scratch:QI 3                                 "=X,X,X,X,&d"))]
3849   ""
3850   {
3851     return avr_out_lshrpsi3 (insn, operands, NULL);
3852   }
3853   [(set_attr "adjust_len" "lshrpsi")
3854    (set_attr "cc" "clobber")])
3856 ;; "lshrsi3"
3857 ;; "lshrsq3"  "lshrusq3"
3858 ;; "lshrsa3"  "lshrusa3"
3859 (define_insn "lshr<mode>3"
3860   [(set (match_operand:ALL4 0 "register_operand"                  "=r,r,r,r,r,r,r")
3861         (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand"    "0,0,0,r,0,0,0")
3862                        (match_operand:QI 2 "nop_general_operand"   "r,L,P,O,K,n,Qm")))]
3863   ""
3864   {
3865     return lshrsi3_out (insn, operands, NULL);
3866   }
3867   [(set_attr "length" "8,0,4,4,8,10,12")
3868    (set_attr "adjust_len" "lshrsi")
3869    (set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber,clobber")])
3871 ;; Optimize if a scratch register from LD_REGS happens to be available.
3873 (define_peephole2 ; lshrqi3_l_const4
3874   [(set (match_operand:ALL1 0 "l_register_operand" "")
3875         (lshiftrt:ALL1 (match_dup 0)
3876                        (const_int 4)))
3877    (match_scratch:QI 1 "d")]
3878   ""
3879   [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4)))
3880    (set (match_dup 1) (const_int 15))
3881    (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))]
3882   {
3883     operands[2] = avr_to_int_mode (operands[0]);
3884   })
3886 (define_peephole2 ; lshrqi3_l_const5
3887   [(set (match_operand:ALL1 0 "l_register_operand" "")
3888         (lshiftrt:ALL1 (match_dup 0)
3889                        (const_int 5)))
3890    (match_scratch:QI 1 "d")]
3891   ""
3892   [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4)))
3893    (set (match_dup 2) (lshiftrt:QI (match_dup 2) (const_int 1)))
3894    (set (match_dup 1) (const_int 7))
3895    (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))]
3896   {
3897     operands[2] = avr_to_int_mode (operands[0]);
3898   })
3900 (define_peephole2 ; lshrqi3_l_const6
3901   [(set (match_operand:ALL1 0 "l_register_operand" "")
3902         (lshiftrt:ALL1 (match_dup 0)
3903                        (const_int 6)))
3904    (match_scratch:QI 1 "d")]
3905   ""
3906   [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4)))
3907    (set (match_dup 2) (lshiftrt:QI (match_dup 2) (const_int 2)))
3908    (set (match_dup 1) (const_int 3))
3909    (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))]
3910   {
3911     operands[2] = avr_to_int_mode (operands[0]);
3912   })
3914 (define_peephole2
3915   [(match_scratch:QI 3 "d")
3916    (set (match_operand:ALL2 0 "register_operand" "")
3917         (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "")
3918                        (match_operand:QI 2 "const_int_operand" "")))]
3919   ""
3920   [(parallel [(set (match_dup 0)
3921                    (lshiftrt:ALL2 (match_dup 1)
3922                                   (match_dup 2)))
3923               (clobber (match_dup 3))])])
3925 ;; "*lshrhi3_const"
3926 ;; "*lshrhq3_const"  "*lshruhq3_const"
3927 ;; "*lshrha3_const"  "*lshruha3_const"
3928 (define_insn "*lshr<mode>3_const"
3929   [(set (match_operand:ALL2 0 "register_operand"                "=r,r,r,r,r")
3930         (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand"  "0,0,r,0,0")
3931                        (match_operand:QI 2 "const_int_operand"   "L,P,O,K,n")))
3932    (clobber (match_scratch:QI 3                                 "=X,X,X,X,&d"))]
3933   "reload_completed"
3934   {
3935     return lshrhi3_out (insn, operands, NULL);
3936   }
3937   [(set_attr "length" "0,2,2,4,10")
3938    (set_attr "adjust_len" "lshrhi")
3939    (set_attr "cc" "none,clobber,clobber,clobber,clobber")])
3941 (define_peephole2
3942   [(match_scratch:QI 3 "d")
3943    (set (match_operand:ALL4 0 "register_operand" "")
3944         (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "")
3945                        (match_operand:QI 2 "const_int_operand" "")))]
3946   ""
3947   [(parallel [(set (match_dup 0)
3948                    (lshiftrt:ALL4 (match_dup 1)
3949                                   (match_dup 2)))
3950               (clobber (match_dup 3))])])
3952 ;; "*lshrsi3_const"
3953 ;; "*lshrsq3_const"  "*lshrusq3_const"
3954 ;; "*lshrsa3_const"  "*lshrusa3_const"
3955 (define_insn "*lshr<mode>3_const"
3956   [(set (match_operand:ALL4 0 "register_operand"               "=r,r,r,r")
3957         (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r,0")
3958                        (match_operand:QI 2 "const_int_operand"  "L,P,O,n")))
3959    (clobber (match_scratch:QI 3                                "=X,X,X,&d"))]
3960   "reload_completed"
3961   {
3962     return lshrsi3_out (insn, operands, NULL);
3963   }
3964   [(set_attr "length" "0,4,4,10")
3965    (set_attr "adjust_len" "lshrsi")
3966    (set_attr "cc" "none,clobber,clobber,clobber")])
3968 ;; abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x)
3969 ;; abs
3971 (define_insn "absqi2"
3972   [(set (match_operand:QI 0 "register_operand" "=r")
3973         (abs:QI (match_operand:QI 1 "register_operand" "0")))]
3974   ""
3975   "sbrc %0,7
3976         neg %0"
3977   [(set_attr "length" "2")
3978    (set_attr "cc" "clobber")])
3981 (define_insn "abssf2"
3982   [(set (match_operand:SF 0 "register_operand" "=d,r")
3983         (abs:SF (match_operand:SF 1 "register_operand" "0,0")))]
3984   ""
3985   "@
3986         andi %D0,0x7f
3987         clt\;bld %D0,7"
3988   [(set_attr "length" "1,2")
3989    (set_attr "cc" "set_n,clobber")])
3991 ;; 0 - x  0 - x  0 - x  0 - x  0 - x  0 - x  0 - x  0 - x  0 - x  0 - x  0 - x
3992 ;; neg
3994 (define_insn "negqi2"
3995   [(set (match_operand:QI 0 "register_operand" "=r")
3996         (neg:QI (match_operand:QI 1 "register_operand" "0")))]
3997   ""
3998   "neg %0"
3999   [(set_attr "length" "1")
4000    (set_attr "cc" "set_zn")])
4002 (define_insn "*negqihi2"
4003   [(set (match_operand:HI 0 "register_operand"                        "=r")
4004         (neg:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "0"))))]
4005   ""
4006   "clr %B0\;neg %A0\;brge .+2\;com %B0"
4007   [(set_attr "length" "4")
4008    (set_attr "cc" "set_n")])
4010 (define_insn "neghi2"
4011   [(set (match_operand:HI 0 "register_operand"        "=r,&r")
4012         (neg:HI (match_operand:HI 1 "register_operand" "0,r")))]
4013   ""
4014   "@
4015         neg %B0\;neg %A0\;sbc %B0,__zero_reg__
4016         clr %A0\;clr %B0\;sub %A0,%A1\;sbc %B0,%B1"
4017   [(set_attr "length" "3,4")
4018    (set_attr "cc" "set_czn")])
4020 (define_insn "negpsi2"
4021   [(set (match_operand:PSI 0 "register_operand"        "=!d,r,&r")
4022         (neg:PSI (match_operand:PSI 1 "register_operand" "0,0,r")))]
4023   ""
4024   "@
4025         com %C0\;com %B0\;neg %A0\;sbci %B0,-1\;sbci %C0,-1
4026         com %C0\;com %B0\;com %A0\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__
4027         clr %A0\;clr %B0\;clr %C0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1"
4028   [(set_attr "length" "5,6,6")
4029    (set_attr "cc" "set_czn,set_n,set_czn")])
4031 (define_insn "negsi2"
4032   [(set (match_operand:SI 0 "register_operand"       "=!d,r,&r,&r")
4033         (neg:SI (match_operand:SI 1 "register_operand" "0,0,r ,r")))]
4034   ""
4035   "@
4036         com %D0\;com %C0\;com %B0\;neg %A0\;sbci %B0,lo8(-1)\;sbci %C0,lo8(-1)\;sbci %D0,lo8(-1)
4037         com %D0\;com %C0\;com %B0\;com %A0\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__
4038         clr %A0\;clr %B0\;clr %C0\;clr %D0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1
4039         clr %A0\;clr %B0\;movw %C0,%A0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1"
4040   [(set_attr "length" "7,8,8,7")
4041    (set_attr "isa"    "*,*,mov,movw")
4042    (set_attr "cc" "set_czn,set_n,set_czn,set_czn")])
4044 (define_insn "negsf2"
4045   [(set (match_operand:SF 0 "register_operand" "=d,r")
4046         (neg:SF (match_operand:SF 1 "register_operand" "0,0")))]
4047   ""
4048   "@
4049         subi %D0,0x80
4050         bst %D0,7\;com %D0\;bld %D0,7\;com %D0"
4051   [(set_attr "length" "1,4")
4052    (set_attr "cc" "set_n,set_n")])
4054 ;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4055 ;; not
4057 (define_insn "one_cmplqi2"
4058   [(set (match_operand:QI 0 "register_operand" "=r")
4059         (not:QI (match_operand:QI 1 "register_operand" "0")))]
4060   ""
4061   "com %0"
4062   [(set_attr "length" "1")
4063    (set_attr "cc" "set_czn")])
4065 (define_insn "one_cmplhi2"
4066   [(set (match_operand:HI 0 "register_operand" "=r")
4067         (not:HI (match_operand:HI 1 "register_operand" "0")))]
4068   ""
4069   "com %0
4070         com %B0"
4071   [(set_attr "length" "2")
4072    (set_attr "cc" "set_n")])
4074 (define_insn "one_cmplpsi2"
4075   [(set (match_operand:PSI 0 "register_operand" "=r")
4076         (not:PSI (match_operand:PSI 1 "register_operand" "0")))]
4077   ""
4078   "com %0\;com %B0\;com %C0"
4079   [(set_attr "length" "3")
4080    (set_attr "cc" "set_n")])
4082 (define_insn "one_cmplsi2"
4083   [(set (match_operand:SI 0 "register_operand" "=r")
4084         (not:SI (match_operand:SI 1 "register_operand" "0")))]
4085   ""
4086   "com %0
4087         com %B0
4088         com %C0
4089         com %D0"
4090   [(set_attr "length" "4")
4091    (set_attr "cc" "set_n")])
4093 ;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
4094 ;; sign extend
4096 ;; We keep combiner from inserting hard registers into the input of sign- and
4097 ;; zero-extends.  A hard register in the input operand is not wanted because
4098 ;; 32-bit multiply patterns clobber some hard registers and extends with a
4099 ;; hard register that overlaps these clobbers won't be combined to a widening
4100 ;; multiplication.  There is no need for combine to propagate hard registers,
4101 ;; register allocation can do it just as well.
4103 (define_insn "extendqihi2"
4104   [(set (match_operand:HI 0 "register_operand" "=r,r")
4105         (sign_extend:HI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))]
4106   ""
4107   "@
4108         clr %B0\;sbrc %0,7\;com %B0
4109         mov %A0,%A1\;clr %B0\;sbrc %A0,7\;com %B0"
4110   [(set_attr "length" "3,4")
4111    (set_attr "cc" "set_n,set_n")])
4113 (define_insn "extendqipsi2"
4114   [(set (match_operand:PSI 0 "register_operand" "=r,r")
4115         (sign_extend:PSI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))]
4116   ""
4117   "@
4118         clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0
4119         mov %A0,%A1\;clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0"
4120   [(set_attr "length" "4,5")
4121    (set_attr "cc" "set_n,set_n")])
4123 (define_insn "extendqisi2"
4124   [(set (match_operand:SI 0 "register_operand" "=r,r")
4125         (sign_extend:SI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))]
4126   ""
4127   "@
4128         clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0\;mov %D0,%B0
4129         mov %A0,%A1\;clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0\;mov %D0,%B0"
4130   [(set_attr "length" "5,6")
4131    (set_attr "cc" "set_n,set_n")])
4133 (define_insn "extendhipsi2"
4134   [(set (match_operand:PSI 0 "register_operand"                               "=r,r ,r")
4135         (sign_extend:PSI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r,*r")))]
4136   ""
4137   "@
4138         clr %C0\;sbrc %B0,7\;com %C0
4139         mov %A0,%A1\;mov %B0,%B1\;clr %C0\;sbrc %B0,7\;com %C0
4140         movw %A0,%A1\;clr %C0\;sbrc %B0,7\;com %C0"
4141   [(set_attr "length" "3,5,4")
4142    (set_attr "isa" "*,mov,movw")
4143    (set_attr "cc" "set_n")])
4145 (define_insn "extendhisi2"
4146   [(set (match_operand:SI 0 "register_operand"                               "=r,r ,r")
4147         (sign_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r,*r")))]
4148   ""
4149   "@
4150         clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0
4151         mov %A0,%A1\;mov %B0,%B1\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0
4152         movw %A0,%A1\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0"
4153   [(set_attr "length" "4,6,5")
4154    (set_attr "isa" "*,mov,movw")
4155    (set_attr "cc" "set_n")])
4157 (define_insn "extendpsisi2"
4158   [(set (match_operand:SI 0 "register_operand"                                "=r")
4159         (sign_extend:SI (match_operand:PSI 1 "combine_pseudo_register_operand" "0")))]
4160   ""
4161   "clr %D0\;sbrc %C0,7\;com %D0"
4162   [(set_attr "length" "3")
4163    (set_attr "cc" "set_n")])
4165 ;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
4166 ;; zero extend
4168 (define_insn_and_split "zero_extendqihi2"
4169   [(set (match_operand:HI 0 "register_operand" "=r")
4170         (zero_extend:HI (match_operand:QI 1 "combine_pseudo_register_operand" "r")))]
4171   ""
4172   "#"
4173   "reload_completed"
4174   [(set (match_dup 2) (match_dup 1))
4175    (set (match_dup 3) (const_int 0))]
4177   unsigned int low_off = subreg_lowpart_offset (QImode, HImode);
4178   unsigned int high_off = subreg_highpart_offset (QImode, HImode);
4180   operands[2] = simplify_gen_subreg (QImode, operands[0], HImode, low_off);
4181   operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, high_off);
4184 (define_insn_and_split "zero_extendqipsi2"
4185   [(set (match_operand:PSI 0 "register_operand" "=r")
4186         (zero_extend:PSI (match_operand:QI 1 "combine_pseudo_register_operand" "r")))]
4187   ""
4188   "#"
4189   "reload_completed"
4190   [(set (match_dup 2) (match_dup 1))
4191    (set (match_dup 3) (const_int 0))
4192    (set (match_dup 4) (const_int 0))]
4193   {
4194     operands[2] = simplify_gen_subreg (QImode, operands[0], PSImode, 0);
4195     operands[3] = simplify_gen_subreg (QImode, operands[0], PSImode, 1);
4196     operands[4] = simplify_gen_subreg (QImode, operands[0], PSImode, 2);
4197   })
4199 (define_insn_and_split "zero_extendqisi2"
4200   [(set (match_operand:SI 0 "register_operand" "=r")
4201         (zero_extend:SI (match_operand:QI 1 "combine_pseudo_register_operand" "r")))]
4202   ""
4203   "#"
4204   "reload_completed"
4205   [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
4206    (set (match_dup 3) (const_int 0))]
4208   unsigned int low_off = subreg_lowpart_offset (HImode, SImode);
4209   unsigned int high_off = subreg_highpart_offset (HImode, SImode);
4211   operands[2] = simplify_gen_subreg (HImode, operands[0], SImode, low_off);
4212   operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off);
4215 (define_insn_and_split "zero_extendhipsi2"
4216   [(set (match_operand:PSI 0 "register_operand"                               "=r")
4217         (zero_extend:PSI (match_operand:HI 1 "combine_pseudo_register_operand" "r")))]
4218   ""
4219   "#"
4220   "reload_completed"
4221   [(set (match_dup 2) (match_dup 1))
4222    (set (match_dup 3) (const_int 0))]
4223   {
4224     operands[2] = simplify_gen_subreg (HImode, operands[0], PSImode, 0);
4225     operands[3] = simplify_gen_subreg (QImode, operands[0], PSImode, 2);
4226   })
4228 (define_insn_and_split "n_extendhipsi2"
4229   [(set (match_operand:PSI 0 "register_operand"            "=r,r,d,r")
4230         (lo_sum:PSI (match_operand:QI 1 "const_int_operand" "L,P,n,n")
4231                     (match_operand:HI 2 "register_operand"  "r,r,r,r")))
4232    (clobber (match_scratch:QI 3                            "=X,X,X,&d"))]
4233   ""
4234   "#"
4235   "reload_completed"
4236   [(set (match_dup 4) (match_dup 2))
4237    (set (match_dup 3) (match_dup 6))
4238    ; no-op move in the case where no scratch is needed
4239    (set (match_dup 5) (match_dup 3))]
4240   {
4241     operands[4] = simplify_gen_subreg (HImode, operands[0], PSImode, 0);
4242     operands[5] = simplify_gen_subreg (QImode, operands[0], PSImode, 2);
4243     operands[6] = operands[1];
4245     if (GET_CODE (operands[3]) == SCRATCH)
4246       operands[3] = operands[5];
4247   })
4249 (define_insn_and_split "zero_extendhisi2"
4250   [(set (match_operand:SI 0 "register_operand"                               "=r")
4251         (zero_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "r")))]
4252   ""
4253   "#"
4254   "reload_completed"
4255   [(set (match_dup 2) (match_dup 1))
4256    (set (match_dup 3) (const_int 0))]
4258   unsigned int low_off = subreg_lowpart_offset (HImode, SImode);
4259   unsigned int high_off = subreg_highpart_offset (HImode, SImode);
4261   operands[2] = simplify_gen_subreg (HImode, operands[0], SImode, low_off);
4262   operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off);
4265 (define_insn_and_split "zero_extendpsisi2"
4266   [(set (match_operand:SI 0 "register_operand"                                "=r")
4267         (zero_extend:SI (match_operand:PSI 1 "combine_pseudo_register_operand" "r")))]
4268   ""
4269   "#"
4270   "reload_completed"
4271   [(set (match_dup 2) (match_dup 1))
4272    (set (match_dup 3) (const_int 0))]
4273   {
4274     operands[2] = simplify_gen_subreg (PSImode, operands[0], SImode, 0);
4275     operands[3] = simplify_gen_subreg (QImode, operands[0], SImode, 3);
4276   })
4278 (define_insn_and_split "zero_extendqidi2"
4279   [(set (match_operand:DI 0 "register_operand" "=r")
4280         (zero_extend:DI (match_operand:QI 1 "register_operand" "r")))]
4281   ""
4282   "#"
4283   "reload_completed"
4284   [(set (match_dup 2) (zero_extend:SI (match_dup 1)))
4285    (set (match_dup 3) (const_int 0))]
4287   unsigned int low_off = subreg_lowpart_offset (SImode, DImode);
4288   unsigned int high_off = subreg_highpart_offset (SImode, DImode);
4290   operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off);
4291   operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off);
4294 (define_insn_and_split "zero_extendhidi2"
4295   [(set (match_operand:DI 0 "register_operand" "=r")
4296         (zero_extend:DI (match_operand:HI 1 "register_operand" "r")))]
4297   ""
4298   "#"
4299   "reload_completed"
4300   [(set (match_dup 2) (zero_extend:SI (match_dup 1)))
4301    (set (match_dup 3) (const_int 0))]
4303   unsigned int low_off = subreg_lowpart_offset (SImode, DImode);
4304   unsigned int high_off = subreg_highpart_offset (SImode, DImode);
4306   operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off);
4307   operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off);
4310 (define_insn_and_split "zero_extendsidi2"
4311   [(set (match_operand:DI 0 "register_operand" "=r")
4312         (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
4313   ""
4314   "#"
4315   "reload_completed"
4316   [(set (match_dup 2) (match_dup 1))
4317    (set (match_dup 3) (const_int 0))]
4319   unsigned int low_off = subreg_lowpart_offset (SImode, DImode);
4320   unsigned int high_off = subreg_highpart_offset (SImode, DImode);
4322   operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off);
4323   operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off);
4326 ;;<=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=>
4327 ;; compare
4329 ; Optimize negated tests into reverse compare if overflow is undefined.
4330 (define_insn "*negated_tstqi"
4331   [(set (cc0)
4332         (compare (neg:QI (match_operand:QI 0 "register_operand" "r"))
4333                  (const_int 0)))]
4334   "!flag_wrapv && !flag_trapv && flag_strict_overflow"
4335   "cp __zero_reg__,%0"
4336   [(set_attr "cc" "compare")
4337    (set_attr "length" "1")])
4339 (define_insn "*reversed_tstqi"
4340   [(set (cc0)
4341         (compare (const_int 0)
4342                  (match_operand:QI 0 "register_operand" "r")))]
4343   ""
4344   "cp __zero_reg__,%0"
4345 [(set_attr "cc" "compare")
4346  (set_attr "length" "2")])
4348 (define_insn "*negated_tsthi"
4349   [(set (cc0)
4350         (compare (neg:HI (match_operand:HI 0 "register_operand" "r"))
4351                  (const_int 0)))]
4352   "!flag_wrapv && !flag_trapv && flag_strict_overflow"
4353   "cp __zero_reg__,%A0
4354         cpc __zero_reg__,%B0"
4355 [(set_attr "cc" "compare")
4356  (set_attr "length" "2")])
4358 ;; Leave here the clobber used by the cmphi pattern for simplicity, even
4359 ;; though it is unused, because this pattern is synthesized by avr_reorg.
4360 (define_insn "*reversed_tsthi"
4361   [(set (cc0)
4362         (compare (const_int 0)
4363                  (match_operand:HI 0 "register_operand" "r")))
4364    (clobber (match_scratch:QI 1 "=X"))]
4365   ""
4366   "cp __zero_reg__,%A0
4367         cpc __zero_reg__,%B0"
4368 [(set_attr "cc" "compare")
4369  (set_attr "length" "2")])
4371 (define_insn "*negated_tstpsi"
4372   [(set (cc0)
4373         (compare (neg:PSI (match_operand:PSI 0 "register_operand" "r"))
4374                  (const_int 0)))]
4375   "!flag_wrapv && !flag_trapv && flag_strict_overflow"
4376   "cp __zero_reg__,%A0\;cpc __zero_reg__,%B0\;cpc __zero_reg__,%C0"
4377   [(set_attr "cc" "compare")
4378    (set_attr "length" "3")])
4380 (define_insn "*reversed_tstpsi"
4381   [(set (cc0)
4382         (compare (const_int 0)
4383                  (match_operand:PSI 0 "register_operand" "r")))
4384    (clobber (match_scratch:QI 1 "=X"))]
4385   ""
4386   "cp __zero_reg__,%A0\;cpc __zero_reg__,%B0\;cpc __zero_reg__,%C0"
4387   [(set_attr "cc" "compare")
4388    (set_attr "length" "3")])
4390 (define_insn "*negated_tstsi"
4391   [(set (cc0)
4392         (compare (neg:SI (match_operand:SI 0 "register_operand" "r"))
4393                  (const_int 0)))]
4394   "!flag_wrapv && !flag_trapv && flag_strict_overflow"
4395   "cp __zero_reg__,%A0
4396         cpc __zero_reg__,%B0
4397         cpc __zero_reg__,%C0
4398         cpc __zero_reg__,%D0"
4399   [(set_attr "cc" "compare")
4400    (set_attr "length" "4")])
4402 ;; "*reversed_tstsi"
4403 ;; "*reversed_tstsq" "*reversed_tstusq"
4404 ;; "*reversed_tstsa" "*reversed_tstusa"
4405 (define_insn "*reversed_tst<mode>"
4406   [(set (cc0)
4407         (compare (match_operand:ALL4 0 "const0_operand"   "Y00")
4408                  (match_operand:ALL4 1 "register_operand" "r")))
4409    (clobber (match_scratch:QI 2 "=X"))]
4410   ""
4411   "cp __zero_reg__,%A1
4412         cpc __zero_reg__,%B1
4413         cpc __zero_reg__,%C1
4414         cpc __zero_reg__,%D1"
4415   [(set_attr "cc" "compare")
4416    (set_attr "length" "4")])
4419 ;; "*cmpqi"
4420 ;; "*cmpqq" "*cmpuqq"
4421 (define_insn "*cmp<mode>"
4422   [(set (cc0)
4423         (compare (match_operand:ALL1 0 "register_operand"  "r  ,r,d")
4424                  (match_operand:ALL1 1 "nonmemory_operand" "Y00,r,i")))]
4425   ""
4426   "@
4427         tst %0
4428         cp %0,%1
4429         cpi %0,lo8(%1)"
4430   [(set_attr "cc" "compare,compare,compare")
4431    (set_attr "length" "1,1,1")])
4433 (define_insn "*cmpqi_sign_extend"
4434   [(set (cc0)
4435         (compare (sign_extend:HI (match_operand:QI 0 "register_operand" "d"))
4436                  (match_operand:HI 1 "s8_operand"                       "n")))]
4437   ""
4438   "cpi %0,lo8(%1)"
4439   [(set_attr "cc" "compare")
4440    (set_attr "length" "1")])
4442 ;; "*cmphi"
4443 ;; "*cmphq" "*cmpuhq"
4444 ;; "*cmpha" "*cmpuha"
4445 (define_insn "*cmp<mode>"
4446   [(set (cc0)
4447         (compare (match_operand:ALL2 0 "register_operand"  "!w  ,r  ,r,d ,r  ,d,r")
4448                  (match_operand:ALL2 1 "nonmemory_operand"  "Y00,Y00,r,s ,s  ,M,n Ynn")))
4449    (clobber (match_scratch:QI 2                            "=X  ,X  ,X,&d,&d ,X,&d"))]
4450   ""
4451   {
4452     switch (which_alternative)
4453       {
4454       case 0:
4455       case 1:
4456         return avr_out_tsthi (insn, operands, NULL);
4457         
4458       case 2:
4459         return "cp %A0,%A1\;cpc %B0,%B1";
4461       case 3:
4462         if (<MODE>mode != HImode)
4463           break;
4464         return reg_unused_after (insn, operands[0])
4465                ? "subi %A0,lo8(%1)\;sbci %B0,hi8(%1)"
4466                : "ldi %2,hi8(%1)\;cpi %A0,lo8(%1)\;cpc %B0,%2";
4467                
4468       case 4:
4469         if (<MODE>mode != HImode)
4470           break;
4471         return "ldi %2,lo8(%1)\;cp %A0,%2\;ldi %2,hi8(%1)\;cpc %B0,%2";
4472       }
4473       
4474     return avr_out_compare (insn, operands, NULL);
4475   } 
4476   [(set_attr "cc" "compare")
4477    (set_attr "length" "1,2,2,3,4,2,4")
4478    (set_attr "adjust_len" "tsthi,tsthi,*,*,*,compare,compare")])
4480 (define_insn "*cmppsi"
4481   [(set (cc0)
4482         (compare (match_operand:PSI 0 "register_operand"  "r,r,d ,r  ,d,r")
4483                  (match_operand:PSI 1 "nonmemory_operand" "L,r,s ,s  ,M,n")))
4484    (clobber (match_scratch:QI 2                          "=X,X,&d,&d ,X,&d"))]
4485   ""
4486   {
4487     switch (which_alternative)
4488       {
4489       case 0:
4490         return avr_out_tstpsi (insn, operands, NULL);
4492       case 1:
4493         return "cp %A0,%A1\;cpc %B0,%B1\;cpc %C0,%C1";
4495       case 2:
4496         return reg_unused_after (insn, operands[0])
4497                ? "subi %A0,lo8(%1)\;sbci %B0,hi8(%1)\;sbci %C0,hh8(%1)"
4498                : "cpi %A0,lo8(%1)\;ldi %2,hi8(%1)\;cpc %B0,%2\;ldi %2,hh8(%1)\;cpc %C0,%2";
4499                
4500       case 3:
4501         return "ldi %2,lo8(%1)\;cp %A0,%2\;ldi %2,hi8(%1)\;cpc %B0,%2\;ldi %2,hh8(%1)\;cpc %C0,%2";
4502       }
4503     
4504     return avr_out_compare (insn, operands, NULL);
4505   }
4506   [(set_attr "cc" "compare")
4507    (set_attr "length" "3,3,5,6,3,7")
4508    (set_attr "adjust_len" "tstpsi,*,*,*,compare,compare")])
4510 ;; "*cmpsi"
4511 ;; "*cmpsq" "*cmpusq"
4512 ;; "*cmpsa" "*cmpusa"
4513 (define_insn "*cmp<mode>"
4514   [(set (cc0)
4515         (compare (match_operand:ALL4 0 "register_operand"  "r  ,r ,d,r ,r")
4516                  (match_operand:ALL4 1 "nonmemory_operand" "Y00,r ,M,M ,n Ynn")))
4517    (clobber (match_scratch:QI 2                           "=X  ,X ,X,&d,&d"))]
4518   ""
4519   {
4520     if (0 == which_alternative)
4521       return avr_out_tstsi (insn, operands, NULL);
4522     else if (1 == which_alternative)
4523       return "cp %A0,%A1\;cpc %B0,%B1\;cpc %C0,%C1\;cpc %D0,%D1";
4524       
4525     return avr_out_compare (insn, operands, NULL);
4526   }
4527   [(set_attr "cc" "compare")
4528    (set_attr "length" "4,4,4,5,8")
4529    (set_attr "adjust_len" "tstsi,*,compare,compare,compare")])
4532 ;; ----------------------------------------------------------------------
4533 ;; JUMP INSTRUCTIONS
4534 ;; ----------------------------------------------------------------------
4535 ;; Conditional jump instructions
4537 ;; "cbranchqi4"
4538 ;; "cbranchqq4"  "cbranchuqq4"
4539 (define_expand "cbranch<mode>4"
4540   [(set (cc0)
4541         (compare (match_operand:ALL1 1 "register_operand" "")
4542                  (match_operand:ALL1 2 "nonmemory_operand" "")))
4543    (set (pc)
4544         (if_then_else
4545          (match_operator 0 "ordered_comparison_operator" [(cc0)
4546                                                           (const_int 0)])
4547          (label_ref (match_operand 3 "" ""))
4548          (pc)))])
4550 ;; "cbranchhi4"  "cbranchhq4"  "cbranchuhq4"  "cbranchha4"  "cbranchuha4"
4551 ;; "cbranchsi4"  "cbranchsq4"  "cbranchusq4"  "cbranchsa4"  "cbranchusa4"
4552 ;; "cbranchpsi4"
4553 (define_expand "cbranch<mode>4"
4554   [(parallel [(set (cc0)
4555                    (compare (match_operand:ORDERED234 1 "register_operand" "")
4556                             (match_operand:ORDERED234 2 "nonmemory_operand" "")))
4557               (clobber (match_scratch:QI 4 ""))])
4558    (set (pc)
4559         (if_then_else
4560          (match_operator 0 "ordered_comparison_operator" [(cc0)
4561                                                           (const_int 0)])
4562          (label_ref (match_operand 3 "" ""))
4563          (pc)))])
4566 ;; Test a single bit in a QI/HI/SImode register.
4567 ;; Combine will create zero extract patterns for single bit tests.
4568 ;; permit any mode in source pattern by using VOIDmode.
4570 (define_insn "*sbrx_branch<mode>"
4571   [(set (pc)
4572         (if_then_else
4573          (match_operator 0 "eqne_operator"
4574                          [(zero_extract:QIDI
4575                            (match_operand:VOID 1 "register_operand" "r")
4576                            (const_int 1)
4577                            (match_operand 2 "const_int_operand" "n"))
4578                           (const_int 0)])
4579          (label_ref (match_operand 3 "" ""))
4580          (pc)))]
4581   ""
4582   {
4583     return avr_out_sbxx_branch (insn, operands);
4584   }
4585   [(set (attr "length")
4586         (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
4587                            (le (minus (pc) (match_dup 3)) (const_int 2046)))
4588                       (const_int 2)
4589                       (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
4590                                     (const_int 2)
4591                                     (const_int 4))))
4592    (set_attr "cc" "clobber")])
4594 ;; Same test based on bitwise AND.  Keep this in case gcc changes patterns.
4595 ;; or for old peepholes.
4596 ;; Fixme - bitwise Mask will not work for DImode
4598 (define_insn "*sbrx_and_branch<mode>"
4599   [(set (pc)
4600         (if_then_else
4601          (match_operator 0 "eqne_operator"
4602                          [(and:QISI
4603                            (match_operand:QISI 1 "register_operand" "r")
4604                            (match_operand:QISI 2 "single_one_operand" "n"))
4605                           (const_int 0)])
4606          (label_ref (match_operand 3 "" ""))
4607          (pc)))]
4608   ""
4609   {
4610     HOST_WIDE_INT bitnumber;
4611     bitnumber = exact_log2 (GET_MODE_MASK (<MODE>mode) & INTVAL (operands[2]));
4612     operands[2] = GEN_INT (bitnumber);
4613     return avr_out_sbxx_branch (insn, operands);
4614   }
4615   [(set (attr "length")
4616         (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
4617                            (le (minus (pc) (match_dup 3)) (const_int 2046)))
4618                       (const_int 2)
4619                       (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
4620                                     (const_int 2)
4621                                     (const_int 4))))
4622    (set_attr "cc" "clobber")])
4624 ;; Convert sign tests to bit 7/15/31 tests that match the above insns.
4625 (define_peephole2
4626   [(set (cc0) (compare (match_operand:QI 0 "register_operand" "")
4627                        (const_int 0)))
4628    (set (pc) (if_then_else (ge (cc0) (const_int 0))
4629                            (label_ref (match_operand 1 "" ""))
4630                            (pc)))]
4631   ""
4632   [(set (pc) (if_then_else (eq (zero_extract:HI (match_dup 0)
4633                                                 (const_int 1)
4634                                                 (const_int 7))
4635                                (const_int 0))
4636                            (label_ref (match_dup 1))
4637                            (pc)))])
4639 (define_peephole2
4640   [(set (cc0) (compare (match_operand:QI 0 "register_operand" "")
4641                        (const_int 0)))
4642    (set (pc) (if_then_else (lt (cc0) (const_int 0))
4643                            (label_ref (match_operand 1 "" ""))
4644                            (pc)))]
4645   ""
4646   [(set (pc) (if_then_else (ne (zero_extract:HI (match_dup 0)
4647                                                 (const_int 1)
4648                                                 (const_int 7))
4649                                (const_int 0))
4650                            (label_ref (match_dup 1))
4651                            (pc)))])
4653 (define_peephole2
4654   [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "")
4655                                   (const_int 0)))
4656               (clobber (match_operand:HI 2 ""))])
4657    (set (pc) (if_then_else (ge (cc0) (const_int 0))
4658                            (label_ref (match_operand 1 "" ""))
4659                            (pc)))]
4660   ""
4661   [(set (pc) (if_then_else (eq (and:HI (match_dup 0) (const_int -32768))
4662                                (const_int 0))
4663                            (label_ref (match_dup 1))
4664                            (pc)))])
4666 (define_peephole2
4667   [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "")
4668                                   (const_int 0)))
4669               (clobber (match_operand:HI 2 ""))])
4670    (set (pc) (if_then_else (lt (cc0) (const_int 0))
4671                            (label_ref (match_operand 1 "" ""))
4672                            (pc)))]
4673   ""
4674   [(set (pc) (if_then_else (ne (and:HI (match_dup 0) (const_int -32768))
4675                                (const_int 0))
4676                            (label_ref (match_dup 1))
4677                            (pc)))])
4679 (define_peephole2
4680   [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
4681                                   (const_int 0)))
4682               (clobber (match_operand:SI 2 ""))])
4683    (set (pc) (if_then_else (ge (cc0) (const_int 0))
4684                            (label_ref (match_operand 1 "" ""))
4685                            (pc)))]
4686   ""
4687   [(set (pc) (if_then_else (eq (and:SI (match_dup 0) (match_dup 2))
4688                                (const_int 0))
4689                            (label_ref (match_dup 1))
4690                            (pc)))]
4691   "operands[2] = gen_int_mode (-2147483647 - 1, SImode);")
4693 (define_peephole2
4694   [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
4695                                   (const_int 0)))
4696               (clobber (match_operand:SI 2 ""))])
4697    (set (pc) (if_then_else (lt (cc0) (const_int 0))
4698                            (label_ref (match_operand 1 "" ""))
4699                            (pc)))]
4700   ""
4701   [(set (pc) (if_then_else (ne (and:SI (match_dup 0) (match_dup 2))
4702                                (const_int 0))
4703                            (label_ref (match_dup 1))
4704                            (pc)))]
4705   "operands[2] = gen_int_mode (-2147483647 - 1, SImode);")
4707 ;; ************************************************************************
4708 ;; Implementation of conditional jumps here.
4709 ;;  Compare with 0 (test) jumps
4710 ;; ************************************************************************
4712 (define_insn "branch"
4713   [(set (pc)
4714         (if_then_else (match_operator 1 "simple_comparison_operator"
4715                                       [(cc0)
4716                                        (const_int 0)])
4717                       (label_ref (match_operand 0 "" ""))
4718                       (pc)))]
4719   ""
4720   {
4721     return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 0);
4722   }
4723   [(set_attr "type" "branch")
4724    (set_attr "cc" "clobber")])
4727 ;; Same as above but wrap SET_SRC so that this branch won't be transformed
4728 ;; or optimized in the remainder.
4730 (define_insn "branch_unspec"
4731   [(set (pc)
4732         (unspec [(if_then_else (match_operator 1 "simple_comparison_operator"
4733                                                [(cc0)
4734                                                 (const_int 0)])
4735                                (label_ref (match_operand 0 "" ""))
4736                                (pc))
4737                  ] UNSPEC_IDENTITY))]
4738   ""
4739   {
4740     return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 0);
4741   }
4742   [(set_attr "type" "branch")
4743    (set_attr "cc" "none")])
4745 ;; ****************************************************************
4746 ;; AVR does not have following conditional jumps: LE,LEU,GT,GTU.
4747 ;; Convert them all to proper jumps.
4748 ;; ****************************************************************/
4750 (define_insn "difficult_branch"
4751   [(set (pc)
4752         (if_then_else (match_operator 1 "difficult_comparison_operator"
4753                         [(cc0)
4754                          (const_int 0)])
4755                       (label_ref (match_operand 0 "" ""))
4756                       (pc)))]
4757   ""
4758   {
4759     return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 0);
4760   }
4761   [(set_attr "type" "branch1")
4762    (set_attr "cc" "clobber")])
4764 ;; revers branch
4766 (define_insn "rvbranch"
4767   [(set (pc)
4768         (if_then_else (match_operator 1 "simple_comparison_operator" 
4769                                       [(cc0)
4770                                        (const_int 0)])
4771                       (pc)
4772                       (label_ref (match_operand 0 "" ""))))]
4773   ""
4774   {
4775     return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 1);
4776   }
4777   [(set_attr "type" "branch1")
4778    (set_attr "cc" "clobber")])
4780 (define_insn "difficult_rvbranch"
4781   [(set (pc)
4782         (if_then_else (match_operator 1 "difficult_comparison_operator" 
4783                                       [(cc0)
4784                                        (const_int 0)])
4785                       (pc)
4786                       (label_ref (match_operand 0 "" ""))))]
4787   ""
4788   {
4789     return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 1);
4790   }
4791   [(set_attr "type" "branch")
4792    (set_attr "cc" "clobber")])
4794 ;; **************************************************************************
4795 ;; Unconditional and other jump instructions.
4797 (define_insn "jump"
4798   [(set (pc)
4799         (label_ref (match_operand 0 "" "")))]
4800   ""
4801   {
4802     return AVR_HAVE_JMP_CALL && get_attr_length (insn) != 1
4803            ? "jmp %x0"
4804            : "rjmp %x0";
4805   }
4806   [(set (attr "length")
4807         (if_then_else (match_operand 0 "symbol_ref_operand" "") 
4808                       (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
4809                                     (const_int 1)
4810                                     (const_int 2))
4811                       (if_then_else (and (ge (minus (pc) (match_dup 0)) (const_int -2047))
4812                                          (le (minus (pc) (match_dup 0)) (const_int 2047)))
4813                                     (const_int 1)
4814                                     (const_int 2))))
4815    (set_attr "cc" "none")])
4817 ;; call
4819 ;; Operand 1 not used on the AVR.
4820 ;; Operand 2 is 1 for tail-call, 0 otherwise.
4821 (define_expand "call"
4822   [(parallel[(call (match_operand:HI 0 "call_insn_operand" "")
4823                    (match_operand:HI 1 "general_operand" ""))
4824              (use (const_int 0))])])
4826 ;; Operand 1 not used on the AVR.
4827 ;; Operand 2 is 1 for tail-call, 0 otherwise.
4828 (define_expand "sibcall"
4829   [(parallel[(call (match_operand:HI 0 "call_insn_operand" "")
4830                    (match_operand:HI 1 "general_operand" ""))
4831              (use (const_int 1))])])
4833 ;; call value
4835 ;; Operand 2 not used on the AVR.
4836 ;; Operand 3 is 1 for tail-call, 0 otherwise.
4837 (define_expand "call_value"
4838   [(parallel[(set (match_operand 0 "register_operand" "")
4839                   (call (match_operand:HI 1 "call_insn_operand" "")
4840                         (match_operand:HI 2 "general_operand" "")))
4841              (use (const_int 0))])])
4843 ;; Operand 2 not used on the AVR.
4844 ;; Operand 3 is 1 for tail-call, 0 otherwise.
4845 (define_expand "sibcall_value"
4846   [(parallel[(set (match_operand 0 "register_operand" "")
4847                   (call (match_operand:HI 1 "call_insn_operand" "")
4848                         (match_operand:HI 2 "general_operand" "")))
4849              (use (const_int 1))])])
4851 (define_insn "call_insn"
4852   [(parallel[(call (mem:HI (match_operand:HI 0 "nonmemory_operand" "z,s,z,s"))
4853                    (match_operand:HI 1 "general_operand"           "X,X,X,X"))
4854              (use (match_operand:HI 2 "const_int_operand"          "L,L,P,P"))])]
4855   ;; Operand 1 not used on the AVR.
4856   ;; Operand 2 is 1 for tail-call, 0 otherwise.
4857   ""
4858   "@
4859     %!icall
4860     %~call %x0
4861     %!ijmp
4862     %~jmp %x0"
4863   [(set_attr "cc" "clobber")
4864    (set_attr "length" "1,*,1,*")
4865    (set_attr "adjust_len" "*,call,*,call")])
4867 (define_insn "call_value_insn"
4868   [(parallel[(set (match_operand 0 "register_operand"                   "=r,r,r,r")
4869                   (call (mem:HI (match_operand:HI 1 "nonmemory_operand"  "z,s,z,s"))
4870                         (match_operand:HI 2 "general_operand"            "X,X,X,X")))
4871              (use (match_operand:HI 3 "const_int_operand"                "L,L,P,P"))])]
4872   ;; Operand 2 not used on the AVR.
4873   ;; Operand 3 is 1 for tail-call, 0 otherwise.
4874   ""
4875   "@
4876     %!icall
4877     %~call %x1
4878     %!ijmp
4879     %~jmp %x1"
4880   [(set_attr "cc" "clobber")
4881    (set_attr "length" "1,*,1,*")
4882    (set_attr "adjust_len" "*,call,*,call")])
4884 (define_insn "nop"
4885   [(const_int 0)]
4886   ""
4887   "nop"
4888   [(set_attr "cc" "none")
4889    (set_attr "length" "1")])
4891 ; indirect jump
4893 (define_expand "indirect_jump"
4894   [(set (pc)
4895         (match_operand:HI 0 "nonmemory_operand" ""))]
4896   ""
4897   {
4898     if (!AVR_HAVE_JMP_CALL && !register_operand (operands[0], HImode))
4899       {
4900         operands[0] = copy_to_mode_reg (HImode, operands[0]);
4901       }
4902   })
4904 ; indirect jump
4905 (define_insn "*indirect_jump"
4906   [(set (pc)
4907         (match_operand:HI 0 "nonmemory_operand" "i,i,!z,*r,z"))]
4908   ""
4909   "@
4910         rjmp %x0
4911         jmp %x0
4912         ijmp
4913         push %A0\;push %B0\;ret
4914         eijmp"
4915   [(set_attr "length" "1,2,1,3,1")
4916    (set_attr "isa" "rjmp,jmp,ijmp,ijmp,eijmp")
4917    (set_attr "cc" "none")])
4919 ;; table jump
4920 ;; For entries in jump table see avr_output_addr_vec_elt.
4922 ;; Table made from
4923 ;;    "rjmp .L<n>"   instructions for <= 8K devices
4924 ;;    ".word gs(.L<n>)" addresses for >  8K devices
4925 (define_insn "*tablejump"
4926   [(set (pc)
4927         (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r,z")]
4928                    UNSPEC_INDEX_JMP))
4929    (use (label_ref (match_operand 1 "" "")))
4930    (clobber (match_dup 0))]
4931   ""
4932   "@
4933         ijmp
4934         push %A0\;push %B0\;ret
4935         jmp __tablejump2__"
4936   [(set_attr "length" "1,3,2")
4937    (set_attr "isa" "rjmp,rjmp,jmp")
4938    (set_attr "cc" "none,none,clobber")])
4941 (define_expand "casesi"
4942   [(parallel [(set (match_dup 6)
4943                    (minus:HI (subreg:HI (match_operand:SI 0 "register_operand" "") 0)
4944                              (match_operand:HI 1 "register_operand" "")))
4945               (clobber (scratch:QI))])
4946    (parallel [(set (cc0)
4947                    (compare (match_dup 6)
4948                             (match_operand:HI 2 "register_operand" "")))
4949               (clobber (match_scratch:QI 9 ""))])
4950    
4951    (set (pc)
4952         (if_then_else (gtu (cc0)
4953                            (const_int 0))
4954                       (label_ref (match_operand 4 "" ""))
4955                       (pc)))
4957    (set (match_dup 6)
4958         (plus:HI (match_dup 6) (label_ref (match_operand:HI 3 "" ""))))
4960    (parallel [(set (pc) (unspec:HI [(match_dup 6)] UNSPEC_INDEX_JMP))
4961               (use (label_ref (match_dup 3)))
4962               (clobber (match_dup 6))])]
4963   ""
4964   {
4965     operands[6] = gen_reg_rtx (HImode);
4966   })
4969 ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4970 ;; This instruction sets Z flag
4972 (define_insn "sez"
4973   [(set (cc0) (const_int 0))]
4974   ""
4975   "sez"
4976   [(set_attr "length" "1")
4977    (set_attr "cc" "compare")])
4979 ;; Clear/set/test a single bit in I/O address space.
4981 (define_insn "*cbi"
4982   [(set (mem:QI (match_operand 0 "low_io_address_operand" "n"))
4983         (and:QI (mem:QI (match_dup 0))
4984                 (match_operand:QI 1 "single_zero_operand" "n")))]
4985   ""
4986   {
4987     operands[2] = GEN_INT (exact_log2 (~INTVAL (operands[1]) & 0xff));
4988     return "cbi %i0,%2";
4989   }
4990   [(set_attr "length" "1")
4991    (set_attr "cc" "none")])
4993 (define_insn "*sbi"
4994   [(set (mem:QI (match_operand 0 "low_io_address_operand" "n"))
4995         (ior:QI (mem:QI (match_dup 0))
4996                 (match_operand:QI 1 "single_one_operand" "n")))]
4997   ""
4998   {
4999     operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff));
5000     return "sbi %i0,%2";
5001   }
5002   [(set_attr "length" "1")
5003    (set_attr "cc" "none")])
5005 ;; Lower half of the I/O space - use sbic/sbis directly.
5006 (define_insn "*sbix_branch"
5007   [(set (pc)
5008         (if_then_else
5009          (match_operator 0 "eqne_operator"
5010                          [(zero_extract:QIHI
5011                            (mem:QI (match_operand 1 "low_io_address_operand" "n"))
5012                            (const_int 1)
5013                            (match_operand 2 "const_int_operand" "n"))
5014                           (const_int 0)])
5015          (label_ref (match_operand 3 "" ""))
5016          (pc)))]
5017   ""
5018   {
5019     return avr_out_sbxx_branch (insn, operands);
5020   }
5021   [(set (attr "length")
5022         (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
5023                            (le (minus (pc) (match_dup 3)) (const_int 2046)))
5024                       (const_int 2)
5025                       (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
5026                                     (const_int 2)
5027                                     (const_int 4))))
5028    (set_attr "cc" "clobber")])
5030 ;; Tests of bit 7 are pessimized to sign tests, so we need this too...
5031 (define_insn "*sbix_branch_bit7"
5032   [(set (pc)
5033         (if_then_else
5034          (match_operator 0 "gelt_operator"
5035                          [(mem:QI (match_operand 1 "low_io_address_operand" "n"))
5036                           (const_int 0)])
5037          (label_ref (match_operand 2 "" ""))
5038          (pc)))]
5039   ""
5040   {
5041     operands[3] = operands[2];
5042     operands[2] = GEN_INT (7);
5043     return avr_out_sbxx_branch (insn, operands);
5044   }
5045   [(set (attr "length")
5046         (if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046))
5047                            (le (minus (pc) (match_dup 2)) (const_int 2046)))
5048                       (const_int 2)
5049                       (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
5050                                     (const_int 2)
5051                                     (const_int 4))))
5052    (set_attr "cc" "clobber")])
5054 ;; Upper half of the I/O space - read port to __tmp_reg__ and use sbrc/sbrs.
5055 (define_insn "*sbix_branch_tmp"
5056   [(set (pc)
5057         (if_then_else
5058          (match_operator 0 "eqne_operator"
5059                          [(zero_extract:QIHI
5060                            (mem:QI (match_operand 1 "high_io_address_operand" "n"))
5061                            (const_int 1)
5062                            (match_operand 2 "const_int_operand" "n"))
5063                           (const_int 0)])
5064          (label_ref (match_operand 3 "" ""))
5065          (pc)))]
5066   ""
5067   {
5068     return avr_out_sbxx_branch (insn, operands);
5069   }
5070   [(set (attr "length")
5071         (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
5072                            (le (minus (pc) (match_dup 3)) (const_int 2045)))
5073                       (const_int 3)
5074                       (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
5075                                     (const_int 3)
5076                                     (const_int 5))))
5077    (set_attr "cc" "clobber")])
5079 (define_insn "*sbix_branch_tmp_bit7"
5080   [(set (pc)
5081         (if_then_else
5082          (match_operator 0 "gelt_operator"
5083                          [(mem:QI (match_operand 1 "high_io_address_operand" "n"))
5084                           (const_int 0)])
5085          (label_ref (match_operand 2 "" ""))
5086          (pc)))]
5087   ""
5088   {
5089     operands[3] = operands[2];
5090     operands[2] = GEN_INT (7);
5091     return avr_out_sbxx_branch (insn, operands);
5092   }
5093   [(set (attr "length")
5094         (if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046))
5095                            (le (minus (pc) (match_dup 2)) (const_int 2045)))
5096                       (const_int 3)
5097                       (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
5098                                     (const_int 3)
5099                                     (const_int 5))))
5100    (set_attr "cc" "clobber")])
5102 ;; ************************* Peepholes ********************************
5104 (define_peephole ; "*dec-and-branchsi!=-1.d.clobber"
5105   [(parallel [(set (match_operand:SI 0 "d_register_operand" "")
5106                    (plus:SI (match_dup 0)
5107                             (const_int -1)))
5108               (clobber (scratch:QI))])
5109    (parallel [(set (cc0)
5110                    (compare (match_dup 0)
5111                             (const_int -1)))
5112               (clobber (match_operand:QI 1 "d_register_operand" ""))])
5113    (set (pc)
5114         (if_then_else (eqne (cc0)
5115                             (const_int 0))
5116                       (label_ref (match_operand 2 "" ""))
5117                       (pc)))]
5118   ""
5119   {
5120     const char *op;
5121     int jump_mode;
5122     CC_STATUS_INIT;
5123     if (test_hard_reg_class (ADDW_REGS, operands[0]))
5124       output_asm_insn ("sbiw %0,1" CR_TAB
5125                        "sbc %C0,__zero_reg__" CR_TAB
5126                        "sbc %D0,__zero_reg__", operands);
5127     else
5128       output_asm_insn ("subi %A0,1" CR_TAB
5129                        "sbc %B0,__zero_reg__" CR_TAB
5130                        "sbc %C0,__zero_reg__" CR_TAB
5131                        "sbc %D0,__zero_reg__", operands);
5133     jump_mode = avr_jump_mode (operands[2], insn);
5134     op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs";
5135     operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
5137     switch (jump_mode)
5138       {
5139       case 1: return "%1 %2";
5140       case 2: return "%1 .+2\;rjmp %2";
5141       case 3: return "%1 .+4\;jmp %2";
5142       }
5144     gcc_unreachable();
5145     return "";
5146   })
5148 (define_peephole ; "*dec-and-branchhi!=-1"
5149   [(set (match_operand:HI 0 "d_register_operand" "")
5150         (plus:HI (match_dup 0)
5151                  (const_int -1)))
5152    (parallel [(set (cc0)
5153                    (compare (match_dup 0)
5154                             (const_int -1)))
5155               (clobber (match_operand:QI 1 "d_register_operand" ""))])
5156    (set (pc)
5157         (if_then_else (eqne (cc0)
5158                             (const_int 0))
5159                       (label_ref (match_operand 2 "" ""))
5160                       (pc)))]
5161   ""
5162   {
5163     const char *op;
5164     int jump_mode;
5165     CC_STATUS_INIT;
5166     if (test_hard_reg_class (ADDW_REGS, operands[0]))
5167       output_asm_insn ("sbiw %0,1", operands);
5168     else
5169       output_asm_insn ("subi %A0,1" CR_TAB
5170                        "sbc %B0,__zero_reg__", operands);
5172     jump_mode = avr_jump_mode (operands[2], insn);
5173     op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs";
5174     operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
5176     switch (jump_mode)
5177       {
5178       case 1: return "%1 %2";
5179       case 2: return "%1 .+2\;rjmp %2";
5180       case 3: return "%1 .+4\;jmp %2";
5181       }
5183     gcc_unreachable();
5184     return "";
5185   })
5187 ;; Same as above but with clobber flavour of addhi3
5188 (define_peephole ; "*dec-and-branchhi!=-1.d.clobber"
5189   [(parallel [(set (match_operand:HI 0 "d_register_operand" "")
5190                    (plus:HI (match_dup 0)
5191                             (const_int -1)))
5192               (clobber (scratch:QI))])
5193    (parallel [(set (cc0)
5194                    (compare (match_dup 0)
5195                             (const_int -1)))
5196               (clobber (match_operand:QI 1 "d_register_operand" ""))])
5197    (set (pc)
5198         (if_then_else (eqne (cc0)
5199                             (const_int 0))
5200                       (label_ref (match_operand 2 "" ""))
5201                       (pc)))]
5202   ""
5203   {
5204     const char *op;
5205     int jump_mode;
5206     CC_STATUS_INIT;
5207     if (test_hard_reg_class (ADDW_REGS, operands[0]))
5208       output_asm_insn ("sbiw %0,1", operands);
5209     else
5210       output_asm_insn ("subi %A0,1" CR_TAB
5211                        "sbc %B0,__zero_reg__", operands);
5213     jump_mode = avr_jump_mode (operands[2], insn);
5214     op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs";
5215     operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
5217     switch (jump_mode)
5218       {
5219       case 1: return "%1 %2";
5220       case 2: return "%1 .+2\;rjmp %2";
5221       case 3: return "%1 .+4\;jmp %2";
5222       }
5224     gcc_unreachable();
5225     return "";
5226   })
5228 ;; Same as above but with clobber flavour of addhi3
5229 (define_peephole ; "*dec-and-branchhi!=-1.l.clobber"
5230   [(parallel [(set (match_operand:HI 0 "l_register_operand" "")
5231                    (plus:HI (match_dup 0)
5232                             (const_int -1)))
5233               (clobber (match_operand:QI 3 "d_register_operand" ""))])
5234    (parallel [(set (cc0)
5235                    (compare (match_dup 0)
5236                             (const_int -1)))
5237               (clobber (match_operand:QI 1 "d_register_operand" ""))])
5238    (set (pc)
5239         (if_then_else (eqne (cc0)
5240                             (const_int 0))
5241                       (label_ref (match_operand 2 "" ""))
5242                       (pc)))]
5243   ""
5244   {
5245     const char *op;
5246     int jump_mode;
5247     CC_STATUS_INIT;
5248     output_asm_insn ("ldi %3,1"   CR_TAB
5249                      "sub %A0,%3" CR_TAB
5250                      "sbc %B0,__zero_reg__", operands);
5252     jump_mode = avr_jump_mode (operands[2], insn);
5253     op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs";
5254     operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
5256     switch (jump_mode)
5257       {
5258       case 1: return "%1 %2";
5259       case 2: return "%1 .+2\;rjmp %2";
5260       case 3: return "%1 .+4\;jmp %2";
5261       }
5263     gcc_unreachable();
5264     return "";
5265   })
5267 (define_peephole ; "*dec-and-branchqi!=-1"
5268   [(set (match_operand:QI 0 "d_register_operand" "")
5269         (plus:QI (match_dup 0)
5270                  (const_int -1)))
5271    (set (cc0)
5272         (compare (match_dup 0)
5273                  (const_int -1)))
5274    (set (pc)
5275         (if_then_else (eqne (cc0)
5276                             (const_int 0))
5277                       (label_ref (match_operand 1 "" ""))
5278                       (pc)))]
5279   ""
5280   {
5281     const char *op;
5282     int jump_mode;
5283     CC_STATUS_INIT;
5284     cc_status.value1 = operands[0];
5285     cc_status.flags |= CC_OVERFLOW_UNUSABLE;
5287     output_asm_insn ("subi %A0,1", operands);
5289     jump_mode = avr_jump_mode (operands[1], insn);
5290     op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs";
5291     operands[0] = gen_rtx_CONST_STRING (VOIDmode, op);
5293     switch (jump_mode)
5294       {
5295       case 1: return "%0 %1";
5296       case 2: return "%0 .+2\;rjmp %1";
5297       case 3: return "%0 .+4\;jmp %1";
5298       }
5300     gcc_unreachable();
5301     return "";
5302   })
5305 (define_peephole ; "*cpse.eq"
5306   [(set (cc0)
5307         (compare (match_operand:ALL1 1 "register_operand" "r,r")
5308                  (match_operand:ALL1 2 "reg_or_0_operand" "r,Y00")))
5309    (set (pc)
5310         (if_then_else (eq (cc0)
5311                           (const_int 0))
5312                       (label_ref (match_operand 0 "" ""))
5313                       (pc)))]
5314   "jump_over_one_insn_p (insn, operands[0])"
5315   "@
5316         cpse %1,%2
5317         cpse %1,__zero_reg__")
5319 ;; This peephole avoids code like
5321 ;;     TST   Rn     ; *cmpqi
5322 ;;     BREQ  .+2    ; branch
5323 ;;     RJMP  .Lm
5325 ;; Notice that the peephole is always shorter than cmpqi + branch.
5326 ;; The reason to write it as peephole is that sequences like
5327 ;;     
5328 ;;     AND   Rm, Rn
5329 ;;     BRNE  .La
5331 ;; shall not be superseeded.  With a respective combine pattern
5332 ;; the latter sequence would be 
5333 ;;     
5334 ;;     AND   Rm, Rn
5335 ;;     CPSE  Rm, __zero_reg__
5336 ;;     RJMP  .La
5338 ;; and thus longer and slower and not easy to be rolled back.
5340 (define_peephole ; "*cpse.ne"
5341   [(set (cc0)
5342         (compare (match_operand:ALL1 1 "register_operand" "")
5343                  (match_operand:ALL1 2 "reg_or_0_operand" "")))
5344    (set (pc)
5345         (if_then_else (ne (cc0)
5346                           (const_int 0))
5347                       (label_ref (match_operand 0 "" ""))
5348                       (pc)))]
5349   "!AVR_HAVE_JMP_CALL
5350    || !avr_current_device->errata_skip"
5351   {
5352     if (operands[2] == CONST0_RTX (<MODE>mode))
5353       operands[2] = zero_reg_rtx;
5355     return 3 == avr_jump_mode (operands[0], insn)
5356       ? "cpse %1,%2\;jmp %0"
5357       : "cpse %1,%2\;rjmp %0";
5358   })
5360 ;;pppppppppppppppppppppppppppppppppppppppppppppppppppp
5361 ;;prologue/epilogue support instructions
5363 (define_insn "popqi"
5364   [(set (match_operand:QI 0 "register_operand" "=r")
5365         (mem:QI (pre_inc:HI (reg:HI REG_SP))))]
5366   ""
5367   "pop %0"
5368   [(set_attr "cc" "none")
5369    (set_attr "length" "1")])
5371 ;; Enable Interrupts
5372 (define_expand "enable_interrupt"
5373   [(clobber (const_int 0))]
5374   ""
5375   {
5376     rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
5377     MEM_VOLATILE_P (mem) = 1;
5378     emit_insn (gen_cli_sei (const1_rtx, mem));
5379     DONE;
5380   })
5382 ;; Disable Interrupts
5383 (define_expand "disable_interrupt"
5384   [(clobber (const_int 0))]
5385   ""
5386   {
5387     rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
5388     MEM_VOLATILE_P (mem) = 1;
5389     emit_insn (gen_cli_sei (const0_rtx, mem));
5390     DONE;
5391   })
5393 (define_insn "cli_sei"
5394   [(unspec_volatile [(match_operand:QI 0 "const_int_operand" "L,P")]
5395                     UNSPECV_ENABLE_IRQS)
5396    (set (match_operand:BLK 1 "" "")
5397         (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))]
5398   ""
5399   "@
5400         cli
5401         sei"
5402   [(set_attr "length" "1")
5403    (set_attr "cc" "none")])
5405 ;;  Library prologue saves
5406 (define_insn "call_prologue_saves"
5407   [(unspec_volatile:HI [(const_int 0)] UNSPECV_PROLOGUE_SAVES)
5408    (match_operand:HI 0 "immediate_operand" "i,i")
5409    (set (reg:HI REG_SP)
5410         (minus:HI (reg:HI REG_SP)
5411                   (match_operand:HI 1 "immediate_operand" "i,i")))
5412    (use (reg:HI REG_X))
5413    (clobber (reg:HI REG_Z))]
5414   ""
5415   "ldi r30,lo8(gs(1f))
5416         ldi r31,hi8(gs(1f))
5417         %~jmp __prologue_saves__+((18 - %0) * 2)
5419   [(set_attr "length" "5,6")
5420    (set_attr "cc" "clobber")
5421    (set_attr "isa" "rjmp,jmp")])
5422   
5423 ;  epilogue  restores using library
5424 (define_insn "epilogue_restores"
5425   [(unspec_volatile:QI [(const_int 0)] UNSPECV_EPILOGUE_RESTORES)
5426    (set (reg:HI REG_Y)
5427         (plus:HI (reg:HI REG_Y)
5428                  (match_operand:HI 0 "immediate_operand" "i,i")))
5429    (set (reg:HI REG_SP)
5430         (plus:HI (reg:HI REG_Y)
5431                  (match_dup 0)))
5432    (clobber (reg:QI REG_Z))]
5433   ""
5434   "ldi r30, lo8(%0)
5435         %~jmp __epilogue_restores__ + ((18 - %0) * 2)"
5436   [(set_attr "length" "2,3")
5437    (set_attr "cc" "clobber")
5438    (set_attr "isa" "rjmp,jmp")])
5439   
5440 ; return
5441 (define_insn "return"
5442   [(return)]
5443   "reload_completed && avr_simple_epilogue ()"
5444   "ret"
5445   [(set_attr "cc" "none")
5446    (set_attr "length" "1")])
5448 (define_insn "return_from_epilogue"
5449   [(return)]
5450   "reload_completed 
5451    && cfun->machine 
5452    && !(cfun->machine->is_interrupt || cfun->machine->is_signal)
5453    && !cfun->machine->is_naked"
5454   "ret"
5455   [(set_attr "cc" "none")
5456    (set_attr "length" "1")])
5458 (define_insn "return_from_interrupt_epilogue"
5459   [(return)]
5460   "reload_completed 
5461    && cfun->machine 
5462    && (cfun->machine->is_interrupt || cfun->machine->is_signal)
5463    && !cfun->machine->is_naked"
5464   "reti"
5465   [(set_attr "cc" "none")
5466    (set_attr "length" "1")])
5468 (define_insn "return_from_naked_epilogue"
5469   [(return)]
5470   "reload_completed 
5471    && cfun->machine 
5472    && cfun->machine->is_naked"
5473   ""
5474   [(set_attr "cc" "none")
5475    (set_attr "length" "0")])
5477 (define_expand "prologue"
5478   [(const_int 0)]
5479   ""
5480   {
5481     expand_prologue (); 
5482     DONE;
5483   })
5485 (define_expand "epilogue"
5486   [(const_int 0)]
5487   ""
5488   {
5489     expand_epilogue (false /* sibcall_p */);
5490     DONE;
5491   })
5493 (define_expand "sibcall_epilogue"
5494   [(const_int 0)]
5495   ""
5496   {
5497     expand_epilogue (true /* sibcall_p */);
5498     DONE;
5499   })
5501 ;; Some instructions resp. instruction sequences available
5502 ;; via builtins.
5504 (define_insn "delay_cycles_1"
5505   [(unspec_volatile [(match_operand:QI 0 "const_int_operand" "n")
5506                      (const_int 1)]
5507                     UNSPECV_DELAY_CYCLES)
5508    (set (match_operand:BLK 1 "" "")
5509         (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))
5510    (clobber (match_scratch:QI 2 "=&d"))]
5511   ""
5512   "ldi %2,lo8(%0)
5513         1: dec %2
5514         brne 1b"
5515   [(set_attr "length" "3")
5516    (set_attr "cc" "clobber")])
5518 (define_insn "delay_cycles_2"
5519   [(unspec_volatile [(match_operand:HI 0 "const_int_operand" "n")
5520                      (const_int 2)]
5521                     UNSPECV_DELAY_CYCLES)
5522    (set (match_operand:BLK 1 "" "")
5523         (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))
5524    (clobber (match_scratch:HI 2 "=&w"))]
5525   ""
5526   "ldi %A2,lo8(%0)
5527         ldi %B2,hi8(%0)
5528         1: sbiw %A2,1
5529         brne 1b"
5530   [(set_attr "length" "4")
5531    (set_attr "cc" "clobber")])
5533 (define_insn "delay_cycles_3"
5534   [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n")
5535                      (const_int 3)]
5536                     UNSPECV_DELAY_CYCLES)
5537    (set (match_operand:BLK 1 "" "")
5538         (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))
5539    (clobber (match_scratch:QI 2 "=&d"))
5540    (clobber (match_scratch:QI 3 "=&d"))
5541    (clobber (match_scratch:QI 4 "=&d"))]
5542   ""
5543   "ldi %2,lo8(%0)
5544         ldi %3,hi8(%0)
5545         ldi %4,hlo8(%0)
5546         1: subi %2,1
5547         sbci %3,0
5548         sbci %4,0
5549         brne 1b"
5550   [(set_attr "length" "7")
5551    (set_attr "cc" "clobber")])
5553 (define_insn "delay_cycles_4"
5554   [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n")
5555                      (const_int 4)]
5556                     UNSPECV_DELAY_CYCLES)
5557    (set (match_operand:BLK 1 "" "")
5558         (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))
5559    (clobber (match_scratch:QI 2 "=&d"))
5560    (clobber (match_scratch:QI 3 "=&d"))
5561    (clobber (match_scratch:QI 4 "=&d"))
5562    (clobber (match_scratch:QI 5 "=&d"))]
5563   ""
5564   "ldi %2,lo8(%0)
5565         ldi %3,hi8(%0)
5566         ldi %4,hlo8(%0)
5567         ldi %5,hhi8(%0)
5568         1: subi %2,1
5569         sbci %3,0
5570         sbci %4,0
5571         sbci %5,0
5572         brne 1b"
5573   [(set_attr "length" "9")
5574    (set_attr "cc" "clobber")])
5577 ;; __builtin_avr_insert_bits
5579 (define_insn "insert_bits"
5580   [(set (match_operand:QI 0 "register_operand"              "=r  ,d  ,r")
5581         (unspec:QI [(match_operand:SI 1 "const_int_operand"  "C0f,Cxf,C0f")
5582                     (match_operand:QI 2 "register_operand"   "r  ,r  ,r")
5583                     (match_operand:QI 3 "nonmemory_operand"  "n  ,0  ,0")]
5584                    UNSPEC_INSERT_BITS))]
5585   ""
5586   {
5587     return avr_out_insert_bits (operands, NULL);
5588   }
5589   [(set_attr "adjust_len" "insert_bits")
5590    (set_attr "cc" "clobber")])
5593 ;; __builtin_avr_flash_segment
5595 ;; Just a helper for the next "official" expander.
5597 (define_expand "flash_segment1"
5598   [(set (match_operand:QI 0 "register_operand" "")
5599         (subreg:QI (match_operand:PSI 1 "register_operand" "")
5600                    2))
5601    (set (cc0)
5602         (compare (match_dup 0)
5603                  (const_int 0)))
5604    (set (pc)
5605         (if_then_else (ge (cc0)
5606                           (const_int 0))
5607                       (label_ref (match_operand 2 "" ""))
5608                       (pc)))
5609    (set (match_dup 0)
5610         (const_int -1))])
5612 (define_expand "flash_segment"
5613   [(parallel [(match_operand:QI 0 "register_operand" "")
5614               (match_operand:PSI 1 "register_operand" "")])]
5615   ""
5616   {
5617     rtx label = gen_label_rtx ();
5618     emit (gen_flash_segment1 (operands[0], operands[1], label));
5619     emit_label (label);
5620     DONE;
5621   })
5623 ;; Actually, it's too late now to work out address spaces known at compiletime.
5624 ;; Best place would be to fold ADDR_SPACE_CONVERT_EXPR in avr_fold_builtin.
5625 ;; However, avr_addr_space_convert can add some built-in knowledge for PSTR
5626 ;; so that ADDR_SPACE_CONVERT_EXPR in the built-in must not be resolved.
5628 (define_insn_and_split "*split.flash_segment"
5629   [(set (match_operand:QI 0 "register_operand"                        "=d")
5630         (subreg:QI (lo_sum:PSI (match_operand:QI 1 "nonmemory_operand" "ri")
5631                                (match_operand:HI 2 "register_operand"  "r"))
5632                    2))]
5633   ""
5634   { gcc_unreachable(); }
5635   ""
5636   [(set (match_dup 0)
5637         (match_dup 1))])
5640 ;; Parity
5642 ;; Postpone expansion of 16-bit parity to libgcc call until after combine for
5643 ;; better 8-bit parity recognition.
5645 (define_expand "parityhi2"
5646   [(parallel [(set (match_operand:HI 0 "register_operand" "")
5647                    (parity:HI (match_operand:HI 1 "register_operand" "")))
5648               (clobber (reg:HI 24))])])
5650 (define_insn_and_split "*parityhi2"
5651   [(set (match_operand:HI 0 "register_operand"           "=r")
5652         (parity:HI (match_operand:HI 1 "register_operand" "r")))
5653    (clobber (reg:HI 24))]
5654   "!reload_completed"
5655   { gcc_unreachable(); }
5656   "&& 1"
5657   [(set (reg:HI 24)
5658         (match_dup 1))
5659    (set (reg:HI 24)
5660         (parity:HI (reg:HI 24)))
5661    (set (match_dup 0)
5662         (reg:HI 24))])
5664 (define_insn_and_split "*parityqihi2"
5665   [(set (match_operand:HI 0 "register_operand"           "=r")
5666         (parity:HI (match_operand:QI 1 "register_operand" "r")))
5667    (clobber (reg:HI 24))]
5668   "!reload_completed"
5669   { gcc_unreachable(); }
5670   "&& 1"
5671   [(set (reg:QI 24)
5672         (match_dup 1))
5673    (set (reg:HI 24)
5674         (zero_extend:HI (parity:QI (reg:QI 24))))
5675    (set (match_dup 0)
5676         (reg:HI 24))])
5678 (define_expand "paritysi2"
5679   [(set (reg:SI 22)
5680         (match_operand:SI 1 "register_operand" ""))
5681    (set (reg:HI 24)
5682         (truncate:HI (parity:SI (reg:SI 22))))
5683    (set (match_dup 2)
5684         (reg:HI 24))
5685    (set (match_operand:SI 0 "register_operand" "")
5686         (zero_extend:SI (match_dup 2)))]
5687   ""
5688   {
5689     operands[2] = gen_reg_rtx (HImode);
5690   })
5692 (define_insn "*parityhi2.libgcc"
5693   [(set (reg:HI 24)
5694         (parity:HI (reg:HI 24)))]
5695   ""
5696   "%~call __parityhi2"
5697   [(set_attr "type" "xcall")
5698    (set_attr "cc" "clobber")])
5700 (define_insn "*parityqihi2.libgcc"
5701   [(set (reg:HI 24)
5702         (zero_extend:HI (parity:QI (reg:QI 24))))]
5703   ""
5704   "%~call __parityqi2"
5705   [(set_attr "type" "xcall")
5706    (set_attr "cc" "clobber")])
5708 (define_insn "*paritysihi2.libgcc"
5709   [(set (reg:HI 24)
5710         (truncate:HI (parity:SI (reg:SI 22))))]
5711   ""
5712   "%~call __paritysi2"
5713   [(set_attr "type" "xcall")
5714    (set_attr "cc" "clobber")])
5717 ;; Popcount
5719 (define_expand "popcounthi2"
5720   [(set (reg:HI 24)
5721         (match_operand:HI 1 "register_operand" ""))
5722    (set (reg:HI 24)
5723         (popcount:HI (reg:HI 24)))
5724    (set (match_operand:HI 0 "register_operand" "")
5725         (reg:HI 24))]
5726   ""
5727   "")
5729 (define_expand "popcountsi2"
5730   [(set (reg:SI 22)
5731         (match_operand:SI 1 "register_operand" ""))
5732    (set (reg:HI 24)
5733         (truncate:HI (popcount:SI (reg:SI 22))))
5734    (set (match_dup 2)
5735         (reg:HI 24))
5736    (set (match_operand:SI 0 "register_operand" "")
5737         (zero_extend:SI (match_dup 2)))]
5738   ""
5739   {
5740     operands[2] = gen_reg_rtx (HImode);
5741   })
5743 (define_insn "*popcounthi2.libgcc"
5744   [(set (reg:HI 24)
5745         (popcount:HI (reg:HI 24)))]
5746   ""
5747   "%~call __popcounthi2"
5748   [(set_attr "type" "xcall")
5749    (set_attr "cc" "clobber")])
5751 (define_insn "*popcountsi2.libgcc"
5752   [(set (reg:HI 24)
5753         (truncate:HI (popcount:SI (reg:SI 22))))]
5754   ""
5755   "%~call __popcountsi2"
5756   [(set_attr "type" "xcall")
5757    (set_attr "cc" "clobber")])
5759 (define_insn "*popcountqi2.libgcc"
5760   [(set (reg:QI 24)
5761         (popcount:QI (reg:QI 24)))]
5762   ""
5763   "%~call __popcountqi2"
5764   [(set_attr "type" "xcall")
5765    (set_attr "cc" "clobber")])
5767 (define_insn_and_split "*popcountqihi2.libgcc"
5768   [(set (reg:HI 24)
5769         (zero_extend:HI (popcount:QI (reg:QI 24))))]
5770   ""
5771   "#"
5772   ""
5773   [(set (reg:QI 24)
5774         (popcount:QI (reg:QI 24)))
5775    (set (reg:QI 25)
5776         (const_int 0))])
5778 ;; Count Leading Zeros
5780 (define_expand "clzhi2"
5781   [(set (reg:HI 24)
5782         (match_operand:HI 1 "register_operand" ""))
5783    (parallel [(set (reg:HI 24)
5784                    (clz:HI (reg:HI 24)))
5785               (clobber (reg:QI 26))])
5786    (set (match_operand:HI 0 "register_operand" "")
5787         (reg:HI 24))])
5789 (define_expand "clzsi2"
5790   [(set (reg:SI 22)
5791         (match_operand:SI 1 "register_operand" ""))
5792    (parallel [(set (reg:HI 24)
5793                    (truncate:HI (clz:SI (reg:SI 22))))
5794               (clobber (reg:QI 26))])
5795    (set (match_dup 2)
5796         (reg:HI 24))
5797    (set (match_operand:SI 0 "register_operand" "")
5798         (zero_extend:SI (match_dup 2)))]
5799   ""
5800   {
5801     operands[2] = gen_reg_rtx (HImode);
5802   })
5804 (define_insn "*clzhi2.libgcc"
5805   [(set (reg:HI 24)
5806         (clz:HI (reg:HI 24)))
5807    (clobber (reg:QI 26))]
5808   ""
5809   "%~call __clzhi2"
5810   [(set_attr "type" "xcall")
5811    (set_attr "cc" "clobber")])
5813 (define_insn "*clzsihi2.libgcc"
5814   [(set (reg:HI 24)
5815         (truncate:HI (clz:SI (reg:SI 22))))
5816    (clobber (reg:QI 26))]
5817   ""
5818   "%~call __clzsi2"
5819   [(set_attr "type" "xcall")
5820    (set_attr "cc" "clobber")])
5822 ;; Count Trailing Zeros
5824 (define_expand "ctzhi2"
5825   [(set (reg:HI 24)
5826         (match_operand:HI 1 "register_operand" ""))
5827    (parallel [(set (reg:HI 24)
5828                    (ctz:HI (reg:HI 24)))
5829               (clobber (reg:QI 26))])
5830    (set (match_operand:HI 0 "register_operand" "")
5831         (reg:HI 24))])
5833 (define_expand "ctzsi2"
5834   [(set (reg:SI 22)
5835         (match_operand:SI 1 "register_operand" ""))
5836    (parallel [(set (reg:HI 24)
5837                    (truncate:HI (ctz:SI (reg:SI 22))))
5838               (clobber (reg:QI 22))
5839               (clobber (reg:QI 26))])
5840    (set (match_dup 2)
5841         (reg:HI 24))
5842    (set (match_operand:SI 0 "register_operand" "")
5843         (zero_extend:SI (match_dup 2)))]
5844   ""
5845   {
5846     operands[2] = gen_reg_rtx (HImode);
5847   })
5849 (define_insn "*ctzhi2.libgcc"
5850   [(set (reg:HI 24)
5851         (ctz:HI (reg:HI 24)))
5852    (clobber (reg:QI 26))]
5853   ""
5854   "%~call __ctzhi2"
5855   [(set_attr "type" "xcall")
5856    (set_attr "cc" "clobber")])
5858 (define_insn "*ctzsihi2.libgcc"
5859   [(set (reg:HI 24)
5860         (truncate:HI (ctz:SI (reg:SI 22))))
5861    (clobber (reg:QI 22))
5862    (clobber (reg:QI 26))]
5863   ""
5864   "%~call __ctzsi2"
5865   [(set_attr "type" "xcall")
5866    (set_attr "cc" "clobber")])
5868 ;; Find First Set
5870 (define_expand "ffshi2"
5871   [(set (reg:HI 24)
5872         (match_operand:HI 1 "register_operand" ""))
5873    (parallel [(set (reg:HI 24)
5874                    (ffs:HI (reg:HI 24)))
5875               (clobber (reg:QI 26))])
5876    (set (match_operand:HI 0 "register_operand" "")
5877         (reg:HI 24))])
5879 (define_expand "ffssi2"
5880   [(set (reg:SI 22)
5881         (match_operand:SI 1 "register_operand" ""))
5882    (parallel [(set (reg:HI 24)
5883                    (truncate:HI (ffs:SI (reg:SI 22))))
5884               (clobber (reg:QI 22))
5885               (clobber (reg:QI 26))])
5886    (set (match_dup 2)
5887         (reg:HI 24))
5888    (set (match_operand:SI 0 "register_operand" "")
5889         (zero_extend:SI (match_dup 2)))]
5890   ""
5891   {
5892     operands[2] = gen_reg_rtx (HImode);
5893   })
5895 (define_insn "*ffshi2.libgcc"
5896   [(set (reg:HI 24)
5897         (ffs:HI (reg:HI 24)))
5898    (clobber (reg:QI 26))]
5899   ""
5900   "%~call __ffshi2"
5901   [(set_attr "type" "xcall")
5902    (set_attr "cc" "clobber")])
5904 (define_insn "*ffssihi2.libgcc"
5905   [(set (reg:HI 24)
5906         (truncate:HI (ffs:SI (reg:SI 22))))
5907    (clobber (reg:QI 22))
5908    (clobber (reg:QI 26))]
5909   ""
5910   "%~call __ffssi2"
5911   [(set_attr "type" "xcall")
5912    (set_attr "cc" "clobber")])
5914 ;; Copysign
5916 (define_insn "copysignsf3"
5917   [(set (match_operand:SF 0 "register_operand"             "=r")
5918         (unspec:SF [(match_operand:SF 1 "register_operand"  "0")
5919                     (match_operand:SF 2 "register_operand"  "r")]
5920                    UNSPEC_COPYSIGN))]
5921   ""
5922   "bst %D2,7\;bld %D0,7"
5923   [(set_attr "length" "2")
5924    (set_attr "cc" "none")])
5925   
5926 ;; Swap Bytes (change byte-endianess)
5928 (define_expand "bswapsi2"
5929   [(set (reg:SI 22)
5930         (match_operand:SI 1 "register_operand" ""))
5931    (set (reg:SI 22)
5932         (bswap:SI (reg:SI 22)))
5933    (set (match_operand:SI 0 "register_operand" "")
5934         (reg:SI 22))])
5936 (define_insn "*bswapsi2.libgcc"
5937   [(set (reg:SI 22)
5938         (bswap:SI (reg:SI 22)))]
5939   ""
5940   "%~call __bswapsi2"
5941   [(set_attr "type" "xcall")
5942    (set_attr "cc" "clobber")])
5945 ;; CPU instructions
5947 ;; NOP taking 1 or 2 Ticks 
5948 (define_expand "nopv"
5949   [(parallel [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "")] 
5950                                UNSPECV_NOP)
5951               (set (match_dup 1)
5952                    (unspec_volatile:BLK [(match_dup 1)]
5953                                         UNSPECV_MEMORY_BARRIER))])]
5954   ""
5955   {
5956     operands[1] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
5957     MEM_VOLATILE_P (operands[1]) = 1;
5958   })
5960 (define_insn "*nopv"
5961   [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "P,K")] 
5962                     UNSPECV_NOP)
5963    (set (match_operand:BLK 1 "" "")
5964         (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))]
5965   ""
5966   "@
5967         nop
5968         rjmp ."
5969   [(set_attr "length" "1")
5970    (set_attr "cc" "none")])
5972 ;; SLEEP
5973 (define_expand "sleep"
5974   [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_SLEEP)
5975               (set (match_dup 0)
5976                    (unspec_volatile:BLK [(match_dup 0)]
5977                                         UNSPECV_MEMORY_BARRIER))])]
5978   ""
5979   {
5980     operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
5981     MEM_VOLATILE_P (operands[0]) = 1;
5982   })
5984 (define_insn "*sleep"
5985   [(unspec_volatile [(const_int 0)] UNSPECV_SLEEP)
5986    (set (match_operand:BLK 0 "" "")
5987         (unspec_volatile:BLK [(match_dup 0)] UNSPECV_MEMORY_BARRIER))]
5988   ""
5989   "sleep"
5990   [(set_attr "length" "1")
5991    (set_attr "cc" "none")])
5993 ;; WDR
5994 (define_expand "wdr"
5995   [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_WDR)
5996               (set (match_dup 0)
5997                    (unspec_volatile:BLK [(match_dup 0)]
5998                                         UNSPECV_MEMORY_BARRIER))])]
5999   ""
6000   {
6001     operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
6002     MEM_VOLATILE_P (operands[0]) = 1;
6003   })
6005 (define_insn "*wdr"
6006   [(unspec_volatile [(const_int 0)] UNSPECV_WDR)
6007    (set (match_operand:BLK 0 "" "")
6008         (unspec_volatile:BLK [(match_dup 0)] UNSPECV_MEMORY_BARRIER))]
6009   ""
6010   "wdr"
6011   [(set_attr "length" "1")
6012    (set_attr "cc" "none")])
6013   
6014 ;; FMUL
6015 (define_expand "fmul"
6016   [(set (reg:QI 24)
6017         (match_operand:QI 1 "register_operand" ""))
6018    (set (reg:QI 25)
6019         (match_operand:QI 2 "register_operand" ""))
6020    (parallel [(set (reg:HI 22)
6021                    (unspec:HI [(reg:QI 24)
6022                                (reg:QI 25)] UNSPEC_FMUL))
6023               (clobber (reg:HI 24))])
6024    (set (match_operand:HI 0 "register_operand" "")
6025         (reg:HI 22))]
6026   ""
6027   {
6028     if (AVR_HAVE_MUL)
6029       {
6030         emit_insn (gen_fmul_insn (operand0, operand1, operand2));
6031         DONE;
6032       }
6033   })
6035 (define_insn "fmul_insn"
6036   [(set (match_operand:HI 0 "register_operand" "=r")
6037         (unspec:HI [(match_operand:QI 1 "register_operand" "a")
6038                     (match_operand:QI 2 "register_operand" "a")]
6039                    UNSPEC_FMUL))]
6040   "AVR_HAVE_MUL"
6041   "fmul %1,%2
6042         movw %0,r0
6043         clr __zero_reg__"
6044   [(set_attr "length" "3")
6045    (set_attr "cc" "clobber")])
6047 (define_insn "*fmul.call"
6048   [(set (reg:HI 22)
6049         (unspec:HI [(reg:QI 24)
6050                     (reg:QI 25)] UNSPEC_FMUL))
6051    (clobber (reg:HI 24))]
6052   "!AVR_HAVE_MUL"
6053   "%~call __fmul"
6054   [(set_attr "type" "xcall")
6055    (set_attr "cc" "clobber")])
6057 ;; FMULS
6058 (define_expand "fmuls"
6059   [(set (reg:QI 24)
6060         (match_operand:QI 1 "register_operand" ""))
6061    (set (reg:QI 25)
6062         (match_operand:QI 2 "register_operand" ""))
6063    (parallel [(set (reg:HI 22)
6064                    (unspec:HI [(reg:QI 24)
6065                                (reg:QI 25)] UNSPEC_FMULS))
6066               (clobber (reg:HI 24))])
6067    (set (match_operand:HI 0 "register_operand" "")
6068         (reg:HI 22))]
6069   ""
6070   {
6071     if (AVR_HAVE_MUL)
6072       {
6073         emit_insn (gen_fmuls_insn (operand0, operand1, operand2));
6074         DONE;
6075       }
6076   })
6078 (define_insn "fmuls_insn"
6079   [(set (match_operand:HI 0 "register_operand" "=r")
6080         (unspec:HI [(match_operand:QI 1 "register_operand" "a")
6081                     (match_operand:QI 2 "register_operand" "a")]
6082                    UNSPEC_FMULS))]
6083   "AVR_HAVE_MUL"
6084   "fmuls %1,%2
6085         movw %0,r0
6086         clr __zero_reg__"
6087   [(set_attr "length" "3")
6088    (set_attr "cc" "clobber")])
6090 (define_insn "*fmuls.call"
6091   [(set (reg:HI 22)
6092         (unspec:HI [(reg:QI 24)
6093                     (reg:QI 25)] UNSPEC_FMULS))
6094    (clobber (reg:HI 24))]
6095   "!AVR_HAVE_MUL"
6096   "%~call __fmuls"
6097   [(set_attr "type" "xcall")
6098    (set_attr "cc" "clobber")])
6100 ;; FMULSU
6101 (define_expand "fmulsu"
6102   [(set (reg:QI 24)
6103         (match_operand:QI 1 "register_operand" ""))
6104    (set (reg:QI 25)
6105         (match_operand:QI 2 "register_operand" ""))
6106    (parallel [(set (reg:HI 22)
6107                    (unspec:HI [(reg:QI 24)
6108                                (reg:QI 25)] UNSPEC_FMULSU))
6109               (clobber (reg:HI 24))])
6110    (set (match_operand:HI 0 "register_operand" "")
6111         (reg:HI 22))]
6112   ""
6113   {
6114     if (AVR_HAVE_MUL)
6115       {
6116         emit_insn (gen_fmulsu_insn (operand0, operand1, operand2));
6117         DONE;
6118       }
6119   })
6121 (define_insn "fmulsu_insn"
6122   [(set (match_operand:HI 0 "register_operand" "=r")
6123         (unspec:HI [(match_operand:QI 1 "register_operand" "a")
6124                     (match_operand:QI 2 "register_operand" "a")]
6125                    UNSPEC_FMULSU))]
6126   "AVR_HAVE_MUL"
6127   "fmulsu %1,%2
6128         movw %0,r0
6129         clr __zero_reg__"
6130   [(set_attr "length" "3")
6131    (set_attr "cc" "clobber")])
6133 (define_insn "*fmulsu.call"
6134   [(set (reg:HI 22)
6135         (unspec:HI [(reg:QI 24)
6136                     (reg:QI 25)] UNSPEC_FMULSU))
6137    (clobber (reg:HI 24))]
6138   "!AVR_HAVE_MUL"
6139   "%~call __fmulsu"
6140   [(set_attr "type" "xcall")
6141    (set_attr "cc" "clobber")])
6144 ;; Some combiner patterns dealing with bits.
6145 ;; See PR42210
6147 ;; Move bit $3.0 into bit $0.$4
6148 (define_insn "*movbitqi.1-6.a"
6149   [(set (match_operand:QI 0 "register_operand"                               "=r")
6150         (ior:QI (and:QI (match_operand:QI 1 "register_operand"                "0")
6151                         (match_operand:QI 2 "single_zero_operand"             "n"))
6152                 (and:QI (ashift:QI (match_operand:QI 3 "register_operand"     "r")
6153                                    (match_operand:QI 4 "const_0_to_7_operand" "n"))
6154                         (match_operand:QI 5 "single_one_operand"              "n"))))]
6155   "INTVAL(operands[4]) == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))
6156    && INTVAL(operands[4]) == exact_log2 (INTVAL(operands[5]) & GET_MODE_MASK (QImode))"
6157   "bst %3,0\;bld %0,%4"
6158   [(set_attr "length" "2")
6159    (set_attr "cc" "none")])
6161 ;; Move bit $3.0 into bit $0.$4
6162 ;; Variation of above. Unfortunately, there is no canonicalized representation
6163 ;; of moving around bits.  So what we see here depends on how user writes down
6164 ;; bit manipulations.
6165 (define_insn "*movbitqi.1-6.b"
6166   [(set (match_operand:QI 0 "register_operand"                            "=r")
6167         (ior:QI (and:QI (match_operand:QI 1 "register_operand"             "0")
6168                         (match_operand:QI 2 "single_zero_operand"          "n"))
6169                 (ashift:QI (and:QI (match_operand:QI 3 "register_operand"  "r")
6170                                    (const_int 1))
6171                            (match_operand:QI 4 "const_0_to_7_operand"      "n"))))]
6172   "INTVAL(operands[4]) == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))"
6173   "bst %3,0\;bld %0,%4"
6174   [(set_attr "length" "2")
6175    (set_attr "cc" "none")])
6177 ;; Move bit $3.0 into bit $0.0.
6178 ;; For bit 0, combiner generates slightly different pattern.
6179 (define_insn "*movbitqi.0"
6180   [(set (match_operand:QI 0 "register_operand"                     "=r")
6181         (ior:QI (and:QI (match_operand:QI 1 "register_operand"      "0")
6182                         (match_operand:QI 2 "single_zero_operand"   "n"))
6183                 (and:QI (match_operand:QI 3 "register_operand"      "r")
6184                         (const_int 1))))]
6185   "0 == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))"
6186   "bst %3,0\;bld %0,0"
6187   [(set_attr "length" "2")
6188    (set_attr "cc" "none")])
6190 ;; Move bit $2.0 into bit $0.7.
6191 ;; For bit 7, combiner generates slightly different pattern
6192 (define_insn "*movbitqi.7"
6193   [(set (match_operand:QI 0 "register_operand"                      "=r")
6194         (ior:QI (and:QI (match_operand:QI 1 "register_operand"       "0")
6195                         (const_int 127))
6196                 (ashift:QI (match_operand:QI 2 "register_operand"    "r")
6197                            (const_int 7))))]
6198   ""
6199   "bst %2,0\;bld %0,7"
6200   [(set_attr "length" "2")
6201    (set_attr "cc" "none")])
6203 ;; Combiner transforms above four pattern into ZERO_EXTRACT if it sees MEM
6204 ;; and input/output match.  We provide a special pattern for this, because
6205 ;; in contrast to a IN/BST/BLD/OUT sequence we need less registers and the
6206 ;; operation on I/O is atomic.
6207 (define_insn "*insv.io"
6208   [(set (zero_extract:QI (mem:QI (match_operand 0 "low_io_address_operand" "n,n,n"))
6209                          (const_int 1)
6210                          (match_operand:QI 1 "const_0_to_7_operand"        "n,n,n"))
6211         (match_operand:QI 2 "nonmemory_operand"                            "L,P,r"))]
6212   ""
6213   "@
6214         cbi %i0,%1
6215         sbi %i0,%1
6216         sbrc %2,0\;sbi %i0,%1\;sbrs %2,0\;cbi %i0,%1"
6217   [(set_attr "length" "1,1,4")
6218    (set_attr "cc" "none")])
6220 (define_insn "*insv.not.io"
6221   [(set (zero_extract:QI (mem:QI (match_operand 0 "low_io_address_operand" "n"))
6222                          (const_int 1)
6223                          (match_operand:QI 1 "const_0_to_7_operand"        "n"))
6224         (not:QI (match_operand:QI 2 "register_operand"                     "r")))]
6225   ""
6226   "sbrs %2,0\;sbi %i0,%1\;sbrc %2,0\;cbi %i0,%1"
6227   [(set_attr "length" "4")
6228    (set_attr "cc" "none")])
6230 ;; The insv expander.
6231 ;; We only support 1-bit inserts
6232 (define_expand "insv"
6233   [(set (zero_extract:QI (match_operand:QI 0 "register_operand" "")
6234                          (match_operand:QI 1 "const1_operand" "")        ; width
6235                          (match_operand:QI 2 "const_0_to_7_operand" "")) ; pos
6236         (match_operand:QI 3 "nonmemory_operand" ""))]
6237   "optimize")
6239 ;; Insert bit $2.0 into $0.$1
6240 (define_insn "*insv.reg"
6241   [(set (zero_extract:QI (match_operand:QI 0 "register_operand"    "+r,d,d,l,l")
6242                          (const_int 1)
6243                          (match_operand:QI 1 "const_0_to_7_operand" "n,n,n,n,n"))
6244         (match_operand:QI 2 "nonmemory_operand"                     "r,L,P,L,P"))]
6245   ""
6246   "@
6247         bst %2,0\;bld %0,%1
6248         andi %0,lo8(~(1<<%1))
6249         ori %0,lo8(1<<%1)
6250         clt\;bld %0,%1
6251         set\;bld %0,%1"
6252   [(set_attr "length" "2,1,1,2,2")
6253    (set_attr "cc" "none,set_zn,set_zn,none,none")])
6256 ;; Some combine patterns that try to fix bad code when a value is composed
6257 ;; from byte parts like in PR27663.
6258 ;; The patterns give some release but the code still is not optimal,
6259 ;; in particular when subreg lowering (-fsplit-wide-types) is turned on.
6260 ;; That switch obfuscates things here and in many other places.
6262 ;; "*iorhiqi.byte0"   "*iorpsiqi.byte0"   "*iorsiqi.byte0"
6263 ;; "*xorhiqi.byte0"   "*xorpsiqi.byte0"   "*xorsiqi.byte0"
6264 (define_insn_and_split "*<code_stdname><mode>qi.byte0"
6265   [(set (match_operand:HISI 0 "register_operand"                 "=r")
6266         (xior:HISI
6267          (zero_extend:HISI (match_operand:QI 1 "register_operand" "r"))
6268          (match_operand:HISI 2 "register_operand"                 "0")))]
6269   ""
6270   "#"
6271   "reload_completed"
6272   [(set (match_dup 3)
6273         (xior:QI (match_dup 3)
6274                  (match_dup 1)))]
6275   {
6276     operands[3] = simplify_gen_subreg (QImode, operands[0], <MODE>mode, 0);
6277   })
6279 ;; "*iorhiqi.byte1-3"  "*iorpsiqi.byte1-3"  "*iorsiqi.byte1-3"
6280 ;; "*xorhiqi.byte1-3"  "*xorpsiqi.byte1-3"  "*xorsiqi.byte1-3"
6281 (define_insn_and_split "*<code_stdname><mode>qi.byte1-3"
6282   [(set (match_operand:HISI 0 "register_operand"                              "=r")
6283         (xior:HISI
6284          (ashift:HISI (zero_extend:HISI (match_operand:QI 1 "register_operand" "r"))
6285                       (match_operand:QI 2 "const_8_16_24_operand"              "n"))
6286          (match_operand:HISI 3 "register_operand"                              "0")))]
6287   "INTVAL(operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
6288   "#"
6289   "&& reload_completed"
6290   [(set (match_dup 4)
6291         (xior:QI (match_dup 4)
6292                  (match_dup 1)))]
6293   {
6294     int byteno = INTVAL(operands[2]) / BITS_PER_UNIT;
6295     operands[4] = simplify_gen_subreg (QImode, operands[0], <MODE>mode, byteno);
6296   })
6298 (define_expand "extzv"
6299   [(set (match_operand:QI 0 "register_operand" "")
6300         (zero_extract:QI (match_operand:QI 1 "register_operand"  "")
6301                          (match_operand:QI 2 "const1_operand" "")
6302                          (match_operand:QI 3 "const_0_to_7_operand" "")))])
6304 (define_insn "*extzv"
6305   [(set (match_operand:QI 0 "register_operand"                   "=*d,*d,*d,*d,r")
6306         (zero_extract:QI (match_operand:QI 1 "register_operand"     "0,r,0,0,r")
6307                          (const_int 1)
6308                          (match_operand:QI 2 "const_0_to_7_operand" "L,L,P,C04,n")))]
6309   ""
6310   "@
6311         andi %0,1
6312         mov %0,%1\;andi %0,1
6313         lsr %0\;andi %0,1
6314         swap %0\;andi %0,1
6315         bst %1,%2\;clr %0\;bld %0,0"
6316   [(set_attr "length" "1,2,2,2,3")
6317    (set_attr "cc" "set_zn,set_zn,set_zn,set_zn,clobber")])
6319 (define_insn_and_split "*extzv.qihi1"
6320   [(set (match_operand:HI 0 "register_operand"                     "=r")
6321         (zero_extract:HI (match_operand:QI 1 "register_operand"     "r")
6322                          (const_int 1)
6323                          (match_operand:QI 2 "const_0_to_7_operand" "n")))]
6324   ""
6325   "#"
6326   ""
6327   [(set (match_dup 3)
6328         (zero_extract:QI (match_dup 1)
6329                          (const_int 1)
6330                          (match_dup 2)))
6331    (set (match_dup 4)
6332         (const_int 0))]
6333   {
6334     operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
6335     operands[4] = simplify_gen_subreg (QImode, operands[0], HImode, 1);
6336   })
6338 (define_insn_and_split "*extzv.qihi2"
6339   [(set (match_operand:HI 0 "register_operand"                      "=r")
6340         (zero_extend:HI 
6341          (zero_extract:QI (match_operand:QI 1 "register_operand"     "r")
6342                           (const_int 1)
6343                           (match_operand:QI 2 "const_0_to_7_operand" "n"))))]
6344   ""
6345   "#"
6346   ""
6347   [(set (match_dup 3)
6348         (zero_extract:QI (match_dup 1)
6349                          (const_int 1)
6350                          (match_dup 2)))
6351    (set (match_dup 4)
6352         (const_int 0))]
6353   {
6354     operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
6355     operands[4] = simplify_gen_subreg (QImode, operands[0], HImode, 1);
6356   })
6359 ;; Fixed-point instructions
6360 (include "avr-fixed.md")
6362 ;; Operations on 64-bit registers
6363 (include "avr-dimode.md")