1 ;; Machine description for GNU compiler,
2 ;; for ATMEL AVR micro controllers.
3 ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008,
4 ;; 2009, 2010, 2011 Free Software Foundation, Inc.
5 ;; Contributed by Denis Chertykov (chertykov@gmail.com)
7 ;; This file is part of GCC.
9 ;; GCC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 3, or (at your option)
14 ;; GCC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GCC; see the file COPYING3. If not see
21 ;; <http://www.gnu.org/licenses/>.
23 ;; Special characters after '%':
24 ;; A No effect (add 0).
25 ;; B Add 1 to REG number, MEM address or CONST_INT.
28 ;; j Branch condition.
29 ;; k Reverse branch condition.
30 ;;..m..Constant Direct Data memory address.
31 ;; i Print the SFR address quivalent of a CONST_INT or a CONST_INT
32 ;; RAM address. The resulting addres is suitable to be used in IN/OUT.
33 ;; o Displacement for (mem (plus (reg) (const_int))) operands.
34 ;; p POST_INC or PRE_DEC address as a pointer (X, Y, Z)
35 ;; r POST_INC or PRE_DEC address as a register (r26, r28, r30)
36 ;; T/T Print operand suitable for BLD/BST instruction, i.e. register and
37 ;; bit number. This gets 2 operands: The first %T gets a REG_P and
38 ;; just cashes the operand for the next %T. The second %T gets
39 ;; a CONST_INT that represents a bit position.
40 ;; Example: With %0 = (reg:HI 18) and %1 = (const_int 13)
41 ;; "%T0%T1" it will print "r19,5".
42 ;; Notice that you must not write a comma between %T0 and %T1.
43 ;; T/t Similar to above, but don't print the comma and the bit number.
44 ;; Example: With %0 = (reg:HI 18) and %1 = (const_int 13)
45 ;; "%T0%t1" it will print "r19".
46 ;;..x..Constant Direct Program memory address.
47 ;; ~ Output 'r' if not AVR_HAVE_JMP_CALL.
48 ;; ! Output 'e' if AVR_HAVE_EIJMP_EICALL.
57 (LPM_REGNO 0) ; implicit target register of LPM
58 (TMP_REGNO 0) ; temporary register r0
59 (ZERO_REGNO 1) ; zero register r1
62 (define_c_enum "unspec"
74 (define_c_enum "unspecv"
75 [UNSPECV_PROLOGUE_SAVES
76 UNSPECV_EPILOGUE_RESTORES
87 (include "predicates.md")
88 (include "constraints.md")
90 ;; Condition code settings.
91 (define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber,
92 out_plus, out_plus_noclobber,ldi"
93 (const_string "none"))
95 (define_attr "type" "branch,branch1,arith,xcall"
96 (const_string "arith"))
98 ;; The size of instructions in bytes.
99 ;; XXX may depend from "cc"
101 (define_attr "length" ""
102 (cond [(eq_attr "type" "branch")
103 (if_then_else (and (ge (minus (pc) (match_dup 0))
105 (le (minus (pc) (match_dup 0))
108 (if_then_else (and (ge (minus (pc) (match_dup 0))
110 (le (minus (pc) (match_dup 0))
114 (eq_attr "type" "branch1")
115 (if_then_else (and (ge (minus (pc) (match_dup 0))
117 (le (minus (pc) (match_dup 0))
120 (if_then_else (and (ge (minus (pc) (match_dup 0))
122 (le (minus (pc) (match_dup 0))
126 (eq_attr "type" "xcall")
127 (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
132 ;; Lengths of several insns are adjusted in avr.c:adjust_insn_length().
133 ;; Following insn attribute tells if and how the adjustment has to be
135 ;; no No adjustment needed; attribute "length" is fine.
136 ;; Otherwise do special processing depending on the attribute.
138 (define_attr "adjust_len"
139 "out_bitop, out_plus, out_plus_noclobber, plus64, addto_sp,
140 tsthi, tstpsi, tstsi, compare, compare64, call,
141 mov8, mov16, mov24, mov32, reload_in16, reload_in24, reload_in32,
143 ashlqi, ashrqi, lshrqi,
144 ashlhi, ashrhi, lshrhi,
145 ashlsi, ashrsi, lshrsi,
146 ashlpsi, ashrpsi, lshrpsi,
151 ;; Flavours of instruction set architecture (ISA), used in enabled attribute
153 ;; mov : ISA has no MOVW movw : ISA has MOVW
154 ;; rjmp : ISA has no CALL/JMP jmp : ISA has CALL/JMP
155 ;; ijmp : ISA has no EICALL/EIJMP eijmp : ISA has EICALL/EIJMP
156 ;; lpm : ISA has no LPMX lpmx : ISA has LPMX
157 ;; elpm : ISA has ELPM but no ELPMX elpmx : ISA has ELPMX
160 "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx,
162 (const_string "standard"))
164 (define_attr "enabled" ""
165 (cond [(eq_attr "isa" "standard")
168 (and (eq_attr "isa" "mov")
169 (match_test "!AVR_HAVE_MOVW"))
172 (and (eq_attr "isa" "movw")
173 (match_test "AVR_HAVE_MOVW"))
176 (and (eq_attr "isa" "rjmp")
177 (match_test "!AVR_HAVE_JMP_CALL"))
180 (and (eq_attr "isa" "jmp")
181 (match_test "AVR_HAVE_JMP_CALL"))
184 (and (eq_attr "isa" "ijmp")
185 (match_test "!AVR_HAVE_EIJMP_EICALL"))
188 (and (eq_attr "isa" "eijmp")
189 (match_test "AVR_HAVE_EIJMP_EICALL"))
192 (and (eq_attr "isa" "lpm")
193 (match_test "!AVR_HAVE_LPMX"))
196 (and (eq_attr "isa" "lpmx")
197 (match_test "AVR_HAVE_LPMX"))
200 (and (eq_attr "isa" "elpm")
201 (match_test "AVR_HAVE_ELPM && !AVR_HAVE_ELPMX"))
204 (and (eq_attr "isa" "elpmx")
205 (match_test "AVR_HAVE_ELPMX"))
210 ;; Define mode iterators
211 (define_mode_iterator QIHI [(QI "") (HI "")])
212 (define_mode_iterator QIHI2 [(QI "") (HI "")])
213 (define_mode_iterator QISI [(QI "") (HI "") (PSI "") (SI "")])
214 (define_mode_iterator QIDI [(QI "") (HI "") (PSI "") (SI "") (DI "")])
215 (define_mode_iterator HISI [(HI "") (PSI "") (SI "")])
217 ;; All supported move-modes
218 (define_mode_iterator MOVMODE [(QI "") (HI "") (SI "") (SF "") (PSI "")])
220 ;; Define code iterators
221 ;; Define two incarnations so that we can build the cross product.
222 (define_code_iterator any_extend [sign_extend zero_extend])
223 (define_code_iterator any_extend2 [sign_extend zero_extend])
225 ;; Define code attributes
226 (define_code_attr extend_su
230 (define_code_attr extend_u
234 (define_code_attr extend_s
238 ;; Constrain input operand of widening multiply, i.e. MUL resp. MULS.
239 (define_code_attr mul_r_d
243 ;; Map RTX code to its standard insn name
244 (define_code_attr code_stdname
250 ;;========================================================================
251 ;; The following is used by nonlocal_goto and setjmp.
252 ;; The receiver pattern will create no instructions since internally
253 ;; virtual_stack_vars = hard_frame_pointer + 1 so the RTL become R28=R28
254 ;; This avoids creating add/sub offsets in frame_pointer save/resore.
255 ;; The 'null' receiver also avoids problems with optimisation
256 ;; not recognising incoming jmp and removing code that resets frame_pointer.
257 ;; The code derived from builtins.c.
259 (define_expand "nonlocal_goto_receiver"
261 (unspec_volatile:HI [(const_int 0)] UNSPECV_GOTO_RECEIVER))]
264 emit_move_insn (virtual_stack_vars_rtx,
265 gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx,
266 gen_int_mode (STARTING_FRAME_OFFSET,
268 /* This might change the hard frame pointer in ways that aren't
269 apparent to early optimization passes, so force a clobber. */
270 emit_clobber (hard_frame_pointer_rtx);
275 ;; Defining nonlocal_goto_receiver means we must also define this.
276 ;; even though its function is identical to that in builtins.c
278 (define_expand "nonlocal_goto"
279 [(use (match_operand 0 "general_operand"))
280 (use (match_operand 1 "general_operand"))
281 (use (match_operand 2 "general_operand"))
282 (use (match_operand 3 "general_operand"))]
285 rtx r_label = copy_to_reg (operands[1]);
286 rtx r_fp = operands[3];
287 rtx r_sp = operands[2];
289 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
291 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
293 emit_move_insn (hard_frame_pointer_rtx, r_fp);
294 emit_stack_restore (SAVE_NONLOCAL, r_sp);
296 emit_use (hard_frame_pointer_rtx);
297 emit_use (stack_pointer_rtx);
299 emit_indirect_jump (r_label);
304 (define_insn "pushqi1"
305 [(set (mem:QI (post_dec:HI (reg:HI REG_SP)))
306 (match_operand:QI 0 "reg_or_0_operand" "r,L"))]
311 [(set_attr "length" "1,1")])
313 ;; All modes for a multi-byte push. We must include complex modes here too,
314 ;; lest emit_single_push_insn "helpfully " create the auto-inc itself.
315 (define_mode_iterator MPUSH
323 (define_expand "push<mode>1"
324 [(match_operand:MPUSH 0 "" "")]
328 for (i = GET_MODE_SIZE (<MODE>mode) - 1; i >= 0; --i)
330 rtx part = simplify_gen_subreg (QImode, operands[0], <MODE>mode, i);
331 if (part != const0_rtx)
332 part = force_reg (QImode, part);
333 emit_insn (gen_pushqi1 (part));
338 ;; Notice a special-case when adding N to SP where N results in a
339 ;; zero REG_ARGS_SIZE. This is equivalent to a move from FP.
341 [(set (reg:HI REG_SP) (match_operand:HI 0 "register_operand" ""))]
343 && frame_pointer_needed
344 && !cfun->calls_alloca
345 && find_reg_note (insn, REG_ARGS_SIZE, const0_rtx)"
346 [(set (reg:HI REG_SP) (reg:HI REG_Y))]
349 ;;========================================================================
352 (define_expand "load<mode>_libgcc"
355 (set (reg:MOVMODE 22)
356 (match_operand:MOVMODE 1 "memory_operand" ""))
357 (set (match_operand:MOVMODE 0 "register_operand" "")
359 "avr_load_libgcc_p (operands[1])"
361 operands[3] = gen_rtx_REG (HImode, REG_Z);
362 operands[2] = force_operand (XEXP (operands[1], 0), NULL_RTX);
363 operands[1] = replace_equiv_address (operands[1], operands[3]);
364 set_mem_addr_space (operands[1], ADDR_SPACE_FLASH);
367 (define_insn "load_<mode>_libgcc"
368 [(set (reg:MOVMODE 22)
369 (match_operand:MOVMODE 0 "memory_operand" "m,m"))]
370 "avr_load_libgcc_p (operands[0])
371 && REG_P (XEXP (operands[0], 0))
372 && REG_Z == REGNO (XEXP (operands[0], 0))"
374 operands[0] = GEN_INT (GET_MODE_SIZE (<MODE>mode));
375 return "%~call __load_%0";
377 [(set_attr "length" "1,2")
378 (set_attr "isa" "rjmp,jmp")
379 (set_attr "cc" "clobber")])
382 (define_insn_and_split "xload8_A"
383 [(set (match_operand:QI 0 "register_operand" "=r")
384 (match_operand:QI 1 "memory_operand" "m"))
385 (clobber (reg:HI REG_Z))]
386 "can_create_pseudo_p()
387 && !avr_xload_libgcc_p (QImode)
388 && avr_mem_memx_p (operands[1])
389 && REG_P (XEXP (operands[1], 0))"
390 { gcc_unreachable(); }
392 [(clobber (const_int 0))]
394 rtx insn, addr = XEXP (operands[1], 0);
395 rtx hi8 = gen_reg_rtx (QImode);
396 rtx reg_z = gen_rtx_REG (HImode, REG_Z);
398 emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0));
399 emit_move_insn (hi8, simplify_gen_subreg (QImode, addr, PSImode, 2));
401 insn = emit_insn (gen_xload_8 (operands[0], hi8));
402 set_mem_addr_space (SET_SRC (single_set (insn)),
403 MEM_ADDR_SPACE (operands[1]));
407 (define_insn_and_split "xload<mode>_A"
408 [(set (match_operand:MOVMODE 0 "register_operand" "=r")
409 (match_operand:MOVMODE 1 "memory_operand" "m"))
410 (clobber (reg:QI 21))
411 (clobber (reg:HI REG_Z))]
412 "can_create_pseudo_p()
413 && avr_mem_memx_p (operands[1])
414 && REG_P (XEXP (operands[1], 0))"
415 { gcc_unreachable(); }
417 [(clobber (const_int 0))]
419 rtx addr = XEXP (operands[1], 0);
420 rtx reg_z = gen_rtx_REG (HImode, REG_Z);
421 rtx addr_hi8 = simplify_gen_subreg (QImode, addr, PSImode, 2);
422 addr_space_t as = MEM_ADDR_SPACE (operands[1]);
425 /* Split the address to R21:Z */
426 emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0));
427 emit_move_insn (gen_rtx_REG (QImode, 21), addr_hi8);
429 /* Load with code from libgcc */
430 insn = emit_insn (gen_xload_<mode>_libgcc ());
431 set_mem_addr_space (SET_SRC (single_set (insn)), as);
433 /* Move to destination */
434 emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, 22));
439 ;; Move value from address space memx to a register
440 ;; These insns must be prior to respective generic move insn.
442 (define_insn "xload_8"
443 [(set (match_operand:QI 0 "register_operand" "=&r,r")
444 (mem:QI (lo_sum:PSI (match_operand:QI 1 "register_operand" "r,r")
446 "!avr_xload_libgcc_p (QImode)"
448 return avr_out_xload (insn, operands, NULL);
450 [(set_attr "length" "3,4")
451 (set_attr "adjust_len" "*,xload")
452 (set_attr "isa" "lpmx,lpm")
453 (set_attr "cc" "none")])
457 ;; "xload_psi_libgcc"
460 (define_insn "xload_<mode>_libgcc"
461 [(set (reg:MOVMODE 22)
462 (mem:MOVMODE (lo_sum:PSI (reg:QI 21)
464 (clobber (reg:QI 21))
465 (clobber (reg:HI REG_Z))]
466 "avr_xload_libgcc_p (<MODE>mode)"
468 rtx x_bytes = GEN_INT (GET_MODE_SIZE (<MODE>mode));
470 output_asm_insn ("%~call __xload_%0", &x_bytes);
473 [(set_attr "type" "xcall")
474 (set_attr "cc" "clobber")])
477 ;; General move expanders
484 (define_expand "mov<mode>"
485 [(set (match_operand:MOVMODE 0 "nonimmediate_operand" "")
486 (match_operand:MOVMODE 1 "general_operand" ""))]
489 rtx dest = operands[0];
490 rtx src = operands[1];
492 if (avr_mem_flash_p (dest))
495 /* One of the operands has to be in a register. */
496 if (!register_operand (dest, <MODE>mode)
497 && !(register_operand (src, <MODE>mode)
498 || src == CONST0_RTX (<MODE>mode)))
500 operands[1] = src = copy_to_mode_reg (<MODE>mode, src);
503 if (avr_mem_memx_p (src))
505 rtx addr = XEXP (src, 0);
508 src = replace_equiv_address (src, copy_to_mode_reg (PSImode, addr));
510 if (!avr_xload_libgcc_p (<MODE>mode))
511 emit_insn (gen_xload8_A (dest, src));
513 emit_insn (gen_xload<mode>_A (dest, src));
518 if (avr_load_libgcc_p (src))
520 /* For the small devices, do loads per libgcc call. */
521 emit_insn (gen_load<mode>_libgcc (dest, src));
526 ;;========================================================================
528 ;; The last alternative (any immediate constant to any register) is
529 ;; very expensive. It should be optimized by peephole2 if a scratch
530 ;; register is available, but then that register could just as well be
531 ;; allocated for the variable we are loading. But, most of NO_LD_REGS
532 ;; are call-saved registers, and most of LD_REGS are call-used registers,
533 ;; so this may still be a win for registers live across function calls.
535 (define_insn "movqi_insn"
536 [(set (match_operand:QI 0 "nonimmediate_operand" "=r ,d,Qm,r ,q,r,*r")
537 (match_operand:QI 1 "nox_general_operand" "rL,i,rL,Qm,r,q,i"))]
538 "register_operand (operands[0], QImode)
539 || register_operand (operands[1], QImode)
540 || const0_rtx == operands[1]"
542 return output_movqi (insn, operands, NULL);
544 [(set_attr "length" "1,1,5,5,1,1,4")
545 (set_attr "adjust_len" "mov8")
546 (set_attr "cc" "ldi,none,clobber,clobber,none,none,clobber")])
548 ;; This is used in peephole2 to optimize loading immediate constants
549 ;; if a scratch register from LD_REGS happens to be available.
551 (define_insn "*reload_inqi"
552 [(set (match_operand:QI 0 "register_operand" "=l")
553 (match_operand:QI 1 "immediate_operand" "i"))
554 (clobber (match_operand:QI 2 "register_operand" "=&d"))]
558 [(set_attr "length" "2")
559 (set_attr "cc" "none")])
562 [(match_scratch:QI 2 "d")
563 (set (match_operand:QI 0 "l_register_operand" "")
564 (match_operand:QI 1 "immediate_operand" ""))]
565 "(operands[1] != const0_rtx
566 && operands[1] != const1_rtx
567 && operands[1] != constm1_rtx)"
568 [(parallel [(set (match_dup 0) (match_dup 1))
569 (clobber (match_dup 2))])]
572 ;;============================================================================
573 ;; move word (16 bit)
575 ;; Move register $1 to the Stack Pointer register SP.
576 ;; This insn is emit during function prologue/epilogue generation.
577 ;; $2 = 0: We know that IRQs are off
578 ;; $2 = 1: We know that IRQs are on
579 ;; Remaining cases when the state of the I-Flag is unknown are
580 ;; handled by generic movhi insn.
582 (define_insn "movhi_sp_r"
583 [(set (match_operand:HI 0 "stack_register_operand" "=q,q")
584 (unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r,r")
585 (match_operand:HI 2 "const_int_operand" "L,P")]
589 out __SP_H__,%B1\;out __SP_L__,%A1
590 cli\;out __SP_H__,%B1\;sei\;out __SP_L__,%A1"
591 [(set_attr "length" "2,4")
592 (set_attr "cc" "none")])
595 [(match_scratch:QI 2 "d")
596 (set (match_operand:HI 0 "l_register_operand" "")
597 (match_operand:HI 1 "immediate_operand" ""))]
598 "(operands[1] != const0_rtx
599 && operands[1] != constm1_rtx)"
600 [(parallel [(set (match_dup 0) (match_dup 1))
601 (clobber (match_dup 2))])]
604 ;; '*' because it is not used in rtl generation, only in above peephole
605 (define_insn "*reload_inhi"
606 [(set (match_operand:HI 0 "register_operand" "=r")
607 (match_operand:HI 1 "immediate_operand" "i"))
608 (clobber (match_operand:QI 2 "register_operand" "=&d"))]
611 return output_reload_inhi (operands, operands[2], NULL);
613 [(set_attr "length" "4")
614 (set_attr "adjust_len" "reload_in16")
615 (set_attr "cc" "none")])
617 (define_insn "*movhi"
618 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m ,d,*r,q,r")
619 (match_operand:HI 1 "nox_general_operand" "r,L,m,rL,i,i ,r,q"))]
620 "register_operand (operands[0], HImode)
621 || register_operand (operands[1], HImode)
622 || const0_rtx == operands[1]"
624 return output_movhi (insn, operands, NULL);
626 [(set_attr "length" "2,2,6,7,2,6,5,2")
627 (set_attr "adjust_len" "mov16")
628 (set_attr "cc" "none,none,clobber,clobber,none,clobber,none,none")])
630 (define_peephole2 ; movw
631 [(set (match_operand:QI 0 "even_register_operand" "")
632 (match_operand:QI 1 "even_register_operand" ""))
633 (set (match_operand:QI 2 "odd_register_operand" "")
634 (match_operand:QI 3 "odd_register_operand" ""))]
636 && REGNO (operands[0]) == REGNO (operands[2]) - 1
637 && REGNO (operands[1]) == REGNO (operands[3]) - 1)"
638 [(set (match_dup 4) (match_dup 5))]
640 operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
641 operands[5] = gen_rtx_REG (HImode, REGNO (operands[1]));
644 (define_peephole2 ; movw_r
645 [(set (match_operand:QI 0 "odd_register_operand" "")
646 (match_operand:QI 1 "odd_register_operand" ""))
647 (set (match_operand:QI 2 "even_register_operand" "")
648 (match_operand:QI 3 "even_register_operand" ""))]
650 && REGNO (operands[2]) == REGNO (operands[0]) - 1
651 && REGNO (operands[3]) == REGNO (operands[1]) - 1)"
652 [(set (match_dup 4) (match_dup 5))]
654 operands[4] = gen_rtx_REG (HImode, REGNO (operands[2]));
655 operands[5] = gen_rtx_REG (HImode, REGNO (operands[3]));
658 ;; For LPM loads from AS1 we split
662 ;; Z = Z - sizeof (R)
664 ;; so that the second instruction can be optimized out.
666 (define_split ; "split-lpmx"
667 [(set (match_operand:HISI 0 "register_operand" "")
668 (match_operand:HISI 1 "memory_operand" ""))]
674 (plus:HI (match_dup 3)
677 rtx addr = XEXP (operands[1], 0);
679 if (!avr_mem_flash_p (operands[1])
681 || reg_overlap_mentioned_p (addr, operands[0]))
686 operands[2] = replace_equiv_address (operands[1],
687 gen_rtx_POST_INC (Pmode, addr));
689 operands[4] = gen_int_mode (-GET_MODE_SIZE (<MODE>mode), HImode);
692 ;;==========================================================================
693 ;; xpointer move (24 bit)
695 (define_peephole2 ; *reload_inpsi
696 [(match_scratch:QI 2 "d")
697 (set (match_operand:PSI 0 "l_register_operand" "")
698 (match_operand:PSI 1 "immediate_operand" ""))
700 "operands[1] != const0_rtx
701 && operands[1] != constm1_rtx"
702 [(parallel [(set (match_dup 0)
704 (clobber (match_dup 2))])]
707 ;; '*' because it is not used in rtl generation.
708 (define_insn "*reload_inpsi"
709 [(set (match_operand:PSI 0 "register_operand" "=r")
710 (match_operand:PSI 1 "immediate_operand" "i"))
711 (clobber (match_operand:QI 2 "register_operand" "=&d"))]
714 return avr_out_reload_inpsi (operands, operands[2], NULL);
716 [(set_attr "length" "6")
717 (set_attr "adjust_len" "reload_in24")
718 (set_attr "cc" "clobber")])
720 (define_insn "*movpsi"
721 [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
722 (match_operand:PSI 1 "nox_general_operand" "r,L,Qm,rL,i ,i"))]
723 "register_operand (operands[0], PSImode)
724 || register_operand (operands[1], PSImode)
725 || const0_rtx == operands[1]"
727 return avr_out_movpsi (insn, operands, NULL);
729 [(set_attr "length" "3,3,8,9,4,10")
730 (set_attr "adjust_len" "mov24")
731 (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
733 ;;==========================================================================
734 ;; move double word (32 bit)
736 (define_peephole2 ; *reload_insi
737 [(match_scratch:QI 2 "d")
738 (set (match_operand:SI 0 "l_register_operand" "")
739 (match_operand:SI 1 "const_int_operand" ""))
741 "(operands[1] != const0_rtx
742 && operands[1] != constm1_rtx)"
743 [(parallel [(set (match_dup 0) (match_dup 1))
744 (clobber (match_dup 2))])]
747 ;; '*' because it is not used in rtl generation.
748 (define_insn "*reload_insi"
749 [(set (match_operand:SI 0 "register_operand" "=r")
750 (match_operand:SI 1 "const_int_operand" "n"))
751 (clobber (match_operand:QI 2 "register_operand" "=&d"))]
754 return output_reload_insisf (operands, operands[2], NULL);
756 [(set_attr "length" "8")
757 (set_attr "adjust_len" "reload_in32")
758 (set_attr "cc" "clobber")])
761 (define_insn "*movsi"
762 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
763 (match_operand:SI 1 "nox_general_operand" "r,L,Qm,rL,i ,i"))]
764 "register_operand (operands[0], SImode)
765 || register_operand (operands[1], SImode)
766 || const0_rtx == operands[1]"
768 return output_movsisf (insn, operands, NULL);
770 [(set_attr "length" "4,4,8,9,4,10")
771 (set_attr "adjust_len" "mov32")
772 (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
774 ;; fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
775 ;; move floating point numbers (32 bit)
777 (define_insn "*movsf"
778 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
779 (match_operand:SF 1 "nox_general_operand" "r,G,Qm,rG,F ,F"))]
780 "register_operand (operands[0], SFmode)
781 || register_operand (operands[1], SFmode)
782 || operands[1] == CONST0_RTX (SFmode)"
784 return output_movsisf (insn, operands, NULL);
786 [(set_attr "length" "4,4,8,9,4,10")
787 (set_attr "adjust_len" "mov32")
788 (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
790 (define_peephole2 ; *reload_insf
791 [(match_scratch:QI 2 "d")
792 (set (match_operand:SF 0 "l_register_operand" "")
793 (match_operand:SF 1 "const_double_operand" ""))
795 "operands[1] != CONST0_RTX (SFmode)"
796 [(parallel [(set (match_dup 0)
798 (clobber (match_dup 2))])]
801 ;; '*' because it is not used in rtl generation.
802 (define_insn "*reload_insf"
803 [(set (match_operand:SF 0 "register_operand" "=r")
804 (match_operand:SF 1 "const_double_operand" "F"))
805 (clobber (match_operand:QI 2 "register_operand" "=&d"))]
808 return output_reload_insisf (operands, operands[2], NULL);
810 [(set_attr "length" "8")
811 (set_attr "adjust_len" "reload_in32")
812 (set_attr "cc" "clobber")])
814 ;;=========================================================================
815 ;; move string (like memcpy)
817 (define_expand "movmemhi"
818 [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
819 (match_operand:BLK 1 "memory_operand" ""))
820 (use (match_operand:HI 2 "const_int_operand" ""))
821 (use (match_operand:HI 3 "const_int_operand" ""))])]
824 if (avr_emit_movmemhi (operands))
830 (define_mode_attr MOVMEM_r_d [(QI "r")
833 ;; $0, $4 : & dest (REG_X)
834 ;; $1, $5 : & src (REG_Z)
835 ;; $2 : Address Space
836 ;; $3, $7 : Loop register
837 ;; $6 : Scratch register
841 (define_insn "movmem_<mode>"
842 [(set (mem:BLK (match_operand:HI 0 "register_operand" "x"))
843 (mem:BLK (match_operand:HI 1 "register_operand" "z")))
844 (unspec [(match_operand:QI 2 "const_int_operand" "n")]
846 (use (match_operand:QIHI 3 "register_operand" "<MOVMEM_r_d>"))
847 (clobber (match_operand:HI 4 "register_operand" "=0"))
848 (clobber (match_operand:HI 5 "register_operand" "=1"))
849 (clobber (match_operand:QI 6 "register_operand" "=&r"))
850 (clobber (match_operand:QIHI 7 "register_operand" "=3"))]
853 return avr_out_movmem (insn, operands, NULL);
855 [(set_attr "adjust_len" "movmem")
856 (set_attr "cc" "clobber")])
859 ;; $3, $7 : Loop register = R24
860 ;; $8, $9 : hh8 (& src) = R23
865 (define_insn "movmemx_<mode>"
866 [(set (mem:BLK (match_operand:HI 0 "register_operand" "x"))
867 (mem:BLK (lo_sum:PSI (match_operand:QI 8 "register_operand" "r")
868 (match_operand:HI 1 "register_operand" "z"))))
869 (unspec [(match_operand:QI 2 "const_int_operand" "n")]
871 (use (match_operand:QIHI 3 "register_operand" "w"))
872 (clobber (match_operand:HI 4 "register_operand" "=0"))
873 (clobber (match_operand:HI 5 "register_operand" "=1"))
874 (clobber (match_operand:QI 6 "register_operand" "=&r"))
875 (clobber (match_operand:HI 7 "register_operand" "=3"))
876 (clobber (match_operand:QI 9 "register_operand" "=8"))
877 (clobber (mem:QI (match_operand:QI 10 "io_address_operand" "n")))]
879 "%~call __movmemx_<mode>"
880 [(set_attr "type" "xcall")
881 (set_attr "cc" "clobber")])
884 ;; =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2
885 ;; memset (%0, %2, %1)
887 (define_expand "setmemhi"
888 [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
889 (match_operand 2 "const_int_operand" ""))
890 (use (match_operand:HI 1 "const_int_operand" ""))
891 (use (match_operand:HI 3 "const_int_operand" ""))
892 (clobber (match_scratch:HI 4 ""))
893 (clobber (match_dup 5))])]
897 enum machine_mode mode;
899 /* If value to set is not zero, use the library routine. */
900 if (operands[2] != const0_rtx)
903 if (!CONST_INT_P (operands[1]))
906 mode = u8_operand (operands[1], VOIDmode) ? QImode : HImode;
907 operands[5] = gen_rtx_SCRATCH (mode);
908 operands[1] = copy_to_mode_reg (mode,
909 gen_int_mode (INTVAL (operands[1]), mode));
910 addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
911 operands[0] = gen_rtx_MEM (BLKmode, addr0);
915 (define_insn "*clrmemqi"
916 [(set (mem:BLK (match_operand:HI 0 "register_operand" "e"))
918 (use (match_operand:QI 1 "register_operand" "r"))
919 (use (match_operand:QI 2 "const_int_operand" "n"))
920 (clobber (match_scratch:HI 3 "=0"))
921 (clobber (match_scratch:QI 4 "=&1"))]
923 "0:\;st %a0+,__zero_reg__\;dec %1\;brne 0b"
924 [(set_attr "length" "3")
925 (set_attr "cc" "clobber")])
928 (define_insn "*clrmemhi"
929 [(set (mem:BLK (match_operand:HI 0 "register_operand" "e,e"))
931 (use (match_operand:HI 1 "register_operand" "!w,d"))
932 (use (match_operand:HI 2 "const_int_operand" "n,n"))
933 (clobber (match_scratch:HI 3 "=0,0"))
934 (clobber (match_scratch:HI 4 "=&1,&1"))]
937 0:\;st %a0+,__zero_reg__\;sbiw %A1,1\;brne 0b
938 0:\;st %a0+,__zero_reg__\;subi %A1,1\;sbci %B1,0\;brne 0b"
939 [(set_attr "length" "3,4")
940 (set_attr "cc" "clobber,clobber")])
942 (define_expand "strlenhi"
944 (unspec:HI [(match_operand:BLK 1 "memory_operand" "")
945 (match_operand:QI 2 "const_int_operand" "")
946 (match_operand:HI 3 "immediate_operand" "")]
949 (plus:HI (match_dup 4)
951 (set (match_operand:HI 0 "register_operand" "")
952 (minus:HI (match_dup 4)
957 if (operands[2] != const0_rtx)
959 addr = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
960 operands[1] = gen_rtx_MEM (BLKmode, addr);
962 operands[4] = gen_reg_rtx (HImode);
965 (define_insn "*strlenhi"
966 [(set (match_operand:HI 0 "register_operand" "=e")
967 (unspec:HI [(mem:BLK (match_operand:HI 1 "register_operand" "0"))
969 (match_operand:HI 2 "immediate_operand" "i")]
972 "0:\;ld __tmp_reg__,%a0+\;tst __tmp_reg__\;brne 0b"
973 [(set_attr "length" "3")
974 (set_attr "cc" "clobber")])
976 ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
979 (define_insn "addqi3"
980 [(set (match_operand:QI 0 "register_operand" "=r,d,r,r,r,r")
981 (plus:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
982 (match_operand:QI 2 "nonmemory_operand" "r,i,P,N,K,Cm2")))]
991 [(set_attr "length" "1,1,1,1,2,2")
992 (set_attr "cc" "set_czn,set_czn,set_zn,set_zn,set_zn,set_zn")])
995 (define_expand "addhi3"
996 [(set (match_operand:HI 0 "register_operand" "")
997 (plus:HI (match_operand:HI 1 "register_operand" "")
998 (match_operand:HI 2 "nonmemory_operand" "")))]
1001 if (CONST_INT_P (operands[2]))
1003 operands[2] = gen_int_mode (INTVAL (operands[2]), HImode);
1005 if (can_create_pseudo_p()
1006 && !stack_register_operand (operands[0], HImode)
1007 && !stack_register_operand (operands[1], HImode)
1008 && !d_register_operand (operands[0], HImode)
1009 && !d_register_operand (operands[1], HImode))
1011 emit_insn (gen_addhi3_clobber (operands[0], operands[1], operands[2]));
1018 (define_insn "*addhi3_zero_extend"
1019 [(set (match_operand:HI 0 "register_operand" "=r")
1020 (plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1021 (match_operand:HI 2 "register_operand" "0")))]
1023 "add %A0,%1\;adc %B0,__zero_reg__"
1024 [(set_attr "length" "2")
1025 (set_attr "cc" "set_n")])
1027 (define_insn "*addhi3_zero_extend1"
1028 [(set (match_operand:HI 0 "register_operand" "=r")
1029 (plus:HI (match_operand:HI 1 "register_operand" "0")
1030 (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1032 "add %A0,%2\;adc %B0,__zero_reg__"
1033 [(set_attr "length" "2")
1034 (set_attr "cc" "set_n")])
1036 (define_insn "*addhi3.sign_extend1"
1037 [(set (match_operand:HI 0 "register_operand" "=r")
1038 (plus:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "r"))
1039 (match_operand:HI 2 "register_operand" "0")))]
1042 return reg_overlap_mentioned_p (operands[0], operands[1])
1043 ? "mov __tmp_reg__,%1\;add %A0,%1\;adc %B0,__zero_reg__\;sbrc __tmp_reg__,7\;dec %B0"
1044 : "add %A0,%1\;adc %B0,__zero_reg__\;sbrc %1,7\;dec %B0";
1046 [(set_attr "length" "5")
1047 (set_attr "cc" "clobber")])
1049 (define_insn "*addhi3_sp"
1050 [(set (match_operand:HI 1 "stack_register_operand" "=q")
1051 (plus:HI (match_operand:HI 2 "stack_register_operand" "q")
1052 (match_operand:HI 0 "avr_sp_immediate_operand" "Csp")))]
1055 return avr_out_addto_sp (operands, NULL);
1057 [(set_attr "length" "6")
1058 (set_attr "adjust_len" "addto_sp")])
1060 (define_insn "*addhi3"
1061 [(set (match_operand:HI 0 "register_operand" "=r,d,d")
1062 (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
1063 (match_operand:HI 2 "nonmemory_operand" "r,s,n")))]
1066 static const char * const asm_code[] =
1068 "add %A0,%A2\;adc %B0,%B2",
1069 "subi %A0,lo8(-(%2))\;sbci %B0,hi8(-(%2))",
1073 if (*asm_code[which_alternative])
1074 return asm_code[which_alternative];
1076 return avr_out_plus_noclobber (operands, NULL, NULL);
1078 [(set_attr "length" "2,2,2")
1079 (set_attr "adjust_len" "*,*,out_plus_noclobber")
1080 (set_attr "cc" "set_n,set_czn,out_plus_noclobber")])
1082 ;; Adding a constant to NO_LD_REGS might have lead to a reload of
1083 ;; that constant to LD_REGS. We don't add a scratch to *addhi3
1084 ;; itself because that insn is special to reload.
1086 (define_peephole2 ; addhi3_clobber
1087 [(set (match_operand:HI 0 "d_register_operand" "")
1088 (match_operand:HI 1 "const_int_operand" ""))
1089 (set (match_operand:HI 2 "l_register_operand" "")
1090 (plus:HI (match_dup 2)
1092 "peep2_reg_dead_p (2, operands[0])"
1093 [(parallel [(set (match_dup 2)
1094 (plus:HI (match_dup 2)
1096 (clobber (match_dup 3))])]
1098 operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
1101 ;; Same, but with reload to NO_LD_REGS
1102 ;; Combine *reload_inhi with *addhi3
1104 (define_peephole2 ; addhi3_clobber
1105 [(parallel [(set (match_operand:HI 0 "l_register_operand" "")
1106 (match_operand:HI 1 "const_int_operand" ""))
1107 (clobber (match_operand:QI 2 "d_register_operand" ""))])
1108 (set (match_operand:HI 3 "l_register_operand" "")
1109 (plus:HI (match_dup 3)
1111 "peep2_reg_dead_p (2, operands[0])"
1112 [(parallel [(set (match_dup 3)
1113 (plus:HI (match_dup 3)
1115 (clobber (match_dup 2))])])
1117 (define_insn "addhi3_clobber"
1118 [(set (match_operand:HI 0 "register_operand" "=d,l")
1119 (plus:HI (match_operand:HI 1 "register_operand" "%0,0")
1120 (match_operand:HI 2 "const_int_operand" "n,n")))
1121 (clobber (match_scratch:QI 3 "=X,&d"))]
1124 gcc_assert (REGNO (operands[0]) == REGNO (operands[1]));
1126 return avr_out_plus (operands, NULL, NULL);
1128 [(set_attr "length" "4")
1129 (set_attr "adjust_len" "out_plus")
1130 (set_attr "cc" "out_plus")])
1133 (define_insn "addsi3"
1134 [(set (match_operand:SI 0 "register_operand" "=r,d ,d,r")
1135 (plus:SI (match_operand:SI 1 "register_operand" "%0,0 ,0,0")
1136 (match_operand:SI 2 "nonmemory_operand" "r,s ,n,n")))
1137 (clobber (match_scratch:QI 3 "=X,X ,X,&d"))]
1140 static const char * const asm_code[] =
1142 "add %A0,%A2\;adc %B0,%B2\;adc %C0,%C2\;adc %D0,%D2",
1143 "subi %0,lo8(-(%2))\;sbci %B0,hi8(-(%2))\;sbci %C0,hlo8(-(%2))\;sbci %D0,hhi8(-(%2))",
1148 if (*asm_code[which_alternative])
1149 return asm_code[which_alternative];
1151 return avr_out_plus (operands, NULL, NULL);
1153 [(set_attr "length" "4,4,4,8")
1154 (set_attr "adjust_len" "*,*,out_plus,out_plus")
1155 (set_attr "cc" "set_n,set_czn,out_plus,out_plus")])
1157 (define_insn "*addpsi3_zero_extend.qi"
1158 [(set (match_operand:PSI 0 "register_operand" "=r")
1159 (plus:PSI (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))
1160 (match_operand:PSI 2 "register_operand" "0")))]
1162 "add %A0,%A1\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__"
1163 [(set_attr "length" "3")
1164 (set_attr "cc" "set_n")])
1166 (define_insn "*addpsi3_zero_extend.hi"
1167 [(set (match_operand:PSI 0 "register_operand" "=r")
1168 (plus:PSI (zero_extend:PSI (match_operand:HI 1 "register_operand" "r"))
1169 (match_operand:PSI 2 "register_operand" "0")))]
1171 "add %A0,%A1\;adc %B0,%B1\;adc %C0,__zero_reg__"
1172 [(set_attr "length" "3")
1173 (set_attr "cc" "set_n")])
1175 (define_insn "*addpsi3_sign_extend.hi"
1176 [(set (match_operand:PSI 0 "register_operand" "=r")
1177 (plus:PSI (sign_extend:PSI (match_operand:HI 1 "register_operand" "r"))
1178 (match_operand:PSI 2 "register_operand" "0")))]
1180 "add %A0,%1\;adc %B0,%B1\;adc %C0,__zero_reg__\;sbrc %B1,7\;dec %C0"
1181 [(set_attr "length" "5")
1182 (set_attr "cc" "set_n")])
1184 (define_insn "*addsi3_zero_extend"
1185 [(set (match_operand:SI 0 "register_operand" "=r")
1186 (plus:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
1187 (match_operand:SI 2 "register_operand" "0")))]
1189 "add %A0,%1\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__"
1190 [(set_attr "length" "4")
1191 (set_attr "cc" "set_n")])
1193 (define_insn "*addsi3_zero_extend.hi"
1194 [(set (match_operand:SI 0 "register_operand" "=r")
1195 (plus:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
1196 (match_operand:SI 2 "register_operand" "0")))]
1198 "add %A0,%1\;adc %B0,%B1\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__"
1199 [(set_attr "length" "4")
1200 (set_attr "cc" "set_n")])
1202 (define_insn "addpsi3"
1203 [(set (match_operand:PSI 0 "register_operand" "=r,d ,d,r")
1204 (plus:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0,0")
1205 (match_operand:PSI 2 "nonmemory_operand" "r,s ,n,n")))
1206 (clobber (match_scratch:QI 3 "=X,X ,X,&d"))]
1209 static const char * const asm_code[] =
1211 "add %A0,%A2\;adc %B0,%B2\;adc %C0,%C2",
1212 "subi %0,lo8(-(%2))\;sbci %B0,hi8(-(%2))\;sbci %C0,hlo8(-(%2))",
1217 if (*asm_code[which_alternative])
1218 return asm_code[which_alternative];
1220 return avr_out_plus (operands, NULL, NULL);
1222 [(set_attr "length" "3,3,3,6")
1223 (set_attr "adjust_len" "*,*,out_plus,out_plus")
1224 (set_attr "cc" "set_n,set_czn,out_plus,out_plus")])
1226 (define_insn "subpsi3"
1227 [(set (match_operand:PSI 0 "register_operand" "=r")
1228 (minus:PSI (match_operand:PSI 1 "register_operand" "0")
1229 (match_operand:PSI 2 "register_operand" "r")))]
1231 "sub %0,%2\;sbc %B0,%B2\;sbc %C0,%C2"
1232 [(set_attr "length" "3")
1233 (set_attr "cc" "set_czn")])
1235 (define_insn "*subpsi3_zero_extend.qi"
1236 [(set (match_operand:PSI 0 "register_operand" "=r")
1237 (minus:PSI (match_operand:SI 1 "register_operand" "0")
1238 (zero_extend:PSI (match_operand:QI 2 "register_operand" "r"))))]
1240 "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__"
1241 [(set_attr "length" "3")
1242 (set_attr "cc" "set_czn")])
1244 (define_insn "*subpsi3_zero_extend.hi"
1245 [(set (match_operand:PSI 0 "register_operand" "=r")
1246 (minus:PSI (match_operand:PSI 1 "register_operand" "0")
1247 (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
1249 "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__"
1250 [(set_attr "length" "3")
1251 (set_attr "cc" "set_czn")])
1253 (define_insn "*subpsi3_sign_extend.hi"
1254 [(set (match_operand:PSI 0 "register_operand" "=r")
1255 (minus:PSI (match_operand:PSI 1 "register_operand" "0")
1256 (sign_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
1258 "sub %A0,%A2\;sbc %B0,%B2\;sbc %C0,__zero_reg__\;sbrc %B2,7\;inc %C0"
1259 [(set_attr "length" "5")
1260 (set_attr "cc" "set_czn")])
1262 ;-----------------------------------------------------------------------------
1264 (define_insn "subqi3"
1265 [(set (match_operand:QI 0 "register_operand" "=r,d")
1266 (minus:QI (match_operand:QI 1 "register_operand" "0,0")
1267 (match_operand:QI 2 "nonmemory_operand" "r,i")))]
1272 [(set_attr "length" "1,1")
1273 (set_attr "cc" "set_czn,set_czn")])
1275 (define_insn "subhi3"
1276 [(set (match_operand:HI 0 "register_operand" "=r,d")
1277 (minus:HI (match_operand:HI 1 "register_operand" "0,0")
1278 (match_operand:HI 2 "nonmemory_operand" "r,i")))]
1281 sub %A0,%A2\;sbc %B0,%B2
1282 subi %A0,lo8(%2)\;sbci %B0,hi8(%2)"
1283 [(set_attr "length" "2,2")
1284 (set_attr "cc" "set_czn,set_czn")])
1286 (define_insn "*subhi3_zero_extend1"
1287 [(set (match_operand:HI 0 "register_operand" "=r")
1288 (minus:HI (match_operand:HI 1 "register_operand" "0")
1289 (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1291 "sub %A0,%2\;sbc %B0,__zero_reg__"
1292 [(set_attr "length" "2")
1293 (set_attr "cc" "set_czn")])
1295 (define_insn "*subhi3.sign_extend2"
1296 [(set (match_operand:HI 0 "register_operand" "=r")
1297 (minus:HI (match_operand:HI 1 "register_operand" "0")
1298 (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1301 return reg_overlap_mentioned_p (operands[0], operands[2])
1302 ? "mov __tmp_reg__,%2\;sub %A0,%2\;sbc %B0,__zero_reg__\;sbrc __tmp_reg__,7\;inc %B0"
1303 : "sub %A0,%2\;sbc %B0,__zero_reg__\;sbrc %2,7\;inc %B0";
1305 [(set_attr "length" "5")
1306 (set_attr "cc" "clobber")])
1308 (define_insn "subsi3"
1309 [(set (match_operand:SI 0 "register_operand" "=r")
1310 (minus:SI (match_operand:SI 1 "register_operand" "0")
1311 (match_operand:SI 2 "register_operand" "r")))]
1313 "sub %0,%2\;sbc %B0,%B2\;sbc %C0,%C2\;sbc %D0,%D2"
1314 [(set_attr "length" "4")
1315 (set_attr "cc" "set_czn")])
1317 (define_insn "*subsi3_zero_extend"
1318 [(set (match_operand:SI 0 "register_operand" "=r")
1319 (minus:SI (match_operand:SI 1 "register_operand" "0")
1320 (zero_extend:SI (match_operand:QI 2 "register_operand" "r"))))]
1322 "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
1323 [(set_attr "length" "4")
1324 (set_attr "cc" "set_czn")])
1326 (define_insn "*subsi3_zero_extend.hi"
1327 [(set (match_operand:SI 0 "register_operand" "=r")
1328 (minus:SI (match_operand:SI 1 "register_operand" "0")
1329 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1331 "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
1332 [(set_attr "length" "4")
1333 (set_attr "cc" "set_czn")])
1335 ;******************************************************************************
1338 (define_expand "mulqi3"
1339 [(set (match_operand:QI 0 "register_operand" "")
1340 (mult:QI (match_operand:QI 1 "register_operand" "")
1341 (match_operand:QI 2 "register_operand" "")))]
1346 emit_insn (gen_mulqi3_call (operands[0], operands[1], operands[2]));
1351 (define_insn "*mulqi3_enh"
1352 [(set (match_operand:QI 0 "register_operand" "=r")
1353 (mult:QI (match_operand:QI 1 "register_operand" "r")
1354 (match_operand:QI 2 "register_operand" "r")))]
1359 [(set_attr "length" "3")
1360 (set_attr "cc" "clobber")])
1362 (define_expand "mulqi3_call"
1363 [(set (reg:QI 24) (match_operand:QI 1 "register_operand" ""))
1364 (set (reg:QI 22) (match_operand:QI 2 "register_operand" ""))
1365 (parallel [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22)))
1366 (clobber (reg:QI 22))])
1367 (set (match_operand:QI 0 "register_operand" "") (reg:QI 24))]
1371 (define_insn "*mulqi3_call"
1372 [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22)))
1373 (clobber (reg:QI 22))]
1376 [(set_attr "type" "xcall")
1377 (set_attr "cc" "clobber")])
1379 ;; "umulqi3_highpart"
1380 ;; "smulqi3_highpart"
1381 (define_insn "<extend_su>mulqi3_highpart"
1382 [(set (match_operand:QI 0 "register_operand" "=r")
1384 (lshiftrt:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1385 (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))
1388 "mul<extend_s> %1,%2
1391 [(set_attr "length" "3")
1392 (set_attr "cc" "clobber")])
1395 ;; Used when expanding div or mod inline for some special values
1396 (define_insn "*subqi3.ashiftrt7"
1397 [(set (match_operand:QI 0 "register_operand" "=r")
1398 (minus:QI (match_operand:QI 1 "register_operand" "0")
1399 (ashiftrt:QI (match_operand:QI 2 "register_operand" "r")
1403 [(set_attr "length" "2")
1404 (set_attr "cc" "clobber")])
1406 (define_insn "*addqi3.lt0"
1407 [(set (match_operand:QI 0 "register_operand" "=r")
1408 (plus:QI (lt:QI (match_operand:QI 1 "register_operand" "r")
1410 (match_operand:QI 2 "register_operand" "0")))]
1413 [(set_attr "length" "2")
1414 (set_attr "cc" "clobber")])
1416 (define_insn "*addhi3.lt0"
1417 [(set (match_operand:HI 0 "register_operand" "=w,r")
1418 (plus:HI (lt:HI (match_operand:QI 1 "register_operand" "r,r")
1420 (match_operand:HI 2 "register_operand" "0,0")))
1421 (clobber (match_scratch:QI 3 "=X,&1"))]
1424 sbrc %1,7\;adiw %0,1
1425 lsl %1\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__"
1426 [(set_attr "length" "2,3")
1427 (set_attr "cc" "clobber")])
1429 (define_insn "*addpsi3.lt0"
1430 [(set (match_operand:PSI 0 "register_operand" "=r")
1431 (plus:PSI (lshiftrt:PSI (match_operand:PSI 1 "register_operand" "r")
1433 (match_operand:PSI 2 "register_operand" "0")))]
1435 "mov __tmp_reg__,%C1\;lsl __tmp_reg__
1436 adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__"
1437 [(set_attr "length" "5")
1438 (set_attr "cc" "clobber")])
1440 (define_insn "*addsi3.lt0"
1441 [(set (match_operand:SI 0 "register_operand" "=r")
1442 (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
1444 (match_operand:SI 2 "register_operand" "0")))]
1446 "mov __tmp_reg__,%D1\;lsl __tmp_reg__
1447 adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__"
1448 [(set_attr "length" "6")
1449 (set_attr "cc" "clobber")])
1454 (define_insn "<extend_u>mulqihi3"
1455 [(set (match_operand:HI 0 "register_operand" "=r")
1456 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1457 (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>"))))]
1459 "mul<extend_s> %1,%2
1462 [(set_attr "length" "3")
1463 (set_attr "cc" "clobber")])
1465 (define_insn "usmulqihi3"
1466 [(set (match_operand:HI 0 "register_operand" "=r")
1467 (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "a"))
1468 (sign_extend:HI (match_operand:QI 2 "register_operand" "a"))))]
1473 [(set_attr "length" "3")
1474 (set_attr "cc" "clobber")])
1476 ;; Above insn is not canonicalized by insn combine, so here is a version with
1477 ;; operands swapped.
1479 (define_insn "*sumulqihi3"
1480 [(set (match_operand:HI 0 "register_operand" "=r")
1481 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1482 (zero_extend:HI (match_operand:QI 2 "register_operand" "a"))))]
1487 [(set_attr "length" "3")
1488 (set_attr "cc" "clobber")])
1490 ;; One-extend operand 1
1492 (define_insn "*osmulqihi3"
1493 [(set (match_operand:HI 0 "register_operand" "=&r")
1494 (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "a"))))
1495 (sign_extend:HI (match_operand:QI 2 "register_operand" "a"))))]
1501 [(set_attr "length" "4")
1502 (set_attr "cc" "clobber")])
1504 (define_insn "*oumulqihi3"
1505 [(set (match_operand:HI 0 "register_operand" "=&r")
1506 (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "r"))))
1507 (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
1513 [(set_attr "length" "4")
1514 (set_attr "cc" "clobber")])
1516 ;******************************************************************************
1517 ; multiply-add/sub QI: $0 = $3 +/- $1*$2
1518 ;******************************************************************************
1520 (define_insn "*maddqi4"
1521 [(set (match_operand:QI 0 "register_operand" "=r")
1522 (plus:QI (mult:QI (match_operand:QI 1 "register_operand" "r")
1523 (match_operand:QI 2 "register_operand" "r"))
1524 (match_operand:QI 3 "register_operand" "0")))]
1530 [(set_attr "length" "4")
1531 (set_attr "cc" "clobber")])
1533 (define_insn "*msubqi4"
1534 [(set (match_operand:QI 0 "register_operand" "=r")
1535 (minus:QI (match_operand:QI 3 "register_operand" "0")
1536 (mult:QI (match_operand:QI 1 "register_operand" "r")
1537 (match_operand:QI 2 "register_operand" "r"))))]
1542 [(set_attr "length" "4")
1543 (set_attr "cc" "clobber")])
1545 (define_insn_and_split "*maddqi4.const"
1546 [(set (match_operand:QI 0 "register_operand" "=r")
1547 (plus:QI (mult:QI (match_operand:QI 1 "register_operand" "r")
1548 (match_operand:QI 2 "const_int_operand" "n"))
1549 (match_operand:QI 3 "register_operand" "0")))
1550 (clobber (match_scratch:QI 4 "=&d"))]
1553 "&& reload_completed"
1558 (plus:QI (mult:QI (match_dup 1)
1563 (define_insn_and_split "*msubqi4.const"
1564 [(set (match_operand:QI 0 "register_operand" "=r")
1565 (minus:QI (match_operand:QI 3 "register_operand" "0")
1566 (mult:QI (match_operand:QI 1 "register_operand" "r")
1567 (match_operand:QI 2 "const_int_operand" "n"))))
1568 (clobber (match_scratch:QI 4 "=&d"))]
1571 "&& reload_completed"
1576 (minus:QI (match_dup 3)
1577 (mult:QI (match_dup 1)
1582 ;******************************************************************************
1583 ; multiply-add/sub HI: $0 = $3 +/- $1*$2 with 8-bit values $1, $2
1584 ;******************************************************************************
1586 ;; We don't use standard insns/expanders as they lead to cumbersome code for,
1589 ;; int foo (unsigned char z)
1591 ;; extern int aInt[];
1592 ;; return aInt[3*z+2];
1595 ;; because the constant +4 then is added explicitely instead of consuming it
1596 ;; with the aInt symbol. Therefore, we rely on insn combine which takes costs
1597 ;; into account more accurately and doesn't do burte-force multiply-add/sub.
1598 ;; The implementational effort is the same so we are fine with that approach.
1603 (define_insn "*<extend_u>maddqihi4"
1604 [(set (match_operand:HI 0 "register_operand" "=r")
1605 (plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1606 (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))
1607 (match_operand:HI 3 "register_operand" "0")))]
1610 "mul<extend_s> %1,%2
1614 [(set_attr "length" "4")
1615 (set_attr "cc" "clobber")])
1619 (define_insn "*<extend_u>msubqihi4"
1620 [(set (match_operand:HI 0 "register_operand" "=r")
1621 (minus:HI (match_operand:HI 3 "register_operand" "0")
1622 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1623 (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))))]
1625 "mul<extend_s> %1,%2
1629 [(set_attr "length" "4")
1630 (set_attr "cc" "clobber")])
1634 (define_insn "*<any_extend:extend_su><any_extend2:extend_su>msubqihi4"
1635 [(set (match_operand:HI 0 "register_operand" "=r")
1636 (plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "a"))
1637 (any_extend2:HI (match_operand:QI 2 "register_operand" "a")))
1638 (match_operand:HI 3 "register_operand" "0")))]
1641 && <any_extend:CODE> != <any_extend2:CODE>"
1643 output_asm_insn (<any_extend:CODE> == SIGN_EXTEND
1644 ? "mulsu %1,%2" : "mulsu %2,%1", operands);
1646 return "add %A0,r0\;adc %B0,r1\;clr __zero_reg__";
1648 [(set_attr "length" "4")
1649 (set_attr "cc" "clobber")])
1653 (define_insn "*<any_extend:extend_su><any_extend2:extend_su>msubqihi4"
1654 [(set (match_operand:HI 0 "register_operand" "=r")
1655 (minus:HI (match_operand:HI 3 "register_operand" "0")
1656 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "a"))
1657 (any_extend2:HI (match_operand:QI 2 "register_operand" "a")))))]
1660 && <any_extend:CODE> != <any_extend2:CODE>"
1662 output_asm_insn (<any_extend:CODE> == SIGN_EXTEND
1663 ? "mulsu %1,%2" : "mulsu %2,%1", operands);
1665 return "sub %A0,r0\;sbc %B0,r1\;clr __zero_reg__";
1667 [(set_attr "length" "4")
1668 (set_attr "cc" "clobber")])
1670 ;; Handle small constants
1672 ;; "umaddqihi4.uconst"
1673 ;; "maddqihi4.sconst"
1674 (define_insn_and_split "*<extend_u>maddqihi4.<extend_su>const"
1675 [(set (match_operand:HI 0 "register_operand" "=r")
1676 (plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1677 (match_operand:HI 2 "<extend_su>8_operand" "n"))
1678 (match_operand:HI 3 "register_operand" "0")))
1679 (clobber (match_scratch:QI 4 "=&d"))]
1682 "&& reload_completed"
1685 ; *umaddqihi4 resp. *maddqihi4
1687 (plus:HI (mult:HI (any_extend:HI (match_dup 1))
1688 (any_extend:HI (match_dup 4)))
1691 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1694 ;; "*umsubqihi4.uconst"
1695 ;; "*msubqihi4.sconst"
1696 (define_insn_and_split "*<extend_u>msubqihi4.<extend_su>const"
1697 [(set (match_operand:HI 0 "register_operand" "=r")
1698 (minus:HI (match_operand:HI 3 "register_operand" "0")
1699 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1700 (match_operand:HI 2 "<extend_su>8_operand" "n"))))
1701 (clobber (match_scratch:QI 4 "=&d"))]
1704 "&& reload_completed"
1707 ; *umsubqihi4 resp. *msubqihi4
1709 (minus:HI (match_dup 3)
1710 (mult:HI (any_extend:HI (match_dup 1))
1711 (any_extend:HI (match_dup 4)))))]
1713 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1716 ;; Same as the insn above, but combiner tries versions canonicalized to ASHIFT
1717 ;; for MULT with power of 2 and skips trying MULT insn above.
1719 (define_insn_and_split "*umsubqihi4.uconst.ashift"
1720 [(set (match_operand:HI 0 "register_operand" "=r")
1721 (minus:HI (match_operand:HI 3 "register_operand" "0")
1722 (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1723 (match_operand:HI 2 "const_2_to_7_operand" "n"))))
1724 (clobber (match_scratch:QI 4 "=&d"))]
1727 "&& reload_completed"
1732 (minus:HI (match_dup 3)
1733 (mult:HI (zero_extend:HI (match_dup 1))
1734 (zero_extend:HI (match_dup 4)))))]
1736 operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
1739 ;; Same as the insn above, but combiner tries versions canonicalized to ASHIFT
1740 ;; for MULT with power of 2 and skips trying MULT insn above. We omit 128
1741 ;; because this would require an extra pattern for just one value.
1743 (define_insn_and_split "*msubqihi4.sconst.ashift"
1744 [(set (match_operand:HI 0 "register_operand" "=r")
1745 (minus:HI (match_operand:HI 3 "register_operand" "0")
1746 (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
1747 (match_operand:HI 2 "const_1_to_6_operand" "M"))))
1748 (clobber (match_scratch:QI 4 "=&d"))]
1751 "&& reload_completed"
1756 (minus:HI (match_dup 3)
1757 (mult:HI (sign_extend:HI (match_dup 1))
1758 (sign_extend:HI (match_dup 4)))))]
1760 operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
1763 ;; For signed/unsigned combinations that require narrow constraint "a"
1764 ;; just provide a pattern if signed/unsigned combination is actually needed.
1766 (define_insn_and_split "*sumaddqihi4.uconst"
1767 [(set (match_operand:HI 0 "register_operand" "=r")
1768 (plus:HI (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1769 (match_operand:HI 2 "u8_operand" "M"))
1770 (match_operand:HI 3 "register_operand" "0")))
1771 (clobber (match_scratch:QI 4 "=&a"))]
1773 && !s8_operand (operands[2], VOIDmode)"
1775 "&& reload_completed"
1780 (plus:HI (mult:HI (sign_extend:HI (match_dup 1))
1781 (zero_extend:HI (match_dup 4)))
1784 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1787 (define_insn_and_split "*sumsubqihi4.uconst"
1788 [(set (match_operand:HI 0 "register_operand" "=r")
1789 (minus:HI (match_operand:HI 3 "register_operand" "0")
1790 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1791 (match_operand:HI 2 "u8_operand" "M"))))
1792 (clobber (match_scratch:QI 4 "=&a"))]
1794 && !s8_operand (operands[2], VOIDmode)"
1796 "&& reload_completed"
1801 (minus:HI (match_dup 3)
1802 (mult:HI (sign_extend:HI (match_dup 1))
1803 (zero_extend:HI (match_dup 4)))))]
1805 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1808 ;******************************************************************************
1809 ; mul HI: $1 = sign/zero-extend, $2 = small constant
1810 ;******************************************************************************
1812 ;; "*muluqihi3.uconst"
1813 ;; "*mulsqihi3.sconst"
1814 (define_insn_and_split "*mul<extend_su>qihi3.<extend_su>const"
1815 [(set (match_operand:HI 0 "register_operand" "=r")
1816 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
1817 (match_operand:HI 2 "<extend_su>8_operand" "n")))
1818 (clobber (match_scratch:QI 3 "=&d"))]
1821 "&& reload_completed"
1824 ; umulqihi3 resp. mulqihi3
1826 (mult:HI (any_extend:HI (match_dup 1))
1827 (any_extend:HI (match_dup 3))))]
1829 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1832 (define_insn_and_split "*muluqihi3.sconst"
1833 [(set (match_operand:HI 0 "register_operand" "=r")
1834 (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "a"))
1835 (match_operand:HI 2 "s8_operand" "n")))
1836 (clobber (match_scratch:QI 3 "=&a"))]
1839 "&& reload_completed"
1844 (mult:HI (zero_extend:HI (match_dup 1))
1845 (sign_extend:HI (match_dup 3))))]
1847 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1850 (define_insn_and_split "*mulsqihi3.uconst"
1851 [(set (match_operand:HI 0 "register_operand" "=r")
1852 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1853 (match_operand:HI 2 "u8_operand" "M")))
1854 (clobber (match_scratch:QI 3 "=&a"))]
1857 "&& reload_completed"
1862 (mult:HI (zero_extend:HI (match_dup 3))
1863 (sign_extend:HI (match_dup 1))))]
1865 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1868 (define_insn_and_split "*mulsqihi3.oconst"
1869 [(set (match_operand:HI 0 "register_operand" "=&r")
1870 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1871 (match_operand:HI 2 "o8_operand" "n")))
1872 (clobber (match_scratch:QI 3 "=&a"))]
1875 "&& reload_completed"
1880 (mult:HI (not:HI (zero_extend:HI (not:QI (match_dup 3))))
1881 (sign_extend:HI (match_dup 1))))]
1883 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
1886 ;; The EXTEND of $1 only appears in combine, we don't see it in expand so that
1887 ;; expand decides to use ASHIFT instead of MUL because ASHIFT costs are cheaper
1888 ;; at that time. Fix that.
1890 (define_insn "*ashiftqihi2.signx.1"
1891 [(set (match_operand:HI 0 "register_operand" "=r,*r")
1892 (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "0,r"))
1896 lsl %A0\;sbc %B0,%B0
1897 mov %A0,%1\;lsl %A0\;sbc %B0,%B0"
1898 [(set_attr "length" "2,3")
1899 (set_attr "cc" "clobber")])
1901 (define_insn_and_split "*ashifthi3.signx.const"
1902 [(set (match_operand:HI 0 "register_operand" "=r")
1903 (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
1904 (match_operand:HI 2 "const_2_to_6_operand" "I")))
1905 (clobber (match_scratch:QI 3 "=&d"))]
1908 "&& reload_completed"
1913 (mult:HI (sign_extend:HI (match_dup 1))
1914 (sign_extend:HI (match_dup 3))))]
1916 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
1919 (define_insn_and_split "*ashifthi3.signx.const7"
1920 [(set (match_operand:HI 0 "register_operand" "=r")
1921 (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1923 (clobber (match_scratch:QI 2 "=&a"))]
1926 "&& reload_completed"
1931 (mult:HI (zero_extend:HI (match_dup 2))
1932 (sign_extend:HI (match_dup 1))))]
1934 operands[3] = gen_int_mode (1 << 7, QImode);
1937 (define_insn_and_split "*ashifthi3.zerox.const"
1938 [(set (match_operand:HI 0 "register_operand" "=r")
1939 (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1940 (match_operand:HI 2 "const_2_to_7_operand" "I")))
1941 (clobber (match_scratch:QI 3 "=&d"))]
1944 "&& reload_completed"
1949 (mult:HI (zero_extend:HI (match_dup 1))
1950 (zero_extend:HI (match_dup 3))))]
1952 operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
1955 ;******************************************************************************
1956 ; mul HI: $1 = sign-/zero-/one-extend, $2 = reg
1957 ;******************************************************************************
1959 (define_insn "mulsqihi3"
1960 [(set (match_operand:HI 0 "register_operand" "=&r")
1961 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
1962 (match_operand:HI 2 "register_operand" "a")))]
1969 [(set_attr "length" "5")
1970 (set_attr "cc" "clobber")])
1972 (define_insn "muluqihi3"
1973 [(set (match_operand:HI 0 "register_operand" "=&r")
1974 (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
1975 (match_operand:HI 2 "register_operand" "r")))]
1982 [(set_attr "length" "5")
1983 (set_attr "cc" "clobber")])
1985 ;; one-extend operand 1
1987 (define_insn "muloqihi3"
1988 [(set (match_operand:HI 0 "register_operand" "=&r")
1989 (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "r"))))
1990 (match_operand:HI 2 "register_operand" "r")))]
1998 [(set_attr "length" "6")
1999 (set_attr "cc" "clobber")])
2001 ;******************************************************************************
2003 (define_expand "mulhi3"
2004 [(set (match_operand:HI 0 "register_operand" "")
2005 (mult:HI (match_operand:HI 1 "register_operand" "")
2006 (match_operand:HI 2 "register_or_s9_operand" "")))]
2011 if (!register_operand (operands[2], HImode))
2012 operands[2] = force_reg (HImode, operands[2]);
2014 emit_insn (gen_mulhi3_call (operands[0], operands[1], operands[2]));
2018 /* For small constants we can do better by extending them on the fly.
2019 The constant can be loaded in one instruction and the widening
2020 multiplication is shorter. First try the unsigned variant because it
2021 allows constraint "d" instead of "a" for the signed version. */
2023 if (s9_operand (operands[2], HImode))
2025 rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
2027 if (u8_operand (operands[2], HImode))
2029 emit_insn (gen_muluqihi3 (operands[0], reg, operands[1]));
2031 else if (s8_operand (operands[2], HImode))
2033 emit_insn (gen_mulsqihi3 (operands[0], reg, operands[1]));
2037 emit_insn (gen_muloqihi3 (operands[0], reg, operands[1]));
2043 if (!register_operand (operands[2], HImode))
2044 operands[2] = force_reg (HImode, operands[2]);
2047 (define_insn "*mulhi3_enh"
2048 [(set (match_operand:HI 0 "register_operand" "=&r")
2049 (mult:HI (match_operand:HI 1 "register_operand" "r")
2050 (match_operand:HI 2 "register_operand" "r")))]
2053 return REGNO (operands[1]) == REGNO (operands[2])
2054 ? "mul %A1,%A1\;movw %0,r0\;mul %A1,%B1\;add %B0,r0\;add %B0,r0\;clr r1"
2055 : "mul %A1,%A2\;movw %0,r0\;mul %A1,%B2\;add %B0,r0\;mul %B1,%A2\;add %B0,r0\;clr r1";
2057 [(set_attr "length" "7")
2058 (set_attr "cc" "clobber")])
2060 (define_expand "mulhi3_call"
2061 [(set (reg:HI 24) (match_operand:HI 1 "register_operand" ""))
2062 (set (reg:HI 22) (match_operand:HI 2 "register_operand" ""))
2063 (parallel [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22)))
2064 (clobber (reg:HI 22))
2065 (clobber (reg:QI 21))])
2066 (set (match_operand:HI 0 "register_operand" "") (reg:HI 24))]
2070 (define_insn "*mulhi3_call"
2071 [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22)))
2072 (clobber (reg:HI 22))
2073 (clobber (reg:QI 21))]
2076 [(set_attr "type" "xcall")
2077 (set_attr "cc" "clobber")])
2079 ;; To support widening multiplication with constant we postpone
2080 ;; expanding to the implicit library call until post combine and
2081 ;; prior to register allocation. Clobber all hard registers that
2082 ;; might be used by the (widening) multiply until it is split and
2083 ;; it's final register footprint is worked out.
2085 (define_expand "mulsi3"
2086 [(parallel [(set (match_operand:SI 0 "register_operand" "")
2087 (mult:SI (match_operand:SI 1 "register_operand" "")
2088 (match_operand:SI 2 "nonmemory_operand" "")))
2089 (clobber (reg:HI 26))
2090 (clobber (reg:DI 18))])]
2093 if (u16_operand (operands[2], SImode))
2095 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2096 emit_insn (gen_muluhisi3 (operands[0], operands[2], operands[1]));
2100 if (o16_operand (operands[2], SImode))
2102 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2103 emit_insn (gen_mulohisi3 (operands[0], operands[2], operands[1]));
2108 (define_insn_and_split "*mulsi3"
2109 [(set (match_operand:SI 0 "pseudo_register_operand" "=r")
2110 (mult:SI (match_operand:SI 1 "pseudo_register_operand" "r")
2111 (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn")))
2112 (clobber (reg:HI 26))
2113 (clobber (reg:DI 18))]
2114 "AVR_HAVE_MUL && !reload_completed"
2115 { gcc_unreachable(); }
2121 (parallel [(set (reg:SI 22)
2122 (mult:SI (reg:SI 22)
2124 (clobber (reg:HI 26))])
2128 if (u16_operand (operands[2], SImode))
2130 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2131 emit_insn (gen_muluhisi3 (operands[0], operands[2], operands[1]));
2135 if (o16_operand (operands[2], SImode))
2137 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2138 emit_insn (gen_mulohisi3 (operands[0], operands[2], operands[1]));
2145 (define_insn_and_split "mulu<mode>si3"
2146 [(set (match_operand:SI 0 "pseudo_register_operand" "=r")
2147 (mult:SI (zero_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r"))
2148 (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn")))
2149 (clobber (reg:HI 26))
2150 (clobber (reg:DI 18))]
2151 "AVR_HAVE_MUL && !reload_completed"
2152 { gcc_unreachable(); }
2159 (mult:SI (zero_extend:SI (reg:HI 26))
2164 /* Do the QI -> HI extension explicitely before the multiplication. */
2165 /* Do the HI -> SI extension implicitely and after the multiplication. */
2167 if (QImode == <MODE>mode)
2168 operands[1] = gen_rtx_ZERO_EXTEND (HImode, operands[1]);
2170 if (u16_operand (operands[2], SImode))
2172 operands[1] = force_reg (HImode, operands[1]);
2173 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2174 emit_insn (gen_umulhisi3 (operands[0], operands[1], operands[2]));
2181 (define_insn_and_split "muls<mode>si3"
2182 [(set (match_operand:SI 0 "pseudo_register_operand" "=r")
2183 (mult:SI (sign_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r"))
2184 (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn")))
2185 (clobber (reg:HI 26))
2186 (clobber (reg:DI 18))]
2187 "AVR_HAVE_MUL && !reload_completed"
2188 { gcc_unreachable(); }
2195 (mult:SI (sign_extend:SI (reg:HI 26))
2200 /* Do the QI -> HI extension explicitely before the multiplication. */
2201 /* Do the HI -> SI extension implicitely and after the multiplication. */
2203 if (QImode == <MODE>mode)
2204 operands[1] = gen_rtx_SIGN_EXTEND (HImode, operands[1]);
2206 if (u16_operand (operands[2], SImode)
2207 || s16_operand (operands[2], SImode))
2209 rtx xop2 = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode));
2211 operands[1] = force_reg (HImode, operands[1]);
2213 if (u16_operand (operands[2], SImode))
2214 emit_insn (gen_usmulhisi3 (operands[0], xop2, operands[1]));
2216 emit_insn (gen_mulhisi3 (operands[0], operands[1], xop2));
2222 ;; One-extend operand 1
2224 (define_insn_and_split "mulohisi3"
2225 [(set (match_operand:SI 0 "pseudo_register_operand" "=r")
2226 (mult:SI (not:SI (zero_extend:SI
2227 (not:HI (match_operand:HI 1 "pseudo_register_operand" "r"))))
2228 (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn")))
2229 (clobber (reg:HI 26))
2230 (clobber (reg:DI 18))]
2231 "AVR_HAVE_MUL && !reload_completed"
2232 { gcc_unreachable(); }
2239 (mult:SI (not:SI (zero_extend:SI (not:HI (reg:HI 26))))
2247 (define_expand "<extend_u>mulhisi3"
2248 [(parallel [(set (match_operand:SI 0 "register_operand" "")
2249 (mult:SI (any_extend:SI (match_operand:HI 1 "register_operand" ""))
2250 (any_extend:SI (match_operand:HI 2 "register_operand" ""))))
2251 (clobber (reg:HI 26))
2252 (clobber (reg:DI 18))])]
2256 (define_expand "usmulhisi3"
2257 [(parallel [(set (match_operand:SI 0 "register_operand" "")
2258 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" ""))
2259 (sign_extend:SI (match_operand:HI 2 "register_operand" ""))))
2260 (clobber (reg:HI 26))
2261 (clobber (reg:DI 18))])]
2265 ;; "*uumulqihisi3" "*uumulhiqisi3" "*uumulhihisi3" "*uumulqiqisi3"
2266 ;; "*usmulqihisi3" "*usmulhiqisi3" "*usmulhihisi3" "*usmulqiqisi3"
2267 ;; "*sumulqihisi3" "*sumulhiqisi3" "*sumulhihisi3" "*sumulqiqisi3"
2268 ;; "*ssmulqihisi3" "*ssmulhiqisi3" "*ssmulhihisi3" "*ssmulqiqisi3"
2269 (define_insn_and_split
2270 "*<any_extend:extend_su><any_extend2:extend_su>mul<QIHI:mode><QIHI2:mode>si3"
2271 [(set (match_operand:SI 0 "pseudo_register_operand" "=r")
2272 (mult:SI (any_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r"))
2273 (any_extend2:SI (match_operand:QIHI2 2 "pseudo_register_operand" "r"))))
2274 (clobber (reg:HI 26))
2275 (clobber (reg:DI 18))]
2276 "AVR_HAVE_MUL && !reload_completed"
2277 { gcc_unreachable(); }
2284 (mult:SI (match_dup 3)
2289 rtx xop1 = operands[1];
2290 rtx xop2 = operands[2];
2292 /* Do the QI -> HI extension explicitely before the multiplication. */
2293 /* Do the HI -> SI extension implicitely and after the multiplication. */
2295 if (QImode == <QIHI:MODE>mode)
2296 xop1 = gen_rtx_fmt_e (<any_extend:CODE>, HImode, xop1);
2298 if (QImode == <QIHI2:MODE>mode)
2299 xop2 = gen_rtx_fmt_e (<any_extend2:CODE>, HImode, xop2);
2301 if (<any_extend:CODE> == <any_extend2:CODE>
2302 || <any_extend:CODE> == ZERO_EXTEND)
2306 operands[3] = gen_rtx_fmt_e (<any_extend:CODE>, SImode, gen_rtx_REG (HImode, 18));
2307 operands[4] = gen_rtx_fmt_e (<any_extend2:CODE>, SImode, gen_rtx_REG (HImode, 26));
2311 /* <any_extend:CODE> = SIGN_EXTEND */
2312 /* <any_extend2:CODE> = ZERO_EXTEND */
2316 operands[3] = gen_rtx_ZERO_EXTEND (SImode, gen_rtx_REG (HImode, 18));
2317 operands[4] = gen_rtx_SIGN_EXTEND (SImode, gen_rtx_REG (HImode, 26));
2321 ;; "smulhi3_highpart"
2322 ;; "umulhi3_highpart"
2323 (define_expand "<extend_su>mulhi3_highpart"
2325 (match_operand:HI 1 "nonmemory_operand" ""))
2327 (match_operand:HI 2 "nonmemory_operand" ""))
2328 (parallel [(set (reg:HI 24)
2329 (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
2330 (any_extend:SI (reg:HI 26)))
2332 (clobber (reg:HI 22))])
2333 (set (match_operand:HI 0 "register_operand" "")
2339 (define_insn "*mulsi3_call"
2341 (mult:SI (reg:SI 22)
2343 (clobber (reg:HI 26))]
2346 [(set_attr "type" "xcall")
2347 (set_attr "cc" "clobber")])
2350 ;; "*umulhisi3_call"
2351 (define_insn "*<extend_u>mulhisi3_call"
2353 (mult:SI (any_extend:SI (reg:HI 18))
2354 (any_extend:SI (reg:HI 26))))]
2356 "%~call __<extend_u>mulhisi3"
2357 [(set_attr "type" "xcall")
2358 (set_attr "cc" "clobber")])
2360 ;; "*umulhi3_highpart_call"
2361 ;; "*smulhi3_highpart_call"
2362 (define_insn "*<extend_su>mulhi3_highpart_call"
2364 (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
2365 (any_extend:SI (reg:HI 26)))
2367 (clobber (reg:HI 22))]
2369 "%~call __<extend_u>mulhisi3"
2370 [(set_attr "type" "xcall")
2371 (set_attr "cc" "clobber")])
2373 (define_insn "*usmulhisi3_call"
2375 (mult:SI (zero_extend:SI (reg:HI 18))
2376 (sign_extend:SI (reg:HI 26))))]
2378 "%~call __usmulhisi3"
2379 [(set_attr "type" "xcall")
2380 (set_attr "cc" "clobber")])
2382 (define_insn "*mul<extend_su>hisi3_call"
2384 (mult:SI (any_extend:SI (reg:HI 26))
2387 "%~call __mul<extend_su>hisi3"
2388 [(set_attr "type" "xcall")
2389 (set_attr "cc" "clobber")])
2391 (define_insn "*mulohisi3_call"
2393 (mult:SI (not:SI (zero_extend:SI (not:HI (reg:HI 26))))
2396 "%~call __mulohisi3"
2397 [(set_attr "type" "xcall")
2398 (set_attr "cc" "clobber")])
2400 ; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / %
2403 ;; Generate lib1funcs.S calls ourselves, because:
2404 ;; - we know exactly which registers are clobbered (for QI and HI
2405 ;; modes, some of the call-used registers are preserved)
2406 ;; - we get both the quotient and the remainder at no extra cost
2407 ;; - we split the patterns only after the first CSE passes because
2408 ;; CSE has problems to operate on hard regs.
2410 (define_insn_and_split "divmodqi4"
2411 [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "")
2412 (div:QI (match_operand:QI 1 "pseudo_register_operand" "")
2413 (match_operand:QI 2 "pseudo_register_operand" "")))
2414 (set (match_operand:QI 3 "pseudo_register_operand" "")
2415 (mod:QI (match_dup 1) (match_dup 2)))
2416 (clobber (reg:QI 22))
2417 (clobber (reg:QI 23))
2418 (clobber (reg:QI 24))
2419 (clobber (reg:QI 25))])]
2421 "this divmodqi4 pattern should have been splitted;"
2423 [(set (reg:QI 24) (match_dup 1))
2424 (set (reg:QI 22) (match_dup 2))
2425 (parallel [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
2426 (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
2427 (clobber (reg:QI 22))
2428 (clobber (reg:QI 23))])
2429 (set (match_dup 0) (reg:QI 24))
2430 (set (match_dup 3) (reg:QI 25))]
2433 (define_insn "*divmodqi4_call"
2434 [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
2435 (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
2436 (clobber (reg:QI 22))
2437 (clobber (reg:QI 23))]
2439 "%~call __divmodqi4"
2440 [(set_attr "type" "xcall")
2441 (set_attr "cc" "clobber")])
2443 (define_insn_and_split "udivmodqi4"
2444 [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "")
2445 (udiv:QI (match_operand:QI 1 "pseudo_register_operand" "")
2446 (match_operand:QI 2 "pseudo_register_operand" "")))
2447 (set (match_operand:QI 3 "pseudo_register_operand" "")
2448 (umod:QI (match_dup 1) (match_dup 2)))
2449 (clobber (reg:QI 22))
2450 (clobber (reg:QI 23))
2451 (clobber (reg:QI 24))
2452 (clobber (reg:QI 25))])]
2454 "this udivmodqi4 pattern should have been splitted;"
2456 [(set (reg:QI 24) (match_dup 1))
2457 (set (reg:QI 22) (match_dup 2))
2458 (parallel [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
2459 (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
2460 (clobber (reg:QI 23))])
2461 (set (match_dup 0) (reg:QI 24))
2462 (set (match_dup 3) (reg:QI 25))]
2465 (define_insn "*udivmodqi4_call"
2466 [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
2467 (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
2468 (clobber (reg:QI 23))]
2470 "%~call __udivmodqi4"
2471 [(set_attr "type" "xcall")
2472 (set_attr "cc" "clobber")])
2474 (define_insn_and_split "divmodhi4"
2475 [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "")
2476 (div:HI (match_operand:HI 1 "pseudo_register_operand" "")
2477 (match_operand:HI 2 "pseudo_register_operand" "")))
2478 (set (match_operand:HI 3 "pseudo_register_operand" "")
2479 (mod:HI (match_dup 1) (match_dup 2)))
2480 (clobber (reg:QI 21))
2481 (clobber (reg:HI 22))
2482 (clobber (reg:HI 24))
2483 (clobber (reg:HI 26))])]
2485 "this should have been splitted;"
2487 [(set (reg:HI 24) (match_dup 1))
2488 (set (reg:HI 22) (match_dup 2))
2489 (parallel [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
2490 (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
2491 (clobber (reg:HI 26))
2492 (clobber (reg:QI 21))])
2493 (set (match_dup 0) (reg:HI 22))
2494 (set (match_dup 3) (reg:HI 24))]
2497 (define_insn "*divmodhi4_call"
2498 [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
2499 (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
2500 (clobber (reg:HI 26))
2501 (clobber (reg:QI 21))]
2503 "%~call __divmodhi4"
2504 [(set_attr "type" "xcall")
2505 (set_attr "cc" "clobber")])
2507 (define_insn_and_split "udivmodhi4"
2508 [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "")
2509 (udiv:HI (match_operand:HI 1 "pseudo_register_operand" "")
2510 (match_operand:HI 2 "pseudo_register_operand" "")))
2511 (set (match_operand:HI 3 "pseudo_register_operand" "")
2512 (umod:HI (match_dup 1) (match_dup 2)))
2513 (clobber (reg:QI 21))
2514 (clobber (reg:HI 22))
2515 (clobber (reg:HI 24))
2516 (clobber (reg:HI 26))])]
2518 "this udivmodhi4 pattern should have been splitted.;"
2520 [(set (reg:HI 24) (match_dup 1))
2521 (set (reg:HI 22) (match_dup 2))
2522 (parallel [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
2523 (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
2524 (clobber (reg:HI 26))
2525 (clobber (reg:QI 21))])
2526 (set (match_dup 0) (reg:HI 22))
2527 (set (match_dup 3) (reg:HI 24))]
2530 (define_insn "*udivmodhi4_call"
2531 [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
2532 (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
2533 (clobber (reg:HI 26))
2534 (clobber (reg:QI 21))]
2536 "%~call __udivmodhi4"
2537 [(set_attr "type" "xcall")
2538 (set_attr "cc" "clobber")])
2540 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2543 ;; To support widening multiplication with constant we postpone
2544 ;; expanding to the implicit library call until post combine and
2545 ;; prior to register allocation. Clobber all hard registers that
2546 ;; might be used by the (widening) multiply until it is split and
2547 ;; it's final register footprint is worked out.
2549 (define_expand "mulpsi3"
2550 [(parallel [(set (match_operand:PSI 0 "register_operand" "")
2551 (mult:PSI (match_operand:PSI 1 "register_operand" "")
2552 (match_operand:PSI 2 "nonmemory_operand" "")))
2553 (clobber (reg:HI 26))
2554 (clobber (reg:DI 18))])]
2557 if (s8_operand (operands[2], PSImode))
2559 rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
2560 emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1]));
2565 (define_insn "*umulqihipsi3"
2566 [(set (match_operand:PSI 0 "register_operand" "=&r")
2567 (mult:PSI (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))
2568 (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
2577 [(set_attr "length" "7")
2578 (set_attr "cc" "clobber")])
2580 (define_insn "*umulhiqipsi3"
2581 [(set (match_operand:PSI 0 "register_operand" "=&r")
2582 (mult:PSI (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))
2583 (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))))]
2591 adc %C0,__zero_reg__"
2592 [(set_attr "length" "7")
2593 (set_attr "cc" "clobber")])
2595 (define_insn_and_split "mulsqipsi3"
2596 [(set (match_operand:PSI 0 "pseudo_register_operand" "=r")
2597 (mult:PSI (sign_extend:PSI (match_operand:QI 1 "pseudo_register_operand" "r"))
2598 (match_operand:PSI 2 "pseudo_register_or_const_int_operand" "rn")))
2599 (clobber (reg:HI 26))
2600 (clobber (reg:DI 18))]
2601 "AVR_HAVE_MUL && !reload_completed"
2602 { gcc_unreachable(); }
2609 (mult:PSI (sign_extend:PSI (reg:QI 25))
2614 (define_insn_and_split "*mulpsi3"
2615 [(set (match_operand:PSI 0 "pseudo_register_operand" "=r")
2616 (mult:PSI (match_operand:PSI 1 "pseudo_register_operand" "r")
2617 (match_operand:PSI 2 "pseudo_register_or_const_int_operand" "rn")))
2618 (clobber (reg:HI 26))
2619 (clobber (reg:DI 18))]
2620 "AVR_HAVE_MUL && !reload_completed"
2621 { gcc_unreachable(); }
2627 (parallel [(set (reg:PSI 22)
2628 (mult:PSI (reg:PSI 22)
2630 (clobber (reg:QI 21))
2631 (clobber (reg:QI 25))
2632 (clobber (reg:HI 26))])
2636 if (s8_operand (operands[2], PSImode))
2638 rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
2639 emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1]));
2644 (define_insn "*mulsqipsi3.libgcc"
2646 (mult:PSI (sign_extend:PSI (reg:QI 25))
2649 "%~call __mulsqipsi3"
2650 [(set_attr "type" "xcall")
2651 (set_attr "cc" "clobber")])
2653 (define_insn "*mulpsi3.libgcc"
2655 (mult:PSI (reg:PSI 22)
2657 (clobber (reg:QI 21))
2658 (clobber (reg:QI 25))
2659 (clobber (reg:HI 26))]
2662 [(set_attr "type" "xcall")
2663 (set_attr "cc" "clobber")])
2666 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2667 ;; 24-bit signed/unsigned division and modulo.
2668 ;; Notice that the libgcc implementation return the quotient in R22
2669 ;; and the remainder in R18 whereas the 32-bit [u]divmodsi4
2670 ;; implementation works the other way round.
2672 (define_insn_and_split "divmodpsi4"
2673 [(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "")
2674 (div:PSI (match_operand:PSI 1 "pseudo_register_operand" "")
2675 (match_operand:PSI 2 "pseudo_register_operand" "")))
2676 (set (match_operand:PSI 3 "pseudo_register_operand" "")
2677 (mod:PSI (match_dup 1)
2679 (clobber (reg:DI 18))
2680 (clobber (reg:QI 26))])]
2682 { gcc_unreachable(); }
2684 [(set (reg:PSI 22) (match_dup 1))
2685 (set (reg:PSI 18) (match_dup 2))
2686 (parallel [(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18)))
2687 (set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18)))
2688 (clobber (reg:QI 21))
2689 (clobber (reg:QI 25))
2690 (clobber (reg:QI 26))])
2691 (set (match_dup 0) (reg:PSI 22))
2692 (set (match_dup 3) (reg:PSI 18))])
2694 (define_insn "*divmodpsi4_call"
2695 [(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18)))
2696 (set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18)))
2697 (clobber (reg:QI 21))
2698 (clobber (reg:QI 25))
2699 (clobber (reg:QI 26))]
2701 "%~call __divmodpsi4"
2702 [(set_attr "type" "xcall")
2703 (set_attr "cc" "clobber")])
2705 (define_insn_and_split "udivmodpsi4"
2706 [(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "")
2707 (udiv:PSI (match_operand:PSI 1 "pseudo_register_operand" "")
2708 (match_operand:PSI 2 "pseudo_register_operand" "")))
2709 (set (match_operand:PSI 3 "pseudo_register_operand" "")
2710 (umod:PSI (match_dup 1)
2712 (clobber (reg:DI 18))
2713 (clobber (reg:QI 26))])]
2715 { gcc_unreachable(); }
2717 [(set (reg:PSI 22) (match_dup 1))
2718 (set (reg:PSI 18) (match_dup 2))
2719 (parallel [(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18)))
2720 (set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18)))
2721 (clobber (reg:QI 21))
2722 (clobber (reg:QI 25))
2723 (clobber (reg:QI 26))])
2724 (set (match_dup 0) (reg:PSI 22))
2725 (set (match_dup 3) (reg:PSI 18))])
2727 (define_insn "*udivmodpsi4_call"
2728 [(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18)))
2729 (set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18)))
2730 (clobber (reg:QI 21))
2731 (clobber (reg:QI 25))
2732 (clobber (reg:QI 26))]
2734 "%~call __udivmodpsi4"
2735 [(set_attr "type" "xcall")
2736 (set_attr "cc" "clobber")])
2738 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2740 (define_insn_and_split "divmodsi4"
2741 [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "")
2742 (div:SI (match_operand:SI 1 "pseudo_register_operand" "")
2743 (match_operand:SI 2 "pseudo_register_operand" "")))
2744 (set (match_operand:SI 3 "pseudo_register_operand" "")
2745 (mod:SI (match_dup 1) (match_dup 2)))
2746 (clobber (reg:SI 18))
2747 (clobber (reg:SI 22))
2748 (clobber (reg:HI 26))
2749 (clobber (reg:HI 30))])]
2751 "this divmodsi4 pattern should have been splitted;"
2753 [(set (reg:SI 22) (match_dup 1))
2754 (set (reg:SI 18) (match_dup 2))
2755 (parallel [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
2756 (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
2757 (clobber (reg:HI 26))
2758 (clobber (reg:HI 30))])
2759 (set (match_dup 0) (reg:SI 18))
2760 (set (match_dup 3) (reg:SI 22))]
2763 (define_insn "*divmodsi4_call"
2764 [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
2765 (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
2766 (clobber (reg:HI 26))
2767 (clobber (reg:HI 30))]
2769 "%~call __divmodsi4"
2770 [(set_attr "type" "xcall")
2771 (set_attr "cc" "clobber")])
2773 (define_insn_and_split "udivmodsi4"
2774 [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "")
2775 (udiv:SI (match_operand:SI 1 "pseudo_register_operand" "")
2776 (match_operand:SI 2 "pseudo_register_operand" "")))
2777 (set (match_operand:SI 3 "pseudo_register_operand" "")
2778 (umod:SI (match_dup 1) (match_dup 2)))
2779 (clobber (reg:SI 18))
2780 (clobber (reg:SI 22))
2781 (clobber (reg:HI 26))
2782 (clobber (reg:HI 30))])]
2784 "this udivmodsi4 pattern should have been splitted;"
2786 [(set (reg:SI 22) (match_dup 1))
2787 (set (reg:SI 18) (match_dup 2))
2788 (parallel [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
2789 (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
2790 (clobber (reg:HI 26))
2791 (clobber (reg:HI 30))])
2792 (set (match_dup 0) (reg:SI 18))
2793 (set (match_dup 3) (reg:SI 22))]
2796 (define_insn "*udivmodsi4_call"
2797 [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
2798 (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
2799 (clobber (reg:HI 26))
2800 (clobber (reg:HI 30))]
2802 "%~call __udivmodsi4"
2803 [(set_attr "type" "xcall")
2804 (set_attr "cc" "clobber")])
2806 ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2809 (define_insn "andqi3"
2810 [(set (match_operand:QI 0 "register_operand" "=r,d")
2811 (and:QI (match_operand:QI 1 "register_operand" "%0,0")
2812 (match_operand:QI 2 "nonmemory_operand" "r,i")))]
2817 [(set_attr "length" "1,1")
2818 (set_attr "cc" "set_zn,set_zn")])
2820 (define_insn "andhi3"
2821 [(set (match_operand:HI 0 "register_operand" "=r,d,d,r ,r")
2822 (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0 ,0")
2823 (match_operand:HI 2 "nonmemory_operand" "r,s,n,Ca2,n")))
2824 (clobber (match_scratch:QI 3 "=X,X,X,X ,&d"))]
2827 if (which_alternative == 0)
2828 return "and %A0,%A2\;and %B0,%B2";
2829 else if (which_alternative == 1)
2830 return "andi %A0,lo8(%2)\;andi %B0,hi8(%2)";
2832 return avr_out_bitop (insn, operands, NULL);
2834 [(set_attr "length" "2,2,2,4,4")
2835 (set_attr "adjust_len" "*,*,out_bitop,out_bitop,out_bitop")
2836 (set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
2838 (define_insn "andpsi3"
2839 [(set (match_operand:PSI 0 "register_operand" "=r,d,r ,r")
2840 (and:PSI (match_operand:PSI 1 "register_operand" "%0,0,0 ,0")
2841 (match_operand:PSI 2 "nonmemory_operand" "r,n,Ca3,n")))
2842 (clobber (match_scratch:QI 3 "=X,X,X ,&d"))]
2845 if (which_alternative == 0)
2846 return "and %A0,%A2" CR_TAB
2847 "and %B0,%B2" CR_TAB
2850 return avr_out_bitop (insn, operands, NULL);
2852 [(set_attr "length" "3,3,6,6")
2853 (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
2854 (set_attr "cc" "set_n,clobber,clobber,clobber")])
2856 (define_insn "andsi3"
2857 [(set (match_operand:SI 0 "register_operand" "=r,d,r ,r")
2858 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0 ,0")
2859 (match_operand:SI 2 "nonmemory_operand" "r,n,Ca4,n")))
2860 (clobber (match_scratch:QI 3 "=X,X,X ,&d"))]
2863 if (which_alternative == 0)
2864 return "and %0,%2" CR_TAB
2865 "and %B0,%B2" CR_TAB
2866 "and %C0,%C2" CR_TAB
2869 return avr_out_bitop (insn, operands, NULL);
2871 [(set_attr "length" "4,4,8,8")
2872 (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
2873 (set_attr "cc" "set_n,clobber,clobber,clobber")])
2875 (define_peephole2 ; andi
2876 [(set (match_operand:QI 0 "d_register_operand" "")
2877 (and:QI (match_dup 0)
2878 (match_operand:QI 1 "const_int_operand" "")))
2880 (and:QI (match_dup 0)
2881 (match_operand:QI 2 "const_int_operand" "")))]
2883 [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
2885 operands[1] = GEN_INT (INTVAL (operands[1]) & INTVAL (operands[2]));
2888 ;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2891 (define_insn "iorqi3"
2892 [(set (match_operand:QI 0 "register_operand" "=r,d")
2893 (ior:QI (match_operand:QI 1 "register_operand" "%0,0")
2894 (match_operand:QI 2 "nonmemory_operand" "r,i")))]
2899 [(set_attr "length" "1,1")
2900 (set_attr "cc" "set_zn,set_zn")])
2902 (define_insn "iorhi3"
2903 [(set (match_operand:HI 0 "register_operand" "=r,d,d,r ,r")
2904 (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0 ,0")
2905 (match_operand:HI 2 "nonmemory_operand" "r,s,n,Co2,n")))
2906 (clobber (match_scratch:QI 3 "=X,X,X,X ,&d"))]
2909 if (which_alternative == 0)
2910 return "or %A0,%A2\;or %B0,%B2";
2911 else if (which_alternative == 1)
2912 return "ori %A0,lo8(%2)\;ori %B0,hi8(%2)";
2914 return avr_out_bitop (insn, operands, NULL);
2916 [(set_attr "length" "2,2,2,4,4")
2917 (set_attr "adjust_len" "*,*,out_bitop,out_bitop,out_bitop")
2918 (set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
2920 (define_insn "iorpsi3"
2921 [(set (match_operand:PSI 0 "register_operand" "=r,d,r ,r")
2922 (ior:PSI (match_operand:PSI 1 "register_operand" "%0,0,0 ,0")
2923 (match_operand:PSI 2 "nonmemory_operand" "r,n,Co3,n")))
2924 (clobber (match_scratch:QI 3 "=X,X,X ,&d"))]
2927 if (which_alternative == 0)
2928 return "or %A0,%A2" CR_TAB
2932 return avr_out_bitop (insn, operands, NULL);
2934 [(set_attr "length" "3,3,6,6")
2935 (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
2936 (set_attr "cc" "set_n,clobber,clobber,clobber")])
2938 (define_insn "iorsi3"
2939 [(set (match_operand:SI 0 "register_operand" "=r,d,r ,r")
2940 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0 ,0")
2941 (match_operand:SI 2 "nonmemory_operand" "r,n,Co4,n")))
2942 (clobber (match_scratch:QI 3 "=X,X,X ,&d"))]
2945 if (which_alternative == 0)
2946 return "or %0,%2" CR_TAB
2951 return avr_out_bitop (insn, operands, NULL);
2953 [(set_attr "length" "4,4,8,8")
2954 (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
2955 (set_attr "cc" "set_n,clobber,clobber,clobber")])
2957 ;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2960 (define_insn "xorqi3"
2961 [(set (match_operand:QI 0 "register_operand" "=r")
2962 (xor:QI (match_operand:QI 1 "register_operand" "%0")
2963 (match_operand:QI 2 "register_operand" "r")))]
2966 [(set_attr "length" "1")
2967 (set_attr "cc" "set_zn")])
2969 (define_insn "xorhi3"
2970 [(set (match_operand:HI 0 "register_operand" "=r,r ,r")
2971 (xor:HI (match_operand:HI 1 "register_operand" "%0,0 ,0")
2972 (match_operand:HI 2 "nonmemory_operand" "r,Cx2,n")))
2973 (clobber (match_scratch:QI 3 "=X,X ,&d"))]
2976 if (which_alternative == 0)
2977 return "eor %A0,%A2\;eor %B0,%B2";
2979 return avr_out_bitop (insn, operands, NULL);
2981 [(set_attr "length" "2,2,4")
2982 (set_attr "adjust_len" "*,out_bitop,out_bitop")
2983 (set_attr "cc" "set_n,clobber,clobber")])
2985 (define_insn "xorpsi3"
2986 [(set (match_operand:PSI 0 "register_operand" "=r,r ,r")
2987 (xor:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0")
2988 (match_operand:PSI 2 "nonmemory_operand" "r,Cx3,n")))
2989 (clobber (match_scratch:QI 3 "=X,X ,&d"))]
2992 if (which_alternative == 0)
2993 return "eor %A0,%A2" CR_TAB
2994 "eor %B0,%B2" CR_TAB
2997 return avr_out_bitop (insn, operands, NULL);
2999 [(set_attr "length" "3,6,6")
3000 (set_attr "adjust_len" "*,out_bitop,out_bitop")
3001 (set_attr "cc" "set_n,clobber,clobber")])
3003 (define_insn "xorsi3"
3004 [(set (match_operand:SI 0 "register_operand" "=r,r ,r")
3005 (xor:SI (match_operand:SI 1 "register_operand" "%0,0 ,0")
3006 (match_operand:SI 2 "nonmemory_operand" "r,Cx4,n")))
3007 (clobber (match_scratch:QI 3 "=X,X ,&d"))]
3010 if (which_alternative == 0)
3011 return "eor %0,%2" CR_TAB
3012 "eor %B0,%B2" CR_TAB
3013 "eor %C0,%C2" CR_TAB
3016 return avr_out_bitop (insn, operands, NULL);
3018 [(set_attr "length" "4,8,8")
3019 (set_attr "adjust_len" "*,out_bitop,out_bitop")
3020 (set_attr "cc" "set_n,clobber,clobber")])
3022 ;; swap swap swap swap swap swap swap swap swap swap swap swap swap swap swap
3025 (define_expand "rotlqi3"
3026 [(set (match_operand:QI 0 "register_operand" "")
3027 (rotate:QI (match_operand:QI 1 "register_operand" "")
3028 (match_operand:QI 2 "const_0_to_7_operand" "")))]
3031 if (!CONST_INT_P (operands[2]))
3034 operands[2] = gen_int_mode (INTVAL (operands[2]) & 7, QImode);
3037 ;; Expander used by __builtin_avr_swap
3038 (define_expand "rotlqi3_4"
3039 [(set (match_operand:QI 0 "register_operand" "")
3040 (rotate:QI (match_operand:QI 1 "register_operand" "")
3043 (define_insn "*rotlqi3"
3044 [(set (match_operand:QI 0 "register_operand" "=r,r,r ,r ,r ,r ,r ,r")
3045 (rotate:QI (match_operand:QI 1 "register_operand" "0,0,0 ,0 ,0 ,0 ,0 ,0")
3046 (match_operand:QI 2 "const_0_to_7_operand" "P,K,C03,C04,C05,C06,C07,L")))]
3049 lsl %0\;adc %0,__zero_reg__
3050 lsl %0\;adc %0,__zero_reg__\;lsl %0\;adc %0,__zero_reg__
3051 swap %0\;bst %0,0\;ror %0\;bld %0,7
3053 swap %0\;lsl %0\;adc %0,__zero_reg__
3054 swap %0\;lsl %0\;adc %0,__zero_reg__\;lsl %0\;adc %0,__zero_reg__
3055 bst %0,0\;ror %0\;bld %0,7
3057 [(set_attr "length" "2,4,4,1,3,5,3,0")
3058 (set_attr "cc" "set_n,set_n,clobber,none,set_n,set_n,clobber,none")])
3060 ;; Split all rotates of HI,SI and PSImode registers where rotation is by
3061 ;; a whole number of bytes. The split creates the appropriate moves and
3062 ;; considers all overlap situations.
3064 ;; HImode does not need scratch. Use attribute for this constraint.
3066 (define_mode_attr rotx [(SI "&r,&r,X") (PSI "&r,&r,X") (HI "X,X,X")])
3067 (define_mode_attr rotsmode [(SI "HI") (PSI "QI") (HI "QI")])
3072 (define_expand "rotl<mode>3"
3073 [(parallel [(set (match_operand:HISI 0 "register_operand" "")
3074 (rotate:HISI (match_operand:HISI 1 "register_operand" "")
3075 (match_operand:VOID 2 "const_int_operand" "")))
3076 (clobber (match_dup 3))])]
3081 if (!CONST_INT_P (operands[2]))
3084 offset = INTVAL (operands[2]);
3086 if (0 == offset % 8)
3088 if (AVR_HAVE_MOVW && 0 == offset % 16)
3089 operands[3] = gen_rtx_SCRATCH (<rotsmode>mode);
3091 operands[3] = gen_rtx_SCRATCH (QImode);
3093 else if (offset == 1
3094 || offset == GET_MODE_BITSIZE (<MODE>mode) -1)
3096 /*; Support rotate left/right by 1 */
3098 emit_move_insn (operands[0],
3099 gen_rtx_ROTATE (<MODE>mode, operands[1], operands[2]));
3106 (define_insn "*rotlhi2.1"
3107 [(set (match_operand:HI 0 "register_operand" "=r")
3108 (rotate:HI (match_operand:HI 1 "register_operand" "0")
3111 "lsl %A0\;rol %B0\;adc %A0,__zero_reg__"
3112 [(set_attr "length" "3")
3113 (set_attr "cc" "clobber")])
3115 (define_insn "*rotlhi2.15"
3116 [(set (match_operand:HI 0 "register_operand" "=r")
3117 (rotate:HI (match_operand:HI 1 "register_operand" "0")
3120 "bst %A0,0\;ror %B0\;ror %A0\;bld %B0,7"
3121 [(set_attr "length" "4")
3122 (set_attr "cc" "clobber")])
3124 (define_insn "*rotlpsi2.1"
3125 [(set (match_operand:PSI 0 "register_operand" "=r")
3126 (rotate:PSI (match_operand:PSI 1 "register_operand" "0")
3129 "lsl %A0\;rol %B0\;rol %C0\;adc %A0,__zero_reg__"
3130 [(set_attr "length" "4")
3131 (set_attr "cc" "clobber")])
3133 (define_insn "*rotlpsi2.23"
3134 [(set (match_operand:PSI 0 "register_operand" "=r")
3135 (rotate:PSI (match_operand:PSI 1 "register_operand" "0")
3138 "bst %A0,0\;ror %C0\;ror %B0\;ror %A0\;bld %C0,7"
3139 [(set_attr "length" "5")
3140 (set_attr "cc" "clobber")])
3142 (define_insn "*rotlsi2.1"
3143 [(set (match_operand:SI 0 "register_operand" "=r")
3144 (rotate:SI (match_operand:SI 1 "register_operand" "0")
3147 "lsl %A0\;rol %B0\;rol %C0\;rol %D0\;adc %A0,__zero_reg__"
3148 [(set_attr "length" "5")
3149 (set_attr "cc" "clobber")])
3151 (define_insn "*rotlsi2.31"
3152 [(set (match_operand:SI 0 "register_operand" "=r")
3153 (rotate:SI (match_operand:SI 1 "register_operand" "0")
3156 "bst %A0,0\;ror %D0\;ror %C0\;ror %B0\;ror %A0\;bld %D0,7"
3157 [(set_attr "length" "6")
3158 (set_attr "cc" "clobber")])
3160 ;; Overlapping non-HImode registers often (but not always) need a scratch.
3161 ;; The best we can do is use early clobber alternative "#&r" so that
3162 ;; completely non-overlapping operands dont get a scratch but # so register
3163 ;; allocation does not prefer non-overlapping.
3166 ;; Split word aligned rotates using scratch that is mode dependent.
3170 (define_insn_and_split "*rotw<mode>"
3171 [(set (match_operand:HISI 0 "register_operand" "=r,r,#&r")
3172 (rotate:HISI (match_operand:HISI 1 "register_operand" "0,r,r")
3173 (match_operand 2 "const_int_operand" "n,n,n")))
3174 (clobber (match_scratch:<rotsmode> 3 "=<rotx>"))]
3176 && CONST_INT_P (operands[2])
3177 && GET_MODE_SIZE (<MODE>mode) % 2 == 0
3178 && 0 == INTVAL (operands[2]) % 16"
3180 "&& reload_completed"
3183 avr_rotate_bytes (operands);
3188 ;; Split byte aligned rotates using scratch that is always QI mode.
3193 (define_insn_and_split "*rotb<mode>"
3194 [(set (match_operand:HISI 0 "register_operand" "=r,r,#&r")
3195 (rotate:HISI (match_operand:HISI 1 "register_operand" "0,r,r")
3196 (match_operand 2 "const_int_operand" "n,n,n")))
3197 (clobber (match_scratch:QI 3 "=<rotx>"))]
3198 "CONST_INT_P (operands[2])
3199 && (8 == INTVAL (operands[2]) % 16
3201 || GET_MODE_SIZE (<MODE>mode) % 2 != 0)
3202 && 0 == INTVAL (operands[2]) % 16))"
3204 "&& reload_completed"
3207 avr_rotate_bytes (operands);
3212 ;;<< << << << << << << << << << << << << << << << << << << << << << << << << <<
3213 ;; arithmetic shift left
3215 (define_expand "ashlqi3"
3216 [(set (match_operand:QI 0 "register_operand" "")
3217 (ashift:QI (match_operand:QI 1 "register_operand" "")
3218 (match_operand:QI 2 "nop_general_operand" "")))])
3220 (define_split ; ashlqi3_const4
3221 [(set (match_operand:QI 0 "d_register_operand" "")
3222 (ashift:QI (match_dup 0)
3225 [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
3226 (set (match_dup 0) (and:QI (match_dup 0) (const_int -16)))]
3229 (define_split ; ashlqi3_const5
3230 [(set (match_operand:QI 0 "d_register_operand" "")
3231 (ashift:QI (match_dup 0)
3234 [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
3235 (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))
3236 (set (match_dup 0) (and:QI (match_dup 0) (const_int -32)))]
3239 (define_split ; ashlqi3_const6
3240 [(set (match_operand:QI 0 "d_register_operand" "")
3241 (ashift:QI (match_dup 0)
3244 [(set (match_dup 0) (rotate:QI (match_dup 0) (const_int 4)))
3245 (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 2)))
3246 (set (match_dup 0) (and:QI (match_dup 0) (const_int -64)))]
3249 (define_insn "*ashlqi3"
3250 [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,!d,r,r")
3251 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0 ,0,0")
3252 (match_operand:QI 2 "nop_general_operand" "r,L,P,K,n ,n,Qm")))]
3255 return ashlqi3_out (insn, operands, NULL);
3257 [(set_attr "length" "5,0,1,2,4,6,9")
3258 (set_attr "adjust_len" "ashlqi")
3259 (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")])
3261 (define_insn "ashlhi3"
3262 [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r,r")
3263 (ashift:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
3264 (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
3267 return ashlhi3_out (insn, operands, NULL);
3269 [(set_attr "length" "6,0,2,2,4,10,10")
3270 (set_attr "adjust_len" "ashlhi")
3271 (set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")])
3274 ;; Insns like the following are generated when (implicitly) extending 8-bit shifts
3275 ;; like char1 = char2 << char3. Only the low-byte is needed in that situation.
3279 (define_insn_and_split "*ashl<extend_su>qihiqi3"
3280 [(set (match_operand:QI 0 "register_operand" "=r")
3281 (subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "0"))
3282 (match_operand:QI 2 "register_operand" "r"))
3288 (ashift:QI (match_dup 1)
3292 ;; ??? Combiner does not recognize that it could split the following insn;
3293 ;; presumably because he has no register handy?
3295 ;; "*ashluqihiqi3.mem"
3296 ;; "*ashlsqihiqi3.mem"
3297 (define_insn_and_split "*ashl<extend_su>qihiqi3.mem"
3298 [(set (match_operand:QI 0 "memory_operand" "=m")
3299 (subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "r"))
3300 (match_operand:QI 2 "register_operand" "r"))
3303 { gcc_unreachable(); }
3306 (ashift:QI (match_dup 1)
3311 operands[3] = gen_reg_rtx (QImode);
3316 (define_insn_and_split "*ashlhiqi3"
3317 [(set (match_operand:QI 0 "nonimmediate_operand" "=r")
3318 (subreg:QI (ashift:HI (match_operand:HI 1 "register_operand" "0")
3319 (match_operand:QI 2 "register_operand" "r")) 0))]
3321 { gcc_unreachable(); }
3324 (ashift:QI (match_dup 3)
3329 operands[3] = simplify_gen_subreg (QImode, operands[1], HImode, 0);
3330 operands[4] = gen_reg_rtx (QImode);
3333 ;; High part of 16-bit shift is unused after the instruction:
3334 ;; No need to compute it, map to 8-bit shift.
3337 [(set (match_operand:HI 0 "register_operand" "")
3338 (ashift:HI (match_dup 0)
3339 (match_operand:QI 1 "register_operand" "")))]
3342 (ashift:QI (match_dup 2)
3344 (clobber (match_dup 3))]
3346 operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 1);
3348 if (!peep2_reg_dead_p (1, operands[3]))
3351 operands[2] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
3355 (define_insn "ashlsi3"
3356 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
3357 (ashift:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
3358 (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
3361 return ashlsi3_out (insn, operands, NULL);
3363 [(set_attr "length" "8,0,4,4,8,10,12")