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