OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [avr/] [avr.md] - Blame information for rev 867

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.