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