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