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