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