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