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