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