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