]>
Commit | Line | Data |
---|---|---|
e9a25f70 | 1 | ;; Machine description of the Argonaut ARC cpu for GNU C compiler |
2f83c7d6 | 2 | ;; Copyright (C) 1994, 1997, 1998, 1999, 2000, 2004, 2005, 2007 |
1c563bed | 3 | ;; Free Software Foundation, Inc. |
5680076c | 4 | |
7ec022b2 | 5 | ;; This file is part of GCC. |
5680076c | 6 | |
7ec022b2 | 7 | ;; GCC is free software; you can redistribute it and/or modify |
5680076c | 8 | ;; it under the terms of the GNU General Public License as published by |
2f83c7d6 | 9 | ;; the Free Software Foundation; either version 3, or (at your option) |
5680076c JL |
10 | ;; any later version. |
11 | ||
7ec022b2 | 12 | ;; GCC is distributed in the hope that it will be useful, |
5680076c JL |
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 | |
2f83c7d6 NC |
18 | ;; along with GCC; see the file COPYING3. If not see |
19 | ;; <http://www.gnu.org/licenses/>. | |
5680076c JL |
20 | |
21 | ;; See file "rtl.def" for documentation on define_insn, match_*, et. al. | |
22 | ||
23 | ;; ??? This is an old port, and is undoubtedly suffering from bit rot. | |
24 | \f | |
25 | ;; Insn type. Used to default other attribute values. | |
26 | ||
27 | (define_attr "type" | |
28 | "move,load,store,cmove,unary,binary,compare,shift,mul,uncond_branch,branch,call,call_no_delay_slot,multi,misc" | |
29 | (const_string "binary")) | |
30 | ||
31 | ;; Length (in # of insns, long immediate constants counted too). | |
32 | ;; ??? There's a nasty interaction between the conditional execution fsm | |
33 | ;; and insn lengths: insns with shimm values cannot be conditionally executed. | |
34 | (define_attr "length" "" | |
35 | (cond [(eq_attr "type" "load") | |
36 | (if_then_else (match_operand 1 "long_immediate_loadstore_operand" "") | |
37 | (const_int 2) (const_int 1)) | |
38 | ||
39 | (eq_attr "type" "store") | |
40 | (if_then_else (match_operand 0 "long_immediate_loadstore_operand" "") | |
41 | (const_int 2) (const_int 1)) | |
42 | ||
43 | (eq_attr "type" "move,unary,compare") | |
44 | (if_then_else (match_operand 1 "long_immediate_operand" "") | |
45 | (const_int 2) (const_int 1)) | |
46 | ||
47 | (eq_attr "type" "binary,mul") | |
48 | (if_then_else (match_operand 2 "long_immediate_operand" "") | |
49 | (const_int 2) (const_int 1)) | |
50 | ||
51 | (eq_attr "type" "cmove") | |
52 | (if_then_else (match_operand 2 "register_operand" "") | |
53 | (const_int 1) (const_int 2)) | |
54 | ||
55 | (eq_attr "type" "multi") (const_int 2) | |
56 | ] | |
57 | ||
58 | (const_int 1))) | |
59 | ||
60 | ;; The length here is the length of a single asm. Unfortunately it might be | |
61 | ;; 1 or 2 so we must allow for 2. That's ok though. How often will users | |
62 | ;; lament asm's not being put in delay slots? | |
63 | (define_asm_attributes | |
64 | [(set_attr "length" "2") | |
65 | (set_attr "type" "multi")]) | |
66 | ||
67 | ;; Condition codes: this one is used by final_prescan_insn to speed up | |
68 | ;; conditionalizing instructions. It saves having to scan the rtl to see if | |
69 | ;; it uses or alters the condition codes. | |
70 | ||
112cdef5 | 71 | ;; USE: This insn uses the condition codes (e.g.: a conditional branch). |
5680076c JL |
72 | ;; CANUSE: This insn can use the condition codes (for conditional execution). |
73 | ;; SET: All condition codes are set by this insn. | |
74 | ;; SET_ZN: the Z and N flags are set by this insn. | |
75 | ;; SET_ZNC: the Z, N, and C flags are set by this insn. | |
76 | ;; CLOB: The condition codes are set to unknown values by this insn. | |
77 | ;; NOCOND: This insn can't use and doesn't affect the condition codes. | |
78 | ||
79 | (define_attr "cond" "use,canuse,set,set_zn,set_znc,clob,nocond" | |
80 | (cond [(and (eq_attr "type" "unary,binary,move") | |
81 | (eq_attr "length" "1")) | |
82 | (const_string "canuse") | |
83 | ||
84 | (eq_attr "type" "compare") | |
85 | (const_string "set") | |
86 | ||
87 | (eq_attr "type" "cmove,branch") | |
88 | (const_string "use") | |
89 | ||
90 | (eq_attr "type" "multi,misc") | |
91 | (const_string "clob") | |
92 | ] | |
93 | ||
94 | (const_string "nocond"))) | |
95 | \f | |
96 | ;; Delay slots. | |
97 | ||
98 | (define_attr "in_delay_slot" "false,true" | |
99 | (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi") | |
100 | (const_string "false") | |
101 | ] | |
102 | ||
103 | (if_then_else (eq_attr "length" "1") | |
104 | (const_string "true") | |
105 | (const_string "false")))) | |
106 | ||
107 | (define_delay (eq_attr "type" "call") | |
108 | [(eq_attr "in_delay_slot" "true") | |
109 | (eq_attr "in_delay_slot" "true") | |
110 | (eq_attr "in_delay_slot" "true")]) | |
111 | ||
112 | (define_delay (eq_attr "type" "branch,uncond_branch") | |
113 | [(eq_attr "in_delay_slot" "true") | |
114 | (eq_attr "in_delay_slot" "true") | |
115 | (eq_attr "in_delay_slot" "true")]) | |
116 | \f | |
a59f1942 | 117 | ;; Scheduling description for the ARC |
5680076c | 118 | |
a59f1942 PB |
119 | (define_cpu_unit "branch") |
120 | ||
121 | (define_insn_reservation "any_insn" 1 (eq_attr "type" "!load,compare,branch") | |
122 | "nothing") | |
5680076c JL |
123 | |
124 | ;; 1) A conditional jump cannot immediately follow the insn setting the flags. | |
125 | ;; This isn't a complete solution as it doesn't come with guarantees. That | |
126 | ;; is done in the branch patterns and in arc_print_operand. This exists to | |
127 | ;; avoid inserting a nop when we can. | |
a59f1942 PB |
128 | |
129 | (define_insn_reservation "compare" 1 (eq_attr "type" "compare") | |
130 | "nothing,branch") | |
131 | ||
132 | (define_insn_reservation "branch" 1 (eq_attr "type" "branch") | |
133 | "branch") | |
5680076c JL |
134 | |
135 | ;; 2) References to loaded registers should wait a cycle. | |
136 | ||
137 | ;; Memory with load-delay of 1 (i.e., 2 cycle load). | |
5680076c | 138 | |
a59f1942 PB |
139 | (define_insn_reservation "memory" 2 (eq_attr "type" "load") |
140 | "nothing") | |
5680076c JL |
141 | \f |
142 | ;; Move instructions. | |
143 | ||
144 | (define_expand "movqi" | |
145 | [(set (match_operand:QI 0 "general_operand" "") | |
146 | (match_operand:QI 1 "general_operand" ""))] | |
147 | "" | |
148 | " | |
149 | { | |
150 | /* Everything except mem = const or mem = mem can be done easily. */ | |
151 | ||
152 | if (GET_CODE (operands[0]) == MEM) | |
153 | operands[1] = force_reg (QImode, operands[1]); | |
154 | }") | |
155 | ||
156 | (define_insn "*movqi_insn" | |
157 | [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,m") | |
158 | (match_operand:QI 1 "move_src_operand" "rI,Ji,m,r"))] | |
159 | ;; ??? Needed? | |
160 | "register_operand (operands[0], QImode) | |
161 | || register_operand (operands[1], QImode)" | |
162 | "@ | |
163 | mov%? %0,%1 | |
164 | mov%? %0,%1 | |
165 | ldb%U1%V1 %0,%1 | |
166 | stb%U0%V0 %1,%0" | |
167 | [(set_attr "type" "move,move,load,store")]) | |
168 | ||
169 | ;; ??? This may never match since there's no cmpqi insn. | |
170 | ||
171 | (define_insn "*movqi_set_cc_insn" | |
172 | [(set (reg:CCZN 61) (compare:CCZN | |
173 | (sign_extend:SI (match_operand:QI 1 "move_src_operand" "rIJi")) | |
174 | (const_int 0))) | |
175 | (set (match_operand:QI 0 "move_dest_operand" "=r") | |
176 | (match_dup 1))] | |
177 | "" | |
178 | "mov%?.f %0,%1" | |
179 | [(set_attr "type" "move") | |
180 | (set_attr "cond" "set_zn")]) | |
181 | ||
182 | (define_expand "movhi" | |
183 | [(set (match_operand:HI 0 "general_operand" "") | |
184 | (match_operand:HI 1 "general_operand" ""))] | |
185 | "" | |
186 | " | |
187 | { | |
188 | /* Everything except mem = const or mem = mem can be done easily. */ | |
189 | ||
190 | if (GET_CODE (operands[0]) == MEM) | |
191 | operands[1] = force_reg (HImode, operands[1]); | |
192 | }") | |
193 | ||
194 | (define_insn "*movhi_insn" | |
195 | [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,m") | |
196 | (match_operand:HI 1 "move_src_operand" "rI,Ji,m,r"))] | |
197 | "register_operand (operands[0], HImode) | |
198 | || register_operand (operands[1], HImode)" | |
199 | "@ | |
200 | mov%? %0,%1 | |
201 | mov%? %0,%1 | |
202 | ldw%U1%V1 %0,%1 | |
203 | stw%U0%V0 %1,%0" | |
204 | [(set_attr "type" "move,move,load,store")]) | |
205 | ||
206 | ;; ??? Will this ever match? | |
207 | ||
208 | (define_insn "*movhi_set_cc_insn" | |
209 | [(set (reg:CCZN 61) (compare:CCZN | |
210 | (sign_extend:SI (match_operand:HI 1 "move_src_operand" "rIJi")) | |
211 | (const_int 0))) | |
212 | (set (match_operand:HI 0 "move_dest_operand" "=r") | |
213 | (match_dup 1))] | |
214 | ;; ??? Needed? | |
215 | "register_operand (operands[0], HImode) | |
216 | || register_operand (operands[1], HImode)" | |
217 | "mov%?.f %0,%1" | |
218 | [(set_attr "type" "move") | |
219 | (set_attr "cond" "set_zn")]) | |
220 | ||
221 | (define_expand "movsi" | |
222 | [(set (match_operand:SI 0 "general_operand" "") | |
223 | (match_operand:SI 1 "general_operand" ""))] | |
224 | "" | |
225 | " | |
226 | { | |
227 | /* Everything except mem = const or mem = mem can be done easily. */ | |
228 | ||
229 | if (GET_CODE (operands[0]) == MEM) | |
230 | operands[1] = force_reg (SImode, operands[1]); | |
231 | }") | |
232 | ||
233 | (define_insn "*movsi_insn" | |
234 | [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,m") | |
235 | (match_operand:SI 1 "move_src_operand" "rI,GJi,m,r"))] | |
236 | "register_operand (operands[0], SImode) | |
237 | || register_operand (operands[1], SImode)" | |
238 | "@ | |
239 | mov%? %0,%1 | |
240 | mov%? %0,%S1 | |
241 | ld%U1%V1 %0,%1 | |
242 | st%U0%V0 %1,%0" | |
243 | [(set_attr "type" "move,move,load,store")]) | |
244 | ||
245 | (define_insn "*movsi_set_cc_insn" | |
246 | [(set (reg:CCZN 61) (compare:CCZN | |
247 | (match_operand:SI 1 "move_src_operand" "rIJi") | |
248 | (const_int 0))) | |
249 | (set (match_operand:SI 0 "move_dest_operand" "=r") | |
250 | (match_dup 1))] | |
251 | "register_operand (operands[0], SImode) | |
252 | || register_operand (operands[1], SImode)" | |
253 | "mov%?.f %0,%S1" | |
254 | [(set_attr "type" "move") | |
255 | (set_attr "cond" "set_zn")]) | |
256 | ||
257 | (define_expand "movdi" | |
258 | [(set (match_operand:DI 0 "general_operand" "") | |
259 | (match_operand:DI 1 "general_operand" ""))] | |
260 | "" | |
261 | " | |
262 | { | |
263 | /* Everything except mem = const or mem = mem can be done easily. */ | |
264 | ||
265 | if (GET_CODE (operands[0]) == MEM) | |
266 | operands[1] = force_reg (DImode, operands[1]); | |
267 | }") | |
268 | ||
269 | (define_insn "*movdi_insn" | |
270 | [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,m") | |
271 | (match_operand:DI 1 "move_double_src_operand" "r,HK,m,r"))] | |
272 | "register_operand (operands[0], DImode) | |
273 | || register_operand (operands[1], DImode)" | |
274 | "* | |
275 | { | |
276 | switch (which_alternative) | |
277 | { | |
278 | case 0 : | |
279 | /* We normally copy the low-numbered register first. However, if | |
280 | the first register operand 0 is the same as the second register of | |
281 | operand 1, we must copy in the opposite order. */ | |
282 | if (REGNO (operands[0]) == REGNO (operands[1]) + 1) | |
283 | return \"mov %R0,%R1\;mov %0,%1\"; | |
284 | else | |
285 | return \"mov %0,%1\;mov %R0,%R1\"; | |
286 | case 1 : | |
287 | return \"mov %0,%L1\;mov %R0,%H1\"; | |
288 | case 2 : | |
289 | /* If the low-address word is used in the address, we must load it | |
290 | last. Otherwise, load it first. Note that we cannot have | |
291 | auto-increment in that case since the address register is known to be | |
292 | dead. */ | |
293 | if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, | |
294 | operands [1], 0)) | |
295 | return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\"; | |
296 | else | |
297 | return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\"; | |
298 | case 3 : | |
299 | return \"st%V0 %1,%0\;st%V0 %R1,%R0\"; | |
2b046bda | 300 | default: |
5e16a15b | 301 | gcc_unreachable (); |
5680076c JL |
302 | } |
303 | }" | |
304 | [(set_attr "type" "move,move,load,store") | |
305 | ;; ??? The ld/st values could be 4 if it's [reg,bignum]. | |
306 | (set_attr "length" "2,4,2,2")]) | |
307 | ||
308 | ;(define_expand "movdi" | |
309 | ; [(set (match_operand:DI 0 "general_operand" "") | |
310 | ; (match_operand:DI 1 "general_operand" ""))] | |
311 | ; "" | |
312 | ; " | |
313 | ;{ | |
314 | ; /* Flow doesn't understand that this is effectively a DFmode move. | |
315 | ; It doesn't know that all of `operands[0]' is set. */ | |
c5c76735 | 316 | ; emit_insn (gen_rtx_CLOBBER (VOIDmode, operands[0])); |
5680076c JL |
317 | ; |
318 | ; /* Emit insns that movsi_insn can handle. */ | |
319 | ; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DImode), | |
320 | ; operand_subword (operands[1], 0, 0, DImode))); | |
321 | ; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DImode), | |
322 | ; operand_subword (operands[1], 1, 0, DImode))); | |
323 | ; DONE; | |
324 | ;}") | |
325 | \f | |
326 | ;; Floating point move insns. | |
327 | ||
328 | (define_expand "movsf" | |
329 | [(set (match_operand:SF 0 "general_operand" "") | |
330 | (match_operand:SF 1 "general_operand" ""))] | |
331 | "" | |
332 | " | |
333 | { | |
334 | /* Everything except mem = const or mem = mem can be done easily. */ | |
5680076c JL |
335 | if (GET_CODE (operands[0]) == MEM) |
336 | operands[1] = force_reg (SFmode, operands[1]); | |
337 | }") | |
338 | ||
339 | (define_insn "*movsf_insn" | |
340 | [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m") | |
341 | (match_operand:SF 1 "move_src_operand" "r,E,m,r"))] | |
342 | "register_operand (operands[0], SFmode) | |
343 | || register_operand (operands[1], SFmode)" | |
344 | "@ | |
345 | mov%? %0,%1 | |
346 | mov%? %0,%1 ; %A1 | |
347 | ld%U1%V1 %0,%1 | |
348 | st%U0%V0 %1,%0" | |
349 | [(set_attr "type" "move,move,load,store")]) | |
350 | ||
351 | (define_expand "movdf" | |
352 | [(set (match_operand:DF 0 "general_operand" "") | |
353 | (match_operand:DF 1 "general_operand" ""))] | |
354 | "" | |
355 | " | |
356 | { | |
357 | /* Everything except mem = const or mem = mem can be done easily. */ | |
5680076c JL |
358 | if (GET_CODE (operands[0]) == MEM) |
359 | operands[1] = force_reg (DFmode, operands[1]); | |
360 | }") | |
361 | ||
362 | (define_insn "*movdf_insn" | |
363 | [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m") | |
364 | (match_operand:DF 1 "move_double_src_operand" "r,E,m,r"))] | |
365 | "register_operand (operands[0], DFmode) | |
366 | || register_operand (operands[1], DFmode)" | |
367 | "* | |
368 | { | |
369 | switch (which_alternative) | |
370 | { | |
371 | case 0 : | |
372 | /* We normally copy the low-numbered register first. However, if | |
373 | the first register operand 0 is the same as the second register of | |
374 | operand 1, we must copy in the opposite order. */ | |
375 | if (REGNO (operands[0]) == REGNO (operands[1]) + 1) | |
376 | return \"mov %R0,%R1\;mov %0,%1\"; | |
377 | else | |
378 | return \"mov %0,%1\;mov %R0,%R1\"; | |
379 | case 1 : | |
380 | return \"mov %0,%L1\;mov %R0,%H1 ; %A1\"; | |
381 | case 2 : | |
382 | /* If the low-address word is used in the address, we must load it | |
383 | last. Otherwise, load it first. Note that we cannot have | |
384 | auto-increment in that case since the address register is known to be | |
385 | dead. */ | |
386 | if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, | |
387 | operands [1], 0)) | |
388 | return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\"; | |
389 | else | |
390 | return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\"; | |
391 | case 3 : | |
392 | return \"st%V0 %1,%0\;st%V0 %R1,%R0\"; | |
2b046bda | 393 | default: |
5e16a15b | 394 | gcc_unreachable (); |
5680076c JL |
395 | } |
396 | }" | |
397 | [(set_attr "type" "move,move,load,store") | |
398 | ;; ??? The ld/st values could be 4 if it's [reg,bignum]. | |
399 | (set_attr "length" "2,4,2,2")]) | |
400 | ||
401 | ;(define_expand "movdf" | |
402 | ; [(set (match_operand:DF 0 "general_operand" "") | |
403 | ; (match_operand:DF 1 "general_operand" ""))] | |
404 | ; "" | |
405 | ; " | |
406 | ;{ | |
407 | ; /* Flow doesn't understand that this is effectively a DFmode move. | |
408 | ; It doesn't know that all of `operands[0]' is set. */ | |
c5c76735 | 409 | ; emit_insn (gen_rtx_CLOBBER (VOIDmode, operands[0])); |
5680076c JL |
410 | ; |
411 | ; /* Emit insns that movsi_insn can handle. */ | |
412 | ; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DFmode), | |
413 | ; operand_subword (operands[1], 0, 0, DFmode))); | |
414 | ; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DFmode), | |
415 | ; operand_subword (operands[1], 1, 0, DFmode))); | |
416 | ; DONE; | |
417 | ;}") | |
418 | \f | |
419 | ;; Load/Store with update instructions. | |
420 | ;; | |
421 | ;; Some of these we can get by using pre-decrement or pre-increment, but the | |
422 | ;; hardware can also do cases where the increment is not the size of the | |
423 | ;; object. | |
424 | ;; | |
425 | ;; In all these cases, we use operands 0 and 1 for the register being | |
426 | ;; incremented because those are the operands that local-alloc will | |
427 | ;; tie and these are the pair most likely to be tieable (and the ones | |
428 | ;; that will benefit the most). | |
429 | ;; | |
430 | ;; We use match_operator here because we need to know whether the memory | |
431 | ;; object is volatile or not. | |
432 | ||
433 | (define_insn "*loadqi_update" | |
434 | [(set (match_operand:QI 3 "register_operand" "=r,r") | |
435 | (match_operator:QI 4 "load_update_operand" | |
436 | [(match_operand:SI 1 "register_operand" "0,0") | |
437 | (match_operand:SI 2 "nonmemory_operand" "rI,J")])) | |
438 | (set (match_operand:SI 0 "register_operand" "=r,r") | |
439 | (plus:SI (match_dup 1) (match_dup 2)))] | |
440 | "" | |
441 | "ldb.a%V4 %3,[%0,%2]" | |
442 | [(set_attr "type" "load,load") | |
443 | (set_attr "length" "1,2")]) | |
444 | ||
445 | (define_insn "*load_zeroextendqisi_update" | |
446 | [(set (match_operand:SI 3 "register_operand" "=r,r") | |
447 | (zero_extend:SI (match_operator:QI 4 "load_update_operand" | |
448 | [(match_operand:SI 1 "register_operand" "0,0") | |
449 | (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) | |
450 | (set (match_operand:SI 0 "register_operand" "=r,r") | |
451 | (plus:SI (match_dup 1) (match_dup 2)))] | |
452 | "" | |
453 | "ldb.a%V4 %3,[%0,%2]" | |
454 | [(set_attr "type" "load,load") | |
455 | (set_attr "length" "1,2")]) | |
456 | ||
457 | (define_insn "*load_signextendqisi_update" | |
458 | [(set (match_operand:SI 3 "register_operand" "=r,r") | |
459 | (sign_extend:SI (match_operator:QI 4 "load_update_operand" | |
460 | [(match_operand:SI 1 "register_operand" "0,0") | |
461 | (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) | |
462 | (set (match_operand:SI 0 "register_operand" "=r,r") | |
463 | (plus:SI (match_dup 1) (match_dup 2)))] | |
464 | "" | |
465 | "ldb.x.a%V4 %3,[%0,%2]" | |
466 | [(set_attr "type" "load,load") | |
467 | (set_attr "length" "1,2")]) | |
468 | ||
469 | (define_insn "*storeqi_update" | |
470 | [(set (match_operator:QI 4 "store_update_operand" | |
471 | [(match_operand:SI 1 "register_operand" "0") | |
472 | (match_operand:SI 2 "short_immediate_operand" "I")]) | |
473 | (match_operand:QI 3 "register_operand" "r")) | |
474 | (set (match_operand:SI 0 "register_operand" "=r") | |
475 | (plus:SI (match_dup 1) (match_dup 2)))] | |
476 | "" | |
477 | "stb.a%V4 %3,[%0,%2]" | |
478 | [(set_attr "type" "store") | |
479 | (set_attr "length" "1")]) | |
480 | ||
481 | (define_insn "*loadhi_update" | |
482 | [(set (match_operand:HI 3 "register_operand" "=r,r") | |
483 | (match_operator:HI 4 "load_update_operand" | |
484 | [(match_operand:SI 1 "register_operand" "0,0") | |
485 | (match_operand:SI 2 "nonmemory_operand" "rI,J")])) | |
486 | (set (match_operand:SI 0 "register_operand" "=r,r") | |
487 | (plus:SI (match_dup 1) (match_dup 2)))] | |
488 | "" | |
489 | "ldw.a%V4 %3,[%0,%2]" | |
490 | [(set_attr "type" "load,load") | |
491 | (set_attr "length" "1,2")]) | |
492 | ||
493 | (define_insn "*load_zeroextendhisi_update" | |
494 | [(set (match_operand:SI 3 "register_operand" "=r,r") | |
495 | (zero_extend:SI (match_operator:HI 4 "load_update_operand" | |
496 | [(match_operand:SI 1 "register_operand" "0,0") | |
497 | (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) | |
498 | (set (match_operand:SI 0 "register_operand" "=r,r") | |
499 | (plus:SI (match_dup 1) (match_dup 2)))] | |
500 | "" | |
501 | "ldw.a%V4 %3,[%0,%2]" | |
502 | [(set_attr "type" "load,load") | |
503 | (set_attr "length" "1,2")]) | |
504 | ||
505 | (define_insn "*load_signextendhisi_update" | |
506 | [(set (match_operand:SI 3 "register_operand" "=r,r") | |
507 | (sign_extend:SI (match_operator:HI 4 "load_update_operand" | |
508 | [(match_operand:SI 1 "register_operand" "0,0") | |
509 | (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) | |
510 | (set (match_operand:SI 0 "register_operand" "=r,r") | |
511 | (plus:SI (match_dup 1) (match_dup 2)))] | |
512 | "" | |
513 | "ldw.x.a%V4 %3,[%0,%2]" | |
514 | [(set_attr "type" "load,load") | |
515 | (set_attr "length" "1,2")]) | |
516 | ||
517 | (define_insn "*storehi_update" | |
518 | [(set (match_operator:HI 4 "store_update_operand" | |
519 | [(match_operand:SI 1 "register_operand" "0") | |
520 | (match_operand:SI 2 "short_immediate_operand" "I")]) | |
521 | (match_operand:HI 3 "register_operand" "r")) | |
522 | (set (match_operand:SI 0 "register_operand" "=r") | |
523 | (plus:SI (match_dup 1) (match_dup 2)))] | |
524 | "" | |
525 | "stw.a%V4 %3,[%0,%2]" | |
526 | [(set_attr "type" "store") | |
527 | (set_attr "length" "1")]) | |
528 | ||
529 | (define_insn "*loadsi_update" | |
530 | [(set (match_operand:SI 3 "register_operand" "=r,r") | |
531 | (match_operator:SI 4 "load_update_operand" | |
532 | [(match_operand:SI 1 "register_operand" "0,0") | |
533 | (match_operand:SI 2 "nonmemory_operand" "rI,J")])) | |
534 | (set (match_operand:SI 0 "register_operand" "=r,r") | |
535 | (plus:SI (match_dup 1) (match_dup 2)))] | |
536 | "" | |
537 | "ld.a%V4 %3,[%0,%2]" | |
538 | [(set_attr "type" "load,load") | |
539 | (set_attr "length" "1,2")]) | |
540 | ||
541 | (define_insn "*storesi_update" | |
542 | [(set (match_operator:SI 4 "store_update_operand" | |
543 | [(match_operand:SI 1 "register_operand" "0") | |
544 | (match_operand:SI 2 "short_immediate_operand" "I")]) | |
545 | (match_operand:SI 3 "register_operand" "r")) | |
546 | (set (match_operand:SI 0 "register_operand" "=r") | |
547 | (plus:SI (match_dup 1) (match_dup 2)))] | |
548 | "" | |
549 | "st.a%V4 %3,[%0,%2]" | |
550 | [(set_attr "type" "store") | |
551 | (set_attr "length" "1")]) | |
552 | ||
553 | (define_insn "*loadsf_update" | |
554 | [(set (match_operand:SF 3 "register_operand" "=r,r") | |
555 | (match_operator:SF 4 "load_update_operand" | |
556 | [(match_operand:SI 1 "register_operand" "0,0") | |
557 | (match_operand:SI 2 "nonmemory_operand" "rI,J")])) | |
558 | (set (match_operand:SI 0 "register_operand" "=r,r") | |
559 | (plus:SI (match_dup 1) (match_dup 2)))] | |
560 | "" | |
561 | "ld.a%V4 %3,[%0,%2]" | |
562 | [(set_attr "type" "load,load") | |
563 | (set_attr "length" "1,2")]) | |
564 | ||
565 | (define_insn "*storesf_update" | |
566 | [(set (match_operator:SF 4 "store_update_operand" | |
567 | [(match_operand:SI 1 "register_operand" "0") | |
568 | (match_operand:SI 2 "short_immediate_operand" "I")]) | |
569 | (match_operand:SF 3 "register_operand" "r")) | |
570 | (set (match_operand:SI 0 "register_operand" "=r") | |
571 | (plus:SI (match_dup 1) (match_dup 2)))] | |
572 | "" | |
573 | "st.a%V4 %3,[%0,%2]" | |
574 | [(set_attr "type" "store") | |
575 | (set_attr "length" "1")]) | |
576 | \f | |
577 | ;; Conditional move instructions. | |
578 | ||
579 | (define_expand "movsicc" | |
580 | [(set (match_operand:SI 0 "register_operand" "") | |
71a83373 JJ |
581 | (if_then_else:SI (match_operand 1 "comparison_operator" "") |
582 | (match_operand:SI 2 "nonmemory_operand" "") | |
583 | (match_operand:SI 3 "register_operand" "")))] | |
5680076c JL |
584 | "" |
585 | " | |
586 | { | |
587 | enum rtx_code code = GET_CODE (operands[1]); | |
c5c76735 JL |
588 | rtx ccreg |
589 | = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), | |
590 | 61); | |
5680076c | 591 | |
1c563bed | 592 | operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); |
5680076c JL |
593 | }") |
594 | ||
595 | ;(define_expand "movdicc" | |
596 | ; [(set (match_operand:DI 0 "register_operand" "") | |
71a83373 JJ |
597 | ; (if_then_else:DI (match_operand 1 "comparison_operator" "") |
598 | ; (match_operand:DI 2 "nonmemory_operand" "") | |
599 | ; (match_operand:DI 3 "register_operand" "")))] | |
5680076c JL |
600 | ; "0 /* ??? this would work better if we had cmpdi */" |
601 | ; " | |
602 | ;{ | |
603 | ; enum rtx_code code = GET_CODE (operands[1]); | |
c5c76735 JL |
604 | ; rtx ccreg |
605 | ; = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), | |
606 | ; 61); | |
5680076c | 607 | ; |
1c563bed | 608 | ; operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); |
9a76ab7e | 609 | ;}") |
c5c76735 | 610 | |
71a83373 | 611 | (define_expand "movsfcc" |
5680076c | 612 | [(set (match_operand:SF 0 "register_operand" "") |
71a83373 JJ |
613 | (if_then_else:SF (match_operand 1 "comparison_operator" "") |
614 | (match_operand:SF 2 "nonmemory_operand" "") | |
615 | (match_operand:SF 3 "register_operand" "")))] | |
5680076c JL |
616 | "" |
617 | " | |
618 | { | |
619 | enum rtx_code code = GET_CODE (operands[1]); | |
c5c76735 JL |
620 | rtx ccreg |
621 | = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), | |
622 | 61); | |
5680076c | 623 | |
1c563bed | 624 | operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); |
5680076c JL |
625 | }") |
626 | ||
627 | ;(define_expand "movdfcc" | |
628 | ; [(set (match_operand:DF 0 "register_operand" "") | |
71a83373 JJ |
629 | ; (if_then_else:DF (match_operand 1 "comparison_operator" "") |
630 | ; (match_operand:DF 2 "nonmemory_operand" "") | |
631 | ; (match_operand:DF 3 "register_operand" "")))] | |
5680076c JL |
632 | ; "0 /* ??? can generate less efficient code if constants involved */" |
633 | ; " | |
634 | ;{ | |
c5c76735 JL |
635 | ; enum rtx_code code = GET_CODE (operands[1]); |
636 | ; rtx ccreg | |
637 | ; = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), | |
638 | ; 61); | |
5680076c | 639 | ; |
1c563bed | 640 | ; operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); |
9a76ab7e | 641 | ;}") |
5680076c JL |
642 | |
643 | (define_insn "*movsicc_insn" | |
644 | [(set (match_operand:SI 0 "register_operand" "=r") | |
71a83373 JJ |
645 | (if_then_else:SI (match_operand 1 "comparison_operator" "") |
646 | (match_operand:SI 2 "nonmemory_operand" "rJi") | |
647 | (match_operand:SI 3 "register_operand" "0")))] | |
5680076c JL |
648 | "" |
649 | "mov.%d1 %0,%S2" | |
650 | [(set_attr "type" "cmove")]) | |
651 | ||
652 | ; ??? This doesn't properly handle constants. | |
653 | ;(define_insn "*movdicc_insn" | |
654 | ; [(set (match_operand:DI 0 "register_operand" "=r,r") | |
71a83373 JJ |
655 | ; (if_then_else:DI (match_operand 1 "comparison_operator" "") |
656 | ; (match_operand:DI 2 "nonmemory_operand" "r,Ji") | |
657 | ; (match_operand:DI 3 "register_operand" "0,0")))] | |
5680076c JL |
658 | ; "0" |
659 | ; "* | |
660 | ;{ | |
661 | ; switch (which_alternative) | |
662 | ; { | |
663 | ; case 0 : | |
664 | ; /* We normally copy the low-numbered register first. However, if | |
665 | ; the first register operand 0 is the same as the second register of | |
666 | ; operand 1, we must copy in the opposite order. */ | |
667 | ; if (REGNO (operands[0]) == REGNO (operands[2]) + 1) | |
668 | ; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\"; | |
669 | ; else | |
670 | ; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; | |
671 | ; case 1 : | |
672 | ; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; | |
673 | ; } | |
674 | ;}" | |
675 | ; [(set_attr "type" "cmove,cmove") | |
676 | ; (set_attr "length" "2,4")]) | |
677 | ||
678 | (define_insn "*movsfcc_insn" | |
679 | [(set (match_operand:SF 0 "register_operand" "=r,r") | |
71a83373 JJ |
680 | (if_then_else:SF (match_operand 1 "comparison_operator" "") |
681 | (match_operand:SF 2 "nonmemory_operand" "r,E") | |
682 | (match_operand:SF 3 "register_operand" "0,0")))] | |
5680076c JL |
683 | "" |
684 | "@ | |
685 | mov.%d1 %0,%2 | |
686 | mov.%d1 %0,%2 ; %A2" | |
687 | [(set_attr "type" "cmove,cmove")]) | |
688 | ||
689 | ;(define_insn "*movdfcc_insn" | |
690 | ; [(set (match_operand:DF 0 "register_operand" "=r,r") | |
71a83373 JJ |
691 | ; (if_then_else:DF (match_operand 1 "comparison_operator" "") |
692 | ; (match_operand:DF 2 "nonmemory_operand" "r,E") | |
693 | ; (match_operand:DF 3 "register_operand" "0,0")))] | |
5680076c JL |
694 | ; "0" |
695 | ; "* | |
696 | ;{ | |
697 | ; switch (which_alternative) | |
698 | ; { | |
699 | ; case 0 : | |
700 | ; /* We normally copy the low-numbered register first. However, if | |
701 | ; the first register operand 0 is the same as the second register of | |
702 | ; operand 1, we must copy in the opposite order. */ | |
703 | ; if (REGNO (operands[0]) == REGNO (operands[2]) + 1) | |
704 | ; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\"; | |
705 | ; else | |
706 | ; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; | |
707 | ; case 1 : | |
708 | ; return \"mov.%d1 %0,%L2\;mov.%d1 %R0,%H2 ; %A2\"; | |
709 | ; } | |
710 | ;}" | |
711 | ; [(set_attr "type" "cmove,cmove") | |
712 | ; (set_attr "length" "2,4")]) | |
713 | \f | |
714 | ;; Zero extension instructions. | |
715 | ;; ??? We don't support volatile memrefs here, but I'm not sure why. | |
716 | ||
717 | (define_insn "zero_extendqihi2" | |
718 | [(set (match_operand:HI 0 "register_operand" "=r,r") | |
719 | (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] | |
720 | "" | |
721 | "@ | |
722 | extb%? %0,%1 | |
723 | ldb%U1 %0,%1" | |
724 | [(set_attr "type" "unary,load")]) | |
725 | ||
726 | (define_insn "*zero_extendqihi2_set_cc_insn" | |
727 | [(set (reg:CCZN 61) (compare:CCZN | |
728 | (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) | |
729 | (const_int 0))) | |
730 | (set (match_operand:HI 0 "register_operand" "=r") | |
731 | (zero_extend:HI (match_dup 1)))] | |
732 | "" | |
733 | "extb%?.f %0,%1" | |
734 | [(set_attr "type" "unary") | |
735 | (set_attr "cond" "set_zn")]) | |
736 | ||
737 | (define_insn "zero_extendqisi2" | |
738 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
739 | (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] | |
740 | "" | |
741 | "@ | |
742 | extb%? %0,%1 | |
743 | ldb%U1 %0,%1" | |
744 | [(set_attr "type" "unary,load")]) | |
745 | ||
746 | (define_insn "*zero_extendqisi2_set_cc_insn" | |
747 | [(set (reg:CCZN 61) (compare:CCZN | |
748 | (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) | |
749 | (const_int 0))) | |
750 | (set (match_operand:SI 0 "register_operand" "=r") | |
751 | (zero_extend:SI (match_dup 1)))] | |
752 | "" | |
753 | "extb%?.f %0,%1" | |
754 | [(set_attr "type" "unary") | |
755 | (set_attr "cond" "set_zn")]) | |
756 | ||
757 | (define_insn "zero_extendhisi2" | |
758 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
759 | (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))] | |
760 | "" | |
761 | "@ | |
762 | extw%? %0,%1 | |
763 | ldw%U1 %0,%1" | |
764 | [(set_attr "type" "unary,load")]) | |
765 | ||
766 | (define_insn "*zero_extendhisi2_set_cc_insn" | |
767 | [(set (reg:CCZN 61) (compare:CCZN | |
768 | (zero_extend:SI (match_operand:HI 1 "register_operand" "r")) | |
769 | (const_int 0))) | |
770 | (set (match_operand:SI 0 "register_operand" "=r") | |
771 | (zero_extend:SI (match_dup 1)))] | |
772 | "" | |
773 | "extw%?.f %0,%1" | |
774 | [(set_attr "type" "unary") | |
775 | (set_attr "cond" "set_zn")]) | |
776 | \f | |
777 | ;; Sign extension instructions. | |
778 | ||
779 | (define_insn "extendqihi2" | |
780 | [(set (match_operand:HI 0 "register_operand" "=r,r") | |
781 | (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] | |
782 | "" | |
783 | "@ | |
784 | sexb%? %0,%1 | |
785 | ldb.x%U1 %0,%1" | |
786 | [(set_attr "type" "unary,load")]) | |
787 | ||
788 | (define_insn "*extendqihi2_set_cc_insn" | |
789 | [(set (reg:CCZN 61) (compare:CCZN | |
790 | (sign_extend:SI (match_operand:QI 1 "register_operand" "r")) | |
791 | (const_int 0))) | |
792 | (set (match_operand:HI 0 "register_operand" "=r") | |
793 | (sign_extend:HI (match_dup 1)))] | |
794 | "" | |
795 | "sexb%?.f %0,%1" | |
796 | [(set_attr "type" "unary") | |
797 | (set_attr "cond" "set_zn")]) | |
798 | ||
799 | (define_insn "extendqisi2" | |
800 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
801 | (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] | |
802 | "" | |
803 | "@ | |
804 | sexb%? %0,%1 | |
805 | ldb.x%U1 %0,%1" | |
806 | [(set_attr "type" "unary,load")]) | |
807 | ||
808 | (define_insn "*extendqisi2_set_cc_insn" | |
809 | [(set (reg:CCZN 61) (compare:CCZN | |
810 | (sign_extend:SI (match_operand:QI 1 "register_operand" "r")) | |
811 | (const_int 0))) | |
812 | (set (match_operand:SI 0 "register_operand" "=r") | |
813 | (sign_extend:SI (match_dup 1)))] | |
814 | "" | |
815 | "sexb%?.f %0,%1" | |
816 | [(set_attr "type" "unary") | |
817 | (set_attr "cond" "set_zn")]) | |
818 | ||
819 | (define_insn "extendhisi2" | |
820 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
821 | (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))] | |
822 | "" | |
823 | "@ | |
824 | sexw%? %0,%1 | |
825 | ldw.x%U1 %0,%1" | |
826 | [(set_attr "type" "unary,load")]) | |
827 | ||
828 | (define_insn "*extendhisi2_set_cc_insn" | |
829 | [(set (reg:CCZN 61) (compare:CCZN | |
830 | (sign_extend:SI (match_operand:HI 1 "register_operand" "r")) | |
831 | (const_int 0))) | |
832 | (set (match_operand:SI 0 "register_operand" "=r") | |
833 | (sign_extend:SI (match_dup 1)))] | |
834 | "" | |
835 | "sexw%?.f %0,%1" | |
836 | [(set_attr "type" "unary") | |
837 | (set_attr "cond" "set_zn")]) | |
838 | \f | |
839 | ;; Arithmetic instructions. | |
840 | ||
841 | (define_insn "addsi3" | |
842 | [(set (match_operand:SI 0 "register_operand" "=r") | |
843 | (plus:SI (match_operand:SI 1 "register_operand" "%r") | |
844 | (match_operand:SI 2 "nonmemory_operand" "rIJ")))] | |
845 | "" | |
846 | "add%? %0,%1,%2") | |
847 | ||
848 | (define_insn "*addsi3_set_cc_insn" | |
849 | [(set (reg:CC 61) (compare:CC | |
850 | (plus:SI (match_operand:SI 1 "register_operand" "%r") | |
851 | (match_operand:SI 2 "nonmemory_operand" "rIJ")) | |
852 | (const_int 0))) | |
853 | (set (match_operand:SI 0 "register_operand" "=r") | |
854 | (plus:SI (match_dup 1) | |
855 | (match_dup 2)))] | |
856 | "" | |
857 | "add%?.f %0,%1,%2" | |
858 | [(set_attr "cond" "set")]) | |
859 | ||
860 | (define_insn "adddi3" | |
861 | [(set (match_operand:DI 0 "register_operand" "=r") | |
862 | (plus:DI (match_operand:DI 1 "nonmemory_operand" "%r") | |
863 | (match_operand:DI 2 "nonmemory_operand" "ri"))) | |
864 | (clobber (reg:CC 61))] | |
865 | "" | |
866 | "* | |
867 | { | |
868 | rtx op2 = operands[2]; | |
869 | ||
870 | if (GET_CODE (op2) == CONST_INT) | |
871 | { | |
872 | int sign = INTVAL (op2); | |
873 | if (sign < 0) | |
874 | return \"add.f %L0,%L1,%2\;adc %H0,%H1,-1\"; | |
875 | else | |
876 | return \"add.f %L0,%L1,%2\;adc %H0,%H1,0\"; | |
877 | } | |
878 | else | |
879 | return \"add.f %L0,%L1,%L2\;adc %H0,%H1,%H2\"; | |
880 | }" | |
881 | [(set_attr "length" "2")]) | |
882 | ||
883 | (define_insn "subsi3" | |
884 | [(set (match_operand:SI 0 "register_operand" "=r") | |
885 | (minus:SI (match_operand:SI 1 "register_operand" "r") | |
886 | (match_operand:SI 2 "nonmemory_operand" "rIJ")))] | |
887 | "" | |
888 | "sub%? %0,%1,%2") | |
889 | ||
890 | (define_insn "*subsi3_set_cc_insn" | |
891 | [(set (reg:CC 61) (compare:CC | |
892 | (minus:SI (match_operand:SI 1 "register_operand" "%r") | |
893 | (match_operand:SI 2 "nonmemory_operand" "rIJ")) | |
894 | (const_int 0))) | |
895 | (set (match_operand:SI 0 "register_operand" "=r") | |
896 | (minus:SI (match_dup 1) | |
897 | (match_dup 2)))] | |
898 | "" | |
899 | "sub%?.f %0,%1,%2" | |
900 | [(set_attr "cond" "set")]) | |
901 | ||
902 | (define_insn "subdi3" | |
903 | [(set (match_operand:DI 0 "register_operand" "=r") | |
904 | (minus:DI (match_operand:DI 1 "nonmemory_operand" "r") | |
905 | (match_operand:DI 2 "nonmemory_operand" "ri"))) | |
906 | (clobber (reg:CC 61))] | |
907 | "" | |
908 | "* | |
909 | { | |
910 | rtx op2 = operands[2]; | |
911 | ||
912 | if (GET_CODE (op2) == CONST_INT) | |
913 | { | |
914 | int sign = INTVAL (op2); | |
915 | if (sign < 0) | |
916 | return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,-1\"; | |
917 | else | |
918 | return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,0\"; | |
919 | } | |
920 | else | |
921 | return \"sub.f %L0,%L1,%L2\;sbc %H0,%H1,%H2\"; | |
922 | }" | |
923 | [(set_attr "length" "2")]) | |
924 | \f | |
925 | ;; Boolean instructions. | |
926 | ;; | |
927 | ;; We don't define the DImode versions as expand_binop does a good enough job. | |
928 | ||
929 | (define_insn "andsi3" | |
930 | [(set (match_operand:SI 0 "register_operand" "=r") | |
931 | (and:SI (match_operand:SI 1 "register_operand" "%r") | |
932 | (match_operand:SI 2 "nonmemory_operand" "rIJ")))] | |
933 | "" | |
934 | "and%? %0,%1,%2") | |
935 | ||
936 | (define_insn "*andsi3_set_cc_insn" | |
937 | [(set (reg:CCZN 61) (compare:CCZN | |
938 | (and:SI (match_operand:SI 1 "register_operand" "%r") | |
939 | (match_operand:SI 2 "nonmemory_operand" "rIJ")) | |
940 | (const_int 0))) | |
941 | (set (match_operand:SI 0 "register_operand" "=r") | |
942 | (and:SI (match_dup 1) | |
943 | (match_dup 2)))] | |
944 | "" | |
945 | "and%?.f %0,%1,%2" | |
946 | [(set_attr "cond" "set_zn")]) | |
947 | ||
948 | (define_insn "*bicsi3_insn" | |
949 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") | |
950 | (and:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") | |
951 | (not:SI (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r"))))] | |
952 | "" | |
953 | "bic%? %0,%1,%2" | |
954 | [(set_attr "length" "1,2,1,2")]) | |
955 | ||
956 | (define_insn "*bicsi3_set_cc_insn" | |
957 | [(set (reg:CCZN 61) (compare:CCZN | |
958 | (and:SI (match_operand:SI 1 "register_operand" "%r") | |
959 | (not:SI (match_operand:SI 2 "nonmemory_operand" "rIJ"))) | |
960 | (const_int 0))) | |
961 | (set (match_operand:SI 0 "register_operand" "=r") | |
962 | (and:SI (match_dup 1) | |
963 | (not:SI (match_dup 2))))] | |
964 | "" | |
965 | "bic%?.f %0,%1,%2" | |
966 | [(set_attr "cond" "set_zn")]) | |
967 | ||
968 | (define_insn "iorsi3" | |
969 | [(set (match_operand:SI 0 "register_operand" "=r") | |
970 | (ior:SI (match_operand:SI 1 "register_operand" "%r") | |
971 | (match_operand:SI 2 "nonmemory_operand" "rIJ")))] | |
972 | "" | |
973 | "or%? %0,%1,%2") | |
974 | ||
975 | (define_insn "*iorsi3_set_cc_insn" | |
976 | [(set (reg:CCZN 61) (compare:CCZN | |
977 | (ior:SI (match_operand:SI 1 "register_operand" "%r") | |
978 | (match_operand:SI 2 "nonmemory_operand" "rIJ")) | |
979 | (const_int 0))) | |
980 | (set (match_operand:SI 0 "register_operand" "=r") | |
981 | (ior:SI (match_dup 1) | |
982 | (match_dup 2)))] | |
983 | "" | |
984 | "or%?.f %0,%1,%2" | |
985 | [(set_attr "cond" "set_zn")]) | |
986 | ||
987 | (define_insn "xorsi3" | |
988 | [(set (match_operand:SI 0 "register_operand" "=r") | |
989 | (xor:SI (match_operand:SI 1 "register_operand" "%r") | |
990 | (match_operand:SI 2 "nonmemory_operand" "rIJ")))] | |
991 | "" | |
992 | "xor%? %0,%1,%2") | |
993 | ||
994 | (define_insn "*xorsi3_set_cc_insn" | |
995 | [(set (reg:CCZN 61) (compare:CCZN | |
996 | (xor:SI (match_operand:SI 1 "register_operand" "%r") | |
997 | (match_operand:SI 2 "nonmemory_operand" "rIJ")) | |
998 | (const_int 0))) | |
999 | (set (match_operand:SI 0 "register_operand" "=r") | |
1000 | (xor:SI (match_dup 1) | |
1001 | (match_dup 2)))] | |
1002 | "" | |
1003 | "xor%?.f %0,%1,%2" | |
1004 | [(set_attr "cond" "set_zn")]) | |
1005 | ||
1006 | (define_insn "negsi2" | |
1007 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1008 | (neg:SI (match_operand:SI 1 "register_operand" "r")))] | |
1009 | "" | |
1010 | "sub%? %0,0,%1" | |
1011 | [(set_attr "type" "unary")]) | |
1012 | ||
1013 | (define_insn "*negsi2_set_cc_insn" | |
1014 | [(set (reg:CC 61) (compare:CC | |
1015 | (neg:SI (match_operand:SI 1 "register_operand" "r")) | |
1016 | (const_int 0))) | |
1017 | (set (match_operand:SI 0 "register_operand" "=r") | |
1018 | (neg:SI (match_dup 1)))] | |
1019 | "" | |
1020 | "sub%?.f %0,0,%1" | |
1021 | [(set_attr "type" "unary") | |
1022 | (set_attr "cond" "set")]) | |
1023 | ||
1024 | (define_insn "negdi2" | |
1025 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1026 | (neg:DI (match_operand:DI 1 "register_operand" "r"))) | |
1027 | (clobber (reg:SI 61))] | |
1028 | "" | |
1029 | "sub.f %L0,0,%L1\;sbc %H0,0,%H1" | |
1030 | [(set_attr "type" "unary") | |
1031 | (set_attr "length" "2")]) | |
1032 | ||
1033 | (define_insn "one_cmplsi2" | |
1034 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1035 | (not:SI (match_operand:SI 1 "register_operand" "r")))] | |
1036 | "" | |
1037 | "xor%? %0,%1,-1" | |
1038 | [(set_attr "type" "unary")]) | |
1039 | ||
1040 | (define_insn "*one_cmplsi2_set_cc_insn" | |
ee5332b8 | 1041 | [(set (reg:CCZN 61) (compare:CCZN |
5680076c JL |
1042 | (not:SI (match_operand:SI 1 "register_operand" "r")) |
1043 | (const_int 0))) | |
1044 | (set (match_operand:SI 0 "register_operand" "=r") | |
1045 | (not:SI (match_dup 1)))] | |
1046 | "" | |
1047 | "xor%?.f %0,%1,-1" | |
1048 | [(set_attr "type" "unary") | |
1049 | (set_attr "cond" "set_zn")]) | |
1050 | \f | |
1051 | ;; Shift instructions. | |
1052 | ||
1053 | (define_expand "ashlsi3" | |
1054 | [(set (match_operand:SI 0 "register_operand" "") | |
1055 | (ashift:SI (match_operand:SI 1 "register_operand" "") | |
1056 | (match_operand:SI 2 "nonmemory_operand" "")))] | |
1057 | "" | |
1058 | " | |
1059 | { | |
1060 | if (! TARGET_SHIFTER) | |
1061 | { | |
c5c76735 JL |
1062 | emit_insn (gen_rtx_PARALLEL |
1063 | (VOIDmode, | |
5680076c | 1064 | gen_rtvec (2, |
c5c76735 JL |
1065 | gen_rtx_SET (VOIDmode, operands[0], |
1066 | gen_rtx_ASHIFT (SImode, operands[1], | |
1067 | operands[2])), | |
1068 | gen_rtx_CLOBBER (VOIDmode, | |
1069 | gen_rtx_SCRATCH (SImode))))); | |
5680076c JL |
1070 | DONE; |
1071 | } | |
1072 | }") | |
1073 | ||
1074 | (define_expand "ashrsi3" | |
1075 | [(set (match_operand:SI 0 "register_operand" "") | |
1076 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "") | |
1077 | (match_operand:SI 2 "nonmemory_operand" "")))] | |
1078 | "" | |
1079 | " | |
1080 | { | |
1081 | if (! TARGET_SHIFTER) | |
1082 | { | |
c5c76735 JL |
1083 | emit_insn (gen_rtx_PARALLEL |
1084 | (VOIDmode, | |
5680076c | 1085 | gen_rtvec (2, |
c5c76735 JL |
1086 | gen_rtx_SET (VOIDmode, operands[0], |
1087 | gen_rtx_ASHIFTRT (SImode, | |
1088 | operands[1], | |
1089 | operands[2])), | |
1090 | gen_rtx_CLOBBER (VOIDmode, | |
1091 | gen_rtx_SCRATCH (SImode))))); | |
5680076c JL |
1092 | DONE; |
1093 | } | |
1094 | }") | |
1095 | ||
1096 | (define_expand "lshrsi3" | |
1097 | [(set (match_operand:SI 0 "register_operand" "") | |
1098 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "") | |
1099 | (match_operand:SI 2 "nonmemory_operand" "")))] | |
1100 | "" | |
1101 | " | |
1102 | { | |
1103 | if (! TARGET_SHIFTER) | |
1104 | { | |
c5c76735 JL |
1105 | emit_insn (gen_rtx_PARALLEL |
1106 | (VOIDmode, | |
5680076c | 1107 | gen_rtvec (2, |
c5c76735 JL |
1108 | gen_rtx_SET (VOIDmode, operands[0], |
1109 | gen_rtx_LSHIFTRT (SImode, | |
1110 | operands[1], | |
1111 | operands[2])), | |
1112 | gen_rtx_CLOBBER (VOIDmode, | |
1113 | gen_rtx_SCRATCH (SImode))))); | |
5680076c JL |
1114 | DONE; |
1115 | } | |
1116 | }") | |
1117 | ||
1118 | (define_insn "*ashlsi3_insn" | |
1119 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") | |
1120 | (ashift:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") | |
1121 | (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] | |
1122 | "TARGET_SHIFTER" | |
1123 | "asl%? %0,%1,%2" | |
1124 | [(set_attr "type" "shift") | |
1125 | (set_attr "length" "1,2,1,2")]) | |
1126 | ||
1127 | (define_insn "*ashrsi3_insn" | |
1128 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") | |
1129 | (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") | |
1130 | (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] | |
1131 | "TARGET_SHIFTER" | |
1132 | "asr%? %0,%1,%2" | |
1133 | [(set_attr "type" "shift") | |
1134 | (set_attr "length" "1,2,1,2")]) | |
1135 | ||
1136 | (define_insn "*lshrsi3_insn" | |
1137 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") | |
1138 | (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") | |
1139 | (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] | |
1140 | "TARGET_SHIFTER" | |
1141 | "lsr%? %0,%1,%2" | |
1142 | [(set_attr "type" "shift") | |
1143 | (set_attr "length" "1,2,1,2")]) | |
1144 | ||
1145 | (define_insn "*shift_si3" | |
1146 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1147 | (match_operator:SI 3 "shift_operator" | |
1148 | [(match_operand:SI 1 "register_operand" "0") | |
1149 | (match_operand:SI 2 "nonmemory_operand" "rIJ")])) | |
1150 | (clobber (match_scratch:SI 4 "=&r"))] | |
1151 | "! TARGET_SHIFTER" | |
1152 | "* return output_shift (operands);" | |
1153 | [(set_attr "type" "shift") | |
1154 | (set_attr "length" "8")]) | |
1155 | \f | |
1156 | ;; Compare instructions. | |
1157 | ;; This controls RTL generation and register allocation. | |
1158 | ||
1159 | ;; We generate RTL for comparisons and branches by having the cmpxx | |
1160 | ;; patterns store away the operands. Then, the scc and bcc patterns | |
1161 | ;; emit RTL for both the compare and the branch. | |
1162 | ||
1163 | (define_expand "cmpsi" | |
1164 | [(set (reg:CC 61) | |
1165 | (compare:CC (match_operand:SI 0 "register_operand" "") | |
1166 | (match_operand:SI 1 "nonmemory_operand" "")))] | |
1167 | "" | |
1168 | " | |
1169 | { | |
1170 | arc_compare_op0 = operands[0]; | |
1171 | arc_compare_op1 = operands[1]; | |
1172 | DONE; | |
1173 | }") | |
1174 | ||
1175 | ;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0. | |
1176 | ;; This assumes sub.f 0,symbol,0 is a valid insn. | |
1177 | ;; Note that "sub.f 0,r0,1" is an 8 byte insn. To avoid unnecessarily | |
1178 | ;; creating 8 byte insns we duplicate %1 in the destination reg of the insn | |
1179 | ;; if it's a small constant. | |
1180 | ||
1181 | (define_insn "*cmpsi_cc_insn" | |
1182 | [(set (reg:CC 61) | |
1183 | (compare:CC (match_operand:SI 0 "register_operand" "r,r,r") | |
1184 | (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] | |
1185 | "" | |
1186 | "@ | |
1187 | sub.f 0,%0,%1 | |
1188 | sub.f %1,%0,%1 | |
1189 | sub.f 0,%0,%1" | |
1190 | [(set_attr "type" "compare,compare,compare")]) | |
1191 | ||
1192 | (define_insn "*cmpsi_cczn_insn" | |
1193 | [(set (reg:CCZN 61) | |
1194 | (compare:CCZN (match_operand:SI 0 "register_operand" "r,r,r") | |
1195 | (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] | |
1196 | "" | |
1197 | "@ | |
1198 | sub.f 0,%0,%1 | |
1199 | sub.f %1,%0,%1 | |
1200 | sub.f 0,%0,%1" | |
1201 | [(set_attr "type" "compare,compare,compare")]) | |
1202 | ||
1203 | (define_insn "*cmpsi_ccznc_insn" | |
1204 | [(set (reg:CCZNC 61) | |
1205 | (compare:CCZNC (match_operand:SI 0 "register_operand" "r,r,r") | |
1206 | (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] | |
1207 | "" | |
1208 | "@ | |
1209 | sub.f 0,%0,%1 | |
1210 | sub.f %1,%0,%1 | |
1211 | sub.f 0,%0,%1" | |
1212 | [(set_attr "type" "compare,compare,compare")]) | |
1213 | ||
1214 | ;; Next come the scc insns. | |
1215 | ||
1216 | (define_expand "seq" | |
1217 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1218 | (eq:SI (match_dup 1) (const_int 0)))] | |
1219 | "" | |
1220 | " | |
1221 | { | |
1222 | operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1); | |
1223 | }") | |
1224 | ||
1225 | (define_expand "sne" | |
1226 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1227 | (ne:SI (match_dup 1) (const_int 0)))] | |
1228 | "" | |
1229 | " | |
1230 | { | |
1231 | operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1); | |
1232 | }") | |
1233 | ||
1234 | (define_expand "sgt" | |
1235 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1236 | (gt:SI (match_dup 1) (const_int 0)))] | |
1237 | "" | |
1238 | " | |
1239 | { | |
1240 | operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1); | |
1241 | }") | |
1242 | ||
1243 | (define_expand "sle" | |
1244 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1245 | (le:SI (match_dup 1) (const_int 0)))] | |
1246 | "" | |
1247 | " | |
1248 | { | |
1249 | operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1); | |
1250 | }") | |
1251 | ||
1252 | (define_expand "sge" | |
1253 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1254 | (ge:SI (match_dup 1) (const_int 0)))] | |
1255 | "" | |
1256 | " | |
1257 | { | |
1258 | operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1); | |
1259 | }") | |
1260 | ||
1261 | (define_expand "slt" | |
1262 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1263 | (lt:SI (match_dup 1) (const_int 0)))] | |
1264 | "" | |
1265 | " | |
1266 | { | |
1267 | operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1); | |
1268 | }") | |
1269 | ||
1270 | (define_expand "sgtu" | |
1271 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1272 | (gtu:SI (match_dup 1) (const_int 0)))] | |
1273 | "" | |
1274 | " | |
1275 | { | |
1276 | operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1); | |
1277 | }") | |
1278 | ||
1279 | (define_expand "sleu" | |
1280 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1281 | (leu:SI (match_dup 1) (const_int 0)))] | |
1282 | "" | |
1283 | " | |
1284 | { | |
1285 | operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1); | |
1286 | }") | |
1287 | ||
1288 | (define_expand "sgeu" | |
1289 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1290 | (geu:SI (match_dup 1) (const_int 0)))] | |
1291 | "" | |
1292 | " | |
1293 | { | |
1294 | operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1); | |
1295 | }") | |
1296 | ||
1297 | (define_expand "sltu" | |
1298 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1299 | (ltu:SI (match_dup 1) (const_int 0)))] | |
1300 | "" | |
1301 | " | |
1302 | { | |
1303 | operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1); | |
1304 | }") | |
1305 | ||
1306 | (define_insn "*scc_insn" | |
1307 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1308 | (match_operator:SI 1 "comparison_operator" [(reg 61) (const_int 0)]))] | |
1309 | "" | |
1310 | "mov %0,1\;sub.%D1 %0,%0,%0" | |
1311 | [(set_attr "type" "unary") | |
1312 | (set_attr "length" "2")]) | |
1313 | ||
1314 | ;; ??? Look up negscc insn. See pa.md for example. | |
1315 | (define_insn "*neg_scc_insn" | |
1316 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1317 | (neg:SI (match_operator:SI 1 "comparison_operator" | |
1318 | [(reg 61) (const_int 0)])))] | |
1319 | "" | |
1320 | "mov %0,-1\;sub.%D1 %0,%0,%0" | |
1321 | [(set_attr "type" "unary") | |
1322 | (set_attr "length" "2")]) | |
1323 | ||
1324 | (define_insn "*not_scc_insn" | |
1325 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1326 | (not:SI (match_operator:SI 1 "comparison_operator" | |
1327 | [(reg 61) (const_int 0)])))] | |
1328 | "" | |
1329 | "mov %0,1\;sub.%d1 %0,%0,%0" | |
1330 | [(set_attr "type" "unary") | |
1331 | (set_attr "length" "2")]) | |
1332 | \f | |
1333 | ;; These control RTL generation for conditional jump insns | |
1334 | ||
1335 | (define_expand "beq" | |
1336 | [(set (pc) | |
1337 | (if_then_else (eq (match_dup 1) (const_int 0)) | |
1338 | (label_ref (match_operand 0 "" "")) | |
1339 | (pc)))] | |
1340 | "" | |
1341 | " | |
1342 | { | |
1343 | operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1); | |
1344 | }") | |
1345 | ||
1346 | (define_expand "bne" | |
1347 | [(set (pc) | |
1348 | (if_then_else (ne (match_dup 1) (const_int 0)) | |
1349 | (label_ref (match_operand 0 "" "")) | |
1350 | (pc)))] | |
1351 | "" | |
1352 | " | |
1353 | { | |
1354 | operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1); | |
1355 | }") | |
1356 | ||
1357 | (define_expand "bgt" | |
1358 | [(set (pc) | |
1359 | (if_then_else (gt (match_dup 1) (const_int 0)) | |
1360 | (label_ref (match_operand 0 "" "")) | |
1361 | (pc)))] | |
1362 | "" | |
1363 | " | |
1364 | { | |
1365 | operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1); | |
1366 | }") | |
1367 | ||
1368 | (define_expand "ble" | |
1369 | [(set (pc) | |
1370 | (if_then_else (le (match_dup 1) (const_int 0)) | |
1371 | (label_ref (match_operand 0 "" "")) | |
1372 | (pc)))] | |
1373 | "" | |
1374 | " | |
1375 | { | |
1376 | operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1); | |
1377 | }") | |
1378 | ||
1379 | (define_expand "bge" | |
1380 | [(set (pc) | |
1381 | (if_then_else (ge (match_dup 1) (const_int 0)) | |
1382 | (label_ref (match_operand 0 "" "")) | |
1383 | (pc)))] | |
1384 | "" | |
1385 | " | |
1386 | { | |
1387 | operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1); | |
1388 | }") | |
1389 | ||
1390 | (define_expand "blt" | |
1391 | [(set (pc) | |
1392 | (if_then_else (lt (match_dup 1) (const_int 0)) | |
1393 | (label_ref (match_operand 0 "" "")) | |
1394 | (pc)))] | |
1395 | "" | |
1396 | " | |
1397 | { | |
1398 | operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1); | |
1399 | }") | |
1400 | ||
1401 | (define_expand "bgtu" | |
1402 | [(set (pc) | |
1403 | (if_then_else (gtu (match_dup 1) (const_int 0)) | |
1404 | (label_ref (match_operand 0 "" "")) | |
1405 | (pc)))] | |
1406 | "" | |
1407 | " | |
1408 | { | |
1409 | operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1); | |
1410 | }") | |
1411 | ||
1412 | (define_expand "bleu" | |
1413 | [(set (pc) | |
1414 | (if_then_else (leu (match_dup 1) (const_int 0)) | |
1415 | (label_ref (match_operand 0 "" "")) | |
1416 | (pc)))] | |
1417 | "" | |
1418 | " | |
1419 | { | |
1420 | operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1); | |
1421 | }") | |
1422 | ||
1423 | (define_expand "bgeu" | |
1424 | [(set (pc) | |
1425 | (if_then_else (geu (match_dup 1) (const_int 0)) | |
1426 | (label_ref (match_operand 0 "" "")) | |
1427 | (pc)))] | |
1428 | "" | |
1429 | " | |
1430 | { | |
1431 | operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1); | |
1432 | }") | |
1433 | ||
1434 | (define_expand "bltu" | |
1435 | [(set (pc) | |
1436 | (if_then_else (ltu (match_dup 1) (const_int 0)) | |
1437 | (label_ref (match_operand 0 "" "")) | |
1438 | (pc)))] | |
1439 | "" | |
1440 | " | |
1441 | { | |
1442 | operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1); | |
1443 | }") | |
1444 | ||
1445 | ;; Now match both normal and inverted jump. | |
1446 | ||
1447 | (define_insn "*branch_insn" | |
1448 | [(set (pc) | |
1449 | (if_then_else (match_operator 1 "proper_comparison_operator" | |
1450 | [(reg 61) (const_int 0)]) | |
1451 | (label_ref (match_operand 0 "" "")) | |
1452 | (pc)))] | |
1453 | "" | |
1454 | "* | |
1455 | { | |
1456 | if (arc_ccfsm_branch_deleted_p ()) | |
1457 | { | |
1458 | arc_ccfsm_record_branch_deleted (); | |
1459 | return \"; branch deleted, next insns conditionalized\"; | |
1460 | } | |
1461 | else | |
1462 | return \"%~b%d1%# %l0\"; | |
1463 | }" | |
1464 | [(set_attr "type" "branch")]) | |
1465 | ||
1466 | (define_insn "*rev_branch_insn" | |
1467 | [(set (pc) | |
1468 | (if_then_else (match_operator 1 "proper_comparison_operator" | |
1469 | [(reg 61) (const_int 0)]) | |
1470 | (pc) | |
1471 | (label_ref (match_operand 0 "" ""))))] | |
1472 | "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))" | |
1473 | "* | |
1474 | { | |
1475 | if (arc_ccfsm_branch_deleted_p ()) | |
1476 | { | |
1477 | arc_ccfsm_record_branch_deleted (); | |
1478 | return \"; branch deleted, next insns conditionalized\"; | |
1479 | } | |
1480 | else | |
1481 | return \"%~b%D1%# %l0\"; | |
1482 | }" | |
1483 | [(set_attr "type" "branch")]) | |
1484 | \f | |
1485 | ;; Unconditional and other jump instructions. | |
1486 | ||
1487 | (define_insn "jump" | |
1488 | [(set (pc) (label_ref (match_operand 0 "" "")))] | |
1489 | "" | |
1490 | "b%* %l0" | |
1491 | [(set_attr "type" "uncond_branch")]) | |
1492 | ||
1493 | (define_insn "indirect_jump" | |
1494 | [(set (pc) (match_operand:SI 0 "address_operand" "p"))] | |
1495 | "" | |
1496 | "j%* %a0" | |
1497 | [(set_attr "type" "uncond_branch")]) | |
1498 | ||
1499 | ;; Implement a switch statement. | |
1500 | ;; This wouldn't be necessary in the non-pic case if we could distinguish | |
1501 | ;; label refs of the jump table from other label refs. The problem is that | |
1502 | ;; label refs are output as "%st(.LL42)" but we don't want the %st - we want | |
1503 | ;; the real address since it's the address of the table. | |
1504 | ||
1505 | (define_expand "casesi" | |
1506 | [(set (match_dup 5) | |
1507 | (minus:SI (match_operand:SI 0 "register_operand" "") | |
1508 | (match_operand:SI 1 "nonmemory_operand" ""))) | |
1509 | (set (reg:CC 61) | |
1510 | (compare:CC (match_dup 5) | |
1511 | (match_operand:SI 2 "nonmemory_operand" ""))) | |
1512 | (set (pc) | |
1513 | (if_then_else (gtu (reg:CC 61) | |
1514 | (const_int 0)) | |
1515 | (label_ref (match_operand 4 "" "")) | |
1516 | (pc))) | |
1517 | (parallel | |
1518 | [(set (pc) | |
1519 | (mem:SI (plus:SI (mult:SI (match_dup 5) | |
1520 | (const_int 4)) | |
1521 | (label_ref (match_operand 3 "" ""))))) | |
1522 | (clobber (match_scratch:SI 6 "")) | |
1523 | (clobber (match_scratch:SI 7 ""))])] | |
1524 | "" | |
1525 | " | |
1526 | { | |
1527 | operands[5] = gen_reg_rtx (SImode); | |
1528 | }") | |
1529 | ||
1530 | (define_insn "*casesi_insn" | |
1531 | [(set (pc) | |
1532 | (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r") | |
1533 | (const_int 4)) | |
1534 | (label_ref (match_operand 1 "" ""))))) | |
1535 | (clobber (match_scratch:SI 2 "=r")) | |
1536 | (clobber (match_scratch:SI 3 "=r"))] | |
1537 | "" | |
1538 | "* | |
1539 | { | |
1540 | output_asm_insn (\"mov %2,%1\", operands); | |
1541 | if (TARGET_SHIFTER) | |
1542 | output_asm_insn (\"asl %3,%0,2\", operands); | |
1543 | else | |
1544 | output_asm_insn (\"asl %3,%0\;asl %3,%3\", operands); | |
1545 | output_asm_insn (\"ld %2,[%2,%3]\", operands); | |
1546 | output_asm_insn (\"j.nd %a2\", operands); | |
1547 | return \"\"; | |
1548 | }" | |
1549 | [(set_attr "type" "uncond_branch") | |
1550 | (set_attr "length" "6")]) | |
1551 | ||
1552 | (define_insn "tablejump" | |
1553 | [(set (pc) (match_operand:SI 0 "address_operand" "p")) | |
1554 | (use (label_ref (match_operand 1 "" "")))] | |
1555 | "0 /* disabled -> using casesi now */" | |
1556 | "j%* %a0" | |
1557 | [(set_attr "type" "uncond_branch")]) | |
1558 | ||
1559 | (define_expand "call" | |
1560 | ;; operands[1] is stack_size_rtx | |
1561 | ;; operands[2] is next_arg_register | |
1562 | [(parallel [(call (match_operand:SI 0 "call_operand" "") | |
1563 | (match_operand 1 "" "")) | |
1564 | (clobber (reg:SI 31))])] | |
1565 | "" | |
1566 | "") | |
1567 | ||
1568 | (define_insn "*call_via_reg" | |
1569 | [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) | |
1570 | (match_operand 1 "" "")) | |
1571 | (clobber (reg:SI 31))] | |
1572 | "" | |
1573 | "lr blink,[status]\;j.d %0\;add blink,blink,2" | |
1574 | [(set_attr "type" "call_no_delay_slot") | |
1575 | (set_attr "length" "3")]) | |
1576 | ||
1577 | (define_insn "*call_via_label" | |
1578 | [(call (mem:SI (match_operand:SI 0 "call_address_operand" "")) | |
1579 | (match_operand 1 "" "")) | |
1580 | (clobber (reg:SI 31))] | |
1581 | "" | |
1582 | ; The %~ is necessary in case this insn gets conditionalized and the previous | |
1583 | ; insn is the cc setter. | |
1584 | "%~bl%!%* %0" | |
1585 | [(set_attr "type" "call") | |
1586 | (set_attr "cond" "canuse")]) | |
1587 | ||
1588 | (define_expand "call_value" | |
1589 | ;; operand 2 is stack_size_rtx | |
1590 | ;; operand 3 is next_arg_register | |
1591 | [(parallel [(set (match_operand 0 "register_operand" "=r") | |
1592 | (call (match_operand:SI 1 "call_operand" "") | |
1593 | (match_operand 2 "" ""))) | |
1594 | (clobber (reg:SI 31))])] | |
1595 | "" | |
1596 | "") | |
1597 | ||
1598 | (define_insn "*call_value_via_reg" | |
1599 | [(set (match_operand 0 "register_operand" "=r") | |
1600 | (call (mem:SI (match_operand:SI 1 "register_operand" "r")) | |
1601 | (match_operand 2 "" ""))) | |
1602 | (clobber (reg:SI 31))] | |
1603 | "" | |
1604 | "lr blink,[status]\;j.d %1\;add blink,blink,2" | |
1605 | [(set_attr "type" "call_no_delay_slot") | |
1606 | (set_attr "length" "3")]) | |
1607 | ||
1608 | (define_insn "*call_value_via_label" | |
1609 | [(set (match_operand 0 "register_operand" "=r") | |
1610 | (call (mem:SI (match_operand:SI 1 "call_address_operand" "")) | |
1611 | (match_operand 2 "" ""))) | |
1612 | (clobber (reg:SI 31))] | |
1613 | "" | |
1614 | ; The %~ is necessary in case this insn gets conditionalized and the previous | |
1615 | ; insn is the cc setter. | |
1616 | "%~bl%!%* %1" | |
1617 | [(set_attr "type" "call") | |
1618 | (set_attr "cond" "canuse")]) | |
1619 | \f | |
1620 | (define_insn "nop" | |
1621 | [(const_int 0)] | |
1622 | "" | |
1623 | "nop" | |
1624 | [(set_attr "type" "misc")]) | |
1625 | ||
1626 | ;; Special pattern to flush the icache. | |
1627 | ;; ??? Not sure what to do here. Some ARC's are known to support this. | |
1628 | ||
1629 | (define_insn "flush_icache" | |
1630 | [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)] | |
1631 | "" | |
1632 | "* return \"\";" | |
1633 | [(set_attr "type" "misc")]) | |
1634 | \f | |
1635 | ;; Split up troublesome insns for better scheduling. | |
1636 | \f | |
1637 | ;; Peepholes go at the end. |