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