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