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