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