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