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