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