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