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