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