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