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