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