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