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