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