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