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