xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/avr/avr.md (revision 154bfe8e089c1a0a4e9ed8414f08d3da90949162)
1;;   Machine description for GNU compiler,
2;;   for ATMEL AVR micro controllers.
3;;   Copyright (C) 1998-2018 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_MOVMEM
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, movmem,
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 SC
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 "movmemhi"
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_movmemhi (operands))
1003      DONE;
1004
1005    FAIL;
1006  })
1007
1008(define_mode_attr MOVMEM_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;; "movmem_qi"
1017;; "movmem_hi"
1018(define_insn "movmem_<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_MOVMEM)
1023   (use (match_operand:QIHI 1 "register_operand" "<MOVMEM_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_movmem (insn, operands, NULL);
1031  }
1032  [(set_attr "adjust_len" "movmem")
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;; "movmemx_qi"
1043;; "movmemx_hi"
1044(define_insn "movmemx_<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_MOVMEM)
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