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