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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
;;  Machine Description for Renesas RX processors
2
;;  Copyright (C) 2008, 2009, 2010, 2011, 2012
3
;;  Free Software Foundation, Inc.
4
;;  Contributed by Red Hat.
5
 
6
;; This file is part of GCC.
7
 
8
;; GCC is free software; you can redistribute it and/or modify
9
;; it under the terms of the GNU General Public License as published by
10
;; the Free Software Foundation; either version 3, or (at your option)
11
;; any later version.
12
 
13
;; GCC is distributed in the hope that it will be useful,
14
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
;; GNU General Public License for more details.
17
 
18
;; You should have received a copy of the GNU General Public License
19
;; along with GCC; see the file COPYING3.  If not see
20
;; .
21
 
22
 
23
;; This code iterator is used for sign- and zero- extensions.
24
(define_mode_iterator small_int_modes [(HI "") (QI "")])
25
 
26
;; This code iterator is used for max and min operations.
27
(define_mode_iterator int_modes [(SI "") (HI "") (QI "")])
28
 
29
;; We do not handle DFmode here because it is either
30
;; the same as SFmode, or if -m64bit-doubles is active
31
;; then all operations on doubles have to be handled by
32
;; library functions.
33
(define_mode_iterator register_modes
34
  [(SF "ALLOW_RX_FPU_INSNS") (SI "") (HI "") (QI "")])
35
 
36
(define_constants
37
  [
38
   (SP_REG 0)
39
   (CC_REG                 16)
40
 
41
   (UNSPEC_LOW_REG         0)
42
   (UNSPEC_HIGH_REG        1)
43
 
44
   (UNSPEC_RTE             10)
45
   (UNSPEC_RTFI            11)
46
   (UNSPEC_NAKED           12)
47
   (UNSPEC_CONST           13)
48
 
49
   (UNSPEC_MOVSTR          20)
50
   (UNSPEC_MOVMEM          21)
51
   (UNSPEC_SETMEM          22)
52
   (UNSPEC_STRLEN          23)
53
   (UNSPEC_CMPSTRN         24)
54
 
55
   (UNSPEC_BUILTIN_BRK     30)
56
   (UNSPEC_BUILTIN_CLRPSW  31)
57
   (UNSPEC_BUILTIN_INT     32)
58
   (UNSPEC_BUILTIN_MACHI   33)
59
   (UNSPEC_BUILTIN_MACLO   34)
60
   (UNSPEC_BUILTIN_MULHI   35)
61
   (UNSPEC_BUILTIN_MULLO   36)
62
   (UNSPEC_BUILTIN_MVFACHI 37)
63
   (UNSPEC_BUILTIN_MVFACMI 38)
64
   (UNSPEC_BUILTIN_MVFC    39)
65
   (UNSPEC_BUILTIN_MVFCP   40)
66
   (UNSPEC_BUILTIN_MVTACHI 41)
67
   (UNSPEC_BUILTIN_MVTACLO 42)
68
   (UNSPEC_BUILTIN_MVTC    43)
69
   (UNSPEC_BUILTIN_MVTIPL  44)
70
   (UNSPEC_BUILTIN_RACW    45)
71
   (UNSPEC_BUILTIN_REVW    46)
72
   (UNSPEC_BUILTIN_RMPA    47)
73
   (UNSPEC_BUILTIN_ROUND   48)
74
   (UNSPEC_BUILTIN_SAT     49)
75
   (UNSPEC_BUILTIN_SETPSW  50)
76
   (UNSPEC_BUILTIN_WAIT    51)
77
 
78
   (UNSPEC_PID_ADDR        52)
79
  ]
80
)
81
 
82
(define_attr "length" "" (const_int 8))
83
 
84
(include "predicates.md")
85
(include "constraints.md")
86
 
87
;; Pipeline description.
88
 
89
;; The RX only has a single pipeline.  It has five stages (fetch,
90
;; decode, execute, memory access, writeback) each of which normally
91
;; takes a single CPU clock cycle.
92
 
93
;; The timings attribute consists of two numbers, the first is the
94
;; throughput, which is the number of cycles the instruction takes
95
;; to execute and generate a result.  The second is the latency
96
;; which is the effective number of cycles the instruction takes to
97
;; execute if its result is used by the following instruction.  The
98
;; latency is always greater than or equal to the throughput.
99
;; These values were taken from tables 2.13 and 2.14 in section 2.8
100
;; of the RX610 Group Hardware Manual v0.11
101
 
102
;; Note - it would be nice to use strings rather than integers for
103
;; the possible values of this attribute, so that we can have the
104
;; gcc build mechanism check for values that are not supported by
105
;; the reservations below.  But this will not work because the code
106
;; in rx_adjust_sched_cost() needs integers not strings.
107
 
108
(define_attr "timings" "" (const_int 11))
109
 
110
(define_automaton "pipelining")
111
(define_cpu_unit "throughput" "pipelining")
112
 
113
(define_insn_reservation "throughput__1_latency__1"  1
114
  (eq_attr "timings" "11") "throughput")
115
(define_insn_reservation "throughput__1_latency__2"  2
116
  (eq_attr "timings" "12") "throughput,nothing")
117
(define_insn_reservation "throughput__2_latency__2"  1
118
  (eq_attr "timings" "22") "throughput*2")
119
(define_insn_reservation "throughput__3_latency__3"  1
120
  (eq_attr "timings" "33") "throughput*3")
121
(define_insn_reservation "throughput__3_latency__4"  2
122
  (eq_attr "timings" "34") "throughput*3,nothing")
123
(define_insn_reservation "throughput__4_latency__4"  1
124
  (eq_attr "timings" "44") "throughput*4")
125
(define_insn_reservation "throughput__4_latency__5"  2
126
  (eq_attr "timings" "45") "throughput*4,nothing")
127
(define_insn_reservation "throughput__5_latency__5"  1
128
  (eq_attr "timings" "55") "throughput*5")
129
(define_insn_reservation "throughput__5_latency__6"  2
130
  (eq_attr "timings" "56") "throughput*5,nothing")
131
(define_insn_reservation "throughput__6_latency__6"  1
132
  (eq_attr "timings" "66") "throughput*6")
133
(define_insn_reservation "throughput_10_latency_10"  1
134
  (eq_attr "timings" "1010") "throughput*10")
135
(define_insn_reservation "throughput_11_latency_11"  1
136
  (eq_attr "timings" "1111") "throughput*11")
137
(define_insn_reservation "throughput_16_latency_16"  1
138
  (eq_attr "timings" "1616") "throughput*16")
139
(define_insn_reservation "throughput_18_latency_18"  1
140
  (eq_attr "timings" "1818") "throughput*18")
141
 
142
;; ----------------------------------------------------------------------------
143
 
144
;; Comparisons
145
 
146
;; Note - we do not specify the two instructions necessary to perform
147
;; a compare-and-branch in the cbranchsi4 pattern because that would
148
;; allow the comparison to be moved away from the jump before the reload
149
;; pass has completed.  That would be problematical because reload can
150
;; generate ADDSI3 instructions which would corrupt the PSW flags.
151
 
152
(define_expand "cbranchsi4"
153
  [(set (pc)
154
        (if_then_else
155
          (match_operator 0 "comparison_operator"
156
            [(match_operand:SI 1 "register_operand")
157
             (match_operand:SI 2 "rx_source_operand")])
158
          (label_ref (match_operand 3 ""))
159
          (pc)))]
160
  ""
161
)
162
 
163
(define_insn_and_split "*cbranchsi4"
164
  [(set (pc)
165
        (if_then_else
166
          (match_operator 3 "comparison_operator"
167
            [(match_operand:SI  0 "register_operand"  "r")
168
             (match_operand:SI  1 "rx_source_operand" "riQ")])
169
          (match_operand        2 "label_ref_operand" "")
170
          (pc)))]
171
  ""
172
  "#"
173
  "reload_completed"
174
  [(const_int 0)]
175
{
176
  rx_split_cbranch (CCmode, GET_CODE (operands[3]),
177
                    operands[0], operands[1], operands[2]);
178
  DONE;
179
})
180
 
181
(define_insn "*cmpsi"
182
  [(set (reg:CC CC_REG)
183
        (compare:CC (match_operand:SI 0 "register_operand"  "r,r,r,r,r,r,r")
184
                    (match_operand:SI 1 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")))]
185
  "reload_completed"
186
  "cmp\t%Q1, %0"
187
  [(set_attr "timings" "11,11,11,11,11,11,33")
188
   (set_attr "length"  "2,2,3,4,5,6,5")]
189
)
190
 
191
;; Canonical method for representing TST.
192
(define_insn_and_split "*cbranchsi4_tst"
193
  [(set (pc)
194
        (if_then_else
195
          (match_operator 3 "rx_zs_comparison_operator"
196
            [(and:SI (match_operand:SI  0 "register_operand"  "r")
197
                     (match_operand:SI  1 "rx_source_operand" "riQ"))
198
             (const_int 0)])
199
          (match_operand 2 "label_ref_operand" "")
200
          (pc)))]
201
  ""
202
  "#"
203
  "reload_completed"
204
  [(const_int 0)]
205
{
206
  rx_split_cbranch (CC_ZSmode, GET_CODE (operands[3]),
207
                    XEXP (operands[3], 0), XEXP (operands[3], 1),
208
                    operands[2]);
209
  DONE;
210
})
211
 
212
;; Various other ways that GCC codes "var & const"
213
(define_insn_and_split "*cbranchsi4_tst_ext"
214
  [(set (pc)
215
        (if_then_else
216
          (match_operator 4 "rx_z_comparison_operator"
217
            [(zero_extract:SI
218
                (match_operand:SI 0 "register_operand" "r")
219
                (match_operand:SI 1 "rx_constshift_operand" "")
220
                (match_operand:SI 2 "rx_constshift_operand" ""))
221
             (const_int 0)])
222
          (match_operand 3 "label_ref_operand" "")
223
          (pc)))]
224
  ""
225
  "#"
226
  "reload_completed"
227
  [(const_int 0)]
228
{
229
  HOST_WIDE_INT mask;
230
  rtx x;
231
 
232
  mask = 1;
233
  mask <<= INTVAL (operands[1]);
234
  mask -= 1;
235
  mask <<= INTVAL (operands[2]);
236
  x = gen_rtx_AND (SImode, operands[0], gen_int_mode (mask, SImode));
237
 
238
  rx_split_cbranch (CC_ZSmode, GET_CODE (operands[4]),
239
                    x, const0_rtx, operands[3]);
240
  DONE;
241
})
242
 
243
(define_insn "*tstsi"
244
  [(set (reg:CC_ZS CC_REG)
245
        (compare:CC_ZS
246
          (and:SI (match_operand:SI 0 "register_operand"  "r,r,r")
247
                  (match_operand:SI 1 "rx_source_operand" "r,i,Q"))
248
          (const_int 0)))]
249
  "reload_completed"
250
  "tst\t%Q1, %0"
251
  [(set_attr "timings" "11,11,33")
252
   (set_attr "length"  "3,7,6")]
253
)
254
 
255
(define_expand "cbranchsf4"
256
  [(set (pc)
257
        (if_then_else
258
          (match_operator 0 "rx_fp_comparison_operator"
259
            [(match_operand:SF 1 "register_operand")
260
             (match_operand:SF 2 "rx_source_operand")])
261
          (label_ref (match_operand 3 ""))
262
          (pc)))]
263
  "ALLOW_RX_FPU_INSNS"
264
)
265
 
266
(define_insn_and_split "*cbranchsf4"
267
  [(set (pc)
268
        (if_then_else
269
          (match_operator 3 "rx_fp_comparison_operator"
270
            [(match_operand:SF  0 "register_operand"  "r")
271
             (match_operand:SF  1 "rx_source_operand" "rFQ")])
272
          (match_operand        2 "label_ref_operand" "")
273
          (pc)))]
274
  "ALLOW_RX_FPU_INSNS"
275
  "#"
276
  "&& reload_completed"
277
  [(const_int 0)]
278
{
279
  rx_split_cbranch (CC_Fmode, GET_CODE (operands[3]),
280
                    operands[0], operands[1], operands[2]);
281
  DONE;
282
})
283
 
284
(define_insn "*cmpsf"
285
  [(set (reg:CC_F CC_REG)
286
        (compare:CC_F
287
          (match_operand:SF 0 "register_operand"  "r,r,r")
288
          (match_operand:SF 1 "rx_source_operand" "r,F,Q")))]
289
  "ALLOW_RX_FPU_INSNS && reload_completed"
290
  "fcmp\t%1, %0"
291
  [(set_attr "timings" "11,11,33")
292
   (set_attr "length" "3,7,5")]
293
)
294
 
295
;; Flow Control Instructions:
296
 
297
(define_insn "*conditional_branch"
298
  [(set (pc)
299
        (if_then_else
300
          (match_operator 1 "comparison_operator"
301
            [(reg CC_REG) (const_int 0)])
302
          (label_ref (match_operand 0 "" ""))
303
          (pc)))]
304
  "reload_completed"
305
  "b%B1\t%0"
306
  [(set_attr "length" "8")    ;; This length is wrong, but it is
307
                              ;; too hard to compute statically.
308
   (set_attr "timings" "33")] ;; The timing assumes that the branch is taken.
309
)
310
 
311
;; ----------------------------------------------------------------------------
312
 
313
(define_insn "jump"
314
  [(set (pc)
315
        (label_ref (match_operand 0 "" "")))]
316
  ""
317
  "bra\t%0"
318
  [(set_attr "length" "4")
319
   (set_attr "timings" "33")]
320
)
321
 
322
(define_insn "indirect_jump"
323
  [(set (pc)
324
        (match_operand:SI 0 "register_operand" "r"))]
325
  ""
326
  "jmp\t%0"
327
  [(set_attr "length" "2")
328
   (set_attr "timings" "33")]
329
)
330
 
331
(define_insn "tablejump"
332
  [(set (pc)
333
        (match_operand:SI          0 "register_operand" "r"))
334
   (use (label_ref (match_operand  1 "" "")))]
335
  ""
336
  { return TARGET_PID ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
337
                                             : "\n1:\tbra\t%0")
338
                                             : "\n1:jmp\t%0";
339
  }
340
  [(set_attr "timings" "33")
341
   (set_attr "length" "2")]
342
)
343
 
344
(define_expand "return"
345
  [(return)]
346
  "rx_can_use_simple_return ()"
347
  "rx_expand_epilogue (false); DONE;"
348
)
349
 
350
(define_insn "simple_return"
351
  [(return)]
352
  ""
353
  "rts"
354
  [(set_attr "length" "1")
355
   (set_attr "timings" "55")]
356
)
357
 
358
;; Unspec used so that the constant will not be invalid
359
;; if -mmax-constant-size has been specified.
360
(define_insn "deallocate_and_return"
361
  [(set (reg:SI SP_REG)
362
        (plus:SI (reg:SI SP_REG)
363
                 (const:SI (unspec:SI [(match_operand 0 "const_int_operand" "n")] UNSPEC_CONST))))
364
   (return)]
365
  ""
366
  "rtsd\t%0"
367
  [(set_attr "length" "2")
368
   (set_attr "timings" "55")]
369
)
370
 
371
(define_insn "pop_and_return"
372
  [(match_parallel 1 "rx_rtsd_vector"
373
     [(set (reg:SI SP_REG)
374
           (plus:SI (reg:SI SP_REG)
375
                    (match_operand:SI 0 "const_int_operand" "n")))])
376
   (return)]
377
  "reload_completed"
378
  {
379
    rx_emit_stack_popm (operands, false);
380
    return "";
381
  }
382
  [(set_attr "length" "3")
383
   (set_attr "timings" "56")]
384
)
385
 
386
(define_insn "fast_interrupt_return"
387
  [(unspec_volatile [(return)] UNSPEC_RTFI) ]
388
  ""
389
  "rtfi"
390
  [(set_attr "length" "2")
391
   (set_attr "timings" "33")]
392
)
393
 
394
(define_insn "exception_return"
395
  [(unspec_volatile [(return)] UNSPEC_RTE) ]
396
  ""
397
  "rte"
398
  [(set_attr "length" "2")
399
   (set_attr "timings" "66")]
400
)
401
 
402
(define_insn "naked_return"
403
  [(unspec_volatile [(return)] UNSPEC_NAKED) ]
404
  ""
405
  "; Naked function: epilogue provided by programmer."
406
)
407
 
408
 
409
;; Note - the following set of patterns do not use the "memory_operand"
410
;; predicate or an "m" constraint because we do not allow symbol_refs
411
;; or label_refs as legitmate memory addresses.  This matches the
412
;; behaviour of most of the RX instructions.  Only the call/branch
413
;; instructions are allowed to refer to symbols/labels directly.
414
;; The call operands are in QImode because that is the value of
415
;; FUNCTION_MODE
416
 
417
(define_expand "call"
418
  [(call (match_operand:QI 0 "general_operand")
419
         (match_operand:SI 1 "general_operand"))]
420
  ""
421
  {
422
    rtx dest = XEXP (operands[0], 0);
423
 
424
    if (! rx_call_operand (dest, Pmode))
425
      dest = force_reg (Pmode, dest);
426
    emit_call_insn (gen_call_internal (dest));
427
    DONE;
428
  }
429
)
430
 
431
(define_insn "call_internal"
432
  [(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,Symbol"))
433
         (const_int 0))
434
   (clobber (reg:CC CC_REG))]
435
  ""
436
  "@
437
  jsr\t%0
438
  bsr\t%A0"
439
  [(set_attr "length" "2,4")
440
   (set_attr "timings" "33")]
441
)
442
 
443
(define_expand "call_value"
444
  [(set (match_operand          0 "register_operand")
445
        (call (match_operand:QI 1 "general_operand")
446
              (match_operand:SI 2 "general_operand")))]
447
  ""
448
  {
449
    rtx dest = XEXP (operands[1], 0);
450
 
451
    if (! rx_call_operand (dest, Pmode))
452
      dest = force_reg (Pmode, dest);
453
    emit_call_insn (gen_call_value_internal (operands[0], dest));
454
    DONE;
455
  }
456
)
457
 
458
(define_insn "call_value_internal"
459
  [(set (match_operand                  0 "register_operand" "=r,r")
460
        (call (mem:QI (match_operand:SI 1 "rx_call_operand"   "r,Symbol"))
461
              (const_int 0)))
462
   (clobber (reg:CC CC_REG))]
463
  ""
464
  "@
465
  jsr\t%1
466
  bsr\t%A1"
467
  [(set_attr "length" "2,4")
468
   (set_attr "timings" "33")]
469
)
470
 
471
;; Note - we do not allow indirect sibcalls (with the address
472
;; held in a register) because we cannot guarantee that the register
473
;; chosen will be a call-used one.  If it is a call-saved register,
474
;; then the epilogue code will corrupt it by popping the saved value
475
;; off of the stack.
476
(define_expand "sibcall"
477
  [(parallel
478
    [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand"))
479
           (match_operand:SI         1 "general_operand"))
480
     (return)])]
481
  ""
482
  {
483
    if (MEM_P (operands[0]))
484
      operands[0] = XEXP (operands[0], 0);
485
    emit_call_insn (gen_sibcall_internal (operands[0]));
486
    DONE;
487
  }
488
)
489
 
490
(define_insn "sibcall_internal"
491
  [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand" "Symbol"))
492
         (const_int 0))
493
   (return)]
494
  ""
495
  "bra\t%A0"
496
  [(set_attr "length"  "4")
497
   (set_attr "timings" "33")]
498
)
499
 
500
(define_expand "sibcall_value"
501
 [(parallel
502
   [(set (match_operand                  0 "register_operand")
503
         (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand"))
504
               (match_operand:SI         2 "general_operand")))
505
    (return)])]
506
  ""
507
  {
508
    if (MEM_P (operands[1]))
509
      operands[1] = XEXP (operands[1], 0);
510
    emit_call_insn (gen_sibcall_value_internal (operands[0], operands[1]));
511
    DONE;
512
  }
513
)
514
 
515
(define_insn "sibcall_value_internal"
516
 [(set (match_operand                  0 "register_operand"         "=r")
517
       (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand" "Symbol"))
518
             (const_int 0)))
519
  (return)]
520
  ""
521
  "bra\t%A1"
522
  [(set_attr "length"  "4")
523
   (set_attr "timings" "33")]
524
)
525
 
526
;; Function Prologue/Epilogue Instructions
527
 
528
(define_expand "prologue"
529
  [(const_int 0)]
530
  ""
531
  "rx_expand_prologue (); DONE;"
532
)
533
 
534
(define_expand "epilogue"
535
  [(return)]
536
  ""
537
  "rx_expand_epilogue (false); DONE;"
538
)
539
 
540
(define_expand "sibcall_epilogue"
541
  [(return)]
542
  ""
543
  "rx_expand_epilogue (true); DONE;"
544
)
545
 
546
;; Move Instructions
547
 
548
;; Note - we do not allow memory to memory moves, even though the ISA
549
;; supports them.  The reason is that the conditions on such moves are
550
;; too restrictive, specifically the source addressing mode is limited
551
;; by the destination addressing mode and vice versa.  (For example it
552
;; is not possible to use indexed register indirect addressing for one
553
;; of the operands if the other operand is anything other than a register,
554
;; but it is possible to use register relative addressing when the other
555
;; operand also uses register relative or register indirect addressing).
556
;;
557
;; GCC does not support computing legitimate addresses based on the
558
;; nature of other operands involved in the instruction, and reload is
559
;; not smart enough to cope with a whole variety of different memory
560
;; addressing constraints, so it is simpler and safer to just refuse
561
;; to support memory to memory moves.
562
 
563
(define_expand "mov"
564
  [(set (match_operand:register_modes 0 "general_operand")
565
        (match_operand:register_modes 1 "general_operand"))]
566
  ""
567
  {
568
    if (MEM_P (operands[0]) && MEM_P (operands[1]))
569
      operands[1] = copy_to_mode_reg (mode, operands[1]);
570
    operands[0] = rx_maybe_pidify_operand (operands[0], 0);
571
    operands[1] = rx_maybe_pidify_operand (operands[1], 0);
572
    if (GET_CODE (operands[0]) != REG
573
        && GET_CODE (operands[1]) == PLUS)
574
      operands[1] = copy_to_mode_reg (mode, operands[1]);
575
    if (GET_CODE (operands[1]) == PLUS && GET_MODE (operands[1]) == SImode)
576
      {
577
        emit_insn (gen_addsi3 (operands[0], XEXP (operands[1], 0), XEXP (operands[1], 1)));
578
        DONE;
579
      }
580
    if (CONST_INT_P (operand1)
581
        && ! rx_is_legitimate_constant (mode, operand1))
582
      FAIL;
583
  }
584
)
585
 
586
(define_insn "*mov_internal"
587
  [(set (match_operand:register_modes
588
 
589
        (match_operand:register_modes
590
         1 "general_operand" "Int08,Sint16,Sint24,i,r,m,r,Int08,Sint16,Sint24,i,RpdaRpid"))]
591
  ""
592
  { return rx_gen_move_template (operands, false); }
593
  [(set_attr "length" "3,4,5,6,2,4,6,5,6,7,8,8")
594
   (set_attr "timings" "11,11,11,11,11,12,11,11,11,11,11,11")]
595
)
596
 
597
(define_insn "extendsi2"
598
  [(set (match_operand:SI 0 "register_operand"    "=r,r")
599
        (sign_extend:SI (match_operand:small_int_modes
600
                          1 "nonimmediate_operand" "r,m")))]
601
  ""
602
  { return rx_gen_move_template (operands, false); }
603
  [(set_attr "length" "2,6")
604
   (set_attr "timings" "11,12")]
605
)
606
 
607
(define_insn "zero_extendsi2"
608
  [(set (match_operand:SI 0 "register_operand"     "=r,r")
609
        (zero_extend:SI (match_operand:small_int_modes
610
                          1 "nonimmediate_operand"  "r,m")))]
611
  ""
612
  { return rx_gen_move_template (operands, true); }
613
  [(set_attr "length" "2,4")
614
   (set_attr "timings" "11,12")]
615
)
616
 
617
(define_insn "stack_push"
618
  [(set (reg:SI SP_REG)
619
        (minus:SI (reg:SI SP_REG)
620
                  (const_int 4)))
621
   (set (mem:SI (reg:SI SP_REG))
622
        (match_operand:SI 0 "register_operand" "r"))]
623
  ""
624
  "push.l\t%0"
625
  [(set_attr "length" "2")]
626
)
627
 
628
(define_insn "stack_pushm"
629
  [(match_parallel 1 "rx_store_multiple_vector"
630
     [(set (reg:SI SP_REG)
631
           (minus:SI (reg:SI SP_REG)
632
                     (match_operand:SI 0 "const_int_operand" "n")))])]
633
  "reload_completed"
634
  {
635
    rx_emit_stack_pushm (operands);
636
    return "";
637
  }
638
  [(set_attr "length" "2")
639
   (set_attr "timings" "44")] ;; The timing is a guesstimate average timing.
640
)
641
 
642
(define_insn "stack_pop"
643
  [(set (match_operand:SI 0 "register_operand" "=r")
644
        (mem:SI (reg:SI SP_REG)))
645
   (set (reg:SI SP_REG)
646
        (plus:SI (reg:SI SP_REG)
647
                 (const_int 4)))]
648
  ""
649
  "pop\t%0"
650
  [(set_attr "length" "2")
651
   (set_attr "timings" "12")]
652
)
653
 
654
(define_insn "stack_popm"
655
  [(match_parallel 1 "rx_load_multiple_vector"
656
     [(set (reg:SI SP_REG)
657
           (plus:SI (reg:SI SP_REG)
658
                    (match_operand:SI 0 "const_int_operand" "n")))])]
659
  "reload_completed"
660
  {
661
    rx_emit_stack_popm (operands, true);
662
    return "";
663
  }
664
  [(set_attr "length" "2")
665
   (set_attr "timings" "45")] ;; The timing is a guesstimate average timing.
666
)
667
 
668
(define_insn_and_split "cstoresi4"
669
  [(set (match_operand:SI   0 "register_operand" "=r")
670
        (match_operator:SI  1 "comparison_operator"
671
          [(match_operand:SI 2 "register_operand"  "r")
672
           (match_operand:SI 3 "rx_source_operand" "riQ")]))
673
   (clobber (reg:CC CC_REG))]
674
  ""
675
  "#"
676
  "reload_completed"
677
  [(const_int 0)]
678
{
679
  rtx flags, x;
680
 
681
  flags = gen_rtx_REG (CCmode, CC_REG);
682
  x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
683
  x = gen_rtx_SET (VOIDmode, flags, x);
684
  emit_insn (x);
685
 
686
  x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
687
  x = gen_rtx_SET (VOIDmode, operands[0], x);
688
  emit_insn (x);
689
  DONE;
690
})
691
 
692
(define_insn "*sccc"
693
  [(set (match_operand:SI 0 "register_operand" "=r")
694
        (match_operator:SI 1 "comparison_operator"
695
          [(reg CC_REG) (const_int 0)]))]
696
  "reload_completed"
697
  "sc%B1.L\t%0"
698
  [(set_attr "length" "3")]
699
)
700
 
701
(define_insn_and_split "cstoresf4"
702
  [(set (match_operand:SI 0 "register_operand" "=r")
703
        (match_operator:SI 1 "rx_fp_comparison_operator"
704
         [(match_operand:SF 2 "register_operand" "r")
705
          (match_operand:SF 3 "rx_source_operand" "rFQ")]))]
706
  "ALLOW_RX_FPU_INSNS"
707
  "#"
708
  "reload_completed"
709
  [(const_int 0)]
710
{
711
  rtx flags, x;
712
 
713
  flags = gen_rtx_REG (CC_Fmode, CC_REG);
714
  x = gen_rtx_COMPARE (CC_Fmode, operands[2], operands[3]);
715
  x = gen_rtx_SET (VOIDmode, flags, x);
716
  emit_insn (x);
717
 
718
  x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
719
  x = gen_rtx_SET (VOIDmode, operands[0], x);
720
  emit_insn (x);
721
  DONE;
722
})
723
 
724
(define_expand "movsicc"
725
  [(parallel
726
    [(set (match_operand:SI                  0 "register_operand")
727
          (if_then_else:SI (match_operand:SI 1 "comparison_operator")
728
                           (match_operand:SI 2 "nonmemory_operand")
729
                           (match_operand:SI 3 "nonmemory_operand")))
730
     (clobber (reg:CC CC_REG))])]
731
  ""
732
{
733
  /* One operand must be a constant or a register, the other must be a register.  */
734
  if (   ! CONSTANT_P (operands[2])
735
      && ! CONSTANT_P (operands[3])
736
      && ! (REG_P (operands[2]) && REG_P (operands[3])))
737
    FAIL;
738
})
739
 
740
(define_insn_and_split "*movsicc"
741
  [(set (match_operand:SI     0 "register_operand" "=r,r,r")
742
        (if_then_else:SI
743
          (match_operator     5 "comparison_operator"
744
           [(match_operand:SI 3 "register_operand"  "r,r,r")
745
            (match_operand:SI 4 "rx_source_operand" "riQ,riQ,riQ")])
746
          (match_operand:SI   1 "nonmemory_operand" "i,ri,r")
747
          (match_operand:SI   2 "nonmemory_operand" "ri,i,r")))
748
   (clobber (reg:CC CC_REG))]
749
  "(CONSTANT_P (operands[1]) || CONSTANT_P (operands[2]))
750
    || (REG_P (operands[1]) && REG_P (operands[2]))"
751
  "#"
752
  "&& reload_completed"
753
  [(const_int 0)]
754
{
755
  rtx x, flags, op0, op1, op2;
756
  enum rtx_code cmp_code;
757
 
758
  flags = gen_rtx_REG (CCmode, CC_REG);
759
  x = gen_rtx_COMPARE (CCmode, operands[3], operands[4]);
760
  emit_insn (gen_rtx_SET (VOIDmode, flags, x));
761
 
762
  cmp_code = GET_CODE (operands[5]);
763
  op0 = operands[0];
764
  op1 = operands[1];
765
  op2 = operands[2];
766
 
767
  /* If OP2 is the constant, reverse the sense of the move.
768
     Likewise if both operands are registers but OP1 == OP0.  */
769
  if ((! CONSTANT_P (operands[1]) && CONSTANT_P (operands[2]))
770
      || (REG_P (operands[1]) && REG_P (operands[2])
771
          && rtx_equal_p (op0, op1)))
772
    {
773
      x = op1, op1 = op2, op2 = x;
774
      cmp_code = reverse_condition (cmp_code);
775
    }
776
 
777
  /* If OP2 does not match the output, copy it into place.  We have allowed
778
     these alternatives so that the destination can legitimately be one of
779
     the comparison operands without increasing register pressure.  */
780
  if (! rtx_equal_p (op0, op2))
781
    emit_move_insn (op0, op2);
782
 
783
  x = gen_rtx_fmt_ee (cmp_code, VOIDmode, flags, const0_rtx);
784
  x = gen_rtx_IF_THEN_ELSE (SImode, x, op1, op0);
785
  emit_insn (gen_rtx_SET (VOIDmode, op0, x));
786
  DONE;
787
})
788
 
789
(define_insn "*stcc"
790
  [(set (match_operand:SI 0 "register_operand" "+r,r,r,r")
791
        (if_then_else:SI
792
          (match_operator 2 "rx_z_comparison_operator"
793
            [(reg CC_REG) (const_int 0)])
794
          (match_operand:SI 1 "immediate_operand" "Sint08,Sint16,Sint24,i")
795
          (match_dup 0)))]
796
  "reload_completed
797
   && ((GET_CODE (operands[2]) == EQ) || (GET_CODE (operands[2]) == NE))"
798
  {
799
    if (GET_CODE (operands[2]) == EQ)
800
      return "stz\t%1, %0";
801
    else
802
     return "stnz\t%1, %0";
803
  }
804
  [(set_attr "length" "4,5,6,7")]
805
)
806
 
807
(define_insn "*stcc_reg"
808
  [(set (match_operand:SI 0 "register_operand" "+r,r,r,r,r,r")
809
        (if_then_else:SI
810
          (match_operator 2 "comparison_operator"
811
            [(reg CC_REG) (const_int 0)])
812
          (match_operand:SI 1 "nonmemory_operand"
813
                              "r,Uint04,Sint08,Sint16,Sint24,i")
814
          (match_dup 0)))]
815
  "reload_completed"
816
  {
817
    PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2])));
818
    return "b%B2 1f\n\tmov %1, %0\n1:";
819
  }
820
  [(set_attr "length" "3,3,4,5,6,7")]
821
)
822
 
823
;; Arithmetic Instructions
824
 
825
(define_insn "abssi2"
826
  [(set (match_operand:SI         0 "register_operand" "=r,r")
827
        (abs:SI (match_operand:SI 1 "register_operand"  "0,r")))
828
   (clobber (reg:CC CC_REG))]
829
  ""
830
  "@
831
  abs\t%0
832
  abs\t%1, %0"
833
  [(set_attr "length" "2,3")]
834
)
835
 
836
(define_insn "*abssi2_flags"
837
  [(set (match_operand:SI         0 "register_operand" "=r,r")
838
        (abs:SI (match_operand:SI 1 "register_operand"  "0,r")))
839
   (set (reg CC_REG)
840
        (compare (abs:SI (match_dup 1))
841
                 (const_int 0)))]
842
  ;; Note - although the ABS instruction does set the O bit in the processor
843
  ;; status word, it does not do so in a way that is comparable with the CMP
844
  ;; instruction.  Hence we use CC_ZSmode rather than CC_ZSOmode.
845
  "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
846
  "@
847
  abs\t%0
848
  abs\t%1, %0"
849
  [(set_attr "length" "2,3")]
850
)
851
 
852
(define_expand "addsi3"
853
  [(parallel [(set (match_operand:SI          0 "register_operand"  "")
854
        (plus:SI (match_operand:SI 1 "register_operand"  "")
855
                 (match_operand:SI 2 "rx_source_operand" "")))
856
    (clobber (reg:CC CC_REG))])]
857
  ""
858
  "
859
      operands[0] = rx_maybe_pidify_operand (operands[0], 1);
860
      operands[1] = rx_maybe_pidify_operand (operands[1], 1);
861
      operands[2] = rx_maybe_pidify_operand (operands[2], 1);
862
  "
863
)
864
 
865
(define_insn "addsi3_internal"
866
  [(set (match_operand:SI          0 "register_operand"  "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
867
        (plus:SI (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
868
                 (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
869
   (clobber (reg:CC CC_REG))]
870
  ""
871
  "@
872
  add\t%2, %0
873
  add\t%2, %0
874
  sub\t%N2, %0
875
  add\t%2, %0
876
  add\t%2, %0
877
  add\t%2, %0
878
  add\t%2, %0
879
  add\t%1, %0
880
  add\t%2, %1, %0
881
  add\t%2, %1, %0
882
  add\t%2, %1, %0
883
  add\t%2, %1, %0
884
  add\t%2, %1, %0
885
  add\t%Q2, %0"
886
  [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
887
   (set_attr "length"   "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
888
)
889
 
890
(define_insn "*addsi3_flags"
891
  [(set (match_operand:SI          0 "register_operand"  "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
892
        (plus:SI (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
893
                 (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
894
   (set (reg CC_REG)
895
        (compare (plus:SI (match_dup 1) (match_dup 2))
896
                 (const_int 0)))]
897
  "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
898
  "@
899
  add\t%2, %0
900
  add\t%2, %0
901
  sub\t%N2, %0
902
  add\t%2, %0
903
  add\t%2, %0
904
  add\t%2, %0
905
  add\t%2, %0
906
  add\t%1, %0
907
  add\t%2, %1, %0
908
  add\t%2, %1, %0
909
  add\t%2, %1, %0
910
  add\t%2, %1, %0
911
  add\t%2, %1, %0
912
  add\t%Q2, %0"
913
  [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
914
   (set_attr "length"   "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
915
)
916
 
917
;; A helper to expand the above with the CC_MODE filled in.
918
(define_expand "addsi3_flags"
919
  [(parallel [(set (match_operand:SI 0 "register_operand")
920
                   (plus:SI (match_operand:SI 1 "register_operand")
921
                            (match_operand:SI 2 "rx_source_operand")))
922
              (set (reg:CC_ZSC CC_REG)
923
                   (compare:CC_ZSC (plus:SI (match_dup 1) (match_dup 2))
924
                                   (const_int 0)))])]
925
)
926
 
927
(define_insn "adc_internal"
928
  [(set (match_operand:SI     0 "register_operand"  "=r,r,r,r,r,r")
929
        (plus:SI
930
          (plus:SI
931
            (ltu:SI (reg:CC CC_REG) (const_int 0))
932
            (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0"))
933
          (match_operand:SI   2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
934
    (clobber (reg:CC CC_REG))]
935
  "reload_completed"
936
  "adc\t%2, %0"
937
  [(set_attr "timings" "11,11,11,11,11,33")
938
   (set_attr "length"   "3,4,5,6,7,6")]
939
)
940
 
941
(define_insn "*adc_flags"
942
  [(set (match_operand:SI     0 "register_operand"  "=r,r,r,r,r,r")
943
        (plus:SI
944
          (plus:SI
945
            (ltu:SI (reg:CC CC_REG) (const_int 0))
946
            (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0"))
947
          (match_operand:SI   2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
948
   (set (reg CC_REG)
949
        (compare
950
          (plus:SI
951
            (plus:SI
952
              (ltu:SI (reg:CC CC_REG) (const_int 0))
953
              (match_dup 1))
954
            (match_dup 2))
955
          (const_int 0)))]
956
  "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
957
  "adc\t%2, %0"
958
  [(set_attr "timings" "11,11,11,11,11,33")
959
   (set_attr "length"   "3,4,5,6,7,6")]
960
)
961
 
962
;; Peepholes to match:
963
;;   (set (reg A) (reg B))
964
;;   (set (CC) (compare:CC (reg A/reg B) (const_int 0)))
965
;; and replace them with the addsi3_flags pattern, using an add
966
;; of zero to copy the register and set the condition code bits.
967
(define_peephole2
968
  [(set (match_operand:SI 0 "register_operand")
969
        (match_operand:SI 1 "register_operand"))
970
   (set (reg:CC CC_REG)
971
        (compare:CC (match_dup 0)
972
                    (const_int 0)))]
973
  ""
974
  [(parallel [(set (match_dup 0)
975
                   (plus:SI (match_dup 1) (const_int 0)))
976
              (set (reg:CC_ZSC CC_REG)
977
                   (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
978
                                   (const_int 0)))])]
979
)
980
 
981
(define_peephole2
982
  [(set (match_operand:SI 0 "register_operand")
983
        (match_operand:SI 1 "register_operand"))
984
   (set (reg:CC CC_REG)
985
        (compare:CC (match_dup 1)
986
                    (const_int 0)))]
987
  ""
988
  [(parallel [(set (match_dup 0)
989
                   (plus:SI (match_dup 1) (const_int 0)))
990
              (set (reg:CC_ZSC CC_REG)
991
                   (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
992
                                   (const_int 0)))])]
993
)
994
 
995
(define_expand "adddi3"
996
  [(set (match_operand:DI          0 "register_operand")
997
        (plus:DI (match_operand:DI 1 "register_operand")
998
                 (match_operand:DI 2 "rx_source_operand")))]
999
  ""
1000
{
1001
  rtx op0l, op0h, op1l, op1h, op2l, op2h;
1002
 
1003
  op0l = gen_lowpart (SImode, operands[0]);
1004
  op1l = gen_lowpart (SImode, operands[1]);
1005
  op2l = gen_lowpart (SImode, operands[2]);
1006
  op0h = gen_highpart (SImode, operands[0]);
1007
  op1h = gen_highpart (SImode, operands[1]);
1008
  op2h = gen_highpart_mode (SImode, DImode, operands[2]);
1009
 
1010
  emit_insn (gen_adddi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
1011
  DONE;
1012
})
1013
 
1014
(define_insn_and_split "adddi3_internal"
1015
  [(set (match_operand:SI          0 "register_operand"  "=&r")
1016
        (plus:SI (match_operand:SI 2 "register_operand"  "r")
1017
                 (match_operand:SI 3 "rx_source_operand" "riQ")))
1018
   (set (match_operand:SI          1 "register_operand"  "=r")
1019
        (plus:SI
1020
          (plus:SI
1021
            (ltu:SI (plus:SI (match_dup 2) (match_dup 3)) (match_dup 2))
1022
            (match_operand:SI      4 "register_operand"  "%1"))
1023
          (match_operand:SI        5 "rx_source_operand" "riQ")))
1024
   (clobber (match_scratch:SI      6                     "=&r"))
1025
   (clobber (reg:CC CC_REG))]
1026
  ""
1027
  "#"
1028
  "reload_completed"
1029
  [(const_int 0)]
1030
{
1031
  rtx op0l = operands[0];
1032
  rtx op0h = operands[1];
1033
  rtx op1l = operands[2];
1034
  rtx op2l = operands[3];
1035
  rtx op1h = operands[4];
1036
  rtx op2h = operands[5];
1037
  rtx scratch = operands[6];
1038
  rtx x;
1039
 
1040
  if (reg_overlap_mentioned_p (op0l, op1h))
1041
    {
1042
      emit_move_insn (scratch, op0l);
1043
      op1h = scratch;
1044
      if (reg_overlap_mentioned_p (op0l, op2h))
1045
        op2h = scratch;
1046
    }
1047
  else if (reg_overlap_mentioned_p (op0l, op2h))
1048
    {
1049
      emit_move_insn (scratch, op0l);
1050
      op2h = scratch;
1051
    }
1052
 
1053
  if (rtx_equal_p (op0l, op1l))
1054
    ;
1055
  /* It is preferable that op0l == op1l...  */
1056
  else if (rtx_equal_p (op0l, op2l))
1057
    x = op1l, op1l = op2l, op2l = x;
1058
  /* ... but it is only a requirement if op2l == MEM.  */
1059
  else if (MEM_P (op2l))
1060
    {
1061
      /* Let's hope that we still have a scratch register free.  */
1062
      gcc_assert (op1h != scratch);
1063
      emit_move_insn (scratch, op2l);
1064
      op2l = scratch;
1065
    }
1066
 
1067
  emit_insn (gen_addsi3_flags (op0l, op1l, op2l));
1068
 
1069
  if (rtx_equal_p (op0h, op1h))
1070
    ;
1071
  else if (rtx_equal_p (op0h, op2h))
1072
    x = op1h, op1h = op2h, op2h = x;
1073
  else
1074
    {
1075
      emit_move_insn (op0h, op1h);
1076
      op1h = op0h;
1077
    }
1078
  emit_insn (gen_adc_internal (op0h, op1h, op2h));
1079
  DONE;
1080
})
1081
 
1082
(define_insn "andsi3"
1083
  [(set (match_operand:SI         0 "register_operand"  "=r,r,r,r,r,r,r,r,r")
1084
        (and:SI (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0,r,r,0")
1085
                (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1086
   (clobber (reg:CC CC_REG))]
1087
  ""
1088
  "@
1089
  and\t%2, %0
1090
  and\t%2, %0
1091
  and\t%2, %0
1092
  and\t%2, %0
1093
  and\t%2, %0
1094
  and\t%2, %0
1095
  and\t%1, %0
1096
  and\t%2, %1, %0
1097
  and\t%Q2, %0"
1098
  [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1099
   (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1100
)
1101
 
1102
(define_insn "*andsi3_flags"
1103
  [(set (match_operand:SI         0 "register_operand"  "=r,r,r,r,r,r,r,r,r")
1104
        (and:SI (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0,r,r,0")
1105
                (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1106
   (set (reg CC_REG)
1107
        (compare (and:SI (match_dup 1) (match_dup 2))
1108
                 (const_int 0)))]
1109
  "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1110
  "@
1111
  and\t%2, %0
1112
  and\t%2, %0
1113
  and\t%2, %0
1114
  and\t%2, %0
1115
  and\t%2, %0
1116
  and\t%2, %0
1117
  and\t%1, %0
1118
  and\t%2, %1, %0
1119
  and\t%Q2, %0"
1120
  [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1121
   (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1122
)
1123
 
1124
;; Byte swap (single 32-bit value).
1125
(define_insn "bswapsi2"
1126
  [(set (match_operand:SI           0 "register_operand" "=r")
1127
        (bswap:SI (match_operand:SI 1 "register_operand"  "r")))]
1128
  ""
1129
  "revl\t%1, %0"
1130
  [(set_attr "length" "3")]
1131
)
1132
 
1133
;; Byte swap (single 16-bit value).  Note - we ignore the swapping of the high 16-bits.
1134
(define_insn "bswaphi2"
1135
  [(set (match_operand:HI           0 "register_operand" "=r")
1136
        (bswap:HI (match_operand:HI 1 "register_operand"  "r")))]
1137
  ""
1138
  "revw\t%1, %0"
1139
  [(set_attr "length" "3")]
1140
)
1141
 
1142
(define_insn "divsi3"
1143
  [(set (match_operand:SI         0 "register_operand" "=r,r,r,r,r,r")
1144
        (div:SI (match_operand:SI 1 "register_operand"  "0,0,0,0,0,0")
1145
                (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
1146
   (clobber (reg:CC CC_REG))]
1147
  ""
1148
  "div\t%Q2, %0"
1149
  [(set_attr "timings" "1111") ;; Strictly speaking the timing should be
1150
                               ;; 2222, but that is a worst case sceanario.
1151
   (set_attr "length" "3,4,5,6,7,6")]
1152
)
1153
 
1154
(define_insn "udivsi3"
1155
  [(set (match_operand:SI          0 "register_operand"  "=r,r,r,r,r,r")
1156
        (udiv:SI (match_operand:SI 1 "register_operand"   "0,0,0,0,0,0")
1157
                 (match_operand:SI 2 "rx_source_operand"  "r,Sint08,Sint16,Sint24,i,Q")))
1158
   (clobber (reg:CC CC_REG))]
1159
  ""
1160
  "divu\t%Q2, %0"
1161
  [(set_attr "timings" "1010") ;; Strictly speaking the timing should be
1162
                               ;; 2020, but that is a worst case sceanario.
1163
   (set_attr "length" "3,4,5,6,7,6")]
1164
)
1165
 
1166
;; Note - these patterns are suppressed in big-endian mode because they
1167
;; generate a little endian result.  ie the most significant word of the
1168
;; result is placed in the higher numbered register of the destination
1169
;; register pair.
1170
 
1171
(define_insn "mulsidi3"
1172
  [(set (match_operand:DI          0 "register_operand"  "=r,r,r,r,r,r")
1173
        (mult:DI (sign_extend:DI (match_operand:SI
1174
                                  1 "register_operand"  "%0,0,0,0,0,0"))
1175
                 (sign_extend:DI (match_operand:SI
1176
                                  2 "rx_source_operand"
1177
                                  "r,Sint08,Sint16,Sint24,i,Q"))))]
1178
  "! TARGET_BIG_ENDIAN_DATA"
1179
  "emul\t%Q2, %0"
1180
  [(set_attr "length" "3,4,5,6,7,6")
1181
   (set_attr "timings" "22,22,22,22,22,44")]
1182
)
1183
 
1184
;; See comment for mulsidi3.
1185
;; Note - the zero_extends are to distinguish this pattern from the
1186
;; mulsidi3 pattern.  Immediate mode addressing is not supported
1187
;; because gcc cannot handle the expression: (zero_extend (const_int)).
1188
(define_insn "umulsidi3"
1189
  [(set (match_operand:DI                          0 "register_operand"  "=r,r")
1190
        (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"  "%0,0"))
1191
                 (zero_extend:DI (match_operand:SI 2 "rx_compare_operand" "r,Q"))))]
1192
  "! TARGET_BIG_ENDIAN_DATA"
1193
  "emulu\t%Q2, %0"
1194
  [(set_attr "length" "3,6")
1195
   (set_attr "timings" "22,44")]
1196
)
1197
 
1198
(define_insn "smaxsi3"
1199
  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1200
        (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1201
                 (match_operand:SI 2 "rx_source_operand"
1202
                                   "r,Sint08,Sint16,Sint24,i,Q")))]
1203
  ""
1204
  "max\t%Q2, %0"
1205
  [(set_attr "length" "3,4,5,6,7,6")
1206
   (set_attr "timings" "11,11,11,11,11,33")]
1207
)
1208
 
1209
(define_insn "sminsi3"
1210
  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1211
        (smin:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1212
                 (match_operand:SI 2 "rx_source_operand"
1213
                                   "r,Sint08,Sint16,Sint24,i,Q")))]
1214
  ""
1215
  "min\t%Q2, %0"
1216
  [(set_attr "length"  "3,4,5,6,7,6")
1217
   (set_attr "timings" "11,11,11,11,11,33")]
1218
)
1219
 
1220
(define_insn "umax3_u"
1221
  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1222
        (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1223
                 (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1224
                                                                "r,Sint08,Sint16,Sint24,i,Q"))))]
1225
  ""
1226
  "max\t%R2, %0"
1227
  [(set_attr "length"  "3,4,5,6,7,6")
1228
   (set_attr "timings" "11,11,11,11,11,33")]
1229
)
1230
 
1231
(define_insn "umin3_ur"
1232
  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1233
        (smin:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1234
                                                                "r,Sint08,Sint16,Sint24,i,Q"))
1235
                 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))]
1236
  ""
1237
  "min\t%R2, %0"
1238
  [(set_attr "length"  "3,4,5,6,7,6")
1239
   (set_attr "timings" "11,11,11,11,11,33")]
1240
)
1241
 
1242
(define_insn "umax3_ur"
1243
  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1244
        (smax:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1245
                                                                "r,Sint08,Sint16,Sint24,i,Q"))
1246
                 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))]
1247
  ""
1248
  "max\t%R2, %0"
1249
  [(set_attr "length"  "3,4,5,6,7,6")
1250
   (set_attr "timings" "11,11,11,11,11,33")]
1251
)
1252
 
1253
(define_expand "umax3"
1254
  [(set (match_dup 4)
1255
        (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
1256
   (set (match_dup 3)
1257
        (smax:SI (match_dup 4)
1258
                 (match_operand:small_int_modes 2 "rx_source_operand"
1259
                                                "r,Sint08,Sint16,Sint24,i,Q")))
1260
   (set (match_operand:small_int_modes          0 "register_operand" "=r,r,r,r,r,r")
1261
        (match_dup 6))
1262
   ]
1263
  ""
1264
  "operands[3] = gen_reg_rtx (SImode);
1265
   operands[4] = gen_reg_rtx (SImode);
1266
   operands[5] = gen_reg_rtx (SImode);
1267
   operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3],
1268
     TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0);
1269
   if (GET_CODE (operands[2]) != CONST_INT)
1270
     {
1271
       emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
1272
       operands[2] = operands[5];
1273
     }
1274
  "
1275
)
1276
 
1277
(define_expand "umin3"
1278
  [(set (match_dup 4)
1279
        (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
1280
   (set (match_dup 3)
1281
        (smin:SI (match_dup 4)
1282
                 (match_operand:small_int_modes 2 "rx_source_operand"
1283
                                                "r,Sint08,Sint16,Sint24,i,Q")))
1284
   (set (match_operand:small_int_modes          0 "register_operand" "=r,r,r,r,r,r")
1285
        (match_dup 6))
1286
   ]
1287
  ""
1288
  "operands[3] = gen_reg_rtx (SImode);
1289
   operands[4] = gen_reg_rtx (SImode);
1290
   operands[5] = gen_reg_rtx (SImode);
1291
   operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3],
1292
     TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0);
1293
   if (GET_CODE (operands[2]) != CONST_INT)
1294
     {
1295
       emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
1296
       operands[2] = operands[5];
1297
     }
1298
   "
1299
)
1300
 
1301
(define_insn "mulsi3"
1302
  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1303
        (mult:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r")
1304
                 (match_operand:SI 2 "rx_source_operand"
1305
                                   "r,Uint04,Sint08,Sint16,Sint24,i,Q,0,r")))]
1306
  ""
1307
  "@
1308
  mul\t%2, %0
1309
  mul\t%2, %0
1310
  mul\t%2, %0
1311
  mul\t%2, %0
1312
  mul\t%2, %0
1313
  mul\t%Q2, %0
1314
  mul\t%Q2, %0
1315
  mul\t%1, %0
1316
  mul\t%2, %1, %0"
1317
  [(set_attr "length"  "2,2,3,4,5,6,5,2,3")
1318
   (set_attr "timings" "11,11,11,11,11,11,33,11,11")]
1319
)
1320
 
1321
(define_insn "negsi2"
1322
  [(set (match_operand:SI         0 "register_operand" "=r,r")
1323
        (neg:SI (match_operand:SI 1 "register_operand"  "0,r")))
1324
   (clobber (reg:CC CC_REG))]
1325
  ""
1326
  "@
1327
  neg\t%0
1328
  neg\t%1, %0"
1329
  [(set_attr "length" "2,3")]
1330
)
1331
 
1332
;; Note that the O and C flags are not set as per a normal compare,
1333
;; and thus are unusable in that context.
1334
(define_insn "*negsi2_flags"
1335
  [(set (match_operand:SI         0 "register_operand" "=r,r")
1336
        (neg:SI (match_operand:SI 1 "register_operand"  "0,r")))
1337
   (set (reg CC_REG)
1338
        (compare (neg:SI (match_dup 1))
1339
                 (const_int 0)))]
1340
  "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1341
  "@
1342
  neg\t%0
1343
  neg\t%1, %0"
1344
  [(set_attr "length" "2,3")]
1345
)
1346
 
1347
(define_insn "one_cmplsi2"
1348
  [(set (match_operand:SI         0 "register_operand" "=r,r")
1349
        (not:SI (match_operand:SI 1 "register_operand"  "0,r")))
1350
   (clobber (reg:CC CC_REG))]
1351
  ""
1352
  "@
1353
  not\t%0
1354
  not\t%1, %0"
1355
  [(set_attr "length" "2,3")]
1356
)
1357
 
1358
(define_insn "*one_cmplsi2_flags"
1359
  [(set (match_operand:SI         0 "register_operand" "=r,r")
1360
        (not:SI (match_operand:SI 1 "register_operand"  "0,r")))
1361
   (set (reg CC_REG)
1362
        (compare (not:SI (match_dup 1))
1363
                 (const_int 0)))]
1364
  "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1365
  "@
1366
  not\t%0
1367
  not\t%1, %0"
1368
  [(set_attr "length" "2,3")]
1369
)
1370
 
1371
(define_insn "iorsi3"
1372
  [(set (match_operand:SI         0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1373
        (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1374
                (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1375
   (clobber (reg:CC CC_REG))]
1376
  ""
1377
  "@
1378
  or\t%2, %0
1379
  or\t%2, %0
1380
  or\t%2, %0
1381
  or\t%2, %0
1382
  or\t%2, %0
1383
  or\t%Q2, %0
1384
  or\t%1, %0
1385
  or\t%2, %1, %0
1386
  or\t%Q2, %0"
1387
  [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1388
   (set_attr "length"  "2,2,3,4,5,6,2,3,5")]
1389
)
1390
 
1391
(define_insn "*iorsi3_flags"
1392
  [(set (match_operand:SI         0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1393
        (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1394
                (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1395
   (set (reg CC_REG)
1396
        (compare (ior:SI (match_dup 1) (match_dup 2))
1397
                 (const_int 0)))]
1398
  "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1399
  "@
1400
  or\t%2, %0
1401
  or\t%2, %0
1402
  or\t%2, %0
1403
  or\t%2, %0
1404
  or\t%2, %0
1405
  or\t%Q2, %0
1406
  or\t%1, %0
1407
  or\t%2, %1, %0
1408
  or\t%Q2, %0"
1409
  [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1410
   (set_attr "length"  "2,2,3,4,5,6,2,3,5")]
1411
)
1412
 
1413
(define_insn "rotlsi3"
1414
  [(set (match_operand:SI            0 "register_operand" "=r")
1415
        (rotate:SI (match_operand:SI 1 "register_operand"  "0")
1416
                   (match_operand:SI 2 "rx_shift_operand" "rn")))
1417
   (clobber (reg:CC CC_REG))]
1418
  ""
1419
  "rotl\t%2, %0"
1420
  [(set_attr "length" "3")]
1421
)
1422
 
1423
(define_insn "*rotlsi3_flags"
1424
  [(set (match_operand:SI            0 "register_operand" "=r")
1425
        (rotate:SI (match_operand:SI 1 "register_operand"  "0")
1426
                   (match_operand:SI 2 "rx_shift_operand" "rn")))
1427
   (set (reg CC_REG)
1428
        (compare (rotate:SI (match_dup 1) (match_dup 2))
1429
                 (const_int 0)))]
1430
  "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1431
  "rotl\t%2, %0"
1432
  [(set_attr "length" "3")]
1433
)
1434
 
1435
(define_insn "rotrsi3"
1436
  [(set (match_operand:SI              0 "register_operand" "=r")
1437
        (rotatert:SI (match_operand:SI 1 "register_operand"  "0")
1438
                     (match_operand:SI 2 "rx_shift_operand" "rn")))
1439
   (clobber (reg:CC CC_REG))]
1440
  ""
1441
  "rotr\t%2, %0"
1442
  [(set_attr "length" "3")]
1443
)
1444
 
1445
(define_insn "*rotrsi3_flags"
1446
  [(set (match_operand:SI              0 "register_operand" "=r")
1447
        (rotatert:SI (match_operand:SI 1 "register_operand"  "0")
1448
                     (match_operand:SI 2 "rx_shift_operand" "rn")))
1449
   (set (reg CC_REG)
1450
        (compare (rotatert:SI (match_dup 1) (match_dup 2))
1451
                 (const_int 0)))]
1452
  "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1453
  "rotr\t%2, %0"
1454
  [(set_attr "length" "3")]
1455
)
1456
 
1457
(define_insn "ashrsi3"
1458
  [(set (match_operand:SI              0 "register_operand" "=r,r,r")
1459
        (ashiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1460
                     (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))
1461
   (clobber (reg:CC CC_REG))]
1462
  ""
1463
  "@
1464
  shar\t%2, %0
1465
  shar\t%2, %0
1466
  shar\t%2, %1, %0"
1467
  [(set_attr "length" "3,2,3")]
1468
)
1469
 
1470
(define_insn "*ashrsi3_flags"
1471
  [(set (match_operand:SI              0 "register_operand" "=r,r,r")
1472
        (ashiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1473
                     (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))
1474
   (set (reg CC_REG)
1475
        (compare (ashiftrt:SI (match_dup 1) (match_dup 2))
1476
                 (const_int 0)))]
1477
  "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1478
  "@
1479
  shar\t%2, %0
1480
  shar\t%2, %0
1481
  shar\t%2, %1, %0"
1482
  [(set_attr "length" "3,2,3")]
1483
)
1484
 
1485
(define_insn "lshrsi3"
1486
  [(set (match_operand:SI              0 "register_operand" "=r,r,r")
1487
        (lshiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1488
                     (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))
1489
   (clobber (reg:CC CC_REG))]
1490
  ""
1491
  "@
1492
  shlr\t%2, %0
1493
  shlr\t%2, %0
1494
  shlr\t%2, %1, %0"
1495
  [(set_attr "length" "3,2,3")]
1496
)
1497
 
1498
(define_insn "*lshrsi3_flags"
1499
  [(set (match_operand:SI              0 "register_operand" "=r,r,r")
1500
        (lshiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1501
                     (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))
1502
   (set (reg CC_REG)
1503
        (compare (lshiftrt:SI (match_dup 1) (match_dup 2))
1504
                 (const_int 0)))]
1505
  "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1506
  "@
1507
  shlr\t%2, %0
1508
  shlr\t%2, %0
1509
  shlr\t%2, %1, %0"
1510
  [(set_attr "length" "3,2,3")]
1511
)
1512
 
1513
(define_insn "ashlsi3"
1514
  [(set (match_operand:SI            0 "register_operand" "=r,r,r")
1515
        (ashift:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1516
                   (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))
1517
   (clobber (reg:CC CC_REG))]
1518
  ""
1519
  "@
1520
  shll\t%2, %0
1521
  shll\t%2, %0
1522
  shll\t%2, %1, %0"
1523
  [(set_attr "length" "3,2,3")]
1524
)
1525
 
1526
(define_insn "*ashlsi3_flags"
1527
  [(set (match_operand:SI            0 "register_operand" "=r,r,r")
1528
        (ashift:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1529
                   (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))
1530
   (set (reg CC_REG)
1531
        (compare (ashift:SI (match_dup 1) (match_dup 2))
1532
                 (const_int 0)))]
1533
  "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1534
  "@
1535
  shll\t%2, %0
1536
  shll\t%2, %0
1537
  shll\t%2, %1, %0"
1538
  [(set_attr "length" "3,2,3")]
1539
)
1540
 
1541
;; Saturate to 32-bits
1542
(define_insn_and_split "ssaddsi3"
1543
  [(set (match_operand:SI             0 "register_operand" "=r")
1544
        (ss_plus:SI (match_operand:SI 1 "register_operand"  "r")
1545
                    (match_operand:SI 2 "rx_source_operand" "riQ")))
1546
   (clobber (reg:CC CC_REG))]
1547
  ""
1548
  "#"
1549
  "reload_completed"
1550
  [(parallel [(set (match_dup 0)
1551
                   (plus:SI (match_dup 1) (match_dup 2)))
1552
              (set (reg:CC_ZSC CC_REG)
1553
                   (compare:CC_ZSC
1554
                     (plus:SI (match_dup 1) (match_dup 2))
1555
                     (const_int 0)))])
1556
   (set (match_dup 0)
1557
        (unspec:SI [(match_dup 0) (reg:CC CC_REG)]
1558
                   UNSPEC_BUILTIN_SAT))]
1559
   ""
1560
)
1561
 
1562
(define_insn "*sat"
1563
  [(set (match_operand:SI             0 "register_operand" "=r")
1564
        (unspec:SI [(match_operand:SI 1 "register_operand"  "0")
1565
                    (reg:CC CC_REG)]
1566
                   UNSPEC_BUILTIN_SAT))]
1567
  "reload_completed"
1568
  "sat\t%0"
1569
  [(set_attr "length" "2")]
1570
)
1571
 
1572
(define_insn "subsi3"
1573
  [(set (match_operand:SI           0 "register_operand" "=r,r,r,r,r")
1574
        (minus:SI (match_operand:SI 1 "register_operand"  "0,0,0,r,0")
1575
                  (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))
1576
   (clobber (reg:CC CC_REG))]
1577
  ""
1578
  "@
1579
  sub\t%2, %0
1580
  sub\t%2, %0
1581
  add\t%N2, %0
1582
  sub\t%2, %1, %0
1583
  sub\t%Q2, %0"
1584
  [(set_attr "timings" "11,11,11,11,33")
1585
   (set_attr "length" "2,2,6,3,5")]
1586
)
1587
 
1588
;; Note that the O flag is set as if (compare op1 op2) not for
1589
;; what is described here, (compare op0 0).
1590
(define_insn "*subsi3_flags"
1591
  [(set (match_operand:SI           0 "register_operand" "=r,r,r,r,r")
1592
        (minus:SI (match_operand:SI 1 "register_operand"  "0,0,0,r,0")
1593
                  (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))
1594
   (set (reg CC_REG)
1595
        (compare (minus:SI (match_dup 1) (match_dup 2))
1596
                 (const_int 0)))]
1597
  "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
1598
  "@
1599
  sub\t%2, %0
1600
  sub\t%2, %0
1601
  add\t%N2, %0
1602
  sub\t%2, %1, %0
1603
  sub\t%Q2, %0"
1604
  [(set_attr "timings" "11,11,11,11,33")
1605
   (set_attr "length" "2,2,6,3,5")]
1606
)
1607
 
1608
;; A helper to expand the above with the CC_MODE filled in.
1609
(define_expand "subsi3_flags"
1610
  [(parallel [(set (match_operand:SI 0 "register_operand")
1611
                   (minus:SI (match_operand:SI 1 "register_operand")
1612
                             (match_operand:SI 2 "rx_source_operand")))
1613
              (set (reg:CC_ZSC CC_REG)
1614
                   (compare:CC_ZSC (minus:SI (match_dup 1) (match_dup 2))
1615
                                   (const_int 0)))])]
1616
)
1617
 
1618
(define_insn "sbb_internal"
1619
  [(set (match_operand:SI     0 "register_operand"   "=r,r")
1620
        (minus:SI
1621
          (minus:SI
1622
            (match_operand:SI 1 "register_operand"   " 0,0")
1623
            (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1624
          (geu:SI (reg:CC CC_REG) (const_int 0))))
1625
    (clobber (reg:CC CC_REG))]
1626
  "reload_completed"
1627
  "sbb\t%2, %0"
1628
  [(set_attr "timings" "11,33")
1629
   (set_attr "length"  "3,6")]
1630
)
1631
 
1632
(define_insn "*sbb_flags"
1633
  [(set (match_operand:SI     0 "register_operand"   "=r,r")
1634
        (minus:SI
1635
          (minus:SI
1636
            (match_operand:SI 1 "register_operand"   " 0,0")
1637
            (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1638
          (geu:SI (reg:CC CC_REG) (const_int 0))))
1639
   (set (reg CC_REG)
1640
        (compare
1641
          (minus:SI
1642
            (minus:SI (match_dup 1) (match_dup 2))
1643
            (geu:SI (reg:CC CC_REG) (const_int 0)))
1644
          (const_int 0)))]
1645
  "reload_completed"
1646
  "sbb\t%2, %0"
1647
  [(set_attr "timings" "11,33")
1648
   (set_attr "length"  "3,6")]
1649
)
1650
 
1651
(define_expand "subdi3"
1652
  [(set (match_operand:DI           0 "register_operand")
1653
        (minus:DI (match_operand:DI 1 "register_operand")
1654
                  (match_operand:DI 2 "rx_compare_operand")))]
1655
  ""
1656
{
1657
  rtx op0l, op0h, op1l, op1h, op2l, op2h;
1658
 
1659
  op0l = gen_lowpart (SImode, operands[0]);
1660
  op1l = gen_lowpart (SImode, operands[1]);
1661
  op2l = gen_lowpart (SImode, operands[2]);
1662
  op0h = gen_highpart (SImode, operands[0]);
1663
  op1h = gen_highpart (SImode, operands[1]);
1664
  op2h = gen_highpart_mode (SImode, DImode, operands[2]);
1665
 
1666
  emit_insn (gen_subdi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
1667
  DONE;
1668
})
1669
 
1670
(define_insn_and_split "subdi3_internal"
1671
  [(set (match_operand:SI          0 "register_operand"   "=&r,&r")
1672
        (minus:SI (match_operand:SI 2 "register_operand"  "  0, r")
1673
                  (match_operand:SI 3 "rx_compare_operand" "rQ, r")))
1674
   (set (match_operand:SI          1 "register_operand"   "= r, r")
1675
        (minus:SI
1676
          (minus:SI
1677
            (match_operand:SI      4 "register_operand"   "  1, 1")
1678
            (match_operand:SI      5 "rx_compare_operand" " rQ,rQ"))
1679
          (geu:SI (match_dup 2) (match_dup 3))))
1680
   (clobber (reg:CC CC_REG))]
1681
  ""
1682
  "#"
1683
  "reload_completed"
1684
  [(const_int 0)]
1685
{
1686
  emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3]));
1687
  emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5]));
1688
  DONE;
1689
})
1690
 
1691
(define_insn "xorsi3"
1692
  [(set (match_operand:SI         0 "register_operand" "=r,r,r,r,r,r")
1693
        (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1694
                (match_operand:SI 2 "rx_source_operand"
1695
                                  "r,Sint08,Sint16,Sint24,i,Q")))
1696
   (clobber (reg:CC CC_REG))]
1697
  ""
1698
  "xor\t%Q2, %0"
1699
  [(set_attr "timings" "11,11,11,11,11,33")
1700
   (set_attr "length" "3,4,5,6,7,6")]
1701
)
1702
 
1703
(define_insn "*xorsi3_flags"
1704
  [(set (match_operand:SI         0 "register_operand" "=r,r,r,r,r,r")
1705
        (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1706
                (match_operand:SI 2 "rx_source_operand"
1707
                                  "r,Sint08,Sint16,Sint24,i,Q")))
1708
   (set (reg CC_REG)
1709
        (compare (xor:SI (match_dup 1) (match_dup 2))
1710
                 (const_int 0)))]
1711
  "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1712
  "xor\t%Q2, %0"
1713
  [(set_attr "timings" "11,11,11,11,11,33")
1714
   (set_attr "length" "3,4,5,6,7,6")]
1715
)
1716
 
1717
;; A set of peepholes to catch extending loads followed by arithmetic operations.
1718
;; We use iterators where possible to reduce the amount of typing and hence the
1719
;; possibilities for typos.
1720
 
1721
(define_code_iterator extend_types [(zero_extend "") (sign_extend "")])
1722
(define_code_attr     letter       [(zero_extend "R") (sign_extend "Q")])
1723
 
1724
(define_code_iterator memex_commutative [(plus "") (and "") (ior "") (xor "")])
1725
(define_code_iterator memex_noncomm     [(div "") (udiv "") (minus "")])
1726
(define_code_iterator memex_nocc        [(smax "") (smin "") (mult "")])
1727
 
1728
(define_code_attr     op                [(plus "add") (and "and") (div "div") (udiv "divu") (smax "max") (smin "min") (mult "mul") (ior "or") (minus "sub") (xor "xor")])
1729
 
1730
(define_peephole2
1731
  [(set (match_operand:SI                               0 "register_operand")
1732
        (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1733
   (parallel [(set (match_operand:SI                    2 "register_operand")
1734
                   (memex_commutative:SI (match_dup 0)
1735
                                         (match_dup 2)))
1736
              (clobber (reg:CC CC_REG))])]
1737
  "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1738
  [(parallel [(set:SI (match_dup 2)
1739
                      (memex_commutative:SI (match_dup 2)
1740
                                            (extend_types:SI (match_dup 1))))
1741
              (clobber (reg:CC CC_REG))])]
1742
)
1743
 
1744
(define_peephole2
1745
  [(set (match_operand:SI                               0 "register_operand")
1746
        (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1747
   (parallel [(set (match_operand:SI                    2 "register_operand")
1748
                   (memex_commutative:SI (match_dup 2)
1749
                                         (match_dup 0)))
1750
              (clobber (reg:CC CC_REG))])]
1751
  "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1752
  [(parallel [(set:SI (match_dup 2)
1753
                      (memex_commutative:SI (match_dup 2)
1754
                                            (extend_types:SI (match_dup 1))))
1755
              (clobber (reg:CC CC_REG))])]
1756
)
1757
 
1758
(define_peephole2
1759
  [(set (match_operand:SI                               0 "register_operand")
1760
        (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1761
   (parallel [(set (match_operand:SI                    2 "register_operand")
1762
                   (memex_noncomm:SI (match_dup 2)
1763
                                     (match_dup 0)))
1764
              (clobber (reg:CC CC_REG))])]
1765
  "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1766
  [(parallel [(set:SI (match_dup 2)
1767
                      (memex_noncomm:SI (match_dup 2)
1768
                                        (extend_types:SI (match_dup 1))))
1769
              (clobber (reg:CC CC_REG))])]
1770
)
1771
 
1772
(define_peephole2
1773
  [(set (match_operand:SI                               0 "register_operand")
1774
        (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1775
   (set (match_operand:SI                               2 "register_operand")
1776
        (memex_nocc:SI (match_dup 0)
1777
                       (match_dup 2)))]
1778
  "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1779
  [(set:SI (match_dup 2)
1780
           (memex_nocc:SI (match_dup 2)
1781
                          (extend_types:SI (match_dup 1))))]
1782
)
1783
 
1784
(define_peephole2
1785
  [(set (match_operand:SI                               0 "register_operand")
1786
        (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1787
   (set (match_operand:SI                               2 "register_operand")
1788
        (memex_nocc:SI (match_dup 2)
1789
                       (match_dup 0)))]
1790
  "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1791
  [(set:SI (match_dup 2)
1792
           (memex_nocc:SI (match_dup 2)
1793
                          (extend_types:SI (match_dup 1))))]
1794
)
1795
 
1796
(define_insn "si3_"
1797
  [(set (match_operand:SI                                                     0 "register_operand" "=r")
1798
        (memex_commutative:SI (match_operand:SI                               1 "register_operand" "%0")
1799
                              (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1800
   (clobber (reg:CC CC_REG))]
1801
  "(optimize < 3 || optimize_size)"
1802
  "\t%2, %0"
1803
  [(set_attr "timings" "33")
1804
   (set_attr "length"  "5")] ;; This length is corrected in rx_adjust_insn_length
1805
)
1806
 
1807
(define_insn "si3_"
1808
  [(set (match_operand:SI                                                 0 "register_operand" "=r")
1809
        (memex_noncomm:SI (match_operand:SI                               1 "register_operand" "0")
1810
                          (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1811
   (clobber (reg:CC CC_REG))]
1812
  "(optimize < 3 || optimize_size)"
1813
  "\t%2, %0"
1814
  [(set_attr "timings" "33")
1815
   (set_attr "length"  "5")] ;; This length is corrected in rx_adjust_insn_length
1816
)
1817
 
1818
(define_insn "si3_"
1819
  [(set (match_operand:SI                                              0 "register_operand" "=r")
1820
        (memex_nocc:SI (match_operand:SI                               1 "register_operand" "%0")
1821
                       (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))]
1822
  "(optimize < 3 || optimize_size)"
1823
  "\t%2, %0"
1824
  [(set_attr "timings" "33")
1825
   (set_attr "length"  "5")] ;; This length is corrected in rx_adjust_insn_length
1826
)
1827
 
1828
(define_peephole2
1829
  [(set (match_operand:SI                               0 "register_operand")
1830
        (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1831
   (set (reg:CC CC_REG)
1832
        (compare:CC (match_operand:SI                   2 "register_operand")
1833
                    (match_dup 0)))]
1834
  "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1835
  [(set (reg:CC CC_REG)
1836
        (compare:CC (match_dup 2)
1837
                    (extend_types:SI (match_dup 1))))]
1838
)
1839
 
1840
;; Convert:
1841
;;   (set (reg1) (sign_extend (mem))
1842
;;   (set (reg2) (zero_extend (reg1))
1843
;; into
1844
;;   (set (reg2) (zero_extend (mem)))
1845
(define_peephole2
1846
  [(set (match_operand:SI                              0 "register_operand")
1847
        (sign_extend:SI (match_operand:small_int_modes 1 "memory_operand")))
1848
   (set (match_operand:SI                              2 "register_operand")
1849
        (zero_extend:SI (match_operand:small_int_modes 3 "register_operand")))]
1850
  "REGNO (operands[0]) == REGNO (operands[3])
1851
   && (REGNO (operands[0]) == REGNO (operands[2])
1852
       || peep2_regno_dead_p (2, REGNO (operands[0])))"
1853
  [(set (match_dup 2)
1854
        (zero_extend:SI (match_dup 1)))]
1855
)
1856
 
1857
;; Remove the redundant sign extension from:
1858
;;   (set (reg) (extend (mem)))
1859
;;   (set (reg) (extend (reg)))
1860
(define_peephole2
1861
  [(set (match_operand:SI                               0 "register_operand")
1862
        (extend_types:SI (match_operand:small_int_modes 1 "memory_operand")))
1863
   (set (match_dup 0)
1864
        (extend_types:SI (match_operand:small_int_modes 2 "register_operand")))]
1865
  "REGNO (operands[0]) == REGNO (operands[2])"
1866
  [(set (match_dup 0) (extend_types:SI (match_dup 1)))]
1867
)
1868
 
1869
(define_insn "comparesi3_"
1870
  [(set (reg:CC CC_REG)
1871
        (compare:CC (match_operand:SI                               0 "register_operand" "=r")
1872
                    (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand" "Q"))))]
1873
  "(optimize < 3 || optimize_size)"
1874
  "cmp\t%1, %0"
1875
  [(set_attr "timings" "33")
1876
   (set_attr "length"  "5")] ;; This length is corrected in rx_adjust_insn_length
1877
)
1878
 
1879
;; Floating Point Instructions
1880
 
1881
(define_insn "addsf3"
1882
  [(set (match_operand:SF          0 "register_operand"  "=r,r,r")
1883
        (plus:SF (match_operand:SF 1 "register_operand"  "%0,0,0")
1884
                 (match_operand:SF 2 "rx_source_operand"  "r,F,Q")))
1885
   (clobber (reg:CC CC_REG))]
1886
  "ALLOW_RX_FPU_INSNS"
1887
  "fadd\t%2, %0"
1888
  [(set_attr "timings" "44,44,66")
1889
   (set_attr "length" "3,7,5")]
1890
)
1891
 
1892
(define_insn "divsf3"
1893
  [(set (match_operand:SF         0 "register_operand" "=r,r,r")
1894
        (div:SF (match_operand:SF 1 "register_operand"  "0,0,0")
1895
                (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1896
   (clobber (reg:CC CC_REG))]
1897
  "ALLOW_RX_FPU_INSNS"
1898
  "fdiv\t%2, %0"
1899
  [(set_attr "timings" "1616,1616,1818")
1900
   (set_attr "length" "3,7,5")]
1901
)
1902
 
1903
(define_insn "mulsf3"
1904
  [(set (match_operand:SF          0 "register_operand" "=r,r,r")
1905
        (mult:SF (match_operand:SF 1 "register_operand" "%0,0,0")
1906
                (match_operand:SF  2 "rx_source_operand" "r,F,Q")))
1907
   (clobber (reg:CC CC_REG))]
1908
  "ALLOW_RX_FPU_INSNS"
1909
  "fmul\t%2, %0"
1910
  [(set_attr "timings" "33,33,55")
1911
   (set_attr "length"  "3,7,5")]
1912
)
1913
 
1914
(define_insn "subsf3"
1915
  [(set (match_operand:SF           0 "register_operand" "=r,r,r")
1916
        (minus:SF (match_operand:SF 1 "register_operand"  "0,0,0")
1917
                  (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1918
   (clobber (reg:CC CC_REG))]
1919
  "ALLOW_RX_FPU_INSNS"
1920
  "fsub\t%Q2, %0"
1921
  [(set_attr "timings" "44,44,66")
1922
   (set_attr "length" "3,7,5")]
1923
)
1924
 
1925
(define_insn "fix_truncsfsi2"
1926
  [(set (match_operand:SI         0 "register_operand"  "=r,r")
1927
        (fix:SI (match_operand:SF 1 "rx_compare_operand" "r,Q")))
1928
   (clobber (reg:CC CC_REG))]
1929
  "ALLOW_RX_FPU_INSNS"
1930
  "ftoi\t%Q1, %0"
1931
  [(set_attr "timings" "22,44")
1932
   (set_attr "length" "3,5")]
1933
)
1934
 
1935
(define_insn "floatsisf2"
1936
  [(set (match_operand:SF           0 "register_operand"  "=r,r")
1937
        (float:SF (match_operand:SI 1 "rx_compare_operand" "r,Q")))
1938
   (clobber (reg:CC CC_REG))]
1939
  "ALLOW_RX_FPU_INSNS"
1940
  "itof\t%Q1, %0"
1941
  [(set_attr "timings" "22,44")
1942
   (set_attr "length" "3,6")]
1943
)
1944
 
1945
;; Bit manipulation instructions.
1946
 
1947
;; ??? The *_in_memory patterns will not be matched without further help.
1948
;; At one time we had the insv expander generate them, but I suspect that
1949
;; in general we get better performance by exposing the register load to
1950
;; the optimizers.
1951
;;
1952
;; An alternate solution would be to re-organize these patterns such
1953
;; that allow both register and memory operands.  This would allow the
1954
;; register allocator to spill and not load the register operand.  This
1955
;; would be possible only for operations for which we have a constant
1956
;; bit offset, so that we can adjust the address by ofs/8 and replace
1957
;; the offset in the insn by ofs%8.
1958
 
1959
(define_insn "*bitset"
1960
  [(set (match_operand:SI                    0 "register_operand" "=r")
1961
        (ior:SI (ashift:SI (const_int 1)
1962
                           (match_operand:SI 1 "rx_shift_operand" "ri"))
1963
                (match_operand:SI            2 "register_operand" "0")))]
1964
  ""
1965
  "bset\t%1, %0"
1966
  [(set_attr "length" "3")]
1967
)
1968
 
1969
(define_insn "*bitset_in_memory"
1970
  [(set (match_operand:QI                    0 "rx_restricted_mem_operand" "+Q")
1971
        (ior:QI (ashift:QI (const_int 1)
1972
                           (match_operand:QI 1 "nonmemory_operand" "ri"))
1973
                (match_dup 0)))]
1974
  ""
1975
  "bset\t%1, %0.B"
1976
  [(set_attr "length" "3")
1977
   (set_attr "timings" "33")]
1978
)
1979
 
1980
(define_insn "*bitinvert"
1981
  [(set (match_operand:SI 0 "register_operand" "=r")
1982
        (xor:SI (ashift:SI (const_int 1)
1983
                           (match_operand:SI 1 "rx_shift_operand" "ri"))
1984
                (match_operand:SI 2 "register_operand" "0")))]
1985
  ""
1986
  "bnot\t%1, %0"
1987
  [(set_attr "length" "3")]
1988
)
1989
 
1990
(define_insn "*bitinvert_in_memory"
1991
  [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
1992
        (xor:QI (ashift:QI (const_int 1)
1993
                           (match_operand:QI 1 "nonmemory_operand" "ri"))
1994
                (match_dup 0)))]
1995
  ""
1996
  "bnot\t%1, %0.B"
1997
  [(set_attr "length" "5")
1998
   (set_attr "timings" "33")]
1999
)
2000
 
2001
(define_insn "*bitclr"
2002
  [(set (match_operand:SI 0 "register_operand" "=r")
2003
        (and:SI (not:SI
2004
                  (ashift:SI
2005
                    (const_int 1)
2006
                    (match_operand:SI 1 "rx_shift_operand" "ri")))
2007
                (match_operand:SI 2 "register_operand" "0")))]
2008
  ""
2009
  "bclr\t%1, %0"
2010
  [(set_attr "length" "3")]
2011
)
2012
 
2013
(define_insn "*bitclr_in_memory"
2014
  [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
2015
        (and:QI (not:QI
2016
                  (ashift:QI
2017
                    (const_int 1)
2018
                    (match_operand:QI 1 "nonmemory_operand" "ri")))
2019
                (match_dup 0)))]
2020
  ""
2021
  "bclr\t%1, %0.B"
2022
  [(set_attr "length" "3")
2023
   (set_attr "timings" "33")]
2024
)
2025
 
2026
(define_insn "*insv_imm"
2027
  [(set (zero_extract:SI
2028
          (match_operand:SI 0 "register_operand" "+r")
2029
          (const_int 1)
2030
          (match_operand:SI 1 "rx_shift_operand" "ri"))
2031
        (match_operand:SI 2 "const_int_operand" ""))]
2032
  ""
2033
{
2034
  if (INTVAL (operands[2]) & 1)
2035
    return "bset\t%1, %0";
2036
  else
2037
    return "bclr\t%1, %0";
2038
}
2039
  [(set_attr "length" "3")]
2040
)
2041
 
2042
(define_insn_and_split "rx_insv_reg"
2043
  [(set (zero_extract:SI
2044
          (match_operand:SI 0 "register_operand" "+r")
2045
          (const_int 1)
2046
          (match_operand:SI 1 "const_int_operand" ""))
2047
        (match_operand:SI 2 "register_operand" "r"))
2048
   (clobber (reg:CC CC_REG))]
2049
  ""
2050
  "#"
2051
  "reload_completed"
2052
  [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2053
        (match_dup 3))]
2054
{
2055
  rtx flags, x;
2056
 
2057
  /* Emit tst #1, op2.  */
2058
  flags = gen_rtx_REG (CC_ZSmode, CC_REG);
2059
  x = gen_rtx_AND (SImode, operands[2], const1_rtx);
2060
  x = gen_rtx_COMPARE (CC_ZSmode, x, const0_rtx);
2061
  x = gen_rtx_SET (VOIDmode, flags, x);
2062
  emit_insn (x);
2063
 
2064
  /* Emit bmne.  */
2065
  operands[3] = gen_rtx_NE (SImode, flags, const0_rtx);
2066
})
2067
 
2068
(define_insn_and_split "*insv_cond"
2069
  [(set (zero_extract:SI
2070
          (match_operand:SI 0 "register_operand" "+r")
2071
          (const_int 1)
2072
          (match_operand:SI 1 "const_int_operand" ""))
2073
        (match_operator:SI 4 "comparison_operator"
2074
          [(match_operand:SI 2 "register_operand" "r")
2075
           (match_operand:SI 3 "rx_source_operand" "riQ")]))
2076
   (clobber (reg:CC CC_REG))]
2077
  ""
2078
  "#"
2079
  "reload_completed"
2080
  [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2081
        (match_dup 4))]
2082
{
2083
  rtx flags, x;
2084
 
2085
  flags = gen_rtx_REG (CCmode, CC_REG);
2086
  x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
2087
  x = gen_rtx_SET (VOIDmode, flags, x);
2088
  emit_insn (x);
2089
 
2090
  operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
2091
                                flags, const0_rtx);
2092
})
2093
 
2094
(define_insn "*bmcc"
2095
  [(set (zero_extract:SI
2096
          (match_operand:SI 0 "register_operand" "+r")
2097
          (const_int 1)
2098
          (match_operand:SI 1 "const_int_operand" ""))
2099
        (match_operator:SI 2 "comparison_operator"
2100
          [(reg CC_REG) (const_int 0)]))]
2101
  "reload_completed"
2102
  "bm%B2\t%1, %0"
2103
  [(set_attr "length" "3")]
2104
)
2105
 
2106
;; Work around the fact that X=Y<0 is preferentially expanded as a shift.
2107
(define_insn_and_split "*insv_cond_lt"
2108
  [(set (zero_extract:SI
2109
          (match_operand:SI 0 "register_operand" "+r")
2110
          (const_int 1)
2111
          (match_operand:SI 1 "const_int_operand" ""))
2112
        (match_operator:SI 3 "rshift_operator"
2113
          [(match_operand:SI 2 "register_operand" "r")
2114
           (const_int 31)]))
2115
   (clobber (reg:CC CC_REG))]
2116
  ""
2117
  "#"
2118
  ""
2119
  [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2120
                   (lt:SI (match_dup 2) (const_int 0)))
2121
              (clobber (reg:CC CC_REG))])]
2122
  ""
2123
)
2124
 
2125
(define_expand "insv"
2126
  [(set (zero_extract:SI
2127
          (match_operand:SI 0 "register_operand")       ;; Destination
2128
          (match_operand:SI 1 "const_int_operand")      ;; # of bits to set
2129
          (match_operand:SI 2 "nonmemory_operand"))     ;; Starting bit
2130
        (match_operand:SI   3 "nonmemory_operand"))]    ;; Bits to insert
2131
  ""
2132
{
2133
  /* We only handle single-bit inserts.  */
2134
  if (!CONST_INT_P (operands[1]) || INTVAL (operands[1]) != 1)
2135
    FAIL;
2136
 
2137
  /* Either the bit to insert or the position must be constant.  */
2138
  if (CONST_INT_P (operands[3]))
2139
    operands[3] = GEN_INT (INTVAL (operands[3]) & 1);
2140
  else if (CONST_INT_P (operands[2]))
2141
    {
2142
      emit_insn (gen_rx_insv_reg (operands[0], operands[2], operands[3]));
2143
      DONE;
2144
    }
2145
  else
2146
    FAIL;
2147
})
2148
 
2149
;; Atomic exchange operation.
2150
 
2151
(define_insn "sync_lock_test_and_setsi"
2152
  [(set (match_operand:SI 0 "register_operand"   "=r,r")
2153
        (match_operand:SI 1 "rx_compare_operand" "=r,Q"))
2154
   (set (match_dup 1)
2155
        (match_operand:SI 2 "register_operand"    "0,0"))]
2156
  ""
2157
  "xchg\t%1, %0"
2158
  [(set_attr "length" "3,6")
2159
   (set_attr "timings" "22")]
2160
)
2161
 
2162
;; Block move functions.
2163
 
2164
(define_expand "movstr"
2165
  [(set (match_operand:BLK 1 "memory_operand")    ;; Dest
2166
        (match_operand:BLK 2 "memory_operand"))   ;; Source
2167
   (use (match_operand:SI  0 "register_operand")) ;; Updated Dest
2168
  ]
2169
  ""
2170
  {
2171
    rtx addr1 = gen_rtx_REG (SImode, 1);
2172
    rtx addr2 = gen_rtx_REG (SImode, 2);
2173
    rtx len   = gen_rtx_REG (SImode, 3);
2174
    rtx dest_copy = gen_reg_rtx (SImode);
2175
 
2176
    emit_move_insn (len, GEN_INT (-1));
2177
    emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2178
    emit_move_insn (addr2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2179
    operands[1] = replace_equiv_address_nv (operands[1], addr1);
2180
    operands[2] = replace_equiv_address_nv (operands[2], addr2);
2181
    emit_move_insn (dest_copy, addr1);
2182
    emit_insn (gen_rx_movstr ());
2183
    emit_move_insn (len, GEN_INT (-1));
2184
    emit_insn (gen_rx_strend (operands[0], dest_copy));
2185
    DONE;
2186
  }
2187
)
2188
 
2189
(define_insn "rx_movstr"
2190
  [(set (mem:BLK (reg:SI 1))
2191
        (mem:BLK (reg:SI 2)))
2192
   (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVSTR)
2193
   (clobber (reg:SI 1))
2194
   (clobber (reg:SI 2))
2195
   (clobber (reg:SI 3))]
2196
  ""
2197
  "smovu"
2198
  [(set_attr "length" "2")
2199
   (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2200
)
2201
 
2202
(define_insn "rx_strend"
2203
  [(set (match_operand:SI                      0 "register_operand" "=r")
2204
        (unspec_volatile:SI [(match_operand:SI 1 "register_operand"  "r")
2205
                                (reg:SI 3)] UNSPEC_STRLEN))
2206
   (clobber (reg:SI 1))
2207
   (clobber (reg:SI 2))
2208
   (clobber (reg:SI 3))
2209
   (clobber (reg:CC CC_REG))
2210
   ]
2211
  ""
2212
  "mov\t%1, r1\n\tmov\t#0, r2\n\tsuntil.b\n\tmov\tr1, %0\n\tsub\t#1, %0"
2213
  [(set_attr "length" "10")
2214
   (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2215
)
2216
 
2217
(define_expand "movmemsi"
2218
  [(parallel
2219
    [(set (match_operand:BLK 0 "memory_operand")    ;; Dest
2220
          (match_operand:BLK 1 "memory_operand"))   ;; Source
2221
     (use (match_operand:SI  2 "register_operand")) ;; Length in bytes
2222
     (match_operand          3 "immediate_operand") ;; Align
2223
     (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)]
2224
    )]
2225
  ""
2226
  {
2227
    rtx addr1 = gen_rtx_REG (SImode, 1);
2228
    rtx addr2 = gen_rtx_REG (SImode, 2);
2229
    rtx len   = gen_rtx_REG (SImode, 3);
2230
 
2231
    /* Do not use when the source or destination are volatile - the SMOVF
2232
       instruction will read and write in word sized blocks, which may be
2233
       outside of the valid address range.  */
2234
    if (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
2235
      FAIL;
2236
    if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
2237
      FAIL;
2238
 
2239
    if (REG_P (operands[0]) && (REGNO (operands[0]) == 2
2240
                                      || REGNO (operands[0]) == 3))
2241
      FAIL;
2242
    if (REG_P (operands[1]) && (REGNO (operands[1]) == 1
2243
                                      || REGNO (operands[1]) == 3))
2244
      FAIL;
2245
    if (REG_P (operands[2]) && (REGNO (operands[2]) == 1
2246
                                      || REGNO (operands[2]) == 2))
2247
      FAIL;
2248
 
2249
    emit_move_insn (addr1, force_operand (XEXP (operands[0], 0), NULL_RTX));
2250
    emit_move_insn (addr2, force_operand (XEXP (operands[1], 0), NULL_RTX));
2251
    emit_move_insn (len, force_operand (operands[2], NULL_RTX));
2252
    operands[0] = replace_equiv_address_nv (operands[0], addr1);
2253
    operands[1] = replace_equiv_address_nv (operands[1], addr2);
2254
    emit_insn (gen_rx_movmem ());
2255
    DONE;
2256
  }
2257
)
2258
 
2259
(define_insn "rx_movmem"
2260
  [(set (mem:BLK (reg:SI 1))
2261
        (mem:BLK (reg:SI 2)))
2262
   (use (reg:SI 3))
2263
   (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)
2264
   (clobber (reg:SI 1))
2265
   (clobber (reg:SI 2))
2266
   (clobber (reg:SI 3))]
2267
  ""
2268
  "smovf"
2269
  [(set_attr "length" "2")
2270
   (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2271
)
2272
 
2273
(define_expand "setmemsi"
2274
  [(set (match_operand:BLK 0 "memory_operand")     ;; Dest
2275
        (match_operand:QI  2 "nonmemory_operand")) ;; Value
2276
   (use (match_operand:SI  1 "nonmemory_operand")) ;; Length
2277
   (match_operand          3 "immediate_operand")  ;; Align
2278
   (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM)]
2279
  ""
2280
  {
2281
    rtx addr = gen_rtx_REG (SImode, 1);
2282
    rtx val  = gen_rtx_REG (QImode, 2);
2283
    rtx len  = gen_rtx_REG (SImode, 3);
2284
 
2285
    emit_move_insn (addr, force_operand (XEXP (operands[0], 0), NULL_RTX));
2286
    emit_move_insn (len, force_operand (operands[1], NULL_RTX));
2287
    emit_move_insn (val, operands[2]);
2288
    emit_insn (gen_rx_setmem ());
2289
    DONE;
2290
  }
2291
)
2292
 
2293
(define_insn "rx_setmem"
2294
  [(set (mem:BLK (reg:SI 1))
2295
        (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM))
2296
   (clobber (reg:SI 1))
2297
   (clobber (reg:SI 3))]
2298
  ""
2299
  "sstr.b"
2300
  [(set_attr "length" "2")
2301
   (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2302
)
2303
 
2304
(define_expand "cmpstrnsi"
2305
  [(set (match_operand:SI                       0 "register_operand")   ;; Result
2306
        (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand")     ;; String1
2307
                             (match_operand:BLK 2 "memory_operand")]    ;; String2
2308
                            UNSPEC_CMPSTRN))
2309
   (use (match_operand:SI                       3 "register_operand"))  ;; Max Length
2310
   (match_operand:SI                            4 "immediate_operand")] ;; Known Align
2311
  ""
2312
  {
2313
    rtx str1 = gen_rtx_REG (SImode, 1);
2314
    rtx str2 = gen_rtx_REG (SImode, 2);
2315
    rtx len  = gen_rtx_REG (SImode, 3);
2316
 
2317
    emit_move_insn (str1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2318
    emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2319
    emit_move_insn (len, force_operand (operands[3], NULL_RTX));
2320
 
2321
    emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2322
    DONE;
2323
  }
2324
)
2325
 
2326
(define_expand "cmpstrsi"
2327
  [(set (match_operand:SI                       0 "register_operand")   ;; Result
2328
        (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand")     ;; String1
2329
                             (match_operand:BLK 2 "memory_operand")]    ;; String2
2330
                            UNSPEC_CMPSTRN))
2331
   (match_operand:SI                            3 "immediate_operand")] ;; Known Align
2332
  ""
2333
  {
2334
    rtx str1 = gen_rtx_REG (SImode, 1);
2335
    rtx str2 = gen_rtx_REG (SImode, 2);
2336
    rtx len  = gen_rtx_REG (SImode, 3);
2337
 
2338
    emit_move_insn (str1, force_reg (SImode, XEXP (operands[1], 0)));
2339
    emit_move_insn (str2, force_reg (SImode, XEXP (operands[2], 0)));
2340
    emit_move_insn (len, GEN_INT (-1));
2341
 
2342
    emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2343
    DONE;
2344
  }
2345
)
2346
 
2347
(define_insn "rx_cmpstrn"
2348
  [(set (match_operand:SI 0 "register_operand" "=r")
2349
        (unspec_volatile:SI [(reg:SI 1) (reg:SI 2) (reg:SI 3)]
2350
                            UNSPEC_CMPSTRN))
2351
   (use (match_operand:BLK 1 "memory_operand" "m"))
2352
   (use (match_operand:BLK 2 "memory_operand" "m"))
2353
   (clobber (reg:SI 1))
2354
   (clobber (reg:SI 2))
2355
   (clobber (reg:SI 3))
2356
   (clobber (reg:CC CC_REG))]
2357
  ""
2358
  "scmpu                ; Perform the string comparison
2359
   mov     #-1, %0      ; Set up -1 result (which cannot be created
2360
                        ; by the SC insn)
2361
   bnc     ?+           ; If Carry is not set skip over
2362
   scne.L  %0           ; Set result based on Z flag
2363
?:
2364
"
2365
  [(set_attr "length" "9")
2366
   (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2367
)
2368
 
2369
;;   Builtin Functions
2370
;;
2371
;; GCC does not have the ability to generate the following instructions
2372
;; on its own so they are provided as builtins instead.  To use them from
2373
;; a program for example invoke them as __builtin_rx_.  For
2374
;; example:
2375
;;
2376
;;    int short_byte_swap (int arg) { return __builtin_rx_revw (arg); }
2377
 
2378
;;---------- Accumulator Support ------------------------
2379
 
2380
;; Multiply & Accumulate (high)
2381
(define_insn "machi"
2382
  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2383
               (match_operand:SI 1 "register_operand" "r")]
2384
              UNSPEC_BUILTIN_MACHI)]
2385
  ""
2386
  "machi\t%0, %1"
2387
  [(set_attr "length" "3")]
2388
)
2389
 
2390
;; Multiply & Accumulate (low)
2391
(define_insn "maclo"
2392
  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2393
               (match_operand:SI 1 "register_operand" "r")]
2394
              UNSPEC_BUILTIN_MACLO)]
2395
  ""
2396
  "maclo\t%0, %1"
2397
  [(set_attr "length" "3")]
2398
)
2399
 
2400
;; Multiply (high)
2401
(define_insn "mulhi"
2402
  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2403
               (match_operand:SI 1 "register_operand" "r")]
2404
              UNSPEC_BUILTIN_MULHI)]
2405
  ""
2406
  "mulhi\t%0, %1"
2407
  [(set_attr "length" "3")]
2408
)
2409
 
2410
;; Multiply (low)
2411
(define_insn "mullo"
2412
  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2413
               (match_operand:SI 1 "register_operand" "r")]
2414
              UNSPEC_BUILTIN_MULLO)]
2415
  ""
2416
  "mullo\t%0, %1"
2417
  [(set_attr "length" "3")]
2418
)
2419
 
2420
;; Move from Accumulator (high)
2421
(define_insn "mvfachi"
2422
  [(set (match_operand:SI 0 "register_operand" "=r")
2423
        (unspec:SI [(const_int 0)]
2424
                   UNSPEC_BUILTIN_MVFACHI))]
2425
  ""
2426
  "mvfachi\t%0"
2427
  [(set_attr "length" "3")]
2428
)
2429
 
2430
;; Move from Accumulator (middle)
2431
(define_insn "mvfacmi"
2432
  [(set (match_operand:SI 0 "register_operand" "=r")
2433
        (unspec:SI [(const_int 0)]
2434
                   UNSPEC_BUILTIN_MVFACMI))]
2435
  ""
2436
  "mvfacmi\t%0"
2437
  [(set_attr "length" "3")]
2438
)
2439
 
2440
;; Move to Accumulator (high)
2441
(define_insn "mvtachi"
2442
  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2443
                       UNSPEC_BUILTIN_MVTACHI)]
2444
  ""
2445
  "mvtachi\t%0"
2446
  [(set_attr "length" "3")]
2447
)
2448
 
2449
;; Move to Accumulator (low)
2450
(define_insn "mvtaclo"
2451
  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2452
                       UNSPEC_BUILTIN_MVTACLO)]
2453
  ""
2454
  "mvtaclo\t%0"
2455
  [(set_attr "length" "3")]
2456
)
2457
 
2458
;; Round Accumulator
2459
(define_insn "racw"
2460
  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2461
                       UNSPEC_BUILTIN_RACW)]
2462
  ""
2463
  "racw\t%0"
2464
  [(set_attr "length" "3")]
2465
)
2466
 
2467
;; Repeat multiply and accumulate
2468
(define_insn "rmpa"
2469
  [(unspec:SI [(const_int 0) (reg:SI 1) (reg:SI 2) (reg:SI 3)
2470
               (reg:SI 4) (reg:SI 5) (reg:SI 6)]
2471
              UNSPEC_BUILTIN_RMPA)
2472
  (clobber (reg:SI 1))
2473
  (clobber (reg:SI 2))
2474
  (clobber (reg:SI 3))]
2475
  ""
2476
  "rmpa"
2477
  [(set_attr "length" "2")
2478
   (set_attr "timings" "1010")]
2479
)
2480
 
2481
;;---------- Arithmetic ------------------------
2482
 
2483
;; Byte swap (two 16-bit values).
2484
(define_insn "revw"
2485
  [(set (match_operand:SI             0 "register_operand" "=r")
2486
        (unspec:SI [(match_operand:SI 1 "register_operand"  "r")]
2487
                   UNSPEC_BUILTIN_REVW))]
2488
  ""
2489
  "revw\t%1, %0"
2490
  [(set_attr "length" "3")]
2491
)
2492
 
2493
;; Round to integer.
2494
(define_insn "lrintsf2"
2495
  [(set (match_operand:SI             0 "register_operand"  "=r,r")
2496
        (unspec:SI [(match_operand:SF 1 "rx_compare_operand" "r,Q")]
2497
                   UNSPEC_BUILTIN_ROUND))
2498
   (clobber (reg:CC CC_REG))]
2499
  ""
2500
  "round\t%1, %0"
2501
  [(set_attr "timings" "22,44")
2502
   (set_attr "length" "3,5")]
2503
)
2504
 
2505
;;---------- Control Registers ------------------------
2506
 
2507
;; Clear Processor Status Word
2508
(define_insn "clrpsw"
2509
  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2510
              UNSPEC_BUILTIN_CLRPSW)
2511
   (clobber (reg:CC CC_REG))]
2512
  ""
2513
  "clrpsw\t%F0"
2514
  [(set_attr "length" "2")]
2515
)
2516
 
2517
;; Set Processor Status Word
2518
(define_insn "setpsw"
2519
  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2520
              UNSPEC_BUILTIN_SETPSW)
2521
   (clobber (reg:CC CC_REG))]
2522
  ""
2523
  "setpsw\t%F0"
2524
  [(set_attr "length" "2")]
2525
)
2526
 
2527
;; Move from control register
2528
(define_insn "mvfc"
2529
  [(set (match_operand:SI             0 "register_operand" "=r")
2530
        (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")]
2531
                   UNSPEC_BUILTIN_MVFC))]
2532
  ""
2533
  "mvfc\t%C1, %0"
2534
  [(set_attr "length" "3")]
2535
)
2536
 
2537
;; Move to control register
2538
(define_insn "mvtc"
2539
  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i,i")
2540
               (match_operand:SI 1 "nonmemory_operand" "r,i")]
2541
              UNSPEC_BUILTIN_MVTC)]
2542
  ""
2543
  "mvtc\t%1, %C0"
2544
  [(set_attr "length" "3,7")]
2545
  ;; Ignore possible clobbering of the comparison flags in the
2546
  ;; PSW register.  This is a cc0 target so any cc0 setting
2547
  ;; instruction will always be paired with a cc0 user, without
2548
  ;; the possibility of this instruction being placed in between
2549
  ;; them.
2550
)
2551
 
2552
;; Move to interrupt priority level
2553
(define_insn "mvtipl"
2554
  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "Uint04")]
2555
              UNSPEC_BUILTIN_MVTIPL)]
2556
  ""
2557
  "mvtipl\t%0"
2558
  [(set_attr "length" "3")]
2559
)
2560
 
2561
;;---------- Interrupts ------------------------
2562
 
2563
;; Break
2564
(define_insn "brk"
2565
  [(unspec_volatile [(const_int 0)]
2566
                    UNSPEC_BUILTIN_BRK)]
2567
  ""
2568
  "brk"
2569
  [(set_attr "length" "1")
2570
   (set_attr "timings" "66")]
2571
)
2572
 
2573
;; Interrupt
2574
(define_insn "int"
2575
  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2576
                       UNSPEC_BUILTIN_INT)]
2577
  ""
2578
  "int\t%0"
2579
  [(set_attr "length" "3")]
2580
)
2581
 
2582
;; Wait
2583
(define_insn "wait"
2584
  [(unspec_volatile [(const_int 0)]
2585
                    UNSPEC_BUILTIN_WAIT)]
2586
  ""
2587
  "wait"
2588
  [(set_attr "length" "2")]
2589
)
2590
 
2591
;;---------- CoProcessor Support ------------------------
2592
 
2593
;; FIXME: The instructions are currently commented out because
2594
;; the bit patterns have not been finalized, so the assembler
2595
;; does not support them.  Once they are decided and the assembler
2596
;; supports them, enable the instructions here.
2597
 
2598
;; Move from co-processor register
2599
(define_insn "mvfcp"
2600
  [(set (match_operand:SI             0 "register_operand" "=r")
2601
        (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")
2602
                    (match_operand:SI 2 "immediate_operand" "i")]
2603
                   UNSPEC_BUILTIN_MVFCP))]
2604
  ""
2605
  "; mvfcp\t%1, %0, %2"
2606
  [(set_attr "length" "5")]
2607
)
2608
 
2609
;;---------- Misc ------------------------
2610
 
2611
;; Required by cfglayout.c...
2612
(define_insn "nop"
2613
  [(const_int 0)]
2614
  ""
2615
  "nop"
2616
  [(set_attr "length" "1")]
2617
)
2618
 
2619
(define_expand "pid_addr"
2620
  [(plus:SI (match_operand:SI 0)
2621
            (const:SI (unspec:SI [(match_operand:SI 1)] UNSPEC_PID_ADDR)))]
2622
  ""
2623
  ""
2624
)

powered by: WebSVN 2.1.0

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