]>
Commit | Line | Data |
---|---|---|
526b7aee | 1 | ;; Machine description of the Synopsys DesignWare ARC cpu for GNU C compiler |
8d9254fc | 2 | ;; Copyright (C) 1994-2020 Free Software Foundation, Inc. |
526b7aee SV |
3 | |
4 | ;; Sources derived from work done by Sankhya Technologies (www.sankhya.com) on | |
5 | ;; behalf of Synopsys Inc. | |
6 | ||
7 | ;; Position Independent Code support added,Code cleaned up, | |
8 | ;; Comments and Support For ARC700 instructions added by | |
9 | ;; Saurabh Verma (saurabh.verma@codito.com) | |
10 | ;; Ramana Radhakrishnan(ramana.radhakrishnan@codito.com) | |
11 | ;; | |
e04ea1da | 12 | ;; Performance improvements by |
526b7aee SV |
13 | ;; Joern Rennecke (joern.rennecke@embecosm.com) |
14 | ;; | |
526b7aee SV |
15 | |
16 | ;; This file is part of GCC. | |
17 | ||
18 | ;; GCC is free software; you can redistribute it and/or modify | |
19 | ;; it under the terms of the GNU General Public License as published by | |
20 | ;; the Free Software Foundation; either version 3, or (at your option) | |
21 | ;; any later version. | |
22 | ||
23 | ;; GCC is distributed in the hope that it will be useful, | |
24 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
26 | ;; GNU General Public License for more details. | |
27 | ||
28 | ;; You should have received a copy of the GNU General Public License | |
29 | ;; along with GCC; see the file COPYING3. If not see | |
30 | ;; <http://www.gnu.org/licenses/>. | |
31 | ||
32 | ;; See file "rtl.def" for documentation on define_insn, match_*, et. al. | |
33 | ||
34 | ;; <op> dest, src Two operand instruction's syntax | |
35 | ;; <op> dest, src1, src2 Three operand instruction's syntax | |
36 | ||
37 | ;; ARC and ARCompact PREDICATES: | |
38 | ;; | |
39 | ;; comparison_operator LT, GT, LE, GE, LTU, GTU, LEU, GEU, EQ, NE | |
40 | ;; memory_operand memory [m] | |
41 | ;; immediate_operand immediate constant [IKLMNOP] | |
42 | ;; register_operand register [rq] | |
43 | ;; general_operand register, memory, constant [rqmIKLMNOP] | |
44 | ||
45 | ;; Note that the predicates are only used when selecting a pattern | |
46 | ;; to determine if an operand is valid. | |
47 | ||
48 | ;; The constraints then select which of the possible valid operands | |
49 | ;; is present (and guide register selection). The actual assembly | |
50 | ;; instruction is then selected on the basis of the constraints. | |
51 | ||
52 | ;; ARC and ARCompact CONSTRAINTS: | |
53 | ;; | |
54 | ;; b stack pointer r28 | |
55 | ;; f frame pointer r27 | |
56 | ;; Rgp global pointer r26 | |
57 | ;; g general reg, memory, constant | |
58 | ;; m memory | |
59 | ;; p memory address | |
60 | ;; q registers commonly used in | |
61 | ;; 16-bit insns r0-r3, r12-r15 | |
62 | ;; c core registers r0-r60, ap, pcl | |
63 | ;; r general registers r0-r28, blink, ap, pcl | |
64 | ;; | |
65 | ;; H fp 16-bit constant | |
66 | ;; I signed 12-bit immediate (for ARCompact) | |
67 | ;; K unsigned 3-bit immediate (for ARCompact) | |
68 | ;; L unsigned 6-bit immediate (for ARCompact) | |
69 | ;; M unsinged 5-bit immediate (for ARCompact) | |
70 | ;; O unsinged 7-bit immediate (for ARCompact) | |
71 | ;; P unsinged 8-bit immediate (for ARCompact) | |
72 | ;; N constant '1' (for ARCompact) | |
73 | ||
74 | ||
75 | ;; TODO: | |
76 | ;; -> prefetch instruction | |
77 | ||
78 | ;; ----------------------------------------------------------------------------- | |
79 | ||
80 | ;; Include DFA scheduluers | |
81 | (include ("arc600.md")) | |
82 | (include ("arc700.md")) | |
f50bb868 CZ |
83 | (include ("arcEM.md")) |
84 | (include ("arcHS.md")) | |
43bb0fc2 | 85 | (include ("arcHS4x.md")) |
526b7aee SV |
86 | |
87 | ;; Predicates | |
88 | ||
89 | (include ("predicates.md")) | |
90 | (include ("constraints.md")) | |
91 | ;; ----------------------------------------------------------------------------- | |
92 | ||
93 | ;; UNSPEC Usage: | |
94 | ;; ~~~~~~~~~~~~ | |
95 | ;; ----------------------------------------------------------------------------- | |
96 | ;; Symbolic name Value Desc. | |
97 | ;; ----------------------------------------------------------------------------- | |
98 | ;; UNSPEC_PLT 3 symbol to be referenced through the PLT | |
99 | ;; UNSPEC_GOT 4 symbol to be rerenced through the GOT | |
100 | ;; UNSPEC_GOTOFF 5 Local symbol.To be referenced relative to the | |
101 | ;; GOTBASE.(Referenced as @GOTOFF) | |
f5e336b1 | 102 | ;; UNSPEC_GOTOFFPC 6 Local symbol. To be referenced pc-relative. |
526b7aee SV |
103 | ;; ---------------------------------------------------------------------------- |
104 | ||
c69899f0 CZ |
105 | (define_c_enum "unspec" [ |
106 | DUMMY_0 | |
107 | DUMMY_1 | |
108 | DUMMY_2 | |
109 | ARC_UNSPEC_PLT | |
110 | ARC_UNSPEC_GOT | |
111 | ARC_UNSPEC_GOTOFF | |
f5e336b1 | 112 | ARC_UNSPEC_GOTOFFPC |
28633bbd CZ |
113 | UNSPEC_TLS_GD |
114 | UNSPEC_TLS_LD | |
115 | UNSPEC_TLS_IE | |
116 | UNSPEC_TLS_OFF | |
c69899f0 CZ |
117 | UNSPEC_ARC_NORM |
118 | UNSPEC_ARC_NORMW | |
119 | UNSPEC_ARC_SWAP | |
120 | UNSPEC_ARC_DIVAW | |
121 | UNSPEC_ARC_DIRECT | |
122 | UNSPEC_ARC_LP | |
123 | UNSPEC_ARC_CASESI | |
124 | UNSPEC_ARC_FFS | |
125 | UNSPEC_ARC_FLS | |
126 | UNSPEC_ARC_MEMBAR | |
127 | UNSPEC_ARC_DMACH | |
128 | UNSPEC_ARC_DMACHU | |
129 | UNSPEC_ARC_DMACWH | |
130 | UNSPEC_ARC_DMACWHU | |
131 | UNSPEC_ARC_QMACH | |
132 | UNSPEC_ARC_QMACHU | |
133 | UNSPEC_ARC_QMPYH | |
134 | UNSPEC_ARC_QMPYHU | |
135 | UNSPEC_ARC_VMAC2H | |
136 | UNSPEC_ARC_VMAC2HU | |
137 | UNSPEC_ARC_VMPY2H | |
138 | UNSPEC_ARC_VMPY2HU | |
c69899f0 | 139 | |
c69899f0 CZ |
140 | VUNSPEC_ARC_RTIE |
141 | VUNSPEC_ARC_SYNC | |
142 | VUNSPEC_ARC_BRK | |
143 | VUNSPEC_ARC_FLAG | |
144 | VUNSPEC_ARC_SLEEP | |
145 | VUNSPEC_ARC_SWI | |
146 | VUNSPEC_ARC_CORE_READ | |
147 | VUNSPEC_ARC_CORE_WRITE | |
148 | VUNSPEC_ARC_LR | |
149 | VUNSPEC_ARC_SR | |
150 | VUNSPEC_ARC_TRAP_S | |
151 | VUNSPEC_ARC_UNIMP_S | |
152 | VUNSPEC_ARC_KFLAG | |
153 | VUNSPEC_ARC_CLRI | |
154 | VUNSPEC_ARC_SETI | |
155 | VUNSPEC_ARC_NOP | |
156 | VUNSPEC_ARC_STACK_IRQ | |
157 | VUNSPEC_ARC_DEXCL | |
158 | VUNSPEC_ARC_DEXCL_NORES | |
159 | VUNSPEC_ARC_LR_HIGH | |
160 | VUNSPEC_ARC_EX | |
161 | VUNSPEC_ARC_CAS | |
162 | VUNSPEC_ARC_SC | |
163 | VUNSPEC_ARC_LL | |
16493b57 | 164 | VUNSPEC_ARC_BLOCKAGE |
3fd6ae8a | 165 | VUNSPEC_ARC_EH_RETURN |
ce9dbf20 | 166 | VUNSPEC_ARC_ARC600_RTIE |
c69899f0 | 167 | ]) |
526b7aee SV |
168 | |
169 | (define_constants | |
e04ea1da | 170 | [(R0_REG 0) |
526b7aee SV |
171 | (R1_REG 1) |
172 | (R2_REG 2) | |
173 | (R3_REG 3) | |
73dac59b CZ |
174 | (R4_REG 4) |
175 | ||
176 | (R9_REG 9) | |
28633bbd | 177 | (R10_REG 10) |
73dac59b | 178 | |
526b7aee | 179 | (R12_REG 12) |
73dac59b CZ |
180 | |
181 | (R15_REG 15) | |
182 | (R16_REG 16) | |
183 | ||
184 | (R25_REG 25) | |
526b7aee | 185 | (SP_REG 28) |
73dac59b CZ |
186 | (ILINK1_REG 29) |
187 | (ILINK2_REG 30) | |
188 | (R30_REG 30) | |
526b7aee | 189 | (RETURN_ADDR_REGNUM 31) |
73dac59b | 190 | (R32_REG 32) |
ce9dbf20 CZ |
191 | (R33_REG 33) |
192 | (R34_REG 34) | |
193 | (R35_REG 35) | |
194 | (R36_REG 36) | |
195 | (R37_REG 37) | |
196 | (R38_REG 38) | |
197 | (R39_REG 39) | |
73dac59b CZ |
198 | (R40_REG 40) |
199 | (R41_REG 41) | |
200 | (R42_REG 42) | |
201 | (R43_REG 43) | |
202 | (R44_REG 44) | |
ce9dbf20 CZ |
203 | (R45_REG 45) |
204 | (R46_REG 46) | |
205 | (R47_REG 47) | |
206 | (R48_REG 48) | |
207 | (R49_REG 49) | |
208 | (R50_REG 50) | |
209 | (R51_REG 51) | |
210 | (R52_REG 52) | |
211 | (R53_REG 53) | |
212 | (R54_REG 54) | |
213 | (R55_REG 55) | |
214 | (R56_REG 56) | |
73dac59b | 215 | (R57_REG 57) |
ce9dbf20 CZ |
216 | (R58_REG 58) |
217 | (R59_REG 59) | |
218 | ||
526b7aee | 219 | (MUL64_OUT_REG 58) |
0f75b668 | 220 | (MUL32x16_REG 56) |
8f3304d0 | 221 | (ARCV2_ACC 58) |
526b7aee SV |
222 | (LP_COUNT 60) |
223 | (CC_REG 61) | |
73dac59b | 224 | (PCL_REG 63) |
526b7aee SV |
225 | ] |
226 | ) | |
227 | ||
228 | (define_attr "is_sfunc" "no,yes" (const_string "no")) | |
229 | ||
230 | ;; Insn type. Used to default other attribute values. | |
231 | ; While the attribute is_sfunc is set for any call of a special function, | |
232 | ; the instruction type sfunc is used only for the special call sequence | |
233 | ; that loads the (pc-relative) function address into r12 and then calls | |
234 | ; via r12. | |
235 | ||
236 | (define_attr "type" | |
237 | "move,load,store,cmove,unary,binary,compare,shift,uncond_branch,jump,branch, | |
ce9dbf20 | 238 | brcc,brcc_no_delay_slot,call,sfunc,call_no_delay_slot,rtie, |
526b7aee SV |
239 | multi,umulti, two_cycle_core,lr,sr,divaw,loop_setup,loop_end,return, |
240 | misc,spfp,dpfp_mult,dpfp_addsub,mulmac_600,cc_arith, | |
241 | simd_vload, simd_vload128, simd_vstore, simd_vmove, simd_vmove_else_zero, | |
242 | simd_vmove_with_acc, simd_varith_1cycle, simd_varith_2cycle, | |
243 | simd_varith_with_acc, simd_vlogic, simd_vlogic_with_acc, | |
244 | simd_vcompare, simd_vpermute, simd_vpack, simd_vpack_with_acc, | |
245 | simd_valign, simd_valign_with_acc, simd_vcontrol, | |
8f3304d0 | 246 | simd_vspecial_3cycle, simd_vspecial_4cycle, simd_dma, mul16_em, div_rem, |
43bb0fc2 | 247 | fpu, fpu_fuse, fpu_sdiv, fpu_ddiv, fpu_cvt, block" |
526b7aee SV |
248 | (cond [(eq_attr "is_sfunc" "yes") |
249 | (cond [(match_test "!TARGET_LONG_CALLS_SET && (!TARGET_MEDIUM_CALLS || GET_CODE (PATTERN (insn)) != COND_EXEC)") (const_string "call") | |
250 | (match_test "flag_pic") (const_string "sfunc")] | |
251 | (const_string "call_no_delay_slot"))] | |
252 | (const_string "binary"))) | |
253 | ||
254 | ;; The following three attributes are mixed case so that they can be | |
255 | ;; used conveniently with the CALL_ATTR macro. | |
256 | (define_attr "is_CALL" "no,yes" | |
257 | (cond [(eq_attr "is_sfunc" "yes") (const_string "yes") | |
258 | (eq_attr "type" "call,call_no_delay_slot") (const_string "yes")] | |
259 | (const_string "no"))) | |
260 | ||
261 | (define_attr "is_SIBCALL" "no,yes" (const_string "no")) | |
262 | ||
263 | (define_attr "is_NON_SIBCALL" "no,yes" | |
264 | (cond [(eq_attr "is_SIBCALL" "yes") (const_string "no") | |
265 | (eq_attr "is_CALL" "yes") (const_string "yes")] | |
266 | (const_string "no"))) | |
267 | ||
526b7aee SV |
268 | ;; true for compact instructions (those with _s suffix) |
269 | ;; "maybe" means compact unless we conditionalize the insn. | |
270 | (define_attr "iscompact" "true,maybe,true_limm,maybe_limm,false" | |
271 | (cond [(eq_attr "type" "sfunc") | |
272 | (const_string "maybe")] | |
273 | (const_string "false"))) | |
274 | ||
275 | ||
276 | ; Is there an instruction that we are actually putting into the delay slot? | |
277 | (define_attr "delay_slot_filled" "no,yes" | |
278 | (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn") | |
279 | (const_string "no") | |
280 | (match_test "!TARGET_AT_DBR_CONDEXEC | |
281 | && JUMP_P (insn) | |
282 | && INSN_ANNULLED_BRANCH_P (insn) | |
283 | && !INSN_FROM_TARGET_P (NEXT_INSN (insn))") | |
284 | (const_string "no")] | |
285 | (const_string "yes"))) | |
286 | ||
287 | ; Is a delay slot present for purposes of shorten_branches? | |
288 | ; We have to take the length of this insn into account for forward branches | |
289 | ; even if we don't put the insn actually into a delay slot. | |
290 | (define_attr "delay_slot_present" "no,yes" | |
291 | (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn") | |
292 | (const_string "no")] | |
293 | (const_string "yes"))) | |
294 | ||
295 | ; We can't use get_attr_length (NEXT_INSN (insn)) because this gives the | |
296 | ; length of a different insn with the same uid. | |
297 | (define_attr "delay_slot_length" "" | |
298 | (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn") | |
299 | (const_int 0)] | |
300 | (symbol_ref "get_attr_length (NEXT_INSN (PREV_INSN (insn))) | |
301 | - get_attr_length (insn)"))) | |
302 | ||
f50bb868 | 303 | ; for ARCv2 we need to disable/enable different instruction alternatives |
fa9c1b3c | 304 | (define_attr "cpu_facility" "std,av1,av2,fpx,cd" |
f50bb868 | 305 | (const_string "std")) |
526b7aee | 306 | |
f50bb868 CZ |
307 | ; We should consider all the instructions enabled until otherwise |
308 | (define_attr "enabled" "no,yes" | |
309 | (cond [(and (eq_attr "cpu_facility" "av1") | |
310 | (match_test "TARGET_V2")) | |
311 | (const_string "no") | |
312 | ||
313 | (and (eq_attr "cpu_facility" "av2") | |
314 | (not (match_test "TARGET_V2"))) | |
315 | (const_string "no") | |
4ac2f36e CZ |
316 | |
317 | (and (eq_attr "cpu_facility" "fpx") | |
318 | (match_test "TARGET_FP_DP_AX")) | |
319 | (const_string "no") | |
fa9c1b3c CZ |
320 | |
321 | (and (eq_attr "cpu_facility" "cd") | |
322 | (not (and (match_test "TARGET_V2") | |
323 | (match_test "TARGET_CODE_DENSITY")))) | |
324 | (const_string "no") | |
f50bb868 CZ |
325 | ] |
326 | (const_string "yes"))) | |
526b7aee SV |
327 | |
328 | (define_attr "predicable" "no,yes" (const_string "no")) | |
329 | ;; if 'predicable' were not so brain-dead, we would specify: | |
330 | ;; (cond [(eq_attr "cond" "!canuse") (const_string "no") | |
331 | ;; (eq_attr "iscompact" "maybe") (const_string "no")] | |
332 | ;; (const_string "yes")) | |
333 | ;; and then for everything but calls, we could just set the cond attribute. | |
334 | ||
335 | ;; Condition codes: this one is used by final_prescan_insn to speed up | |
336 | ;; conditionalizing instructions. It saves having to scan the rtl to see if | |
337 | ;; it uses or alters the condition codes. | |
338 | ||
339 | ;; USE: This insn uses the condition codes (eg: a conditional branch). | |
340 | ;; CANUSE: This insn can use the condition codes (for conditional execution). | |
341 | ;; SET: All condition codes are set by this insn. | |
342 | ;; SET_ZN: the Z and N flags are set by this insn. | |
343 | ;; SET_ZNC: the Z, N, and C flags are set by this insn. | |
344 | ;; CLOB: The condition codes are set to unknown values by this insn. | |
345 | ;; NOCOND: This insn can't use and doesn't affect the condition codes. | |
346 | ||
347 | (define_attr "cond" "use,canuse,canuse_limm,canuse_limm_add,set,set_zn,clob,nocond" | |
348 | (cond | |
349 | [(and (eq_attr "predicable" "yes") | |
350 | (eq_attr "is_sfunc" "no") | |
351 | (eq_attr "delay_slot_filled" "no")) | |
352 | (const_string "canuse") | |
353 | ||
354 | (eq_attr "type" "call") | |
355 | (cond [(eq_attr "delay_slot_filled" "yes") (const_string "nocond") | |
356 | (match_test "!flag_pic") (const_string "canuse_limm")] | |
357 | (const_string "nocond")) | |
358 | ||
359 | (eq_attr "iscompact" "maybe,false") | |
360 | (cond [ (and (eq_attr "type" "move") | |
361 | (match_operand 1 "immediate_operand" "")) | |
362 | (if_then_else | |
363 | (ior (match_operand 1 "u6_immediate_operand" "") | |
364 | (match_operand 1 "long_immediate_operand" "")) | |
365 | (const_string "canuse") | |
366 | (const_string "canuse_limm")) | |
367 | ||
368 | (eq_attr "type" "binary") | |
369 | (cond [(ne (symbol_ref "REGNO (operands[0])") | |
370 | (symbol_ref "REGNO (operands[1])")) | |
371 | (const_string "nocond") | |
372 | (match_operand 2 "register_operand" "") | |
373 | (const_string "canuse") | |
374 | (match_operand 2 "u6_immediate_operand" "") | |
375 | (const_string "canuse") | |
376 | (match_operand 2 "long_immediate_operand" "") | |
377 | (const_string "canuse") | |
378 | (match_operand 2 "const_int_operand" "") | |
379 | (const_string "canuse_limm")] | |
380 | (const_string "nocond")) | |
381 | ||
382 | (eq_attr "type" "compare") | |
383 | (const_string "set") | |
384 | ||
385 | (eq_attr "type" "cmove,branch") | |
386 | (const_string "use") | |
387 | ||
388 | (eq_attr "is_sfunc" "yes") | |
389 | (cond [(match_test "(TARGET_MEDIUM_CALLS | |
390 | && !TARGET_LONG_CALLS_SET | |
391 | && flag_pic)") | |
392 | (const_string "canuse_limm_add") | |
393 | (match_test "(TARGET_MEDIUM_CALLS | |
394 | && !TARGET_LONG_CALLS_SET)") | |
395 | (const_string "canuse_limm")] | |
396 | (const_string "canuse")) | |
397 | ||
398 | ] | |
399 | ||
400 | (const_string "nocond"))] | |
401 | ||
402 | (cond [(eq_attr "type" "compare") | |
403 | (const_string "set") | |
404 | ||
405 | (eq_attr "type" "cmove,branch") | |
406 | (const_string "use") | |
407 | ||
408 | ] | |
409 | ||
410 | (const_string "nocond")))) | |
411 | ||
412 | /* ??? Having all these patterns gives ifcvt more freedom to generate | |
413 | inefficient code. It seem to operate on the premise that | |
414 | register-register copies and registers are free. I see better code | |
415 | with -fno-if-convert now than without. */ | |
416 | (define_cond_exec | |
417 | [(match_operator 0 "proper_comparison_operator" | |
418 | [(reg CC_REG) (const_int 0)])] | |
419 | "true" | |
420 | "") | |
421 | ||
422 | ;; Length (in # of bytes, long immediate constants counted too). | |
423 | ;; ??? There's a nasty interaction between the conditional execution fsm | |
424 | ;; and insn lengths: insns with shimm values cannot be conditionally executed. | |
425 | (define_attr "length" "" | |
426 | (cond | |
16493b57 CZ |
427 | [(eq_attr "iscompact" "true") |
428 | (const_int 2) | |
429 | ||
430 | (eq_attr "iscompact" "maybe") | |
526b7aee SV |
431 | (cond |
432 | [(eq_attr "type" "sfunc") | |
433 | (cond [(match_test "GET_CODE (PATTERN (insn)) == COND_EXEC") | |
434 | (const_int 12)] | |
435 | (const_int 10)) | |
16493b57 CZ |
436 | (match_test "GET_CODE (PATTERN (insn)) == COND_EXEC") (const_int 4) |
437 | (match_test "find_reg_note (insn, REG_SAVE_NOTE, GEN_INT (1))") | |
438 | (const_int 4)] | |
526b7aee SV |
439 | (const_int 2)) |
440 | ||
efdbb285 | 441 | (eq_attr "iscompact" "true_limm") |
526b7aee SV |
442 | (const_int 6) |
443 | ||
efdbb285 CZ |
444 | (eq_attr "iscompact" "maybe_limm") |
445 | (cond [(match_test "GET_CODE (PATTERN (insn)) == COND_EXEC") (const_int 8)] | |
446 | (const_int 6)) | |
447 | ||
526b7aee SV |
448 | (eq_attr "type" "load") |
449 | (if_then_else | |
450 | (match_operand 1 "long_immediate_loadstore_operand" "") | |
451 | (const_int 8) (const_int 4)) | |
452 | ||
453 | (eq_attr "type" "store") | |
454 | (if_then_else | |
455 | (ior (match_operand 0 "long_immediate_loadstore_operand" "") | |
456 | (match_operand 1 "immediate_operand" "")) | |
457 | (const_int 8) (const_int 4)) | |
458 | ||
459 | (eq_attr "type" "move,unary") | |
460 | (cond | |
461 | [(match_operand 1 "u6_immediate_operand" "") (const_int 4) | |
462 | (match_operand 1 "register_operand" "") (const_int 4) | |
463 | (match_operand 1 "long_immediate_operand" "") (const_int 8) | |
464 | (match_test "GET_CODE (PATTERN (insn)) == COND_EXEC") (const_int 8)] | |
465 | (const_int 4)) | |
466 | ||
467 | (and (eq_attr "type" "shift") | |
468 | (match_operand 1 "immediate_operand")) | |
469 | (const_int 8) | |
470 | (eq_attr "type" "binary,shift") | |
471 | (if_then_else | |
472 | (ior (match_operand 2 "long_immediate_operand" "") | |
473 | (and (ne (symbol_ref "REGNO (operands[0])") | |
474 | (symbol_ref "REGNO (operands[1])")) | |
475 | (eq (match_operand 2 "u6_immediate_operand" "") | |
476 | (const_int 0)))) | |
477 | ||
478 | (const_int 8) (const_int 4)) | |
479 | ||
480 | (eq_attr "type" "cmove") | |
481 | (if_then_else (match_operand 1 "register_operand" "") | |
482 | (const_int 4) (const_int 8)) | |
483 | ||
484 | (eq_attr "type" "call_no_delay_slot") (const_int 8) | |
485 | ] | |
486 | ||
487 | (const_int 4)) | |
488 | ) | |
489 | ||
490 | ;; The length here is the length of a single asm. Unfortunately it might be | |
491 | ;; 4 or 8 so we must allow for 8. That's ok though. How often will users | |
492 | ;; lament asm's not being put in delay slots? | |
493 | ;; | |
494 | (define_asm_attributes | |
495 | [(set_attr "length" "8") | |
496 | (set_attr "type" "multi") | |
497 | (set_attr "cond" "clob") ]) | |
498 | ||
499 | ;; Delay slots. | |
500 | ;; The first two cond clauses and the default are necessary for correctness; | |
501 | ;; the remaining cond clause is mainly an optimization, as otherwise nops | |
502 | ;; would be inserted; however, if we didn't do this optimization, we would | |
503 | ;; have to be more conservative in our length calculations. | |
504 | ||
505 | (define_attr "in_delay_slot" "false,true" | |
506 | (cond [(eq_attr "type" "uncond_branch,jump,branch, | |
507 | call,sfunc,call_no_delay_slot, | |
508 | brcc, brcc_no_delay_slot,loop_setup,loop_end") | |
509 | (const_string "false") | |
510 | (match_test "arc_write_ext_corereg (insn)") | |
511 | (const_string "false") | |
512 | (gt (symbol_ref "arc_hazard (prev_active_insn (insn), | |
513 | next_active_insn (insn))") | |
514 | (symbol_ref "(arc_hazard (prev_active_insn (insn), insn) | |
515 | + arc_hazard (insn, next_active_insn (insn)))")) | |
516 | (const_string "false") | |
a0920243 CZ |
517 | (match_test "find_reg_note (insn, REG_SAVE_NOTE, GEN_INT (2))") |
518 | (const_string "false") | |
526b7aee SV |
519 | (eq_attr "iscompact" "maybe") (const_string "true") |
520 | ] | |
521 | ||
522 | (if_then_else (eq_attr "length" "2,4") | |
523 | (const_string "true") | |
524 | (const_string "false")))) | |
525 | ||
526 | ; must not put an insn inside that refers to blink. | |
527 | (define_attr "in_call_delay_slot" "false,true" | |
528 | (cond [(eq_attr "in_delay_slot" "false") | |
529 | (const_string "false") | |
530 | (match_test "arc_regno_use_in (RETURN_ADDR_REGNUM, PATTERN (insn))") | |
531 | (const_string "false")] | |
532 | (const_string "true"))) | |
533 | ||
534 | (define_attr "in_sfunc_delay_slot" "false,true" | |
535 | (cond [(eq_attr "in_call_delay_slot" "false") | |
536 | (const_string "false") | |
537 | (match_test "arc_regno_use_in (12, PATTERN (insn))") | |
538 | (const_string "false")] | |
539 | (const_string "true"))) | |
540 | ||
541 | ;; Instructions that we can put into a delay slot and conditionalize. | |
542 | (define_attr "cond_delay_insn" "no,yes" | |
543 | (cond [(eq_attr "cond" "!canuse") (const_string "no") | |
544 | (eq_attr "type" "call,branch,uncond_branch,jump,brcc") | |
545 | (const_string "no") | |
a0920243 CZ |
546 | (match_test "find_reg_note (insn, REG_SAVE_NOTE, GEN_INT (2))") |
547 | (const_string "no") | |
526b7aee SV |
548 | (eq_attr "length" "2,4") (const_string "yes")] |
549 | (const_string "no"))) | |
550 | ||
551 | (define_attr "in_ret_delay_slot" "no,yes" | |
552 | (cond [(eq_attr "in_delay_slot" "false") | |
553 | (const_string "no") | |
554 | (match_test "regno_clobbered_p | |
ce9dbf20 | 555 | (RETURN_ADDR_REGNUM, insn, SImode, 1)") |
526b7aee SV |
556 | (const_string "no")] |
557 | (const_string "yes"))) | |
558 | ||
559 | (define_attr "cond_ret_delay_insn" "no,yes" | |
560 | (cond [(eq_attr "in_ret_delay_slot" "no") (const_string "no") | |
561 | (eq_attr "cond_delay_insn" "no") (const_string "no")] | |
562 | (const_string "yes"))) | |
563 | ||
564 | (define_attr "annul_ret_delay_insn" "no,yes" | |
565 | (cond [(eq_attr "cond_ret_delay_insn" "yes") (const_string "yes") | |
566 | (match_test "TARGET_AT_DBR_CONDEXEC") (const_string "no") | |
567 | (eq_attr "type" "!call,branch,uncond_branch,jump,brcc,return,sfunc") | |
568 | (const_string "yes")] | |
569 | (const_string "no"))) | |
570 | ||
571 | ||
572 | ;; Delay slot definition for ARCompact ISA | |
573 | ;; ??? FIXME: | |
574 | ;; When outputting an annul-true insn elegible for cond-exec | |
575 | ;; in a cbranch delay slot, unless optimizing for size, we use cond-exec | |
576 | ;; for ARC600; we could also use this for ARC700 if the branch can't be | |
577 | ;; unaligned and is at least somewhat likely (add parameter for this). | |
578 | ||
579 | (define_delay (eq_attr "type" "call") | |
580 | [(eq_attr "in_call_delay_slot" "true") | |
581 | (eq_attr "in_call_delay_slot" "true") | |
582 | (nil)]) | |
583 | ||
584 | (define_delay (and (match_test "!TARGET_AT_DBR_CONDEXEC") | |
585 | (eq_attr "type" "brcc")) | |
586 | [(eq_attr "in_delay_slot" "true") | |
587 | (eq_attr "in_delay_slot" "true") | |
588 | (nil)]) | |
589 | ||
590 | (define_delay (and (match_test "TARGET_AT_DBR_CONDEXEC") | |
591 | (eq_attr "type" "brcc")) | |
592 | [(eq_attr "in_delay_slot" "true") | |
593 | (nil) | |
594 | (nil)]) | |
595 | ||
596 | (define_delay | |
597 | (eq_attr "type" "return") | |
598 | [(eq_attr "in_ret_delay_slot" "yes") | |
599 | (eq_attr "annul_ret_delay_insn" "yes") | |
600 | (eq_attr "cond_ret_delay_insn" "yes")]) | |
601 | ||
a2de90a4 CZ |
602 | (define_delay (eq_attr "type" "loop_end") |
603 | [(eq_attr "in_delay_slot" "true") | |
604 | (eq_attr "in_delay_slot" "true") | |
605 | (nil)]) | |
606 | ||
526b7aee SV |
607 | ;; For ARC600, unexposing the delay sloy incurs a penalty also in the |
608 | ;; non-taken case, so the only meaningful way to have an annull-true | |
609 | ;; filled delay slot is to conditionalize the delay slot insn. | |
610 | (define_delay (and (match_test "TARGET_AT_DBR_CONDEXEC") | |
611 | (eq_attr "type" "branch,uncond_branch,jump") | |
612 | (match_test "!optimize_size")) | |
613 | [(eq_attr "in_delay_slot" "true") | |
614 | (eq_attr "cond_delay_insn" "yes") | |
615 | (eq_attr "cond_delay_insn" "yes")]) | |
616 | ||
617 | ;; For ARC700, anything goes for annulled-true insns, since there is no | |
618 | ;; penalty for the unexposed delay slot when the branch is not taken, | |
619 | ;; however, we must avoid things that have a delay slot themselvese to | |
620 | ;; avoid confusing gcc. | |
621 | (define_delay (and (match_test "!TARGET_AT_DBR_CONDEXEC") | |
622 | (eq_attr "type" "branch,uncond_branch,jump") | |
623 | (match_test "!optimize_size")) | |
624 | [(eq_attr "in_delay_slot" "true") | |
625 | (eq_attr "type" "!call,branch,uncond_branch,jump,brcc,return,sfunc") | |
626 | (eq_attr "cond_delay_insn" "yes")]) | |
627 | ||
628 | ;; -mlongcall -fpic sfuncs use r12 to load the function address | |
629 | (define_delay (eq_attr "type" "sfunc") | |
630 | [(eq_attr "in_sfunc_delay_slot" "true") | |
631 | (eq_attr "in_sfunc_delay_slot" "true") | |
632 | (nil)]) | |
633 | ;; ??? need to use a working strategy for canuse_limm: | |
634 | ;; - either canuse_limm is not eligible for delay slots, and has no | |
635 | ;; delay slots, or arc_reorg has to treat them as nocond, or it has to | |
636 | ;; somehow modify them to become inelegible for delay slots if a decision | |
637 | ;; is made that makes conditional execution required. | |
638 | ||
635aeaa2 CZ |
639 | (define_attr "tune" "none,arc600,arc7xx,arc700_4_2_std,arc700_4_2_xmac, \ |
640 | core_3, archs4x, archs4xd, archs4xd_slow" | |
526b7aee SV |
641 | (const |
642 | (cond [(symbol_ref "arc_tune == TUNE_ARC600") | |
643 | (const_string "arc600") | |
635aeaa2 CZ |
644 | (symbol_ref "arc_tune == ARC_TUNE_ARC7XX") |
645 | (const_string "arc7xx") | |
526b7aee SV |
646 | (symbol_ref "arc_tune == TUNE_ARC700_4_2_STD") |
647 | (const_string "arc700_4_2_std") | |
648 | (symbol_ref "arc_tune == TUNE_ARC700_4_2_XMAC") | |
62f26645 CZ |
649 | (const_string "arc700_4_2_xmac") |
650 | (symbol_ref "arc_tune == ARC_TUNE_CORE_3") | |
43bb0fc2 CZ |
651 | (const_string "core_3") |
652 | (symbol_ref "arc_tune == TUNE_ARCHS4X") | |
653 | (const_string "archs4x") | |
654 | (ior (symbol_ref "arc_tune == TUNE_ARCHS4XD") | |
655 | (symbol_ref "arc_tune == TUNE_ARCHS4XD_SLOW")) | |
656 | (const_string "archs4xd")] | |
526b7aee SV |
657 | (const_string "none")))) |
658 | ||
659 | (define_attr "tune_arc700" "false,true" | |
635aeaa2 | 660 | (if_then_else (eq_attr "tune" "arc7xx, arc700_4_2_std, arc700_4_2_xmac") |
526b7aee SV |
661 | (const_string "true") |
662 | (const_string "false"))) | |
663 | ||
43bb0fc2 CZ |
664 | (define_attr "tune_dspmpy" "none, slow, fast" |
665 | (const | |
666 | (cond [(ior (symbol_ref "arc_tune == TUNE_ARCHS4X") | |
667 | (symbol_ref "arc_tune == TUNE_ARCHS4XD")) | |
668 | (const_string "fast") | |
669 | (symbol_ref "arc_tune == TUNE_ARCHS4XD_SLOW") | |
670 | (const_string "slow")] | |
671 | (const_string "none")))) | |
672 | ||
526b7aee SV |
673 | ;; Move instructions. |
674 | (define_expand "movqi" | |
675 | [(set (match_operand:QI 0 "move_dest_operand" "") | |
676 | (match_operand:QI 1 "general_operand" ""))] | |
677 | "" | |
678 | "if (prepare_move_operands (operands, QImode)) DONE;") | |
679 | ||
680 | ; In order to allow the ccfsm machinery to do its work, the leading compact | |
681 | ; alternatives say 'canuse' - there is another alternative that will match | |
682 | ; when the condition codes are used. | |
683 | ; Rcq won't match if the condition is actually used; to avoid a spurious match | |
684 | ; via q, q is inactivated as constraint there. | |
685 | ; Likewise, the length of an alternative that might be shifted to conditional | |
686 | ; execution must reflect this, lest out-of-range branches are created. | |
687 | ; The iscompact attribute allows the epilogue expander to know for which | |
688 | ; insns it should lengthen the return insn. | |
689 | (define_insn "*movqi_insn" | |
73dac59b CZ |
690 | [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h, w, w,???w,h, w,Rcq, S,!*x, r,r, Ucm,m,???m, m,Usc") |
691 | (match_operand:QI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1,cL, I,?Rac,i,?i, T,Rcq,Usd,Ucm,m,?Rac,c,?Rac,Cm3,i"))] | |
526b7aee | 692 | "register_operand (operands[0], QImode) |
673f01b8 CZ |
693 | || register_operand (operands[1], QImode) |
694 | || (satisfies_constraint_Cm3 (operands[1]) | |
695 | && memory_operand (operands[0], QImode))" | |
526b7aee SV |
696 | "@ |
697 | mov%? %0,%1%& | |
698 | mov%? %0,%1%& | |
699 | mov%? %0,%1%& | |
fc1c2d04 | 700 | mov%? %0,%1%& |
fa9c1b3c CZ |
701 | mov%? %0,%1%& |
702 | mov%? %0,%1 | |
526b7aee SV |
703 | mov%? %0,%1 |
704 | mov%? %0,%1 | |
705 | mov%? %0,%1 | |
6b55f8c9 | 706 | mov%? %0,%1 |
526b7aee SV |
707 | ldb%? %0,%1%& |
708 | stb%? %1,%0%& | |
709 | ldb%? %0,%1%& | |
4d03dc2f | 710 | xldb%U1 %0,%1 |
526b7aee | 711 | ldb%U1%V1 %0,%1 |
4d03dc2f | 712 | xstb%U0 %1,%0 |
526b7aee | 713 | stb%U0%V0 %1,%0 |
fa9c1b3c | 714 | stb%U0%V0 %1,%0 |
1370fccf | 715 | stb%U0%V0 %1,%0 |
526b7aee | 716 | stb%U0%V0 %1,%0" |
1370fccf CZ |
717 | [(set_attr "type" "move,move,move,move,move,move,move,move,move,move,load,store,load,load,load,store,store,store,store,store") |
718 | (set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false,false,maybe_limm,false,true,true,true,false,false,false,false,false,false,false") | |
719 | (set_attr "predicable" "yes,no,yes,no,no,yes,no,yes,yes,yes,no,no,no,no,no,no,no,no,no,no") | |
720 | (set_attr "cpu_facility" "av1,av1,av1,av2,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")]) | |
526b7aee SV |
721 | |
722 | (define_expand "movhi" | |
723 | [(set (match_operand:HI 0 "move_dest_operand" "") | |
724 | (match_operand:HI 1 "general_operand" ""))] | |
725 | "" | |
726 | "if (prepare_move_operands (operands, HImode)) DONE;") | |
727 | ||
728 | (define_insn "*movhi_insn" | |
73dac59b CZ |
729 | [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h, w, w,???w,Rcq#q,h, w,Rcq, S, r,r, Ucm,m,???m, m,VUsc") |
730 | (match_operand:HI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1,cL, I,?Rac, i,i,?i, T,Rcq,Ucm,m,?Rac,c,?Rac,Cm3,i"))] | |
526b7aee SV |
731 | "register_operand (operands[0], HImode) |
732 | || register_operand (operands[1], HImode) | |
733 | || (CONSTANT_P (operands[1]) | |
734 | /* Don't use a LIMM that we could load with a single insn - we loose | |
735 | delay-slot filling opportunities. */ | |
736 | && !satisfies_constraint_I (operands[1]) | |
673f01b8 CZ |
737 | && satisfies_constraint_Usc (operands[0])) |
738 | || (satisfies_constraint_Cm3 (operands[1]) | |
739 | && memory_operand (operands[0], HImode))" | |
526b7aee SV |
740 | "@ |
741 | mov%? %0,%1%& | |
742 | mov%? %0,%1%& | |
743 | mov%? %0,%1%& | |
fc1c2d04 | 744 | mov%? %0,%1%& |
fa9c1b3c | 745 | mov%? %0,%1%& |
526b7aee SV |
746 | mov%? %0,%1 |
747 | mov%? %0,%1 | |
748 | mov%? %0,%1 | |
6b55f8c9 CZ |
749 | mov%? %0,%1%& |
750 | mov%? %0,%1 | |
751 | mov%? %0,%1 | |
f50bb868 CZ |
752 | ld%_%? %0,%1%& |
753 | st%_%? %1,%0%& | |
4d03dc2f | 754 | xld%_%U1 %0,%1 |
f50bb868 | 755 | ld%_%U1%V1 %0,%1 |
4d03dc2f | 756 | xst%_%U0 %1,%0 |
f50bb868 CZ |
757 | st%_%U0%V0 %1,%0 |
758 | st%_%U0%V0 %1,%0 | |
6b55f8c9 CZ |
759 | st%_%U0%V0 %1,%0 |
760 | st%_%U0%V0 %1,%0" | |
fa9c1b3c CZ |
761 | [(set_attr "type" "move,move,move,move,move,move,move,move,move,move,move,load,store,load,load,store,store,store,store,store") |
762 | (set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false,false,maybe_limm,maybe_limm,false,true,true,false,false,false,false,false,false,false") | |
763 | (set_attr "predicable" "yes,no,yes,no,no,yes,no,yes,yes,yes,yes,no,no,no,no,no,no,no,no,no") | |
764 | (set_attr "cpu_facility" "av1,av1,av1,av2,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,*")]) | |
526b7aee SV |
765 | |
766 | (define_expand "movsi" | |
767 | [(set (match_operand:SI 0 "move_dest_operand" "") | |
768 | (match_operand:SI 1 "general_operand" ""))] | |
769 | "" | |
770 | "if (prepare_move_operands (operands, SImode)) DONE;") | |
771 | ||
772 | ; In order to allow the ccfsm machinery to do its work, the leading compact | |
773 | ; alternatives say 'canuse' - there is another alternative that will match | |
774 | ; when the condition codes are used. | |
03301dcc | 775 | ; The length of an alternative that might be shifted to conditional |
526b7aee SV |
776 | ; execution must reflect this, lest out-of-range branches are created. |
777 | ; the iscompact attribute allows the epilogue expander to know for which | |
778 | ; insns it should lengthen the return insn. | |
ce9dbf20 CZ |
779 | (define_insn_and_split "*movsi_insn" ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
780 | [(set (match_operand:SI 0 "move_dest_operand" "=q, q,r,q, h, rl,r, r, r, r, ?r, r, q, h, rl, q, S, Us<,RcqRck,!*x, r,!*Rsd,!*Rcd,r,Ucm, Usd,m, m,VUsc") | |
781 | (match_operand:SI 1 "move_src_operand" "rL,rP,q,P,hCm1,rLl,I,Clo,Chi,Cbi,Cpc,Clb,Cax,Cal,Cal,Uts,Rcq,RcqRck, Us>,Usd,Ucm, Usd, Ucd,m, r,!*Rzd,r,Cm3, C32"))] | |
526b7aee SV |
782 | "register_operand (operands[0], SImode) |
783 | || register_operand (operands[1], SImode) | |
784 | || (CONSTANT_P (operands[1]) | |
03301dcc | 785 | && (!satisfies_constraint_I (operands[1]) || !optimize_size) |
2295aa75 CZ |
786 | && satisfies_constraint_Usc (operands[0])) |
787 | || (satisfies_constraint_Cm3 (operands[1]) | |
788 | && memory_operand (operands[0], SImode))" | |
526b7aee | 789 | "@ |
03301dcc CZ |
790 | mov%?\\t%0,%1 ;0 |
791 | mov%?\\t%0,%1 ;1 | |
792 | mov%?\\t%0,%1 ;2 | |
793 | mov%?\\t%0,%1 ;3 | |
794 | mov%?\\t%0,%1 ;4 | |
795 | mov%?\\t%0,%1 ;5 | |
796 | mov%?\\t%0,%1 ;6 | |
ce9dbf20 CZ |
797 | movl.cl\\t%0,%1 ;7 |
798 | movh.cl\\t%0,%L1>>16 ;8 | |
03301dcc CZ |
799 | * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl\\t%0,%1 >> %p1,%p1,8;9\" : \"movbi.cl\\t%0,%L1 >> 24,24,8;9\"; |
800 | add\\t%0,%1 ;10 | |
801 | add\\t%0,pcl,%1@pcl ;11 | |
802 | # | |
803 | mov%?\\t%0,%j1 ;13 | |
804 | mov%?\\t%0,%j1 ;14 | |
805 | ld%?\\t%0,%1 ;15 | |
ce9dbf20 | 806 | st%?\\t%1,%0 ;16 |
03301dcc CZ |
807 | * return arc_short_long (insn, \"push%?\\t%1%&\", \"st%U0\\t%1,%0%&\"); |
808 | * return arc_short_long (insn, \"pop%?\\t%0%&\", \"ld%U1\\t%0,%1%&\"); | |
809 | ld%?\\t%0,%1 ;19 | |
810 | xld%U1\\t%0,%1 ;20 | |
811 | ld%?\\t%0,%1 ;21 | |
812 | ld%?\\t%0,%1 ;22 | |
813 | ld%U1%V1\\t%0,%1 ;23 | |
814 | xst%U0\\t%1,%0 ;24 | |
815 | st%?\\t%1,%0%& ;25 | |
816 | st%U0%V0\\t%1,%0 ;26 | |
817 | st%U0%V0\\t%1,%0 ;37 | |
818 | st%U0%V0\\t%1,%0 ;28" | |
4653da0b CZ |
819 | "reload_completed |
820 | && GET_CODE (PATTERN (insn)) != COND_EXEC | |
821 | && register_operand (operands[0], SImode) | |
822 | && IN_RANGE (REGNO (operands[0]) ^ 4, 4, 11) | |
823 | && satisfies_constraint_Cax (operands[1])" | |
03301dcc CZ |
824 | [(const_int 0)] |
825 | " | |
826 | arc_split_mov_const (operands); | |
827 | DONE; | |
828 | " | |
829 | ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
830 | [(set_attr "type" "move, move, move,move,move, move, move,shift,shift,shift,binary,binary,multi,move, move,load,store,store,load,load, load,load,load, load,store,store,store,store,store") | |
831 | (set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false,false,false,false, false, false,false,true,false,true, true, true,true,true,false,true,true,false,false, true,false,false,false") | |
832 | (set_attr "length" "*,*,*,*,*,4,4,4,4,4,8,8,*,6,*,*,*,*,*,*,4,*,4,*,*,*,*,*,8") | |
833 | (set_attr "predicable" "yes,no,yes,no,no,yes,no,no,no,yes,no,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no,no,no") | |
834 | (set_attr "cpu_facility" "av1,av1,av1,av2,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,av2,*")]) | |
526b7aee SV |
835 | |
836 | ;; Sometimes generated by the epilogue code. We don't want to | |
837 | ;; recognize these addresses in general, because the limm is costly, | |
838 | ;; and we can't use them for stores. */ | |
839 | (define_insn "*movsi_pre_mod" | |
840 | [(set (match_operand:SI 0 "register_operand" "=w") | |
841 | (mem:SI (pre_modify | |
842 | (reg:SI SP_REG) | |
843 | (plus:SI (reg:SI SP_REG) | |
844 | (match_operand 1 "immediate_operand" "Cal")))))] | |
845 | "reload_completed" | |
846 | "ld.a %0,[sp,%1]" | |
847 | [(set_attr "type" "load") | |
848 | (set_attr "length" "8")]) | |
849 | ||
850 | ;; Store a value to directly to memory. The location might also be cached. | |
851 | ;; Since the cached copy can cause a write-back at unpredictable times, | |
852 | ;; we first write cached, then we write uncached. | |
853 | (define_insn "store_direct" | |
854 | [(set (match_operand:SI 0 "move_dest_operand" "=m") | |
855 | (unspec:SI [(match_operand:SI 1 "register_operand" "c")] | |
c69899f0 | 856 | UNSPEC_ARC_DIRECT))] |
526b7aee SV |
857 | "" |
858 | "st%U0 %1,%0\;st%U0.di %1,%0" | |
859 | [(set_attr "type" "store")]) | |
860 | ||
f7ace5d5 CZ |
861 | ;; Combiner patterns for compare with zero |
862 | (define_mode_iterator SQH [QI HI]) | |
863 | (define_mode_attr SQH_postfix [(QI "b") (HI "%_")]) | |
864 | ||
865 | (define_code_iterator SEZ [sign_extend zero_extend]) | |
866 | (define_code_attr SEZ_prefix [(sign_extend "sex") (zero_extend "ext")]) | |
867 | ||
868 | (define_insn "*<SEZ_prefix>xt<SQH_postfix>_cmp0_noout" | |
869 | [(set (match_operand 0 "cc_set_register" "") | |
870 | (compare:CC_ZN (SEZ:SI (match_operand:SQH 1 "register_operand" "r")) | |
871 | (const_int 0)))] | |
872 | "" | |
873 | "<SEZ_prefix><SQH_postfix>.f\\t0,%1" | |
874 | [(set_attr "type" "compare") | |
875 | (set_attr "cond" "set_zn")]) | |
876 | ||
877 | (define_insn "*<SEZ_prefix>xt<SQH_postfix>_cmp0" | |
878 | [(set (match_operand 0 "cc_set_register" "") | |
879 | (compare:CC_ZN (SEZ:SI (match_operand:SQH 1 "register_operand" "r")) | |
880 | (const_int 0))) | |
881 | (set (match_operand:SI 2 "register_operand" "=r") | |
882 | (SEZ:SI (match_dup 1)))] | |
883 | "" | |
884 | "<SEZ_prefix><SQH_postfix>.f\\t%2,%1" | |
885 | [(set_attr "type" "compare") | |
886 | (set_attr "cond" "set_zn")]) | |
887 | ||
888 | (define_insn "*xbfu_cmp0_noout" | |
889 | [(set (match_operand 0 "cc_set_register" "") | |
890 | (compare:CC_Z | |
891 | (zero_extract:SI | |
892 | (match_operand:SI 1 "register_operand" " r,r") | |
893 | (match_operand:SI 2 "const_int_operand" "C3p,n") | |
894 | (match_operand:SI 3 "const_int_operand" " n,n")) | |
895 | (const_int 0)))] | |
896 | "TARGET_HS && TARGET_BARREL_SHIFTER" | |
897 | { | |
898 | int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL (operands[3]) & 0x1f); | |
899 | operands[2] = GEN_INT (assemble_op2); | |
900 | return "xbfu%?.f\\t0,%1,%2"; | |
901 | } | |
902 | [(set_attr "type" "shift") | |
903 | (set_attr "iscompact" "false") | |
904 | (set_attr "length" "4,8") | |
905 | (set_attr "predicable" "no") | |
906 | (set_attr "cond" "set_zn")]) | |
907 | ||
908 | (define_insn "*xbfu_cmp0" | |
909 | [(set (match_operand 4 "cc_set_register" "") | |
910 | (compare:CC_Z | |
911 | (zero_extract:SI | |
912 | (match_operand:SI 1 "register_operand" "0 ,r,0") | |
913 | (match_operand:SI 2 "const_int_operand" "C3p,n,n") | |
914 | (match_operand:SI 3 "const_int_operand" "n ,n,n")) | |
915 | (const_int 0))) | |
916 | (set (match_operand:SI 0 "register_operand" "=r,r,r") | |
917 | (zero_extract:SI (match_dup 1) (match_dup 2) (match_dup 3)))] | |
918 | "TARGET_HS && TARGET_BARREL_SHIFTER" | |
919 | { | |
920 | int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL (operands[3]) & 0x1f); | |
921 | operands[2] = GEN_INT (assemble_op2); | |
922 | return "xbfu%?.f\\t%0,%1,%2"; | |
923 | } | |
924 | [(set_attr "type" "shift") | |
925 | (set_attr "iscompact" "false") | |
926 | (set_attr "length" "4,8,8") | |
927 | (set_attr "predicable" "yes,no,yes") | |
928 | (set_attr "cond" "set_zn")]) | |
929 | ||
930 | ; splitting to 'tst' allows short insns and combination into brcc. | |
526b7aee | 931 | (define_insn_and_split "*movsi_set_cc_insn" |
f7ace5d5 CZ |
932 | [(set (match_operand 2 "cc_set_register" "") |
933 | (match_operator 3 "zn_compare_operator" | |
934 | [(match_operand:SI 1 "nonmemory_operand" "rL,rI,Cal") | |
935 | (const_int 0)])) | |
936 | (set (match_operand:SI 0 "register_operand" "=r,r,r") | |
526b7aee SV |
937 | (match_dup 1))] |
938 | "" | |
f7ace5d5 | 939 | "mov%?.f\\t%0,%1" |
526b7aee SV |
940 | "reload_completed && operands_match_p (operands[0], operands[1])" |
941 | [(set (match_dup 2) (match_dup 3))] | |
942 | "" | |
943 | [(set_attr "type" "compare") | |
f7ace5d5 | 944 | (set_attr "predicable" "yes,no,yes") |
526b7aee SV |
945 | (set_attr "cond" "set_zn") |
946 | (set_attr "length" "4,4,8")]) | |
947 | ||
948 | (define_insn "unary_comparison" | |
949 | [(set (match_operand:CC_ZN 0 "cc_set_register" "") | |
f50bb868 | 950 | (match_operator:CC_ZN 3 "zn_compare_operator" |
526b7aee SV |
951 | [(match_operator:SI 2 "unary_operator" |
952 | [(match_operand:SI 1 "register_operand" "c")]) | |
953 | (const_int 0)]))] | |
954 | "" | |
955 | "%O2.f 0,%1" | |
956 | [(set_attr "type" "compare") | |
957 | (set_attr "cond" "set_zn")]) | |
958 | ||
959 | ||
960 | ; this pattern is needed by combiner for cases like if (c=(~b)) { ... } | |
961 | (define_insn "*unary_comparison_result_used" | |
962 | [(set (match_operand 2 "cc_register" "") | |
963 | (match_operator 4 "zn_compare_operator" | |
964 | [(match_operator:SI 3 "unary_operator" | |
965 | [(match_operand:SI 1 "register_operand" "c")]) | |
966 | (const_int 0)])) | |
967 | (set (match_operand:SI 0 "register_operand" "=w") | |
968 | (match_dup 3))] | |
969 | "" | |
970 | "%O3.f %0,%1" | |
971 | [(set_attr "type" "compare") | |
972 | (set_attr "cond" "set_zn") | |
973 | (set_attr "length" "4")]) | |
974 | ||
ceaaa9fe JR |
975 | ; reload is too stingy with reloads for Rrq/Cbf/Rrq when it sees |
976 | ; a c/???Cal/X alternative, so we say it's c/???Cal/c instead, | |
977 | ; even if we don't need the clobber. | |
978 | (define_insn_and_split "*tst_movb" | |
979 | [(set | |
980 | (match_operand 0 "cc_register" "") | |
981 | (match_operator 4 "zn_compare_operator" | |
982 | [(and:SI | |
a0947960 | 983 | (match_operand:SI 1 "register_operand" "%Rcq,Rcq, c, c, c, c,Rrq,Rrq, c") |
ceaaa9fe JR |
984 | (match_operand:SI 2 "nonmemory_operand" "Rcq,C0p,cI,C1p,Ccp,Chs,Cbf,Cbf,???Cal")) |
985 | (const_int 0)])) | |
a0947960 | 986 | (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,Rrq,1,c"))] |
ceaaa9fe JR |
987 | "TARGET_NPS_BITOPS" |
988 | "movb.f.cl %3,%1,%p2,%p2,%s2" | |
7841f13c | 989 | "TARGET_NPS_BITOPS && reload_completed |
ceaaa9fe JR |
990 | && (extract_constrain_insn_cached (insn), (which_alternative & ~1) != 6)" |
991 | [(set (match_dup 0) (match_dup 4))]) | |
992 | ||
526b7aee SV |
993 | (define_insn "*tst" |
994 | [(set | |
995 | (match_operand 0 "cc_register" "") | |
996 | (match_operator 3 "zn_compare_operator" | |
997 | [(and:SI | |
998 | (match_operand:SI 1 "register_operand" | |
999 | "%Rcq,Rcq, c, c, c, c, c, c") | |
1000 | (match_operand:SI 2 "nonmemory_operand" | |
ceaaa9fe | 1001 | " Rcq,C0p,cI,cL,C1p,Ccp,Chs,Cal")) |
526b7aee | 1002 | (const_int 0)]))] |
ceaaa9fe JR |
1003 | "reload_completed |
1004 | || !satisfies_constraint_Cbf (operands[2]) | |
1005 | || satisfies_constraint_C0p (operands[2]) | |
1006 | || satisfies_constraint_I (operands[2]) | |
1007 | || satisfies_constraint_C1p (operands[2]) | |
1008 | || satisfies_constraint_Chs (operands[2])" | |
526b7aee SV |
1009 | "* |
1010 | switch (which_alternative) | |
1011 | { | |
1012 | case 0: case 2: case 3: case 7: | |
1013 | return \"tst%? %1,%2\"; | |
1014 | case 1: | |
1015 | return \"btst%? %1,%z2\"; | |
1016 | case 4: | |
1017 | return \"bmsk%?.f 0,%1,%Z2%&\"; | |
1018 | case 5: | |
1019 | return \"bclr%?.f 0,%1,%M2%&\"; | |
1020 | case 6: | |
ceaaa9fe | 1021 | return \"asr.f 0,%1,%p2\"; |
526b7aee SV |
1022 | default: |
1023 | gcc_unreachable (); | |
1024 | } | |
1025 | " | |
1026 | [(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false") | |
43bb0fc2 | 1027 | (set_attr "type" "compare,compare,compare,compare,compare,compare,binary,compare") |
526b7aee SV |
1028 | (set_attr "length" "*,*,4,4,4,4,4,8") |
1029 | (set_attr "predicable" "no,yes,no,yes,no,no,no,yes") | |
1030 | (set_attr "cond" "set_zn")]) | |
1031 | ||
ceaaa9fe JR |
1032 | ; ??? Sometimes, if an AND with a constant can be expressed as a zero_extract, |
1033 | ; combine will do that and not try the AND. | |
1034 | ||
1035 | ; It would take 66 constraint combinations to describe the zero_extract | |
1036 | ; constants that are covered by the 12-bit signed constant for tst | |
1037 | ; (excluding the ones that are better done by mov or btst). | |
1038 | ; so we rather use an extra pattern for tst; | |
1039 | ; since this is about constants, reload shouldn't care. | |
1040 | (define_insn "*tst_bitfield_tst" | |
1041 | [(set (match_operand:CC_ZN 0 "cc_set_register" "") | |
1042 | (match_operator 4 "zn_compare_operator" | |
1043 | [(zero_extract:SI | |
1044 | (match_operand:SI 1 "register_operand" "c") | |
1045 | (match_operand:SI 2 "const_int_operand" "n") | |
1046 | (match_operand:SI 3 "const_int_operand" "n")) | |
1047 | (const_int 0)]))] | |
1048 | "INTVAL (operands[2]) > 1 | |
1049 | && (INTVAL (operands[3]) + INTVAL (operands[2]) <= 11 | |
1050 | || (INTVAL (operands[3]) <= 11 | |
1051 | && INTVAL (operands[3]) + INTVAL (operands[2]) == 32))" | |
8c56cc5a | 1052 | "tst %1,((1<<%2)-1)<<%3" |
ceaaa9fe JR |
1053 | [(set_attr "type" "compare") |
1054 | (set_attr "cond" "set_zn") | |
1055 | (set_attr "length" "4")]) | |
1056 | ||
1057 | ; Likewise for asr.f. | |
1058 | (define_insn "*tst_bitfield_asr" | |
1059 | [(set (match_operand:CC_ZN 0 "cc_set_register" "") | |
1060 | (match_operator 4 "zn_compare_operator" | |
1061 | [(zero_extract:SI | |
1062 | (match_operand:SI 1 "register_operand" "c") | |
1063 | (match_operand:SI 2 "const_int_operand" "n") | |
1064 | (match_operand:SI 3 "const_int_operand" "n")) | |
1065 | (const_int 0)]))] | |
1066 | "INTVAL (operands[2]) > 1 | |
1067 | && INTVAL (operands[3]) + INTVAL (operands[2]) == 32" | |
1068 | "asr.f 0,%1,%3" | |
1069 | [(set_attr "type" "shift") | |
1070 | (set_attr "cond" "set_zn") | |
1071 | (set_attr "length" "4")]) | |
1072 | ||
1073 | (define_insn "*tst_bitfield" | |
1074 | [(set (match_operand:CC_ZN 0 "cc_set_register" "") | |
1075 | (match_operator 5 "zn_compare_operator" | |
1076 | [(zero_extract:SI | |
1077 | (match_operand:SI 1 "register_operand" "%Rcqq,c, c,Rrq,c") | |
1078 | (match_operand:SI 2 "const_int_operand" "N,N, n,Cbn,n") | |
1079 | (match_operand:SI 3 "const_int_operand" "n,n,C_0,Cbn,n")) | |
1080 | (const_int 0)])) | |
1081 | (clobber (match_scratch:SI 4 "=X,X,X,Rrq,X"))] | |
1082 | "" | |
1083 | "@ | |
1084 | btst%? %1,%3 | |
1085 | btst %1,%3 | |
1086 | bmsk.f 0,%1,%2-1 | |
1087 | movb.f.cl %4,%1,%3,%3,%2 | |
1088 | and.f 0,%1,((1<<%2)-1)<<%3" | |
1089 | [(set_attr "iscompact" "maybe,false,false,false,false") | |
1090 | (set_attr "type" "compare,compare,compare,shift,compare") | |
1091 | (set_attr "cond" "set_zn") | |
1092 | (set_attr "length" "*,4,4,4,8")]) | |
1093 | ||
f7ace5d5 CZ |
1094 | ;; The next two patterns are for plos, ior, xor, and, and mult. |
1095 | (define_insn "*commutative_binary_cmp0_noout" | |
1096 | [(set (match_operand 0 "cc_set_register" "") | |
1097 | (match_operator 4 "zn_compare_operator" | |
1098 | [(match_operator:SI 3 "commutative_operator" | |
1099 | [(match_operand:SI 1 "register_operand" "%r,r") | |
1100 | (match_operand:SI 2 "nonmemory_operand" "rL,Cal")]) | |
1101 | (const_int 0)]))] | |
1102 | "" | |
1103 | "%O3.f\\t0,%1,%2" | |
1104 | [(set_attr "type" "compare") | |
1105 | (set_attr "cond" "set_zn") | |
1106 | (set_attr "length" "4,8")]) | |
1107 | ||
1108 | (define_insn "*commutative_binary_cmp0" | |
1109 | [(set (match_operand 3 "cc_set_register" "") | |
1110 | (match_operator 5 "zn_compare_operator" | |
526b7aee | 1111 | [(match_operator:SI 4 "commutative_operator" |
f7ace5d5 CZ |
1112 | [(match_operand:SI 1 "register_operand" "%0, 0,r,r") |
1113 | (match_operand:SI 2 "nonmemory_operand" "rL,rI,r,Cal")]) | |
526b7aee | 1114 | (const_int 0)])) |
f7ace5d5 CZ |
1115 | (set (match_operand:SI 0 "register_operand" "=r,r,r,r") |
1116 | (match_dup 4))] | |
526b7aee | 1117 | "" |
f7ace5d5 | 1118 | "%O4.f\\t%0,%1,%2" |
526b7aee SV |
1119 | [(set_attr "type" "compare") |
1120 | (set_attr "cond" "set_zn") | |
f7ace5d5 CZ |
1121 | (set_attr "predicable" "yes,yes,no,no") |
1122 | (set_attr "length" "4,4,4,8")]) | |
526b7aee SV |
1123 | |
1124 | ; for flag setting 'add' instructions like if (a+b) { ...} | |
1125 | ; the combiner needs this pattern | |
1126 | (define_insn "*addsi_compare" | |
1127 | [(set (reg:CC_ZN CC_REG) | |
1128 | (compare:CC_ZN (match_operand:SI 0 "register_operand" "c") | |
1129 | (neg:SI (match_operand:SI 1 "register_operand" "c"))))] | |
1130 | "" | |
1131 | "add.f 0,%0,%1" | |
1132 | [(set_attr "cond" "set") | |
1133 | (set_attr "type" "compare") | |
1134 | (set_attr "length" "4")]) | |
1135 | ||
1136 | ; for flag setting 'add' instructions like if (a+b < a) { ...} | |
1137 | ; the combiner needs this pattern | |
1138 | (define_insn "addsi_compare_2" | |
1139 | [(set (reg:CC_C CC_REG) | |
1140 | (compare:CC_C (plus:SI (match_operand:SI 0 "register_operand" "c,c") | |
1141 | (match_operand:SI 1 "nonmemory_operand" "cL,Cal")) | |
1142 | (match_dup 0)))] | |
1143 | "" | |
1144 | "add.f 0,%0,%1" | |
1145 | [(set_attr "cond" "set") | |
1146 | (set_attr "type" "compare") | |
1147 | (set_attr "length" "4,8")]) | |
1148 | ||
1149 | (define_insn "*addsi_compare_3" | |
1150 | [(set (reg:CC_C CC_REG) | |
1151 | (compare:CC_C (plus:SI (match_operand:SI 0 "register_operand" "c") | |
1152 | (match_operand:SI 1 "register_operand" "c")) | |
1153 | (match_dup 1)))] | |
1154 | "" | |
1155 | "add.f 0,%0,%1" | |
1156 | [(set_attr "cond" "set") | |
1157 | (set_attr "type" "compare") | |
1158 | (set_attr "length" "4")]) | |
1159 | ||
1160 | ; this pattern is needed by combiner for cases like if (c=a+b) { ... } | |
1161 | (define_insn "*commutative_binary_comparison_result_used" | |
1162 | [(set (match_operand 3 "cc_register" "") | |
1163 | (match_operator 5 "zn_compare_operator" | |
1164 | ; We can accept any commutative operator except mult because | |
1165 | ; our 'w' class below could try to use LP_COUNT. | |
1166 | [(match_operator:SI 4 "commutative_operator_sans_mult" | |
1167 | [(match_operand:SI 1 "register_operand" "c,0,c") | |
1168 | (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")]) | |
1169 | (const_int 0)])) | |
1170 | (set (match_operand:SI 0 "register_operand" "=w,w,w") | |
1171 | (match_dup 4))] | |
1172 | "" | |
1173 | "%O4.f %0,%1,%2 ; non-mult commutative" | |
1174 | [(set_attr "type" "compare,compare,compare") | |
1175 | (set_attr "cond" "set_zn,set_zn,set_zn") | |
1176 | (set_attr "length" "4,4,8")]) | |
1177 | ||
1178 | ; a MULT-specific version of this pattern to avoid touching the | |
1179 | ; LP_COUNT register | |
1180 | (define_insn "*commutative_binary_mult_comparison_result_used" | |
1181 | [(set (match_operand 3 "cc_register" "") | |
1182 | (match_operator 5 "zn_compare_operator" | |
1183 | [(match_operator:SI 4 "mult_operator" | |
1184 | [(match_operand:SI 1 "register_operand" "c,0,c") | |
1185 | (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")]) | |
1186 | (const_int 0)])) | |
1187 | ; Make sure to use the W class to not touch LP_COUNT. | |
1188 | (set (match_operand:SI 0 "register_operand" "=W,W,W") | |
1189 | (match_dup 4))] | |
f50bb868 | 1190 | "!TARGET_ARC600_FAMILY" |
526b7aee SV |
1191 | "%O4.f %0,%1,%2 ; mult commutative" |
1192 | [(set_attr "type" "compare,compare,compare") | |
1193 | (set_attr "cond" "set_zn,set_zn,set_zn") | |
1194 | (set_attr "length" "4,4,8")]) | |
1195 | ||
f7ace5d5 CZ |
1196 | (define_insn "*noncommutative_binary_cmp0" |
1197 | [(set (match_operand 3 "cc_set_register" "") | |
526b7aee SV |
1198 | (match_operator 5 "zn_compare_operator" |
1199 | [(match_operator:SI 4 "noncommutative_operator" | |
f7ace5d5 CZ |
1200 | [(match_operand:SI 1 "register_operand" "0,r,0, 0,r") |
1201 | (match_operand:SI 2 "nonmemory_operand" "rL,r,I,Cal,Cal")]) | |
1202 | (const_int 0)])) | |
1203 | (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") | |
1204 | (match_dup 4))] | |
1205 | "" | |
1206 | "%O4%?.f\\t%0,%1,%2" | |
1207 | [(set_attr "type" "compare") | |
1208 | (set_attr "cond" "set_zn") | |
1209 | (set_attr "predicable" "yes,no,no,yes,no") | |
1210 | (set_attr "length" "4,4,4,8,8")]) | |
526b7aee | 1211 | |
f7ace5d5 CZ |
1212 | (define_insn "*noncommutative_binary_cmp0_noout" |
1213 | [(set (match_operand 0 "cc_set_register" "") | |
1214 | (match_operator 3 "zn_compare_operator" | |
526b7aee | 1215 | [(match_operator:SI 4 "noncommutative_operator" |
f7ace5d5 CZ |
1216 | [(match_operand:SI 1 "register_operand" "r,r") |
1217 | (match_operand:SI 2 "nonmemory_operand" "rL,Cal")]) | |
1218 | (const_int 0)]))] | |
1219 | "" | |
1220 | "%O4.f\\t0,%1,%2" | |
1221 | [(set_attr "type" "compare") | |
1222 | (set_attr "cond" "set_zn") | |
1223 | (set_attr "length" "4,8")]) | |
1224 | ||
1225 | ;;rsub variants | |
1226 | (define_insn "*rsub_cmp0" | |
1227 | [(set (match_operand 4 "cc_set_register" "") | |
1228 | (match_operator 3 "zn_compare_operator" | |
1229 | [(minus:SI | |
1230 | (match_operand:SI 1 "nonmemory_operand" "rL,Cal") | |
1231 | (match_operand:SI 2 "register_operand" "r,r")) | |
526b7aee | 1232 | (const_int 0)])) |
f7ace5d5 CZ |
1233 | (set (match_operand:SI 0 "register_operand" "=r,r") |
1234 | (minus:SI (match_dup 1) (match_dup 2)))] | |
1235 | "" | |
1236 | "rsub.f\\t%0,%2,%1" | |
1237 | [(set_attr "type" "compare") | |
1238 | (set_attr "cond" "set_zn") | |
1239 | (set_attr "length" "4,8")]) | |
1240 | ||
1241 | (define_insn "*rsub_cmp0_noout" | |
1242 | [(set (match_operand 0 "cc_set_register" "") | |
1243 | (match_operator 3 "zn_compare_operator" | |
1244 | [(minus:SI | |
1245 | (match_operand:SI 1 "nonmemory_operand" "rL,Cal") | |
1246 | (match_operand:SI 2 "register_operand" "r,r")) | |
1247 | (const_int 0)]))] | |
1248 | "" | |
1249 | "rsub.f\\t0,%2,%1" | |
526b7aee SV |
1250 | [(set_attr "type" "compare") |
1251 | (set_attr "cond" "set_zn") | |
6f70ebc3 | 1252 | (set_attr "length" "4,8")]) |
526b7aee SV |
1253 | |
1254 | (define_expand "bic_f_zn" | |
1255 | [(parallel | |
1256 | [(set (reg:CC_ZN CC_REG) | |
1257 | (compare:CC_ZN | |
1258 | (and:SI (match_operand:SI 1 "register_operand" "") | |
1259 | (not:SI (match_operand:SI 2 "nonmemory_operand" ""))) | |
1260 | (const_int 0))) | |
1261 | (set (match_operand:SI 0 "register_operand" "") | |
1262 | (and:SI (match_dup 1) (not:SI (match_dup 2))))])] | |
1263 | "") | |
1264 | ||
1265 | (define_insn "*bic_f" | |
d9c50233 | 1266 | [(set (match_operand 3 "cc_set_register" "") |
526b7aee SV |
1267 | (match_operator 4 "zn_compare_operator" |
1268 | [(and:SI (match_operand:SI 1 "register_operand" "c,0,c") | |
1269 | (not:SI | |
1270 | (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal"))) | |
1271 | (const_int 0)])) | |
1272 | (set (match_operand:SI 0 "register_operand" "=w,w,w") | |
1273 | (and:SI (match_dup 1) (not:SI (match_dup 2))))] | |
1274 | "" | |
1275 | "bic.f %0,%1,%2" | |
1276 | [(set_attr "type" "compare,compare,compare") | |
1277 | (set_attr "cond" "set_zn,set_zn,set_zn") | |
1278 | (set_attr "length" "4,4,8")]) | |
1279 | ||
d9c50233 CZ |
1280 | (define_insn "*bic_cmp0_noout" |
1281 | [(set (match_operand 0 "cc_set_register" "") | |
1282 | (compare:CC_ZN | |
1283 | (and:SI (not:SI (match_operand:SI 1 "nonmemory_operand" "Lr,Cal,r")) | |
1284 | (match_operand:SI 2 "nonmemory_operand" "r,r,Cal")) | |
1285 | (const_int 0)))] | |
1286 | "register_operand (operands[1], SImode) | |
1287 | || register_operand (operands[2], SImode)" | |
1288 | "bic.f\\t0,%2,%1" | |
1289 | [(set_attr "type" "unary") | |
1290 | (set_attr "cond" "set_zn") | |
1291 | (set_attr "length" "4,8,8")]) | |
1292 | ||
1293 | (define_insn "*bic_cmp0" | |
1294 | [(set (match_operand 0 "cc_set_register" "") | |
1295 | (compare:CC_ZN | |
1296 | (and:SI (not:SI (match_operand:SI 1 "nonmemory_operand" "Lr,Cal,r")) | |
1297 | (match_operand:SI 2 "nonmemory_operand" "r,r,Cal")) | |
1298 | (const_int 0))) | |
1299 | (set (match_operand:SI 3 "register_operand" "=r,r,r") | |
1300 | (and:SI (not:SI (match_dup 1)) (match_dup 2)))] | |
1301 | "register_operand (operands[1], SImode) | |
1302 | || register_operand (operands[2], SImode)" | |
1303 | "bic.f\\t%3,%2,%1" | |
1304 | [(set_attr "type" "unary") | |
1305 | (set_attr "cond" "set_zn") | |
1306 | (set_attr "length" "4,8,8")]) | |
1307 | ||
526b7aee SV |
1308 | (define_expand "movdi" |
1309 | [(set (match_operand:DI 0 "move_dest_operand" "") | |
1310 | (match_operand:DI 1 "general_operand" ""))] | |
1311 | "" | |
1312 | " | |
491483b0 CZ |
1313 | if (prepare_move_operands (operands, DImode)) |
1314 | DONE; | |
1315 | ") | |
526b7aee SV |
1316 | |
1317 | (define_insn_and_split "*movdi_insn" | |
2295aa75 CZ |
1318 | [(set (match_operand:DI 0 "move_dest_operand" "=w, w,r, m") |
1319 | (match_operand:DI 1 "move_double_src_operand" "c,Hi,m,cCm3"))] | |
526b7aee | 1320 | "register_operand (operands[0], DImode) |
2295aa75 CZ |
1321 | || register_operand (operands[1], DImode) |
1322 | || (satisfies_constraint_Cm3 (operands[1]) | |
1323 | && memory_operand (operands[0], DImode))" | |
526b7aee SV |
1324 | "* |
1325 | { | |
1326 | switch (which_alternative) | |
1327 | { | |
1328 | default: | |
d34a0fdc CZ |
1329 | return \"#\"; |
1330 | ||
1331 | case 2: | |
1332 | if (TARGET_LL64 | |
2295aa75 CZ |
1333 | && memory_operand (operands[1], DImode) |
1334 | && even_register_operand (operands[0], DImode)) | |
d34a0fdc CZ |
1335 | return \"ldd%U1%V1 %0,%1%&\"; |
1336 | return \"#\"; | |
1337 | ||
1338 | case 3: | |
1339 | if (TARGET_LL64 | |
2295aa75 CZ |
1340 | && memory_operand (operands[0], DImode) |
1341 | && (even_register_operand (operands[1], DImode) | |
1342 | || satisfies_constraint_Cm3 (operands[1]))) | |
d34a0fdc CZ |
1343 | return \"std%U0%V0 %1,%0\"; |
1344 | return \"#\"; | |
526b7aee SV |
1345 | } |
1346 | }" | |
d34a0fdc CZ |
1347 | "reload_completed" |
1348 | [(const_int 0)] | |
1349 | { | |
1350 | arc_split_move (operands); | |
1351 | DONE; | |
1352 | } | |
526b7aee SV |
1353 | [(set_attr "type" "move,move,load,store") |
1354 | ;; ??? The ld/st values could be 4 if it's [reg,bignum]. | |
d34a0fdc | 1355 | (set_attr "length" "8,16,*,*")]) |
526b7aee SV |
1356 | |
1357 | ||
1358 | ;; Floating point move insns. | |
1359 | ||
1360 | (define_expand "movsf" | |
491483b0 | 1361 | [(set (match_operand:SF 0 "move_dest_operand" "") |
526b7aee SV |
1362 | (match_operand:SF 1 "general_operand" ""))] |
1363 | "" | |
1364 | "if (prepare_move_operands (operands, SFmode)) DONE;") | |
1365 | ||
1366 | (define_insn "*movsf_insn" | |
a9637757 CZ |
1367 | [(set (match_operand:SF 0 "move_dest_operand" "=h,h, r,r, q,S,Usc,r,m") |
1368 | (match_operand:SF 1 "move_src_operand" "hCfZ,E,rCfZ,E,Uts,q, E,m,r"))] | |
526b7aee SV |
1369 | "register_operand (operands[0], SFmode) |
1370 | || register_operand (operands[1], SFmode)" | |
1371 | "@ | |
a9637757 CZ |
1372 | mov%?\\t%0,%1 |
1373 | mov%?\\t%0,%1 ; %A1 | |
1374 | mov%?\\t%0,%1 | |
1375 | mov%?\\t%0,%1 ; %A1 | |
1376 | ld%?%U1\\t%0,%1 | |
1377 | st%?\\t%1,%0 | |
1378 | st%U0%V0\\t%1,%0 | |
1379 | ld%U1%V1\\t%0,%1 | |
1380 | st%U0%V0\\t%1,%0" | |
1381 | [(set_attr "type" "move,move,move,move,load,store,store,load,store") | |
1382 | (set_attr "predicable" "no,no,yes,yes,no,no,no,no,no") | |
1383 | (set_attr "length" "*,*,4,*,*,*,*,*,*") | |
1384 | (set_attr "iscompact" "true,true_limm,false,false,true,true,false,false,false")]) | |
526b7aee SV |
1385 | |
1386 | (define_expand "movdf" | |
491483b0 | 1387 | [(set (match_operand:DF 0 "move_dest_operand" "") |
526b7aee SV |
1388 | (match_operand:DF 1 "general_operand" ""))] |
1389 | "" | |
1390 | "if (prepare_move_operands (operands, DFmode)) DONE;") | |
1391 | ||
d34a0fdc | 1392 | (define_insn_and_split "*movdf_insn" |
526b7aee SV |
1393 | [(set (match_operand:DF 0 "move_dest_operand" "=D,r,c,c,r,m") |
1394 | (match_operand:DF 1 "move_double_src_operand" "r,D,c,E,m,c"))] | |
1395 | "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)" | |
d34a0fdc CZ |
1396 | "* |
1397 | { | |
1398 | switch (which_alternative) | |
1399 | { | |
1400 | default: | |
1401 | return \"#\"; | |
1402 | case 4: | |
1403 | if (TARGET_LL64 | |
1404 | && ((even_register_operand (operands[0], DFmode) | |
1405 | && memory_operand (operands[1], DFmode)) | |
1406 | || (memory_operand (operands[0], DFmode) | |
1407 | && even_register_operand (operands[1], DFmode)))) | |
1408 | return \"ldd%U1%V1 %0,%1%&\"; | |
1409 | return \"#\"; | |
1410 | ||
1411 | case 5: | |
1412 | if (TARGET_LL64 | |
1413 | && ((even_register_operand (operands[0], DFmode) | |
1414 | && memory_operand (operands[1], DFmode)) | |
1415 | || (memory_operand (operands[0], DFmode) | |
1416 | && even_register_operand (operands[1], DFmode)))) | |
1417 | return \"std%U0%V0 %1,%0\"; | |
1418 | return \"#\"; | |
1419 | } | |
1420 | }" | |
1421 | "reload_completed" | |
1422 | [(const_int 0)] | |
1423 | { | |
1424 | arc_split_move (operands); | |
1425 | DONE; | |
1426 | } | |
526b7aee SV |
1427 | [(set_attr "type" "move,move,move,move,load,store") |
1428 | (set_attr "predicable" "no,no,yes,yes,no,no") | |
1429 | ;; ??? The ld/st values could be 16 if it's [reg,bignum]. | |
1430 | (set_attr "length" "4,16,8,16,16,16")]) | |
1431 | ||
526b7aee SV |
1432 | (define_insn_and_split "*movdf_insn_nolrsr" |
1433 | [(set (match_operand:DF 0 "register_operand" "=r") | |
1434 | (match_operand:DF 1 "arc_double_register_operand" "D")) | |
1435 | (use (match_operand:SI 2 "" "N")) ; aka const1_rtx | |
1436 | ] | |
1437 | "TARGET_DPFP && TARGET_DPFP_DISABLE_LRSR" | |
1438 | "#" | |
1439 | "&& 1" | |
1440 | [ | |
1441 | ; mov r0, 0 | |
1442 | (set (match_dup 0) (match_dup 3)) | |
1443 | ||
1444 | ; daddh?? r1, r0, r0 | |
1445 | (parallel [ | |
1446 | (set (match_dup 1) (plus:DF (match_dup 1) (match_dup 0))) | |
1447 | (use (const_int 1)) | |
1448 | (use (const_int 1)) | |
1449 | (use (match_dup 0)) ; used to block can_combine_p | |
1450 | (set (match_dup 0) (plus:DF (match_dup 1) (match_dup 0))) ; r1 in op 0 | |
1451 | ]) | |
1452 | ||
1453 | ; We have to do this twice, once to read the value into R0 and | |
1454 | ; second time to put back the contents which the first DEXCLx | |
1455 | ; will have overwritten | |
1456 | ; dexcl2 r0, r1, r0 | |
491483b0 CZ |
1457 | (parallel [ |
1458 | (set (match_dup 4) ; aka r0result | |
1459 | ; aka DF, r1, r0 | |
1460 | (unspec_volatile:SI [(match_dup 5) (match_dup 4)] | |
1461 | VUNSPEC_ARC_DEXCL)) | |
1462 | (clobber (match_dup 1)) | |
1463 | ]) | |
526b7aee SV |
1464 | ; Generate the second, which makes sure operand5 and operand4 values |
1465 | ; are put back in the Dx register properly. | |
491483b0 CZ |
1466 | (set (match_dup 1) (unspec_volatile:DF |
1467 | [(match_dup 5) (match_dup 4)] | |
1468 | VUNSPEC_ARC_DEXCL_NORES)) | |
526b7aee SV |
1469 | |
1470 | ; Note: we cannot use a (clobber (match_scratch)) here because | |
1471 | ; the combine pass will end up replacing uses of it with 0 | |
1472 | ] | |
1473 | "operands[3] = CONST0_RTX (DFmode); | |
1474 | operands[4] = simplify_gen_subreg (SImode, operands[0], DFmode, 0); | |
1475 | operands[5] = simplify_gen_subreg (SImode, operands[0], DFmode, 4);" | |
1476 | [(set_attr "type" "move")]) | |
1477 | ||
1478 | ;; Load/Store with update instructions. | |
1479 | ;; | |
1480 | ;; Some of these we can get by using pre-decrement or pre-increment, but the | |
1481 | ;; hardware can also do cases where the increment is not the size of the | |
1482 | ;; object. | |
1483 | ;; | |
1484 | ;; In all these cases, we use operands 0 and 1 for the register being | |
1485 | ;; incremented because those are the operands that local-alloc will | |
1486 | ;; tie and these are the pair most likely to be tieable (and the ones | |
1487 | ;; that will benefit the most). | |
1488 | ;; | |
1489 | ;; We use match_operator here because we need to know whether the memory | |
1490 | ;; object is volatile or not. | |
1491 | ||
1492 | ||
1493 | ;; Note: loadqi_update has no 16-bit variant | |
1494 | (define_insn "*loadqi_update" | |
1495 | [(set (match_operand:QI 3 "dest_reg_operand" "=r,r") | |
0086bd99 AB |
1496 | (match_operator:QI 4 "any_mem_operand" |
1497 | [(plus:SI (match_operand:SI 1 "register_operand" "0,0") | |
a1f70212 | 1498 | (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])) |
526b7aee SV |
1499 | (set (match_operand:SI 0 "dest_reg_operand" "=r,r") |
1500 | (plus:SI (match_dup 1) (match_dup 2)))] | |
1501 | "" | |
6b55f8c9 | 1502 | "ldb.a%V4 %3,[%0,%2]" |
526b7aee SV |
1503 | [(set_attr "type" "load,load") |
1504 | (set_attr "length" "4,8")]) | |
1505 | ||
1506 | (define_insn "*load_zeroextendqisi_update" | |
1507 | [(set (match_operand:SI 3 "dest_reg_operand" "=r,r") | |
0086bd99 AB |
1508 | (zero_extend:SI (match_operator:QI 4 "any_mem_operand" |
1509 | [(plus:SI (match_operand:SI 1 "register_operand" "0,0") | |
a1f70212 | 1510 | (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))) |
526b7aee SV |
1511 | (set (match_operand:SI 0 "dest_reg_operand" "=r,r") |
1512 | (plus:SI (match_dup 1) (match_dup 2)))] | |
1513 | "" | |
6b55f8c9 | 1514 | "ldb.a%V4 %3,[%0,%2]" |
526b7aee SV |
1515 | [(set_attr "type" "load,load") |
1516 | (set_attr "length" "4,8")]) | |
1517 | ||
1518 | (define_insn "*load_signextendqisi_update" | |
1519 | [(set (match_operand:SI 3 "dest_reg_operand" "=r,r") | |
0086bd99 AB |
1520 | (sign_extend:SI (match_operator:QI 4 "any_mem_operand" |
1521 | [(plus:SI (match_operand:SI 1 "register_operand" "0,0") | |
a1f70212 | 1522 | (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))) |
526b7aee SV |
1523 | (set (match_operand:SI 0 "dest_reg_operand" "=r,r") |
1524 | (plus:SI (match_dup 1) (match_dup 2)))] | |
1525 | "" | |
6b55f8c9 | 1526 | "ldb.x.a%V4 %3,[%0,%2]" |
526b7aee SV |
1527 | [(set_attr "type" "load,load") |
1528 | (set_attr "length" "4,8")]) | |
1529 | ||
1530 | (define_insn "*storeqi_update" | |
94d7642b AB |
1531 | [(set (match_operator:QI 4 "any_mem_operand" |
1532 | [(plus:SI (match_operand:SI 1 "register_operand" "0") | |
1533 | (match_operand:SI 2 "short_immediate_operand" "I"))]) | |
526b7aee SV |
1534 | (match_operand:QI 3 "register_operand" "c")) |
1535 | (set (match_operand:SI 0 "dest_reg_operand" "=w") | |
1536 | (plus:SI (match_dup 1) (match_dup 2)))] | |
1537 | "" | |
1538 | "stb.a%V4 %3,[%0,%2]" | |
1539 | [(set_attr "type" "store") | |
1540 | (set_attr "length" "4")]) | |
1541 | ||
1542 | ;; ??? pattern may have to be re-written | |
1543 | ;; Note: no 16-bit variant for this pattern | |
1544 | (define_insn "*loadhi_update" | |
1545 | [(set (match_operand:HI 3 "dest_reg_operand" "=r,r") | |
0086bd99 AB |
1546 | (match_operator:HI 4 "any_mem_operand" |
1547 | [(plus:SI (match_operand:SI 1 "register_operand" "0,0") | |
a1f70212 | 1548 | (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])) |
526b7aee SV |
1549 | (set (match_operand:SI 0 "dest_reg_operand" "=w,w") |
1550 | (plus:SI (match_dup 1) (match_dup 2)))] | |
1551 | "" | |
6b55f8c9 | 1552 | "ld%_.a%V4 %3,[%0,%2]" |
526b7aee SV |
1553 | [(set_attr "type" "load,load") |
1554 | (set_attr "length" "4,8")]) | |
1555 | ||
1556 | (define_insn "*load_zeroextendhisi_update" | |
1557 | [(set (match_operand:SI 3 "dest_reg_operand" "=r,r") | |
0086bd99 AB |
1558 | (zero_extend:SI (match_operator:HI 4 "any_mem_operand" |
1559 | [(plus:SI (match_operand:SI 1 "register_operand" "0,0") | |
a1f70212 | 1560 | (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))) |
526b7aee SV |
1561 | (set (match_operand:SI 0 "dest_reg_operand" "=r,r") |
1562 | (plus:SI (match_dup 1) (match_dup 2)))] | |
1563 | "" | |
6b55f8c9 | 1564 | "ld%_.a%V4 %3,[%0,%2]" |
526b7aee SV |
1565 | [(set_attr "type" "load,load") |
1566 | (set_attr "length" "4,8")]) | |
1567 | ||
1568 | ;; Note: no 16-bit variant for this instruction | |
1569 | (define_insn "*load_signextendhisi_update" | |
1570 | [(set (match_operand:SI 3 "dest_reg_operand" "=r,r") | |
0086bd99 AB |
1571 | (sign_extend:SI (match_operator:HI 4 "any_mem_operand" |
1572 | [(plus:SI (match_operand:SI 1 "register_operand" "0,0") | |
a1f70212 | 1573 | (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))) |
526b7aee SV |
1574 | (set (match_operand:SI 0 "dest_reg_operand" "=w,w") |
1575 | (plus:SI (match_dup 1) (match_dup 2)))] | |
1576 | "" | |
6b55f8c9 | 1577 | "ld%_.x.a%V4 %3,[%0,%2]" |
526b7aee SV |
1578 | [(set_attr "type" "load,load") |
1579 | (set_attr "length" "4,8")]) | |
1580 | ||
1581 | (define_insn "*storehi_update" | |
94d7642b AB |
1582 | [(set (match_operator:HI 4 "any_mem_operand" |
1583 | [(plus:SI (match_operand:SI 1 "register_operand" "0") | |
1584 | (match_operand:SI 2 "short_immediate_operand" "I"))]) | |
526b7aee SV |
1585 | (match_operand:HI 3 "register_operand" "c")) |
1586 | (set (match_operand:SI 0 "dest_reg_operand" "=w") | |
1587 | (plus:SI (match_dup 1) (match_dup 2)))] | |
1588 | "" | |
f50bb868 | 1589 | "st%_.a%V4 %3,[%0,%2]" |
526b7aee SV |
1590 | [(set_attr "type" "store") |
1591 | (set_attr "length" "4")]) | |
1592 | ||
1593 | ;; No 16-bit variant for this instruction pattern | |
1594 | (define_insn "*loadsi_update" | |
1595 | [(set (match_operand:SI 3 "dest_reg_operand" "=r,r") | |
0086bd99 AB |
1596 | (match_operator:SI 4 "any_mem_operand" |
1597 | [(plus:SI (match_operand:SI 1 "register_operand" "0,0") | |
a1f70212 | 1598 | (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])) |
526b7aee SV |
1599 | (set (match_operand:SI 0 "dest_reg_operand" "=w,w") |
1600 | (plus:SI (match_dup 1) (match_dup 2)))] | |
1601 | "" | |
6b55f8c9 | 1602 | "ld.a%V4 %3,[%0,%2]" |
526b7aee SV |
1603 | [(set_attr "type" "load,load") |
1604 | (set_attr "length" "4,8")]) | |
1605 | ||
1606 | (define_insn "*storesi_update" | |
94d7642b AB |
1607 | [(set (match_operator:SI 4 "any_mem_operand" |
1608 | [(plus:SI (match_operand:SI 1 "register_operand" "0") | |
1609 | (match_operand:SI 2 "short_immediate_operand" "I"))]) | |
526b7aee SV |
1610 | (match_operand:SI 3 "register_operand" "c")) |
1611 | (set (match_operand:SI 0 "dest_reg_operand" "=w") | |
1612 | (plus:SI (match_dup 1) (match_dup 2)))] | |
1613 | "" | |
1614 | "st.a%V4 %3,[%0,%2]" | |
1615 | [(set_attr "type" "store") | |
1616 | (set_attr "length" "4")]) | |
1617 | ||
1618 | (define_insn "*loadsf_update" | |
1619 | [(set (match_operand:SF 3 "dest_reg_operand" "=r,r") | |
0086bd99 AB |
1620 | (match_operator:SF 4 "any_mem_operand" |
1621 | [(plus:SI (match_operand:SI 1 "register_operand" "0,0") | |
a1f70212 | 1622 | (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])) |
526b7aee SV |
1623 | (set (match_operand:SI 0 "dest_reg_operand" "=w,w") |
1624 | (plus:SI (match_dup 1) (match_dup 2)))] | |
1625 | "" | |
6b55f8c9 | 1626 | "ld.a%V4 %3,[%0,%2]" |
526b7aee SV |
1627 | [(set_attr "type" "load,load") |
1628 | (set_attr "length" "4,8")]) | |
1629 | ||
1630 | (define_insn "*storesf_update" | |
94d7642b AB |
1631 | [(set (match_operator:SF 4 "any_mem_operand" |
1632 | [(plus:SI (match_operand:SI 1 "register_operand" "0") | |
1633 | (match_operand:SI 2 "short_immediate_operand" "I"))]) | |
526b7aee SV |
1634 | (match_operand:SF 3 "register_operand" "c")) |
1635 | (set (match_operand:SI 0 "dest_reg_operand" "=w") | |
1636 | (plus:SI (match_dup 1) (match_dup 2)))] | |
1637 | "" | |
1638 | "st.a%V4 %3,[%0,%2]" | |
1639 | [(set_attr "type" "store") | |
1640 | (set_attr "length" "4")]) | |
1641 | ||
1642 | ;; Conditional move instructions. | |
1643 | ||
1644 | (define_expand "movsicc" | |
1645 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
1646 | (if_then_else:SI (match_operand 1 "comparison_operator" "") | |
1647 | (match_operand:SI 2 "nonmemory_operand" "") | |
1648 | (match_operand:SI 3 "register_operand" "")))] | |
1649 | "" | |
1650 | "operands[1] = gen_compare_reg (operands[1], VOIDmode);") | |
1651 | ||
1652 | ||
1653 | (define_expand "movdicc" | |
1654 | [(set (match_operand:DI 0 "dest_reg_operand" "") | |
1655 | (if_then_else:DI(match_operand 1 "comparison_operator" "") | |
1656 | (match_operand:DI 2 "nonmemory_operand" "") | |
1657 | (match_operand:DI 3 "register_operand" "")))] | |
1658 | "" | |
1659 | "operands[1] = gen_compare_reg (operands[1], VOIDmode);") | |
1660 | ||
1661 | ||
1662 | (define_expand "movsfcc" | |
1663 | [(set (match_operand:SF 0 "dest_reg_operand" "") | |
1664 | (if_then_else:SF (match_operand 1 "comparison_operator" "") | |
1665 | (match_operand:SF 2 "nonmemory_operand" "") | |
1666 | (match_operand:SF 3 "register_operand" "")))] | |
1667 | "" | |
1668 | "operands[1] = gen_compare_reg (operands[1], VOIDmode);") | |
1669 | ||
1670 | (define_expand "movdfcc" | |
1671 | [(set (match_operand:DF 0 "dest_reg_operand" "") | |
1672 | (if_then_else:DF (match_operand 1 "comparison_operator" "") | |
1673 | (match_operand:DF 2 "nonmemory_operand" "") | |
1674 | (match_operand:DF 3 "register_operand" "")))] | |
1675 | "" | |
1676 | "operands[1] = gen_compare_reg (operands[1], VOIDmode);") | |
1677 | ||
1678 | (define_insn "*movsicc_insn" | |
1679 | [(set (match_operand:SI 0 "dest_reg_operand" "=w,w") | |
1680 | (if_then_else:SI (match_operator 3 "proper_comparison_operator" | |
1681 | [(match_operand 4 "cc_register" "") (const_int 0)]) | |
1682 | (match_operand:SI 1 "nonmemory_operand" "cL,Cal") | |
1683 | (match_operand:SI 2 "register_operand" "0,0")))] | |
1684 | "" | |
1685 | { | |
1686 | if (rtx_equal_p (operands[1], const0_rtx) && GET_CODE (operands[3]) == NE | |
1687 | && satisfies_constraint_Rcq (operands[0])) | |
1688 | return "sub%?.ne %0,%0,%0"; | |
1689 | /* ??? might be good for speed on ARC600 too, *if* properly scheduled. */ | |
f50bb868 | 1690 | if ((optimize_size && (!TARGET_ARC600_FAMILY)) |
526b7aee SV |
1691 | && rtx_equal_p (operands[1], constm1_rtx) |
1692 | && GET_CODE (operands[3]) == LTU) | |
1693 | return "sbc.cs %0,%0,%0"; | |
6b55f8c9 | 1694 | return "mov.%d3 %0,%1"; |
526b7aee SV |
1695 | } |
1696 | [(set_attr "type" "cmove,cmove") | |
1697 | (set_attr "length" "4,8")]) | |
1698 | ||
e389ba30 AB |
1699 | ;; When there's a mask of a single bit, and then a compare to 0 or 1, |
1700 | ;; if the single bit is the sign bit, then GCC likes to convert this | |
1701 | ;; into a sign extend and a compare less than, or greater to zero. | |
1702 | ;; This is usually fine, except for the NXP400 where we have access to | |
1703 | ;; a bit test instruction, along with a special short load instruction | |
1704 | ;; (from CMEM), that doesn't support sign-extension on load. | |
1705 | ;; | |
1706 | ;; This peephole optimisation attempts to restore the use of bit-test | |
1707 | ;; in those cases where it is useful to do so. | |
1708 | (define_peephole2 | |
1709 | [(set (match_operand:SI 0 "register_operand" "") | |
1710 | (sign_extend:SI | |
1711 | (match_operand:QI 1 "any_mem_operand" ""))) | |
1712 | (set (reg:CC_ZN CC_REG) | |
1713 | (compare:CC_ZN (match_dup 0) | |
1714 | (const_int 0))) | |
1715 | (set (pc) | |
1716 | (if_then_else (match_operator 2 "ge_lt_comparison_operator" | |
1717 | [(reg:CC_ZN CC_REG) (const_int 0)]) | |
1718 | (match_operand 3 "" "") | |
1719 | (match_operand 4 "" "")))] | |
1720 | "TARGET_NPS_CMEM | |
1721 | && cmem_address (XEXP (operands[1], 0), SImode) | |
1722 | && peep2_reg_dead_p (2, operands[0]) | |
1723 | && peep2_regno_dead_p (3, CC_REG)" | |
1724 | [(set (match_dup 0) | |
1725 | (zero_extend:SI | |
1726 | (match_dup 1))) | |
1727 | (set (reg:CC_ZN CC_REG) | |
1728 | (compare:CC_ZN (zero_extract:SI | |
1729 | (match_dup 0) | |
1730 | (const_int 1) | |
1731 | (const_int 7)) | |
1732 | (const_int 0))) | |
1733 | (set (pc) | |
1734 | (if_then_else (match_dup 2) | |
1735 | (match_dup 3) | |
1736 | (match_dup 4)))] | |
1737 | "if (GET_CODE (operands[2]) == GE) | |
1738 | operands[2] = gen_rtx_EQ (VOIDmode, gen_rtx_REG (CC_ZNmode, 61), const0_rtx); | |
1739 | else | |
1740 | operands[2] = gen_rtx_NE (VOIDmode, gen_rtx_REG (CC_ZNmode, 61), const0_rtx);") | |
1741 | ||
526b7aee SV |
1742 | ; Try to generate more short moves, and/or less limms, by substituting a |
1743 | ; conditional move with a conditional sub. | |
1744 | (define_peephole2 | |
1745 | [(set (match_operand:SI 0 "compact_register_operand") | |
1746 | (match_operand:SI 1 "const_int_operand")) | |
1747 | (set (match_dup 0) | |
1748 | (if_then_else:SI (match_operator 3 "proper_comparison_operator" | |
1749 | [(match_operand 4 "cc_register" "") (const_int 0)]) | |
1750 | (match_operand:SI 2 "const_int_operand" "") | |
1751 | (match_dup 0)))] | |
1752 | "!satisfies_constraint_P (operands[1]) | |
1753 | && satisfies_constraint_P (operands[2]) | |
1754 | && UNSIGNED_INT6 (INTVAL (operands[2]) - INTVAL (operands[1]))" | |
1755 | [(set (match_dup 0) (match_dup 2)) | |
1756 | (cond_exec | |
1757 | (match_dup 3) | |
1758 | (set (match_dup 0) | |
1759 | (plus:SI (match_dup 0) (match_dup 1))))] | |
1760 | "operands[3] = gen_rtx_fmt_ee (REVERSE_CONDITION (GET_CODE (operands[3]), | |
1761 | GET_MODE (operands[4])), | |
1762 | VOIDmode, operands[4], const0_rtx); | |
1763 | operands[1] = GEN_INT (INTVAL (operands[1]) - INTVAL (operands[2]));") | |
1764 | ||
1765 | (define_insn "*movdicc_insn" | |
1766 | [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w") | |
1767 | (if_then_else:DI (match_operator 3 "proper_comparison_operator" | |
1768 | [(match_operand 4 "cc_register" "") (const_int 0)]) | |
1769 | (match_operand:DI 1 "nonmemory_operand" "c,i") | |
1770 | (match_operand:DI 2 "register_operand" "0,0")))] | |
1771 | "" | |
1772 | "* | |
1773 | { | |
1774 | switch (which_alternative) | |
1775 | { | |
1776 | default: | |
1777 | case 0 : | |
1778 | /* We normally copy the low-numbered register first. However, if | |
1779 | the first register operand 0 is the same as the second register of | |
1780 | operand 1, we must copy in the opposite order. */ | |
1781 | if (REGNO (operands[0]) == REGNO (operands[1]) + 1) | |
1782 | return \"mov.%d3 %R0,%R1\;mov.%d3 %0,%1\"; | |
1783 | else | |
1784 | return \"mov.%d3 %0,%1\;mov.%d3 %R0,%R1\"; | |
1785 | case 1 : | |
1786 | return \"mov.%d3 %L0,%L1\;mov.%d3 %H0,%H1\"; | |
1787 | ||
1788 | ||
1789 | } | |
1790 | }" | |
1791 | [(set_attr "type" "cmove,cmove") | |
1792 | (set_attr "length" "8,16")]) | |
1793 | ||
1794 | ||
1795 | (define_insn "*movsfcc_insn" | |
1796 | [(set (match_operand:SF 0 "dest_reg_operand" "=w,w") | |
1797 | (if_then_else:SF (match_operator 3 "proper_comparison_operator" | |
1798 | [(match_operand 4 "cc_register" "") (const_int 0)]) | |
1799 | (match_operand:SF 1 "nonmemory_operand" "c,E") | |
1800 | (match_operand:SF 2 "register_operand" "0,0")))] | |
1801 | "" | |
1802 | "@ | |
1803 | mov.%d3 %0,%1 | |
1804 | mov.%d3 %0,%1 ; %A1" | |
1805 | [(set_attr "type" "cmove,cmove")]) | |
1806 | ||
1807 | (define_insn "*movdfcc_insn" | |
1808 | [(set (match_operand:DF 0 "dest_reg_operand" "=w,w") | |
1809 | (if_then_else:DF (match_operator 1 "proper_comparison_operator" | |
1810 | [(match_operand 4 "cc_register" "") (const_int 0)]) | |
1811 | (match_operand:DF 2 "nonmemory_operand" "c,E") | |
1812 | (match_operand:DF 3 "register_operand" "0,0")))] | |
1813 | "" | |
1814 | "* | |
1815 | { | |
1816 | switch (which_alternative) | |
1817 | { | |
1818 | default: | |
1819 | case 0 : | |
1820 | /* We normally copy the low-numbered register first. However, if | |
1821 | the first register operand 0 is the same as the second register of | |
1822 | operand 1, we must copy in the opposite order. */ | |
1823 | if (REGNO (operands[0]) == REGNO (operands[2]) + 1) | |
1824 | return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\"; | |
1825 | else | |
1826 | return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; | |
1827 | case 1 : | |
1828 | return \"mov.%d1 %L0,%L2\;mov.%d1 %H0,%H2; %A2 \"; | |
1829 | ||
1830 | } | |
1831 | }" | |
1832 | [(set_attr "type" "cmove,cmove") | |
1833 | (set_attr "length" "8,16")]) | |
1834 | ||
cca18f3b CZ |
1835 | ;; ------------------------------------------------------------------- |
1836 | ;; Sign/Zero extension | |
1837 | ;; ------------------------------------------------------------------- | |
526b7aee SV |
1838 | |
1839 | (define_insn "*zero_extendqihi2_i" | |
cca18f3b CZ |
1840 | [(set (match_operand:HI 0 "dest_reg_operand" "=q,q,r,r,r,r") |
1841 | (zero_extend:HI | |
1842 | (match_operand:QI 1 "nonvol_nonimm_operand" "0,q,0,r,Ucm,m")))] | |
526b7aee SV |
1843 | "" |
1844 | "@ | |
cca18f3b CZ |
1845 | extb%?\\t%0,%1 |
1846 | extb%?\\t%0,%1 | |
1847 | bmsk%?\\t%0,%1,7 | |
1848 | extb\\t%0,%1 | |
1849 | xldb%U1\\t%0,%1 | |
1850 | ldb%U1\\t%0,%1" | |
4d03dc2f JR |
1851 | [(set_attr "type" "unary,unary,unary,unary,load,load") |
1852 | (set_attr "iscompact" "maybe,true,false,false,false,false") | |
1853 | (set_attr "predicable" "no,no,yes,no,no,no")]) | |
526b7aee SV |
1854 | |
1855 | (define_expand "zero_extendqihi2" | |
1856 | [(set (match_operand:HI 0 "dest_reg_operand" "") | |
1857 | (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "")))] | |
1858 | "" | |
e0be3321 | 1859 | "" |
526b7aee SV |
1860 | ) |
1861 | ||
1862 | (define_insn "*zero_extendqisi2_ac" | |
cca18f3b CZ |
1863 | [(set (match_operand:SI 0 "dest_reg_operand" "=q,q,r,r,q,!*x,r,r") |
1864 | (zero_extend:SI | |
1865 | (match_operand:QI 1 "nonvol_nonimm_operand" "0,q,0,r,T,Usd,Ucm,m")))] | |
526b7aee SV |
1866 | "" |
1867 | "@ | |
cca18f3b CZ |
1868 | extb%?\\t%0,%1 |
1869 | extb%?\\t%0,%1 | |
1870 | bmsk%?\\t%0,%1,7 | |
1871 | extb\\t%0,%1 | |
1872 | ldb%?\\t%0,%1 | |
1873 | ldb%?\\t%0,%1 | |
1874 | xldb%U1\\t%0,%1 | |
1875 | ldb%U1\\t%0,%1" | |
4d03dc2f JR |
1876 | [(set_attr "type" "unary,unary,unary,unary,load,load,load,load") |
1877 | (set_attr "iscompact" "maybe,true,false,false,true,true,false,false") | |
1878 | (set_attr "predicable" "no,no,yes,no,no,no,no,no")]) | |
526b7aee SV |
1879 | |
1880 | (define_expand "zero_extendqisi2" | |
1881 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
1882 | (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "")))] | |
1883 | "" | |
e0be3321 | 1884 | "" |
526b7aee SV |
1885 | ) |
1886 | ||
1887 | (define_insn "*zero_extendhisi2_i" | |
cca18f3b CZ |
1888 | [(set (match_operand:SI 0 "dest_reg_operand" "=q,q,r,r,!x,q,r,r") |
1889 | (zero_extend:SI | |
1890 | (match_operand:HI 1 "nonvol_nonimm_operand" "0,q,0,r,Usd,T,Ucm,m")))] | |
526b7aee SV |
1891 | "" |
1892 | "@ | |
cca18f3b CZ |
1893 | ext%_%?\\t%0,%1 |
1894 | ext%_%?\\t%0,%1 | |
1895 | bmsk%?\\t%0,%1,15 | |
1896 | ext%_\\t%0,%1 | |
1897 | ld%_%?\\t%0,%1 | |
1898 | ld%_%?\\t%0,%1 | |
1899 | xldw%U1\\t%0,%1 | |
1900 | ld%_%U1%V1\\t%0,%1" | |
4d03dc2f | 1901 | [(set_attr "type" "unary,unary,unary,unary,load,load,load,load") |
1370fccf | 1902 | (set_attr "iscompact" "maybe,true,false,false,true,true,false,false") |
4d03dc2f | 1903 | (set_attr "predicable" "no,no,yes,no,no,no,no,no")]) |
526b7aee | 1904 | |
526b7aee SV |
1905 | (define_expand "zero_extendhisi2" |
1906 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
1907 | (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "")))] | |
1908 | "" | |
e0be3321 | 1909 | "" |
526b7aee SV |
1910 | ) |
1911 | ||
1912 | ;; Sign extension instructions. | |
1913 | ||
1914 | (define_insn "*extendqihi2_i" | |
cca18f3b CZ |
1915 | [(set (match_operand:HI 0 "dest_reg_operand" "=q,r,r,r") |
1916 | (sign_extend:HI | |
1917 | (match_operand:QI 1 "nonvol_nonimm_operand" "q,r,Uex,m")))] | |
526b7aee SV |
1918 | "" |
1919 | "@ | |
cca18f3b CZ |
1920 | sexb%?\\t%0,%1 |
1921 | sexb\\t%0,%1 | |
1922 | ldb.x%U1\\t%0,%1 | |
1923 | ldb.x%U1\\t%0,%1" | |
4d03dc2f JR |
1924 | [(set_attr "type" "unary,unary,load,load") |
1925 | (set_attr "iscompact" "true,false,false,false") | |
1926 | (set_attr "length" "*,*,*,8")]) | |
526b7aee | 1927 | |
526b7aee SV |
1928 | (define_expand "extendqihi2" |
1929 | [(set (match_operand:HI 0 "dest_reg_operand" "") | |
1930 | (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "")))] | |
1931 | "" | |
e0be3321 | 1932 | "" |
526b7aee SV |
1933 | ) |
1934 | ||
1935 | (define_insn "*extendqisi2_ac" | |
cca18f3b CZ |
1936 | [(set (match_operand:SI 0 "dest_reg_operand" "=q,r,r,r") |
1937 | (sign_extend:SI | |
1938 | (match_operand:QI 1 "nonvol_nonimm_operand" "q,r,Uex,m")))] | |
526b7aee SV |
1939 | "" |
1940 | "@ | |
cca18f3b CZ |
1941 | sexb%?\\t%0,%1 |
1942 | sexb\\t%0,%1 | |
1943 | ldb.x%U1\\t%0,%1 | |
1944 | ldb.x%U1\\t%0,%1" | |
4d03dc2f JR |
1945 | [(set_attr "type" "unary,unary,load,load") |
1946 | (set_attr "iscompact" "true,false,false,false") | |
1947 | (set_attr "length" "*,*,*,8")]) | |
526b7aee SV |
1948 | |
1949 | (define_expand "extendqisi2" | |
1950 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
1951 | (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "")))] | |
1952 | "" | |
e0be3321 | 1953 | "" |
526b7aee SV |
1954 | ) |
1955 | ||
1956 | (define_insn "*extendhisi2_i" | |
cca18f3b CZ |
1957 | [(set (match_operand:SI 0 "dest_reg_operand" "=q,r,q,r,r") |
1958 | (sign_extend:SI | |
1959 | (match_operand:HI 1 "nonvol_nonimm_operand" "q,r,Ucd,Uex,m")))] | |
526b7aee SV |
1960 | "" |
1961 | "@ | |
cca18f3b CZ |
1962 | sex%_%?\\t%0,%1 |
1963 | sex%_\\t%0,%1 | |
1964 | ldh%?.x\\t%0,%1%& | |
1965 | ld%_.x%U1%V1\\t%0,%1 | |
1966 | ld%_.x%U1%V1\\t%0,%1" | |
fc1c2d04 CZ |
1967 | [(set_attr "type" "unary,unary,load,load,load") |
1968 | (set_attr "iscompact" "true,false,true,false,false") | |
1969 | (set_attr "length" "*,*,*,4,8")]) | |
526b7aee SV |
1970 | |
1971 | (define_expand "extendhisi2" | |
1972 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
1973 | (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "")))] | |
1974 | "" | |
e0be3321 | 1975 | "" |
526b7aee SV |
1976 | ) |
1977 | ||
1978 | ;; Unary arithmetic insns | |
1979 | ||
1980 | ;; We allow constant operands to enable late constant propagation, but it is | |
1981 | ;; not worth while to have more than one dedicated alternative to output them - | |
1982 | ;; if we are really worried about getting these the maximum benefit of all | |
1983 | ;; the available alternatives, we should add an extra pass to fold such | |
1984 | ;; operations to movsi. | |
1985 | ||
1986 | ;; Absolute instructions | |
1987 | ||
1988 | (define_insn "*abssi2_mixed" | |
1989 | [(set (match_operand:SI 0 "compact_register_operand" "=q") | |
1990 | (abs:SI (match_operand:SI 1 "compact_register_operand" "q")))] | |
1991 | "TARGET_MIXED_CODE" | |
1992 | "abs%? %0,%1%&" | |
1993 | [(set_attr "type" "two_cycle_core") | |
1994 | (set_attr "iscompact" "true")]) | |
1995 | ||
1996 | (define_insn "abssi2" | |
1997 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,w,w") | |
1998 | (abs:SI (match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,Cal")))] | |
1999 | "" | |
2000 | "abs%? %0,%1%&" | |
2001 | [(set_attr "type" "two_cycle_core") | |
2002 | (set_attr "length" "*,4,8") | |
2003 | (set_attr "iscompact" "true,false,false")]) | |
2004 | ||
2005 | ;; Maximum and minimum insns | |
2006 | ||
2007 | (define_insn "smaxsi3" | |
2008 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw, w, w") | |
2009 | (smax:SI (match_operand:SI 1 "register_operand" "%0, c, c") | |
2010 | (match_operand:SI 2 "nonmemory_operand" "cL,cL,Cal")))] | |
2011 | "" | |
2012 | "max%? %0,%1,%2" | |
2013 | [(set_attr "type" "two_cycle_core") | |
2014 | (set_attr "length" "4,4,8") | |
2015 | (set_attr "predicable" "yes,no,no")] | |
2016 | ) | |
2017 | ||
2018 | (define_insn "sminsi3" | |
2019 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw, w, w") | |
2020 | (smin:SI (match_operand:SI 1 "register_operand" "%0, c, c") | |
2021 | (match_operand:SI 2 "nonmemory_operand" "cL,cL,Cal")))] | |
2022 | "" | |
2023 | "min%? %0,%1,%2" | |
2024 | [(set_attr "type" "two_cycle_core") | |
2025 | (set_attr "length" "4,4,8") | |
2026 | (set_attr "predicable" "yes,no,no")] | |
2027 | ) | |
2028 | ||
2029 | ;; Arithmetic instructions. | |
2030 | ||
2031 | ; We say an insn can be conditionalized if this doesn't introduce a long | |
2032 | ; immediate. We set the type such that we still have good scheduling if the | |
2033 | ; insn is conditionalized. | |
2034 | ; ??? It would make sense to allow introduction of long immediates, but | |
2035 | ; we'd need to communicate to the ccfsm machinery the extra cost. | |
2036 | ; The alternatives in the constraints still serve three purposes: | |
2037 | ; - estimate insn size assuming conditional execution | |
2038 | ; - guide reload to re-order the second and third operand to get a better fit. | |
2039 | ; - give tentative insn type to guide scheduling | |
2040 | ; N.B. "%" for commutativity doesn't help when there is another matching | |
2041 | ; (but longer) alternative. | |
2042 | ; We avoid letting this pattern use LP_COUNT as a register by specifying | |
2043 | ; register class 'W' instead of 'w'. | |
2044 | (define_insn_and_split "*addsi3_mixed" | |
fa9c1b3c CZ |
2045 | ;; 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 |
2046 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,Rcq, h,!*Rsd,Rcq,Rcb,Rcq, Rcqq,Rcqq,Rcw,Rcw, Rcw, W, W,W, W,Rcqq,Rcw, W") | |
2047 | (plus:SI (match_operand:SI 1 "register_operand" "%0, c, 0, Rcqq, 0, 0,Rcb, Rcqq, 0, 0, c, 0, c, c,0, 0, 0, 0, c") | |
2048 | (match_operand:SI 2 "nonmemory_operand" "cL, 0, Cm1, L,CL2,Csp,CM4,RcqqK, cO, cL, 0,cCca,cLCmL,Cca,I,C2a, Cal,Cal,Cal")))] | |
526b7aee SV |
2049 | "" |
2050 | { | |
2051 | arc_output_addsi (operands, arc_ccfsm_cond_exec_p (), true); | |
2052 | return ""; | |
2053 | } | |
2054 | "&& reload_completed && get_attr_length (insn) == 8 | |
2055 | && satisfies_constraint_I (operands[2]) | |
2056 | && GET_CODE (PATTERN (insn)) != COND_EXEC" | |
2057 | [(set (match_dup 0) (match_dup 3)) (set (match_dup 0) (match_dup 4))] | |
2058 | "split_addsi (operands);" | |
fa9c1b3c | 2059 | [(set_attr "type" "*,*,*,*,two_cycle_core,two_cycle_core,*,*,*,*,*,two_cycle_core,*,two_cycle_core,*,two_cycle_core,*,*,*") |
526b7aee SV |
2060 | (set (attr "iscompact") |
2061 | (cond [(match_test "~arc_output_addsi (operands, false, false) & 2") | |
2062 | (const_string "false") | |
2063 | (match_operand 2 "long_immediate_operand" "") | |
2064 | (const_string "maybe_limm")] | |
2065 | (const_string "maybe"))) | |
fa9c1b3c CZ |
2066 | (set_attr "length" "*,*,*,*,*,*,*,*,*,4,4,4,4,4,4,4,*,8,8") |
2067 | (set_attr "predicable" "no,no,no,no,no,no,no,no,no,yes,yes,yes,no,no,no,no,no,yes,no") | |
2068 | (set_attr "cond" "canuse,nocond,nocond,nocond,canuse,canuse,nocond,nocond,nocond,canuse,canuse,canuse,nocond,nocond,canuse_limm,canuse_limm,canuse,canuse,nocond") | |
526b7aee SV |
2069 | ]) |
2070 | ||
f50bb868 CZ |
2071 | ;; ARCv2 MPYW and MPYUW |
2072 | (define_expand "mulhisi3" | |
2073 | [(set (match_operand:SI 0 "register_operand" "") | |
2074 | (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "")) | |
2075 | (sign_extend:SI (match_operand:HI 2 "nonmemory_operand" ""))))] | |
2076 | "TARGET_MPYW" | |
2077 | "{ | |
2078 | if (CONSTANT_P (operands[2])) | |
2079 | { | |
2080 | emit_insn (gen_mulhisi3_imm (operands[0], operands[1], operands[2])); | |
2081 | DONE; | |
2082 | } | |
2083 | }" | |
2084 | ) | |
2085 | ||
2086 | (define_insn "mulhisi3_imm" | |
2087 | [(set (match_operand:SI 0 "register_operand" "=r,r,r, r, r") | |
2088 | (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "0,r,0, 0, r")) | |
2089 | (match_operand:HI 2 "short_const_int_operand" "L,L,I,C16,C16")))] | |
2090 | "TARGET_MPYW" | |
2091 | "mpyw%? %0,%1,%2" | |
2092 | [(set_attr "length" "4,4,4,8,8") | |
2093 | (set_attr "iscompact" "false") | |
2094 | (set_attr "type" "mul16_em") | |
2095 | (set_attr "predicable" "yes,no,no,yes,no") | |
2096 | (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond") | |
2097 | ]) | |
2098 | ||
2099 | (define_insn "mulhisi3_reg" | |
2100 | [(set (match_operand:SI 0 "register_operand" "=Rcqq,r,r") | |
2101 | (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" " 0,0,r")) | |
2102 | (sign_extend:SI (match_operand:HI 2 "nonmemory_operand" "Rcqq,r,r"))))] | |
2103 | "TARGET_MPYW" | |
2104 | "mpyw%? %0,%1,%2" | |
2105 | [(set_attr "length" "*,4,4") | |
2106 | (set_attr "iscompact" "maybe,false,false") | |
2107 | (set_attr "type" "mul16_em") | |
2108 | (set_attr "predicable" "yes,yes,no") | |
2109 | (set_attr "cond" "canuse,canuse,nocond") | |
2110 | ]) | |
2111 | ||
2112 | (define_expand "umulhisi3" | |
2113 | [(set (match_operand:SI 0 "register_operand" "") | |
2114 | (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "")) | |
7132ae19 | 2115 | (zero_extend:SI (match_operand:HI 2 "arc_short_operand" ""))))] |
f50bb868 CZ |
2116 | "TARGET_MPYW" |
2117 | "{ | |
2118 | if (CONSTANT_P (operands[2])) | |
2119 | { | |
2120 | emit_insn (gen_umulhisi3_imm (operands[0], operands[1], operands[2])); | |
2121 | DONE; | |
2122 | } | |
2123 | }" | |
2124 | ) | |
2125 | ||
2126 | (define_insn "umulhisi3_imm" | |
7132ae19 CZ |
2127 | [(set (match_operand:SI 0 "register_operand" "=r, r, r, r, r") |
2128 | (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0, r, 0, 0, r")) | |
2129 | (match_operand:HI 2 "short_unsigned_const_operand" " L, L,J12,J16,J16")))] | |
f50bb868 CZ |
2130 | "TARGET_MPYW" |
2131 | "mpyuw%? %0,%1,%2" | |
2132 | [(set_attr "length" "4,4,4,8,8") | |
2133 | (set_attr "iscompact" "false") | |
2134 | (set_attr "type" "mul16_em") | |
2135 | (set_attr "predicable" "yes,no,no,yes,no") | |
2136 | (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond") | |
2137 | ]) | |
2138 | ||
2139 | (define_insn "umulhisi3_reg" | |
2140 | [(set (match_operand:SI 0 "register_operand" "=Rcqq, r, r") | |
7132ae19 | 2141 | (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" " %0, 0, r")) |
f50bb868 CZ |
2142 | (zero_extend:SI (match_operand:HI 2 "register_operand" " Rcqq, r, r"))))] |
2143 | "TARGET_MPYW" | |
2144 | "mpyuw%? %0,%1,%2" | |
2145 | [(set_attr "length" "*,4,4") | |
2146 | (set_attr "iscompact" "maybe,false,false") | |
2147 | (set_attr "type" "mul16_em") | |
2148 | (set_attr "predicable" "yes,yes,no") | |
2149 | (set_attr "cond" "canuse,canuse,nocond") | |
2150 | ]) | |
2151 | ||
2152 | ;; ARC700/ARC600/V2 multiply | |
526b7aee SV |
2153 | ;; SI <- SI * SI |
2154 | ||
2155 | (define_expand "mulsi3" | |
8180cde0 | 2156 | [(set (match_operand:SI 0 "register_operand" "") |
526b7aee SV |
2157 | (mult:SI (match_operand:SI 1 "register_operand" "") |
2158 | (match_operand:SI 2 "nonmemory_operand" "")))] | |
8180cde0 | 2159 | "TARGET_ANY_MPY" |
526b7aee | 2160 | { |
8180cde0 | 2161 | if (TARGET_MUL64_SET) |
526b7aee | 2162 | { |
8180cde0 | 2163 | emit_insn (gen_mulsi64 (operands[0], operands[1], operands[2])); |
0f75b668 | 2164 | DONE; |
526b7aee SV |
2165 | } |
2166 | else if (TARGET_MULMAC_32BY16_SET) | |
2167 | { | |
8180cde0 | 2168 | emit_insn (gen_mulsi32x16 (operands[0], operands[1], operands[2])); |
0f75b668 | 2169 | DONE; |
526b7aee | 2170 | } |
526b7aee SV |
2171 | }) |
2172 | ||
0f75b668 CZ |
2173 | (define_insn_and_split "mulsi32x16" |
2174 | [(set (match_operand:SI 0 "register_operand" "=w") | |
2175 | (mult:SI (match_operand:SI 1 "register_operand" "%c") | |
2176 | (match_operand:SI 2 "nonmemory_operand" "ci"))) | |
2177 | (clobber (reg:DI MUL32x16_REG))] | |
2178 | "TARGET_MULMAC_32BY16_SET" | |
2179 | "#" | |
2180 | "TARGET_MULMAC_32BY16_SET && reload_completed" | |
2181 | [(const_int 0)] | |
2182 | { | |
2183 | if (immediate_operand (operands[2], SImode) | |
2184 | && INTVAL (operands[2]) >= 0 | |
2185 | && INTVAL (operands[2]) <= 65535) | |
2186 | { | |
2187 | emit_insn (gen_umul_600 (operands[1], operands[2], | |
2188 | gen_acc2 (), gen_acc1 ())); | |
2189 | emit_move_insn (operands[0], gen_acc2 ()); | |
2190 | DONE; | |
2191 | } | |
2192 | emit_insn (gen_umul_600 (operands[1], operands[2], | |
2193 | gen_acc2 (), gen_acc1 ())); | |
2194 | emit_insn (gen_mac_600 (operands[1], operands[2], | |
2195 | gen_acc2 (), gen_acc1 ())); | |
2196 | emit_move_insn (operands[0], gen_acc2 ()); | |
2197 | DONE; | |
2198 | } | |
2199 | [(set_attr "type" "multi") | |
2200 | (set_attr "length" "8")]) | |
2201 | ||
526b7aee SV |
2202 | ; mululw conditional execution without a LIMM clobbers an input register; |
2203 | ; we'd need a different pattern to describe this. | |
2204 | ; To make the conditional execution valid for the LIMM alternative, we | |
2205 | ; have to emit the LIMM before the register operand. | |
2206 | (define_insn "umul_600" | |
2207 | [(set (match_operand:SI 2 "acc2_operand" "") | |
2208 | (mult:SI (match_operand:SI 0 "register_operand" "c,c,c") | |
2209 | (zero_extract:SI (match_operand:SI 1 "nonmemory_operand" | |
2210 | "c,L,Cal") | |
2211 | (const_int 16) | |
2212 | (const_int 0)))) | |
2213 | (clobber (match_operand:SI 3 "acc1_operand" ""))] | |
2214 | "TARGET_MULMAC_32BY16_SET" | |
c5955224 | 2215 | "mululw 0, %0, %1" |
526b7aee | 2216 | [(set_attr "length" "4,4,8") |
c5955224 CZ |
2217 | (set_attr "type" "mulmac_600") |
2218 | (set_attr "predicable" "no") | |
2219 | (set_attr "cond" "nocond")]) | |
526b7aee SV |
2220 | |
2221 | (define_insn "mac_600" | |
2222 | [(set (match_operand:SI 2 "acc2_operand" "") | |
2223 | (plus:SI | |
2224 | (mult:SI (match_operand:SI 0 "register_operand" "c,c,c") | |
2225 | (ashift:SI | |
2226 | (zero_extract:SI (match_operand:SI 1 "nonmemory_operand" "c,L,Cal") | |
2227 | (const_int 16) | |
2228 | (const_int 16)) | |
2229 | (const_int 16))) | |
2230 | (match_dup 2))) | |
2231 | (clobber (match_operand:SI 3 "acc1_operand" ""))] | |
2232 | "TARGET_MULMAC_32BY16_SET" | |
2233 | "machlw%? 0, %0, %1" | |
2234 | [(set_attr "length" "4,4,8") | |
2235 | (set_attr "type" "mulmac_600, mulmac_600, mulmac_600") | |
2236 | (set_attr "predicable" "no, no, yes") | |
2237 | (set_attr "cond" "nocond, canuse_limm, canuse")]) | |
2238 | ||
0f75b668 CZ |
2239 | (define_insn_and_split "mulsi64" |
2240 | [(set (match_operand:SI 0 "register_operand" "=w") | |
2241 | (mult:SI (match_operand:SI 1 "register_operand" "%c") | |
2242 | (match_operand:SI 2 "nonmemory_operand" "ci"))) | |
2243 | (clobber (reg:DI MUL64_OUT_REG))] | |
2244 | "TARGET_MUL64_SET" | |
2245 | "#" | |
2246 | "TARGET_MUL64_SET && reload_completed" | |
2247 | [(const_int 0)] | |
2248 | { | |
2249 | emit_insn (gen_mulsi_600 (operands[1], operands[2], | |
2250 | gen_mlo (), gen_mhi ())); | |
2251 | emit_move_insn (operands[0], gen_mlo ()); | |
2252 | DONE; | |
2253 | } | |
2254 | [(set_attr "type" "multi") | |
2255 | (set_attr "length" "8")]) | |
2256 | ||
526b7aee SV |
2257 | (define_insn "mulsi_600" |
2258 | [(set (match_operand:SI 2 "mlo_operand" "") | |
73f793e3 | 2259 | (mult:SI (match_operand:SI 0 "register_operand" "%Rcq#q,c,c,c") |
526b7aee SV |
2260 | (match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,I,Cal"))) |
2261 | (clobber (match_operand:SI 3 "mhi_operand" ""))] | |
2262 | "TARGET_MUL64_SET" | |
2263 | ; The assembler mis-assembles mul64 / mulu64 with "I" constraint constants, | |
2264 | ; using a machine code pattern that only allows "L" constraint constants. | |
2265 | ; "mul64%? \t0, %0, %1%&" | |
2266 | { | |
2267 | if (satisfies_constraint_I (operands[1]) | |
2268 | && !satisfies_constraint_L (operands[1])) | |
2269 | { | |
2270 | /* MUL64 <0,>b,s12 00101bbb10000100 0BBBssssssSSSSSS */ | |
2271 | int n = true_regnum (operands[0]); | |
2272 | int i = INTVAL (operands[1]); | |
2273 | asm_fprintf (asm_out_file, "\t.short %d`", 0x2884 + ((n & 7) << 8)); | |
2274 | asm_fprintf (asm_out_file, "\t.short %d`", | |
2275 | ((i & 0x3f) << 6) + ((i >> 6) & 0x3f) + ((n & 070) << 9)); | |
2276 | return "; mul64%? \t0, %0, %1%&"; | |
2277 | } | |
2278 | return "mul64%? \t0, %0, %1%&"; | |
2279 | } | |
2280 | [(set_attr "length" "*,4,4,8") | |
2281 | (set_attr "iscompact" "maybe,false,false,false") | |
2282 | (set_attr "type" "multi,multi,multi,multi") | |
2283 | (set_attr "predicable" "yes,yes,no,yes") | |
2284 | (set_attr "cond" "canuse,canuse,canuse_limm,canuse")]) | |
2285 | ||
d476b53c CZ |
2286 | (define_insn_and_split "mulsidi_600" |
2287 | [(set (match_operand:DI 0 "register_operand" "=c, c,c, c") | |
2288 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%Rcq#q, c,c, c")) | |
2289 | (sign_extend:DI (match_operand:SI 2 "nonmemory_operand" "Rcq#q,cL,L,C32")))) | |
2290 | (clobber (reg:DI MUL64_OUT_REG))] | |
2291 | "TARGET_MUL64_SET" | |
2292 | "#" | |
2293 | "TARGET_MUL64_SET" | |
2294 | [(const_int 0)] | |
2295 | "emit_insn (gen_mul64 (operands[1], operands[2])); | |
2296 | emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG)); | |
2297 | DONE;" | |
2298 | [(set_attr "type" "multi") | |
2299 | (set_attr "length" "8")]) | |
2300 | ||
2301 | (define_insn "mul64" | |
526b7aee | 2302 | [(set (reg:DI MUL64_OUT_REG) |
d476b53c CZ |
2303 | (mult:DI |
2304 | (sign_extend:DI (match_operand:SI 0 "register_operand" "%Rcq#q, c,c, c")) | |
2305 | (sign_extend:DI (match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,L,C32"))))] | |
526b7aee SV |
2306 | "TARGET_MUL64_SET" |
2307 | "mul64%? \t0, %0, %1%&" | |
2308 | [(set_attr "length" "*,4,4,8") | |
2309 | (set_attr "iscompact" "maybe,false,false,false") | |
2310 | (set_attr "type" "multi,multi,multi,multi") | |
2311 | (set_attr "predicable" "yes,yes,no,yes") | |
2312 | (set_attr "cond" "canuse,canuse,canuse_limm,canuse")]) | |
2313 | ||
d476b53c CZ |
2314 | (define_insn_and_split "umulsidi_600" |
2315 | [(set (match_operand:DI 0 "register_operand" "=c,c, c") | |
2316 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%c,c, c")) | |
2317 | (sign_extend:DI (match_operand:SI 2 "nonmemory_operand" "cL,L,C32")))) | |
2318 | (clobber (reg:DI MUL64_OUT_REG))] | |
2319 | "TARGET_MUL64_SET" | |
2320 | "#" | |
2321 | "TARGET_MUL64_SET" | |
2322 | [(const_int 0)] | |
2323 | "emit_insn (gen_mulu64 (operands[1], operands[2])); | |
2324 | emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG)); | |
2325 | DONE;" | |
2326 | [(set_attr "type" "umulti") | |
2327 | (set_attr "length" "8")]) | |
2328 | ||
2329 | (define_insn "mulu64" | |
526b7aee | 2330 | [(set (reg:DI MUL64_OUT_REG) |
d476b53c CZ |
2331 | (mult:DI |
2332 | (zero_extend:DI (match_operand:SI 0 "register_operand" "%c,c,c")) | |
2333 | (zero_extend:DI (match_operand:SI 1 "nonmemory_operand" "cL,L,C32"))))] | |
526b7aee SV |
2334 | "TARGET_MUL64_SET" |
2335 | "mulu64%? \t0, %0, %1%&" | |
2336 | [(set_attr "length" "4,4,8") | |
2337 | (set_attr "iscompact" "false") | |
2338 | (set_attr "type" "umulti") | |
2339 | (set_attr "predicable" "yes,no,yes") | |
2340 | (set_attr "cond" "canuse,canuse_limm,canuse")]) | |
2341 | ||
2342 | ; ARC700 mpy* instructions: This is a multi-cycle extension, and thus 'w' | |
2343 | ; may not be used as destination constraint. | |
2344 | ||
2345 | ; The result of mpy and mpyu is the same except for flag setting (if enabled), | |
2346 | ; but mpyu is faster for the standard multiplier. | |
2347 | ; Note: we must make sure LP_COUNT is not one of the destination | |
2348 | ; registers, since it cannot be the destination of a multi-cycle insn | |
2349 | ; like MPY or MPYU. | |
2350 | (define_insn "mulsi3_700" | |
2351 | [(set (match_operand:SI 0 "mpy_dest_reg_operand" "=Rcr,r,r,Rcr,r") | |
f533fdf6 | 2352 | (mult:SI (match_operand:SI 1 "register_operand" "%0,c,0,0,c") |
526b7aee | 2353 | (match_operand:SI 2 "nonmemory_operand" "cL,cL,I,Cal,Cal")))] |
f50bb868 | 2354 | "TARGET_ARC700_MPY" |
526b7aee SV |
2355 | "mpyu%? %0,%1,%2" |
2356 | [(set_attr "length" "4,4,4,8,8") | |
2357 | (set_attr "type" "umulti") | |
2358 | (set_attr "predicable" "yes,no,no,yes,no") | |
2359 | (set_attr "cond" "canuse,nocond,canuse_limm,canuse,nocond")]) | |
2360 | ||
f50bb868 CZ |
2361 | ; ARCv2 has no penalties between mpy and mpyu. So, we use mpy because of its |
2362 | ; short variant. LP_COUNT constraints are still valid. | |
2363 | (define_insn "mulsi3_v2" | |
03301dcc CZ |
2364 | [(set (match_operand:SI 0 "mpy_dest_reg_operand" "=q,q, r, r,r, r, r") |
2365 | (mult:SI (match_operand:SI 1 "register_operand" "%0,q, 0, r,0, 0, c") | |
2366 | (match_operand:SI 2 "nonmemory_operand" "q,0,rL,rL,I,Cal,Cal")))] | |
f50bb868 | 2367 | "TARGET_MULTI" |
03301dcc CZ |
2368 | "@ |
2369 | mpy%?\\t%0,%1,%2 | |
2370 | mpy%?\\t%0,%2,%1 | |
2371 | mpy%?\\t%0,%1,%2 | |
2372 | mpy%?\\t%0,%1,%2 | |
2373 | mpy%?\\t%0,%1,%2 | |
2374 | mpy%?\\t%0,%1,%2 | |
2375 | mpy%?\\t%0,%1,%2" | |
2376 | [(set_attr "length" "*,*,4,4,4,8,8") | |
2377 | (set_attr "iscompact" "maybe,maybe,false,false,false,false,false") | |
f50bb868 | 2378 | (set_attr "type" "umulti") |
03301dcc CZ |
2379 | (set_attr "predicable" "no,no,yes,no,no,yes,no") |
2380 | (set_attr "cond" "nocond,nocond,canuse,nocond,canuse_limm,canuse,nocond")]) | |
f50bb868 | 2381 | |
526b7aee | 2382 | (define_expand "mulsidi3" |
b5a5ade8 CZ |
2383 | [(set (match_operand:DI 0 "register_operand" "") |
2384 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) | |
2385 | (sign_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))))] | |
f50bb868 | 2386 | "TARGET_ANY_MPY" |
0f75b668 | 2387 | { |
79557bae CZ |
2388 | if (TARGET_PLUS_MACD) |
2389 | { | |
2390 | if (CONST_INT_P (operands[2])) | |
2391 | { | |
2392 | emit_insn (gen_mpyd_imm_arcv2hs (operands[0], operands[1], operands[2])); | |
2393 | } | |
2394 | else | |
2395 | { | |
2396 | emit_insn (gen_mpyd_arcv2hs (operands[0], operands[1], operands[2])); | |
2397 | } | |
2398 | DONE; | |
2399 | } | |
f50bb868 | 2400 | if (TARGET_MPY) |
526b7aee SV |
2401 | { |
2402 | operands[2] = force_reg (SImode, operands[2]); | |
2403 | if (!register_operand (operands[0], DImode)) | |
2404 | { | |
2405 | rtx result = gen_reg_rtx (DImode); | |
2406 | ||
2407 | operands[2] = force_reg (SImode, operands[2]); | |
2408 | emit_insn (gen_mulsidi3 (result, operands[1], operands[2])); | |
2409 | emit_move_insn (operands[0], result); | |
2410 | DONE; | |
2411 | } | |
2412 | } | |
2413 | else if (TARGET_MUL64_SET) | |
2414 | { | |
d476b53c | 2415 | emit_insn (gen_mulsidi_600 (operands[0], operands[1], operands[2])); |
526b7aee SV |
2416 | DONE; |
2417 | } | |
2418 | else if (TARGET_MULMAC_32BY16_SET) | |
2419 | { | |
0f75b668 CZ |
2420 | operands[2] = force_reg (SImode, operands[2]); |
2421 | emit_insn (gen_mulsidi64 (operands[0], operands[1], operands[2])); | |
526b7aee SV |
2422 | DONE; |
2423 | } | |
0f75b668 CZ |
2424 | operands[2] = force_reg (SImode, operands[2]); |
2425 | }) | |
2426 | ||
2427 | (define_insn_and_split "mulsidi64" | |
2428 | [(set (match_operand:DI 0 "register_operand" "=w") | |
2429 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%c")) | |
2430 | (sign_extend:DI (match_operand:SI 2 "extend_operand" "ci")))) | |
2431 | (clobber (reg:DI MUL32x16_REG))] | |
2432 | "TARGET_MULMAC_32BY16_SET" | |
2433 | "#" | |
2434 | "TARGET_MULMAC_32BY16_SET && reload_completed" | |
2435 | [(const_int 0)] | |
2436 | { | |
2437 | rtx result_hi = gen_highpart (SImode, operands[0]); | |
2438 | rtx result_low = gen_lowpart (SImode, operands[0]); | |
2439 | ||
2440 | emit_insn (gen_mul64_600 (operands[1], operands[2])); | |
2441 | emit_insn (gen_mac64_600 (result_hi, operands[1], operands[2])); | |
2442 | emit_move_insn (result_low, gen_acc2 ()); | |
2443 | DONE; | |
2444 | } | |
2445 | [(set_attr "type" "multi") | |
2446 | (set_attr "length" "8")]) | |
2447 | ||
526b7aee SV |
2448 | |
2449 | (define_insn "mul64_600" | |
0f75b668 | 2450 | [(set (reg:DI MUL32x16_REG) |
526b7aee SV |
2451 | (mult:DI (sign_extend:DI (match_operand:SI 0 "register_operand" |
2452 | "c,c,c")) | |
2453 | (zero_extract:DI (match_operand:SI 1 "nonmemory_operand" | |
2454 | "c,L,Cal") | |
2455 | (const_int 16) | |
2456 | (const_int 0)))) | |
2457 | ] | |
2458 | "TARGET_MULMAC_32BY16_SET" | |
2459 | "mullw%? 0, %0, %1" | |
2460 | [(set_attr "length" "4,4,8") | |
2461 | (set_attr "type" "mulmac_600") | |
2462 | (set_attr "predicable" "no,no,yes") | |
2463 | (set_attr "cond" "nocond, canuse_limm, canuse")]) | |
2464 | ||
2465 | ||
2466 | ;; ??? check if this is canonical rtl | |
2467 | (define_insn "mac64_600" | |
0f75b668 | 2468 | [(set (reg:DI MUL32x16_REG) |
526b7aee SV |
2469 | (plus:DI |
2470 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "c,c,c")) | |
2471 | (ashift:DI | |
2472 | (sign_extract:DI (match_operand:SI 2 "nonmemory_operand" "c,L,Cal") | |
2473 | (const_int 16) (const_int 16)) | |
2474 | (const_int 16))) | |
0f75b668 | 2475 | (reg:DI MUL32x16_REG))) |
526b7aee SV |
2476 | (set (match_operand:SI 0 "register_operand" "=w,w,w") |
2477 | (zero_extract:SI | |
2478 | (plus:DI | |
2479 | (mult:DI (sign_extend:DI (match_dup 1)) | |
2480 | (ashift:DI | |
2481 | (sign_extract:DI (match_dup 2) | |
2482 | (const_int 16) (const_int 16)) | |
2483 | (const_int 16))) | |
0f75b668 | 2484 | (reg:DI MUL32x16_REG)) |
526b7aee SV |
2485 | (const_int 32) (const_int 32)))] |
2486 | "TARGET_MULMAC_32BY16_SET" | |
2487 | "machlw%? %0, %1, %2" | |
2488 | [(set_attr "length" "4,4,8") | |
2489 | (set_attr "type" "mulmac_600") | |
2490 | (set_attr "predicable" "no,no,yes") | |
2491 | (set_attr "cond" "nocond, canuse_limm, canuse")]) | |
2492 | ||
2493 | ||
2494 | ;; DI <- DI(signed SI) * DI(signed SI) | |
2495 | (define_insn_and_split "mulsidi3_700" | |
2496 | [(set (match_operand:DI 0 "register_operand" "=&r") | |
2497 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%c")) | |
167ba5b9 | 2498 | (sign_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))] |
79557bae | 2499 | "TARGET_MPY && !TARGET_PLUS_MACD" |
526b7aee SV |
2500 | "#" |
2501 | "&& reload_completed" | |
2502 | [(const_int 0)] | |
2503 | { | |
2504 | int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD; | |
2505 | int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0; | |
2506 | rtx l0 = simplify_gen_subreg (word_mode, operands[0], DImode, lo); | |
2507 | rtx h0 = simplify_gen_subreg (word_mode, operands[0], DImode, hi); | |
2508 | emit_insn (gen_mulsi3_highpart (h0, operands[1], operands[2])); | |
f50bb868 | 2509 | emit_insn (gen_mulsi3 (l0, operands[1], operands[2])); |
526b7aee SV |
2510 | DONE; |
2511 | } | |
2512 | [(set_attr "type" "multi") | |
2513 | (set_attr "length" "8")]) | |
2514 | ||
2515 | (define_insn "mulsi3_highpart" | |
2516 | [(set (match_operand:SI 0 "register_operand" "=Rcr,r,Rcr,r") | |
2517 | (truncate:SI | |
2518 | (lshiftrt:DI | |
2519 | (mult:DI | |
2520 | (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,c, 0,c")) | |
167ba5b9 | 2521 | (sign_extend:DI (match_operand:SI 2 "extend_operand" "c,c, i,i"))) |
526b7aee | 2522 | (const_int 32))))] |
f50bb868 CZ |
2523 | "TARGET_MPY" |
2524 | "mpy%+%? %0,%1,%2" | |
526b7aee SV |
2525 | [(set_attr "length" "4,4,8,8") |
2526 | (set_attr "type" "multi") | |
2527 | (set_attr "predicable" "yes,no,yes,no") | |
2528 | (set_attr "cond" "canuse,nocond,canuse,nocond")]) | |
2529 | ||
2530 | ; Note that mpyhu has the same latency as mpy / mpyh, | |
2531 | ; thus we use the type multi. | |
2532 | (define_insn "*umulsi3_highpart_i" | |
2533 | [(set (match_operand:SI 0 "register_operand" "=Rcr,r,Rcr,r") | |
2534 | (truncate:SI | |
2535 | (lshiftrt:DI | |
2536 | (mult:DI | |
2537 | (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,c, 0,c")) | |
167ba5b9 | 2538 | (zero_extend:DI (match_operand:SI 2 "extend_operand" "c,c, i,i"))) |
526b7aee | 2539 | (const_int 32))))] |
f50bb868 CZ |
2540 | "TARGET_MPY" |
2541 | "mpy%+u%? %0,%1,%2" | |
526b7aee SV |
2542 | [(set_attr "length" "4,4,8,8") |
2543 | (set_attr "type" "multi") | |
2544 | (set_attr "predicable" "yes,no,yes,no") | |
2545 | (set_attr "cond" "canuse,nocond,canuse,nocond")]) | |
2546 | ||
526b7aee SV |
2547 | ;; (zero_extend:DI (const_int)) leads to internal errors in combine, so we |
2548 | ;; need a separate pattern for immediates | |
2549 | ;; ??? This is fine for combine, but not for reload. | |
2550 | (define_insn "umulsi3_highpart_int" | |
2551 | [(set (match_operand:SI 0 "register_operand" "=Rcr, r, r,Rcr, r") | |
2552 | (truncate:SI | |
2553 | (lshiftrt:DI | |
2554 | (mult:DI | |
2555 | (zero_extend:DI (match_operand:SI 1 "register_operand" " 0, c, 0, 0, c")) | |
2556 | (match_operand:DI 2 "immediate_usidi_operand" "L, L, I, Cal, Cal")) | |
2557 | (const_int 32))))] | |
f50bb868 CZ |
2558 | "TARGET_MPY" |
2559 | "mpy%+u%? %0,%1,%2" | |
526b7aee SV |
2560 | [(set_attr "length" "4,4,4,8,8") |
2561 | (set_attr "type" "multi") | |
2562 | (set_attr "predicable" "yes,no,no,yes,no") | |
2563 | (set_attr "cond" "canuse,nocond,canuse_limm,canuse,nocond")]) | |
2564 | ||
2565 | (define_expand "umulsi3_highpart" | |
2566 | [(set (match_operand:SI 0 "general_operand" "") | |
2567 | (truncate:SI | |
2568 | (lshiftrt:DI | |
2569 | (mult:DI | |
2570 | (zero_extend:DI (match_operand:SI 1 "register_operand" "")) | |
2571 | (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))) | |
2572 | (const_int 32))))] | |
8180cde0 | 2573 | "TARGET_MPY" |
526b7aee SV |
2574 | " |
2575 | { | |
2576 | rtx target = operands[0]; | |
2577 | ||
526b7aee SV |
2578 | if (!register_operand (target, SImode)) |
2579 | target = gen_reg_rtx (SImode); | |
2580 | ||
2581 | if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) | |
2582 | operands[2] = simplify_const_unary_operation (ZERO_EXTEND, DImode, | |
2583 | operands[2], SImode); | |
2584 | else if (!immediate_operand (operands[2], SImode)) | |
2585 | operands[2] = gen_rtx_ZERO_EXTEND (DImode, operands[2]); | |
2586 | emit_insn (gen_umulsi3_highpart_int (target, operands[1], operands[2])); | |
2587 | if (target != operands[0]) | |
2588 | emit_move_insn (operands[0], target); | |
2589 | DONE; | |
2590 | }") | |
2591 | ||
2592 | (define_expand "umulsidi3" | |
b5a5ade8 CZ |
2593 | [(set (match_operand:DI 0 "register_operand" "") |
2594 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) | |
2595 | (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))))] | |
8180cde0 | 2596 | "TARGET_ANY_MPY" |
526b7aee | 2597 | { |
79557bae CZ |
2598 | if (TARGET_PLUS_MACD) |
2599 | { | |
2600 | if (CONST_INT_P (operands[2])) | |
2601 | { | |
2602 | emit_insn (gen_mpydu_imm_arcv2hs (operands[0], operands[1], operands[2])); | |
2603 | } | |
2604 | else | |
2605 | { | |
2606 | emit_insn (gen_mpydu_arcv2hs (operands[0], operands[1], operands[2])); | |
2607 | } | |
2608 | DONE; | |
2609 | } | |
f50bb868 | 2610 | if (TARGET_MPY) |
526b7aee SV |
2611 | { |
2612 | operands[2] = force_reg (SImode, operands[2]); | |
2613 | if (!register_operand (operands[0], DImode)) | |
2614 | { | |
2615 | rtx result = gen_reg_rtx (DImode); | |
2616 | ||
2617 | emit_insn (gen_umulsidi3 (result, operands[1], operands[2])); | |
2618 | emit_move_insn (operands[0], result); | |
2619 | DONE; | |
2620 | } | |
2621 | } | |
2622 | else if (TARGET_MUL64_SET) | |
2623 | { | |
0f75b668 CZ |
2624 | operands[2] = force_reg (SImode, operands[2]); |
2625 | emit_insn (gen_umulsidi_600 (operands[0], operands[1], operands[2])); | |
526b7aee SV |
2626 | DONE; |
2627 | } | |
2628 | else if (TARGET_MULMAC_32BY16_SET) | |
2629 | { | |
0f75b668 CZ |
2630 | operands[2] = force_reg (SImode, operands[2]); |
2631 | emit_insn (gen_umulsidi64 (operands[0], operands[1], operands[2])); | |
526b7aee SV |
2632 | DONE; |
2633 | } | |
2634 | else | |
8180cde0 CZ |
2635 | { |
2636 | gcc_unreachable (); | |
526b7aee SV |
2637 | } |
2638 | }) | |
2639 | ||
0f75b668 CZ |
2640 | (define_insn_and_split "umulsidi64" |
2641 | [(set (match_operand:DI 0 "register_operand" "=w") | |
2642 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%c")) | |
2643 | (zero_extend:DI (match_operand:SI 2 "extend_operand" "ci")))) | |
2644 | (clobber (reg:DI MUL32x16_REG))] | |
2645 | "TARGET_MULMAC_32BY16_SET" | |
2646 | "#" | |
2647 | "TARGET_MULMAC_32BY16_SET && reload_completed" | |
2648 | [(const_int 0)] | |
2649 | { | |
2650 | rtx result_hi; | |
2651 | rtx result_low; | |
2652 | ||
2653 | result_hi = gen_highpart (SImode, operands[0]); | |
2654 | result_low = gen_lowpart (SImode, operands[0]); | |
2655 | ||
2656 | emit_insn (gen_umul64_600 (operands[1], operands[2])); | |
2657 | emit_insn (gen_umac64_600 (result_hi, operands[1], operands[2])); | |
2658 | emit_move_insn (result_low, gen_acc2 ()); | |
2659 | DONE; | |
2660 | } | |
2661 | [(set_attr "type" "multi") | |
2662 | (set_attr "length" "8")]) | |
2663 | ||
526b7aee | 2664 | (define_insn "umul64_600" |
0f75b668 | 2665 | [(set (reg:DI MUL32x16_REG) |
526b7aee SV |
2666 | (mult:DI (zero_extend:DI (match_operand:SI 0 "register_operand" |
2667 | "c,c,c")) | |
2668 | (zero_extract:DI (match_operand:SI 1 "nonmemory_operand" | |
2669 | "c,L,Cal") | |
2670 | (const_int 16) | |
2671 | (const_int 0)))) | |
2672 | ] | |
2673 | "TARGET_MULMAC_32BY16_SET" | |
c5955224 | 2674 | "mululw 0, %0, %1" |
526b7aee SV |
2675 | [(set_attr "length" "4,4,8") |
2676 | (set_attr "type" "mulmac_600") | |
c5955224 CZ |
2677 | (set_attr "predicable" "no") |
2678 | (set_attr "cond" "nocond")]) | |
526b7aee SV |
2679 | |
2680 | ||
2681 | (define_insn "umac64_600" | |
0f75b668 | 2682 | [(set (reg:DI MUL32x16_REG) |
526b7aee SV |
2683 | (plus:DI |
2684 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "c,c,c")) | |
2685 | (ashift:DI | |
2686 | (zero_extract:DI (match_operand:SI 2 "nonmemory_operand" "c,L,Cal") | |
2687 | (const_int 16) (const_int 16)) | |
2688 | (const_int 16))) | |
0f75b668 | 2689 | (reg:DI MUL32x16_REG))) |
526b7aee SV |
2690 | (set (match_operand:SI 0 "register_operand" "=w,w,w") |
2691 | (zero_extract:SI | |
2692 | (plus:DI | |
2693 | (mult:DI (zero_extend:DI (match_dup 1)) | |
2694 | (ashift:DI | |
2695 | (zero_extract:DI (match_dup 2) | |
2696 | (const_int 16) (const_int 16)) | |
2697 | (const_int 16))) | |
0f75b668 | 2698 | (reg:DI MUL32x16_REG)) |
526b7aee SV |
2699 | (const_int 32) (const_int 32)))] |
2700 | "TARGET_MULMAC_32BY16_SET" | |
2701 | "machulw%? %0, %1, %2" | |
2702 | [(set_attr "length" "4,4,8") | |
2703 | (set_attr "type" "mulmac_600") | |
2704 | (set_attr "predicable" "no,no,yes") | |
2705 | (set_attr "cond" "nocond, canuse_limm, canuse")]) | |
2706 | ||
526b7aee SV |
2707 | ;; DI <- DI(unsigned SI) * DI(unsigned SI) |
2708 | (define_insn_and_split "umulsidi3_700" | |
2709 | [(set (match_operand:DI 0 "dest_reg_operand" "=&r") | |
2710 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%c")) | |
167ba5b9 | 2711 | (zero_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))] |
79557bae | 2712 | "TARGET_MPY && !TARGET_PLUS_MACD" |
526b7aee | 2713 | "#" |
8180cde0 | 2714 | "TARGET_MPY && !TARGET_PLUS_MACD && reload_completed" |
526b7aee SV |
2715 | [(const_int 0)] |
2716 | { | |
2717 | int hi = !TARGET_BIG_ENDIAN; | |
2718 | int lo = !hi; | |
2719 | rtx l0 = operand_subword (operands[0], lo, 0, DImode); | |
2720 | rtx h0 = operand_subword (operands[0], hi, 0, DImode); | |
2721 | emit_insn (gen_umulsi3_highpart (h0, operands[1], operands[2])); | |
f50bb868 | 2722 | emit_insn (gen_mulsi3 (l0, operands[1], operands[2])); |
526b7aee SV |
2723 | DONE; |
2724 | } | |
2725 | [(set_attr "type" "umulti") | |
2726 | (set_attr "length" "8")]) | |
2727 | ||
526b7aee SV |
2728 | (define_expand "addsi3" |
2729 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
2730 | (plus:SI (match_operand:SI 1 "register_operand" "") | |
2731 | (match_operand:SI 2 "nonmemory_operand" "")))] | |
2732 | "" | |
2733 | "if (flag_pic && arc_raw_symbolic_reference_mentioned_p (operands[2], false)) | |
2734 | { | |
2735 | operands[2]=force_reg(SImode, operands[2]); | |
2736 | } | |
526b7aee SV |
2737 | ") |
2738 | ||
2739 | (define_expand "adddi3" | |
2740 | [(parallel [(set (match_operand:DI 0 "dest_reg_operand" "") | |
2741 | (plus:DI (match_operand:DI 1 "register_operand" "") | |
2742 | (match_operand:DI 2 "nonmemory_operand" ""))) | |
2743 | (clobber (reg:CC CC_REG))])] | |
2744 | "" | |
3f2fc95c | 2745 | {}) |
526b7aee SV |
2746 | |
2747 | ; This assumes that there can be no strictly partial overlap between | |
2748 | ; operands[1] and operands[2]. | |
2749 | (define_insn_and_split "*adddi3_i" | |
2750 | [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w,w") | |
2751 | (plus:DI (match_operand:DI 1 "register_operand" "%c,0,c") | |
2752 | (match_operand:DI 2 "nonmemory_operand" "ci,ci,!i"))) | |
2753 | (clobber (reg:CC CC_REG))] | |
2754 | "" | |
2755 | "#" | |
2756 | "reload_completed" | |
2757 | [(const_int 0)] | |
2758 | { | |
2759 | int hi = !TARGET_BIG_ENDIAN; | |
2760 | int lo = !hi; | |
2761 | rtx l0 = operand_subword (operands[0], lo, 0, DImode); | |
2762 | rtx h0 = operand_subword (operands[0], hi, 0, DImode); | |
2763 | rtx l1 = operand_subword (operands[1], lo, 0, DImode); | |
2764 | rtx h1 = operand_subword (operands[1], hi, 0, DImode); | |
2765 | rtx l2 = operand_subword (operands[2], lo, 0, DImode); | |
2766 | rtx h2 = operand_subword (operands[2], hi, 0, DImode); | |
2767 | ||
2768 | ||
2769 | if (l2 == const0_rtx) | |
2770 | { | |
2771 | if (!rtx_equal_p (l0, l1) && !rtx_equal_p (l0, h1)) | |
2772 | emit_move_insn (l0, l1); | |
2773 | emit_insn (gen_addsi3 (h0, h1, h2)); | |
2774 | if (!rtx_equal_p (l0, l1) && rtx_equal_p (l0, h1)) | |
2775 | emit_move_insn (l0, l1); | |
2776 | DONE; | |
2777 | } | |
2778 | if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0 | |
2779 | && INTVAL (operands[2]) >= -0x7fffffff) | |
2780 | { | |
2781 | emit_insn (gen_subdi3_i (operands[0], operands[1], | |
2782 | GEN_INT (-INTVAL (operands[2])))); | |
2783 | DONE; | |
2784 | } | |
2785 | if (rtx_equal_p (l0, h1)) | |
2786 | { | |
2787 | if (h2 != const0_rtx) | |
2788 | emit_insn (gen_addsi3 (h0, h1, h2)); | |
2789 | else if (!rtx_equal_p (h0, h1)) | |
2790 | emit_move_insn (h0, h1); | |
2791 | emit_insn (gen_add_f (l0, l1, l2)); | |
2792 | emit_insn | |
2793 | (gen_rtx_COND_EXEC | |
2794 | (VOIDmode, | |
2795 | gen_rtx_LTU (VOIDmode, gen_rtx_REG (CC_Cmode, CC_REG), GEN_INT (0)), | |
f7df4a84 | 2796 | gen_rtx_SET (h0, plus_constant (SImode, h0, 1)))); |
526b7aee SV |
2797 | DONE; |
2798 | } | |
2799 | emit_insn (gen_add_f (l0, l1, l2)); | |
2800 | emit_insn (gen_adc (h0, h1, h2)); | |
2801 | DONE; | |
2802 | } | |
2803 | [(set_attr "cond" "clob") | |
2804 | (set_attr "type" "binary") | |
2805 | (set_attr "length" "16,16,20")]) | |
2806 | ||
2807 | (define_insn "add_f" | |
2808 | [(set (reg:CC_C CC_REG) | |
2809 | (compare:CC_C | |
2810 | (plus:SI (match_operand:SI 1 "register_operand" "c,0,c") | |
2811 | (match_operand:SI 2 "nonmemory_operand" "cL,I,cCal")) | |
2812 | (match_dup 1))) | |
2813 | (set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w") | |
2814 | (plus:SI (match_dup 1) (match_dup 2)))] | |
2815 | "" | |
2816 | "add.f %0,%1,%2" | |
2817 | [(set_attr "cond" "set") | |
2818 | (set_attr "type" "compare") | |
2819 | (set_attr "length" "4,4,8")]) | |
2820 | ||
2821 | (define_insn "*add_f_2" | |
2822 | [(set (reg:CC_C CC_REG) | |
2823 | (compare:CC_C | |
2824 | (plus:SI (match_operand:SI 1 "register_operand" "c,0,c") | |
2825 | (match_operand:SI 2 "nonmemory_operand" "cL,I,cCal")) | |
2826 | (match_dup 2))) | |
2827 | (set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w") | |
2828 | (plus:SI (match_dup 1) (match_dup 2)))] | |
2829 | "" | |
2830 | "add.f %0,%1,%2" | |
2831 | [(set_attr "cond" "set") | |
2832 | (set_attr "type" "compare") | |
2833 | (set_attr "length" "4,4,8")]) | |
2834 | ||
2835 | ; w/c/c comes first (rather than w/0/C_0) to prevent the middle-end | |
2836 | ; needlessly prioritizing the matching constraint. | |
2837 | ; Rcw/0/C_0 comes before w/c/L so that the lower latency conditional | |
2838 | ; execution is used where possible. | |
2839 | (define_insn_and_split "adc" | |
2840 | [(set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w,Rcw,w") | |
2841 | (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0)) | |
2842 | (match_operand:SI 1 "nonmemory_operand" | |
2843 | "%c,0,c,0,cCal")) | |
2844 | (match_operand:SI 2 "nonmemory_operand" "c,C_0,L,I,cCal")))] | |
2845 | "register_operand (operands[1], SImode) | |
2846 | || register_operand (operands[2], SImode)" | |
2847 | "@ | |
2848 | adc %0,%1,%2 | |
2849 | add.cs %0,%1,1 | |
2850 | adc %0,%1,%2 | |
2851 | adc %0,%1,%2 | |
2852 | adc %0,%1,%2" | |
2853 | ; if we have a bad schedule after sched2, split. | |
2854 | "reload_completed | |
f50bb868 | 2855 | && !optimize_size && (!TARGET_ARC600_FAMILY) |
526b7aee SV |
2856 | && arc_scheduling_not_expected () |
2857 | && arc_sets_cc_p (prev_nonnote_insn (insn)) | |
2858 | /* If next comes a return or other insn that needs a delay slot, | |
2859 | expect the adc to get into the delay slot. */ | |
2860 | && next_nonnote_insn (insn) | |
2861 | && !arc_need_delay (next_nonnote_insn (insn)) | |
2862 | /* Restore operands before emitting. */ | |
2863 | && (extract_insn_cached (insn), 1)" | |
2864 | [(set (match_dup 0) (match_dup 3)) | |
2865 | (cond_exec | |
2866 | (ltu (reg:CC_C CC_REG) (const_int 0)) | |
2867 | (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1))))] | |
2868 | "operands[3] = simplify_gen_binary (PLUS, SImode, operands[1], operands[2]);" | |
2869 | [(set_attr "cond" "use") | |
2870 | (set_attr "type" "cc_arith") | |
2871 | (set_attr "length" "4,4,4,4,8")]) | |
2872 | ||
2873 | ; combiner-splitter cmp / scc -> cmp / adc | |
2874 | (define_split | |
2875 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
2876 | (gtu:SI (match_operand:SI 1 "register_operand" "") | |
2877 | (match_operand:SI 2 "register_operand" ""))) | |
2878 | (clobber (reg CC_REG))] | |
2879 | "" | |
2880 | [(set (reg:CC_C CC_REG) (compare:CC_C (match_dup 2) (match_dup 1))) | |
2881 | (set (match_dup 0) (ltu:SI (reg:CC_C CC_REG) (const_int 0)))]) | |
2882 | ||
2883 | ; combine won't work when an intermediate result is used later... | |
2884 | ; add %0,%1,%2 ` cmp %0,%[12] -> add.f %0,%1,%2 | |
2885 | (define_peephole2 | |
2886 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
2887 | (plus:SI (match_operand:SI 1 "register_operand" "") | |
2888 | (match_operand:SI 2 "nonmemory_operand" ""))) | |
2889 | (set (reg:CC_C CC_REG) | |
2890 | (compare:CC_C (match_dup 0) | |
2891 | (match_operand:SI 3 "nonmemory_operand" "")))] | |
2892 | "rtx_equal_p (operands[1], operands[3]) | |
2893 | || rtx_equal_p (operands[2], operands[3])" | |
2894 | [(parallel | |
2895 | [(set (reg:CC_C CC_REG) | |
2896 | (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1))) | |
2897 | (set (match_dup 0) | |
2898 | (plus:SI (match_dup 1) (match_dup 2)))])]) | |
2899 | ||
f55d4a20 JR |
2900 | ; ??? need to delve into combine to find out why this is not useful. |
2901 | ; We'd like to be able to grok various C idioms for carry bit usage. | |
526b7aee SV |
2902 | ;(define_insn "*adc_0" |
2903 | ; [(set (match_operand:SI 0 "dest_reg_operand" "=w") | |
2904 | ; (plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0)) | |
2905 | ; (match_operand:SI 1 "register_operand" "c")))] | |
2906 | ; "" | |
2907 | ; "adc %0,%1,0" | |
2908 | ; [(set_attr "cond" "use") | |
2909 | ; (set_attr "type" "cc_arith") | |
2910 | ; (set_attr "length" "4")]) | |
2911 | ; | |
2912 | ;(define_split | |
2913 | ; [(set (match_operand:SI 0 "dest_reg_operand" "=w") | |
2914 | ; (plus:SI (gtu:SI (match_operand:SI 1 "register_operand" "c") | |
2915 | ; (match_operand:SI 2 "register_operand" "c")) | |
2916 | ; (match_operand:SI 3 "register_operand" "c"))) | |
2917 | ; (clobber (reg CC_REG))] | |
2918 | ; "" | |
2919 | ; [(set (reg:CC_C CC_REG) (compare:CC_C (match_dup 2) (match_dup 1))) | |
2920 | ; (set (match_dup 0) | |
2921 | ; (plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0)) | |
2922 | ; (match_dup 3)))]) | |
2923 | ||
2924 | (define_expand "subsi3" | |
2925 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
2926 | (minus:SI (match_operand:SI 1 "nonmemory_operand" "") | |
2927 | (match_operand:SI 2 "nonmemory_operand" "")))] | |
2928 | "" | |
2929 | " | |
2930 | { | |
2931 | int c = 1; | |
2932 | ||
2933 | if (!register_operand (operands[2], SImode)) | |
2934 | { | |
2935 | operands[1] = force_reg (SImode, operands[1]); | |
2936 | c = 2; | |
2937 | } | |
2938 | if (flag_pic && arc_raw_symbolic_reference_mentioned_p (operands[c], false)) | |
2939 | operands[c] = force_reg (SImode, operands[c]); | |
526b7aee SV |
2940 | }") |
2941 | ||
2942 | ; the casesi expander might generate a sub of zero, so we have to recognize it. | |
2943 | ; combine should make such an insn go away. | |
2944 | (define_insn_and_split "subsi3_insn" | |
fa9c1b3c CZ |
2945 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcqq,Rcw,Rcw,w,w,w, w, w, w") |
2946 | (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,Rcqq, 0, cL,c,L,I,Cal,Cal, c") | |
2947 | (match_operand:SI 2 "nonmemory_operand" "Rcqq,Rcqq, c, 0,c,c,0, 0, c,Cal")))] | |
526b7aee SV |
2948 | "register_operand (operands[1], SImode) |
2949 | || register_operand (operands[2], SImode)" | |
2950 | "@ | |
fa9c1b3c | 2951 | sub%? %0,%1,%2%& |
526b7aee SV |
2952 | sub%? %0,%1,%2%& |
2953 | sub%? %0,%1,%2 | |
2954 | rsub%? %0,%2,%1 | |
2955 | sub %0,%1,%2 | |
2956 | rsub %0,%2,%1 | |
2957 | rsub %0,%2,%1 | |
2958 | rsub%? %0,%2,%1 | |
2959 | rsub %0,%2,%1 | |
2960 | sub %0,%1,%2" | |
2961 | "reload_completed && get_attr_length (insn) == 8 | |
2962 | && satisfies_constraint_I (operands[1]) | |
2963 | && GET_CODE (PATTERN (insn)) != COND_EXEC" | |
2964 | [(set (match_dup 0) (match_dup 3)) (set (match_dup 0) (match_dup 4))] | |
2965 | "split_subsi (operands);" | |
fa9c1b3c CZ |
2966 | [(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false,false, false") |
2967 | (set_attr "length" "*,*,4,4,4,4,4,8,8,8") | |
2968 | (set_attr "predicable" "yes,no,yes,yes,no,no,no,yes,no,no") | |
2969 | (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond,canuse_limm,canuse,nocond,nocond") | |
2970 | (set_attr "cpu_facility" "*,cd,*,*,*,*,*,*,*,*") | |
2971 | ]) | |
526b7aee SV |
2972 | |
2973 | (define_expand "subdi3" | |
2974 | [(parallel [(set (match_operand:DI 0 "dest_reg_operand" "") | |
2975 | (minus:DI (match_operand:DI 1 "nonmemory_operand" "") | |
2976 | (match_operand:DI 2 "nonmemory_operand" ""))) | |
2977 | (clobber (reg:CC CC_REG))])] | |
2978 | "" | |
2979 | { | |
2980 | if (!register_operand (operands[2], DImode)) | |
2981 | operands[1] = force_reg (DImode, operands[1]); | |
526b7aee SV |
2982 | }) |
2983 | ||
2984 | (define_insn_and_split "subdi3_i" | |
2985 | [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w,w,w,w") | |
2986 | (minus:DI (match_operand:DI 1 "nonmemory_operand" "ci,0,ci,c,!i") | |
2987 | (match_operand:DI 2 "nonmemory_operand" "ci,ci,0,!i,c"))) | |
2988 | (clobber (reg:CC CC_REG))] | |
2989 | "register_operand (operands[1], DImode) | |
2990 | || register_operand (operands[2], DImode)" | |
2991 | "#" | |
2992 | "reload_completed" | |
2993 | [(const_int 0)] | |
2994 | { | |
2995 | int hi = !TARGET_BIG_ENDIAN; | |
2996 | int lo = !hi; | |
2997 | rtx l0 = operand_subword (operands[0], lo, 0, DImode); | |
2998 | rtx h0 = operand_subword (operands[0], hi, 0, DImode); | |
2999 | rtx l1 = operand_subword (operands[1], lo, 0, DImode); | |
3000 | rtx h1 = operand_subword (operands[1], hi, 0, DImode); | |
3001 | rtx l2 = operand_subword (operands[2], lo, 0, DImode); | |
3002 | rtx h2 = operand_subword (operands[2], hi, 0, DImode); | |
3003 | ||
3004 | if (rtx_equal_p (l0, h1) || rtx_equal_p (l0, h2)) | |
3005 | { | |
3006 | h1 = simplify_gen_binary (MINUS, SImode, h1, h2); | |
3007 | if (!rtx_equal_p (h0, h1)) | |
f7df4a84 | 3008 | emit_insn (gen_rtx_SET (h0, h1)); |
526b7aee SV |
3009 | emit_insn (gen_sub_f (l0, l1, l2)); |
3010 | emit_insn | |
3011 | (gen_rtx_COND_EXEC | |
3012 | (VOIDmode, | |
3013 | gen_rtx_LTU (VOIDmode, gen_rtx_REG (CC_Cmode, CC_REG), GEN_INT (0)), | |
f7df4a84 | 3014 | gen_rtx_SET (h0, plus_constant (SImode, h0, -1)))); |
526b7aee SV |
3015 | DONE; |
3016 | } | |
3017 | emit_insn (gen_sub_f (l0, l1, l2)); | |
3018 | emit_insn (gen_sbc (h0, h1, h2, gen_rtx_REG (CCmode, CC_REG))); | |
3019 | DONE; | |
3020 | } | |
3021 | [(set_attr "cond" "clob") | |
3022 | (set_attr "length" "16,16,16,20,20")]) | |
3023 | ||
3024 | (define_insn "*sbc_0" | |
3025 | [(set (match_operand:SI 0 "dest_reg_operand" "=w") | |
3026 | (minus:SI (match_operand:SI 1 "register_operand" "c") | |
3027 | (ltu:SI (match_operand:CC_C 2 "cc_use_register") | |
3028 | (const_int 0))))] | |
3029 | "" | |
3030 | "sbc %0,%1,0" | |
3031 | [(set_attr "cond" "use") | |
3032 | (set_attr "type" "cc_arith") | |
3033 | (set_attr "length" "4")]) | |
3034 | ||
3035 | ; w/c/c comes first (rather than Rcw/0/C_0) to prevent the middle-end | |
3036 | ; needlessly prioritizing the matching constraint. | |
3037 | ; Rcw/0/C_0 comes before w/c/L so that the lower latency conditional execution | |
3038 | ; is used where possible. | |
3039 | (define_insn_and_split "sbc" | |
3040 | [(set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w,Rcw,w") | |
3041 | (minus:SI (minus:SI (match_operand:SI 1 "nonmemory_operand" | |
3042 | "c,0,c,0,cCal") | |
3043 | (ltu:SI (match_operand:CC_C 3 "cc_use_register") | |
3044 | (const_int 0))) | |
3045 | (match_operand:SI 2 "nonmemory_operand" "c,C_0,L,I,cCal")))] | |
3046 | "register_operand (operands[1], SImode) | |
3047 | || register_operand (operands[2], SImode)" | |
3048 | "@ | |
3049 | sbc %0,%1,%2 | |
3050 | sub.cs %0,%1,1 | |
3051 | sbc %0,%1,%2 | |
3052 | sbc %0,%1,%2 | |
3053 | sbc %0,%1,%2" | |
3054 | ; if we have a bad schedule after sched2, split. | |
3055 | "reload_completed | |
f50bb868 | 3056 | && !optimize_size && (!TARGET_ARC600_FAMILY) |
526b7aee SV |
3057 | && arc_scheduling_not_expected () |
3058 | && arc_sets_cc_p (prev_nonnote_insn (insn)) | |
3059 | /* If next comes a return or other insn that needs a delay slot, | |
3060 | expect the adc to get into the delay slot. */ | |
3061 | && next_nonnote_insn (insn) | |
3062 | && !arc_need_delay (next_nonnote_insn (insn)) | |
3063 | /* Restore operands before emitting. */ | |
3064 | && (extract_insn_cached (insn), 1)" | |
3065 | [(set (match_dup 0) (match_dup 4)) | |
3066 | (cond_exec | |
3067 | (ltu (reg:CC_C CC_REG) (const_int 0)) | |
3068 | (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))))] | |
3069 | "operands[4] = simplify_gen_binary (MINUS, SImode, operands[1], operands[2]);" | |
3070 | [(set_attr "cond" "use") | |
3071 | (set_attr "type" "cc_arith") | |
3072 | (set_attr "length" "4,4,4,4,8")]) | |
3073 | ||
3074 | (define_insn "sub_f" | |
3075 | [(set (reg:CC CC_REG) | |
3076 | (compare:CC (match_operand:SI 1 "nonmemory_operand" " c,L,0,I,c,Cal") | |
3077 | (match_operand:SI 2 "nonmemory_operand" "cL,c,I,0,Cal,c"))) | |
3078 | (set (match_operand:SI 0 "dest_reg_operand" "=w,w,Rcw,Rcw,w,w") | |
3079 | (minus:SI (match_dup 1) (match_dup 2)))] | |
3080 | "register_operand (operands[1], SImode) | |
3081 | || register_operand (operands[2], SImode)" | |
3082 | "@ | |
3083 | sub.f %0,%1,%2 | |
3084 | rsub.f %0,%2,%1 | |
3085 | sub.f %0,%1,%2 | |
3086 | rsub.f %0,%2,%1 | |
3087 | sub.f %0,%1,%2 | |
3088 | sub.f %0,%1,%2" | |
3089 | [(set_attr "type" "compare") | |
3090 | (set_attr "length" "4,4,4,4,8,8")]) | |
3091 | ||
3092 | ; combine won't work when an intermediate result is used later... | |
3093 | ; add %0,%1,%2 ` cmp %0,%[12] -> add.f %0,%1,%2 | |
3094 | (define_peephole2 | |
3095 | [(set (reg:CC CC_REG) | |
3096 | (compare:CC (match_operand:SI 1 "register_operand" "") | |
3097 | (match_operand:SI 2 "nonmemory_operand" ""))) | |
3098 | (set (match_operand:SI 0 "dest_reg_operand" "") | |
3099 | (minus:SI (match_dup 1) (match_dup 2)))] | |
3100 | "" | |
3101 | [(parallel | |
3102 | [(set (reg:CC CC_REG) (compare:CC (match_dup 1) (match_dup 2))) | |
3103 | (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])]) | |
3104 | ||
3105 | (define_peephole2 | |
3106 | [(set (reg:CC CC_REG) | |
3107 | (compare:CC (match_operand:SI 1 "register_operand" "") | |
3108 | (match_operand:SI 2 "nonmemory_operand" ""))) | |
3109 | (set (match_operand 3 "" "") (match_operand 4 "" "")) | |
3110 | (set (match_operand:SI 0 "dest_reg_operand" "") | |
3111 | (minus:SI (match_dup 1) (match_dup 2)))] | |
3112 | "!reg_overlap_mentioned_p (operands[3], operands[1]) | |
3113 | && !reg_overlap_mentioned_p (operands[3], operands[2]) | |
3114 | && !reg_overlap_mentioned_p (operands[0], operands[4]) | |
3115 | && !reg_overlap_mentioned_p (operands[0], operands[3])" | |
3116 | [(parallel | |
3117 | [(set (reg:CC CC_REG) (compare:CC (match_dup 1) (match_dup 2))) | |
3118 | (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) | |
3119 | (set (match_dup 3) (match_dup 4))]) | |
3120 | ||
1e466f04 | 3121 | (define_insn "*add_n" |
e04108c7 CZ |
3122 | [(set (match_operand:SI 0 "dest_reg_operand" "=q,r,r") |
3123 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "q,r,r") | |
526b7aee | 3124 | (match_operand:SI 2 "_2_4_8_operand" "")) |
e04108c7 | 3125 | (match_operand:SI 3 "nonmemory_operand" "0,r,Csz")))] |
526b7aee | 3126 | "" |
e04108c7 | 3127 | "add%z2%?\\t%0,%3,%1%&" |
526b7aee | 3128 | [(set_attr "type" "shift") |
e04108c7 CZ |
3129 | (set_attr "length" "*,4,8") |
3130 | (set_attr "predicable" "yes,no,no") | |
3131 | (set_attr "cond" "canuse,nocond,nocond") | |
3132 | (set_attr "iscompact" "maybe,false,false")]) | |
526b7aee SV |
3133 | |
3134 | ;; N.B. sub[123] has the operands of the MINUS in the opposite order from | |
3135 | ;; what synth_mult likes. | |
1e466f04 GM |
3136 | (define_insn "*sub_n" |
3137 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w") | |
3138 | (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,c,?Cal") | |
3139 | (ashift:SI (match_operand:SI 2 "register_operand" "c,c,c") | |
3140 | (match_operand:SI 3 "_1_2_3_operand" ""))))] | |
3141 | "" | |
3142 | "sub%c3%? %0,%1,%2" | |
3143 | [(set_attr "type" "shift") | |
3144 | (set_attr "length" "4,4,8") | |
3145 | (set_attr "predicable" "yes,no,no") | |
3146 | (set_attr "cond" "canuse,nocond,nocond") | |
3147 | (set_attr "iscompact" "false")]) | |
3148 | ||
526b7aee SV |
3149 | (define_insn "*sub_n" |
3150 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w") | |
3151 | (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,c,?Cal") | |
3152 | (mult:SI (match_operand:SI 2 "register_operand" "c,c,c") | |
3153 | (match_operand:SI 3 "_2_4_8_operand" ""))))] | |
3154 | "" | |
3155 | "sub%z3%? %0,%1,%2" | |
3156 | [(set_attr "type" "shift") | |
3157 | (set_attr "length" "4,4,8") | |
3158 | (set_attr "predicable" "yes,no,no") | |
3159 | (set_attr "cond" "canuse,nocond,nocond") | |
3160 | (set_attr "iscompact" "false")]) | |
3161 | ||
3162 | ; ??? check if combine matches this. | |
3163 | (define_insn "*bset" | |
3164 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w") | |
3165 | (ior:SI (ashift:SI (const_int 1) | |
3166 | (match_operand:SI 1 "nonmemory_operand" "cL,cL,c")) | |
3167 | (match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))] | |
3168 | "" | |
3169 | "bset%? %0,%2,%1" | |
3170 | [(set_attr "length" "4,4,8") | |
3171 | (set_attr "predicable" "yes,no,no") | |
3172 | (set_attr "cond" "canuse,nocond,nocond")] | |
3173 | ) | |
3174 | ||
3175 | ; ??? check if combine matches this. | |
3176 | (define_insn "*bxor" | |
3177 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w") | |
3178 | (xor:SI (ashift:SI (const_int 1) | |
3179 | (match_operand:SI 1 "nonmemory_operand" "cL,cL,c")) | |
3180 | (match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))] | |
3181 | "" | |
3182 | "bxor%? %0,%2,%1" | |
3183 | [(set_attr "length" "4,4,8") | |
3184 | (set_attr "predicable" "yes,no,no") | |
3185 | (set_attr "cond" "canuse,nocond,nocond")] | |
3186 | ) | |
3187 | ||
3188 | ; ??? check if combine matches this. | |
3189 | (define_insn "*bclr" | |
3190 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w") | |
3191 | (and:SI (not:SI (ashift:SI (const_int 1) | |
3192 | (match_operand:SI 1 "nonmemory_operand" "cL,cL,c"))) | |
3193 | (match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))] | |
3194 | "" | |
3195 | "bclr%? %0,%2,%1" | |
3196 | [(set_attr "length" "4,4,8") | |
3197 | (set_attr "predicable" "yes,no,no") | |
3198 | (set_attr "cond" "canuse,nocond,nocond")] | |
3199 | ) | |
3200 | ||
3201 | ; ??? FIXME: find combine patterns for bmsk. | |
3202 | ||
3203 | ;;Following are the define_insns added for the purpose of peephole2's | |
3204 | ||
3205 | ; see also iorsi3 for use with constant bit number. | |
3206 | (define_insn "*bset_insn" | |
3207 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w") | |
3208 | (ior:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal") | |
3209 | (ashift:SI (const_int 1) | |
3210 | (match_operand:SI 2 "nonmemory_operand" "cL,cL,c"))) ) ] | |
3211 | "" | |
3212 | "@ | |
3213 | bset%? %0,%1,%2 ;;peep2, constr 1 | |
3214 | bset %0,%1,%2 ;;peep2, constr 2 | |
6b55f8c9 | 3215 | bset %0,%1,%2 ;;peep2, constr 3" |
526b7aee SV |
3216 | [(set_attr "length" "4,4,8") |
3217 | (set_attr "predicable" "yes,no,no") | |
3218 | (set_attr "cond" "canuse,nocond,nocond")] | |
3219 | ) | |
3220 | ||
3221 | ; see also xorsi3 for use with constant bit number. | |
3222 | (define_insn "*bxor_insn" | |
3223 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w") | |
3224 | (xor:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal") | |
3225 | (ashift:SI (const_int 1) | |
3226 | (match_operand:SI 2 "nonmemory_operand" "cL,cL,c"))) ) ] | |
3227 | "" | |
3228 | "@ | |
3229 | bxor%? %0,%1,%2 | |
3230 | bxor %0,%1,%2 | |
6b55f8c9 | 3231 | bxor %0,%1,%2" |
526b7aee SV |
3232 | [(set_attr "length" "4,4,8") |
3233 | (set_attr "predicable" "yes,no,no") | |
3234 | (set_attr "cond" "canuse,nocond,nocond")] | |
3235 | ) | |
3236 | ||
3237 | ; see also andsi3 for use with constant bit number. | |
3238 | (define_insn "*bclr_insn" | |
3239 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w") | |
3240 | (and:SI (not:SI (ashift:SI (const_int 1) | |
3241 | (match_operand:SI 2 "nonmemory_operand" "cL,rL,r"))) | |
3242 | (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")))] | |
3243 | "" | |
3244 | "@ | |
3245 | bclr%? %0,%1,%2 | |
3246 | bclr %0,%1,%2 | |
6b55f8c9 | 3247 | bclr %0,%1,%2" |
526b7aee SV |
3248 | [(set_attr "length" "4,4,8") |
3249 | (set_attr "predicable" "yes,no,no") | |
3250 | (set_attr "cond" "canuse,nocond,nocond")] | |
3251 | ) | |
3252 | ||
3253 | ; see also andsi3 for use with constant bit number. | |
3254 | (define_insn "*bmsk_insn" | |
3255 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w") | |
3256 | (and:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal") | |
3257 | (plus:SI (ashift:SI (const_int 1) | |
3258 | (plus:SI (match_operand:SI 2 "nonmemory_operand" "rL,rL,r") | |
3259 | (const_int 1))) | |
3260 | (const_int -1))))] | |
3261 | "" | |
3262 | "@ | |
6b55f8c9 | 3263 | bmsk%? %0,%1,%2 |
526b7aee | 3264 | bmsk %0,%1,%2 |
6b55f8c9 | 3265 | bmsk %0,%1,%2" |
526b7aee SV |
3266 | [(set_attr "length" "4,4,8") |
3267 | (set_attr "predicable" "yes,no,no") | |
3268 | (set_attr "cond" "canuse,nocond,nocond")] | |
3269 | ) | |
3270 | ||
3271 | ;;Instructions added for peephole2s end | |
3272 | ||
3273 | ;; Boolean instructions. | |
3274 | ||
3275 | (define_expand "andsi3" | |
3276 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
3277 | (and:SI (match_operand:SI 1 "nonimmediate_operand" "") | |
3278 | (match_operand:SI 2 "nonmemory_operand" "")))] | |
3279 | "" | |
3280 | "if (!satisfies_constraint_Cux (operands[2])) | |
3281 | operands[1] = force_reg (SImode, operands[1]); | |
e0be3321 | 3282 | ") |
526b7aee | 3283 | |
03301dcc CZ |
3284 | (define_insn "andsi3_i" ;0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
3285 | [(set (match_operand:SI 0 "dest_reg_operand" "=q,q, q, q, q, r,r, r, r, r,r, r, r, r, r, q,r, r, r, W") | |
3286 | (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,q, 0, 0, q, 0,r, 0, 0, 0,0, r, r, r, r, q,0, 0, r, o") | |
3287 | (match_operand:SI 2 "nonmemory_operand" "q,0,C1p,Ccp,Cux,rL,0,C2pC1p,Ccp,CnL,I,rL,C2pC1p,Ccp,CnL,Cbf,I,Cal,Cal,Cux")))] | |
526b7aee SV |
3288 | "(register_operand (operands[1], SImode) |
3289 | && nonmemory_operand (operands[2], SImode)) | |
3290 | || (memory_operand (operands[1], SImode) | |
3291 | && satisfies_constraint_Cux (operands[2]))" | |
526b7aee SV |
3292 | { |
3293 | switch (which_alternative) | |
3294 | { | |
ceaaa9fe JR |
3295 | case 0: case 5: case 10: case 11: case 16: case 17: case 18: |
3296 | return "and%? %0,%1,%2%&"; | |
526b7aee | 3297 | case 1: case 6: |
ceaaa9fe | 3298 | return "and%? %0,%2,%1%&"; |
fc1c2d04 | 3299 | case 2: |
ceaaa9fe | 3300 | return "bmsk%? %0,%1,%Z2%&"; |
fc1c2d04 CZ |
3301 | case 7: case 12: |
3302 | if (satisfies_constraint_C2p (operands[2])) | |
3303 | { | |
3304 | operands[2] = GEN_INT ((~INTVAL (operands[2]))); | |
3305 | return "bmskn%? %0,%1,%Z2%&"; | |
3306 | } | |
3307 | else | |
3308 | { | |
3309 | return "bmsk%? %0,%1,%Z2%&"; | |
3310 | } | |
526b7aee | 3311 | case 3: case 8: case 13: |
ceaaa9fe | 3312 | return "bclr%? %0,%1,%M2%&"; |
526b7aee SV |
3313 | case 4: |
3314 | return (INTVAL (operands[2]) == 0xff | |
ceaaa9fe | 3315 | ? "extb%? %0,%1%&" : "ext%_%? %0,%1%&"); |
526b7aee | 3316 | case 9: case 14: return \"bic%? %0,%1,%n2-1\"; |
ceaaa9fe JR |
3317 | case 15: |
3318 | return "movb.cl %0,%1,%p2,%p2,%s2"; | |
3319 | ||
3320 | case 19: | |
3321 | const char *tmpl; | |
3322 | ||
3323 | if (satisfies_constraint_Ucm (operands[1])) | |
3324 | tmpl = (INTVAL (operands[2]) == 0xff | |
3325 | ? "xldb%U1 %0,%1" : "xld%_%U1 %0,%1"); | |
3326 | else | |
3327 | tmpl = INTVAL (operands[2]) == 0xff ? "ldb %0,%1" : "ld%_ %0,%1"; | |
3328 | ||
526b7aee SV |
3329 | if (TARGET_BIG_ENDIAN) |
3330 | { | |
3331 | rtx xop[2]; | |
3332 | ||
3333 | xop[0] = operands[0]; | |
3334 | xop[1] = adjust_address (operands[1], QImode, | |
3335 | INTVAL (operands[2]) == 0xff ? 3 : 2); | |
ceaaa9fe JR |
3336 | output_asm_insn (tmpl, xop); |
3337 | return ""; | |
526b7aee | 3338 | } |
ceaaa9fe | 3339 | return tmpl; |
526b7aee SV |
3340 | default: |
3341 | gcc_unreachable (); | |
3342 | } | |
ceaaa9fe JR |
3343 | } |
3344 | [(set_attr "iscompact" "maybe,maybe,maybe,maybe,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false") | |
3345 | (set_attr "type" "binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,shift,binary,binary,binary,load") | |
3346 | (set_attr "length" "*,*,*,*,*,4,4,4,4,4,4,4,4,4,4,4,4,8,8,*") | |
3347 | (set_attr "predicable" "no,no,no,no,no,yes,yes,yes,yes,yes,no,no,no,no,no,no,no,yes,no,no") | |
3348 | (set_attr "cond" "canuse,canuse,canuse,canuse,nocond,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,nocond,nocond,nocond,canuse_limm,canuse,nocond,nocond")]) | |
526b7aee SV |
3349 | |
3350 | ; combiner splitter, pattern found in ldtoa.c . | |
3351 | ; and op3,op0,op1 / cmp op3,op2 -> add op3,op0,op4 / bmsk.f 0,op3,op1 | |
3352 | (define_split | |
3353 | [(set (reg:CC_Z CC_REG) | |
3354 | (compare:CC_Z (and:SI (match_operand:SI 0 "register_operand" "") | |
3355 | (match_operand 1 "const_int_operand" "")) | |
3356 | (match_operand 2 "const_int_operand" ""))) | |
3357 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
3358 | "((INTVAL (operands[1]) + 1) & INTVAL (operands[1])) == 0" | |
3359 | [(set (match_dup 3) | |
3360 | (plus:SI (match_dup 0) (match_dup 4))) | |
3361 | (set (reg:CC_Z CC_REG) | |
3362 | (compare:CC_Z (and:SI (match_dup 3) (match_dup 1)) | |
3363 | (const_int 0)))] | |
3364 | "operands[4] = GEN_INT ( -(~INTVAL (operands[1]) | INTVAL (operands[2])));") | |
3365 | ||
3366 | ;;bic define_insn that allows limm to be the first operand | |
3367 | (define_insn "*bicsi3_insn" | |
3368 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,Rcw,Rcw,w,w,w") | |
3369 | (and:SI (not:SI (match_operand:SI 1 "nonmemory_operand" "Rcqq,Lc,I,Cal,Lc,Cal,c")) | |
3370 | (match_operand:SI 2 "nonmemory_operand" "0,0,0,0,c,c,Cal")))] | |
3371 | "" | |
3372 | "@ | |
3373 | bic%? %0, %2, %1%& ;;constraint 0 | |
3374 | bic%? %0,%2,%1 ;;constraint 1 | |
3375 | bic %0,%2,%1 ;;constraint 2, FIXME: will it ever get generated ??? | |
6b55f8c9 | 3376 | bic%? %0,%2,%1 ;;constraint 3, FIXME: will it ever get generated ??? |
526b7aee | 3377 | bic %0,%2,%1 ;;constraint 4 |
6b55f8c9 CZ |
3378 | bic %0,%2,%1 ;;constraint 5, FIXME: will it ever get generated ??? |
3379 | bic %0,%2,%1 ;;constraint 6" | |
526b7aee SV |
3380 | [(set_attr "length" "*,4,4,8,4,8,8") |
3381 | (set_attr "iscompact" "maybe, false, false, false, false, false, false") | |
3382 | (set_attr "predicable" "no,yes,no,yes,no,no,no") | |
3383 | (set_attr "cond" "canuse,canuse,canuse_limm,canuse,nocond,nocond,nocond")]) | |
3384 | ||
03301dcc CZ |
3385 | (define_insn_and_split "iorsi3" |
3386 | [(set (match_operand:SI 0 "dest_reg_operand" "=q,q, q, r,r, r,r, r, r,r, q, r, r") | |
3387 | (ior:SI (match_operand:SI 1 "register_operand" "%0,q, 0, 0,r, 0,0, r, r,0, r, 0, r") | |
3388 | (match_operand:SI 2 "nonmemory_operand" "q,0,C0p,rL,0,C0p,I,rL,C0p,I,C0x,Cal,Cal")))] | |
526b7aee | 3389 | "" |
03301dcc CZ |
3390 | "@ |
3391 | or%?\\t%0,%1,%2 | |
3392 | or%?\\t%0,%2,%1 | |
3393 | bset%?\\t%0,%1,%z2 | |
3394 | or%?\\t%0,%1,%2 | |
3395 | or%?\\t%0,%2,%1 | |
3396 | bset%?\\t%0,%1,%z2 | |
3397 | or%?\\t%0,%1,%2 | |
3398 | or%?\\t%0,%1,%2 | |
3399 | bset%?\\t%0,%1,%z2 | |
3400 | or%?\\t%0,%1,%2 | |
3401 | # | |
3402 | or%?\\t%0,%1,%2 | |
3403 | or%?\\t%0,%1,%2" | |
4653da0b CZ |
3404 | "reload_completed |
3405 | && GET_CODE (PATTERN (insn)) != COND_EXEC | |
3406 | && register_operand (operands[0], SImode) | |
3407 | && IN_RANGE (REGNO (operands[0]) ^ 4, 4, 11) | |
3408 | && satisfies_constraint_C0x (operands[2])" | |
03301dcc CZ |
3409 | [(const_int 0)] |
3410 | " | |
3411 | arc_split_ior (operands); | |
3412 | DONE; | |
3413 | " | |
3414 | [(set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false,false") | |
3415 | (set_attr "length" "*,*,*,4,4,4,4,4,4,4,*,8,8") | |
3416 | (set_attr "predicable" "no,no,no,yes,yes,yes,no,no,no,no,no,yes,no") | |
3417 | (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,canuse_limm,nocond,canuse,nocond")]) | |
526b7aee SV |
3418 | |
3419 | (define_insn "xorsi3" | |
3420 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcw,Rcw,Rcw,Rcw, w, w,w, w, w") | |
3421 | (xor:SI (match_operand:SI 1 "register_operand" "%0, Rcq, 0, c, 0, 0, c, c,0, 0, c") | |
3422 | (match_operand:SI 2 "nonmemory_operand" " Rcqq, 0, cL, 0,C0p, I,cL,C0p,I,Cal,Cal")))] | |
3423 | "" | |
3424 | "* | |
3425 | switch (which_alternative) | |
3426 | { | |
3427 | case 0: case 2: case 5: case 6: case 8: case 9: case 10: | |
3428 | return \"xor%? %0,%1,%2%&\"; | |
3429 | case 1: case 3: | |
3430 | return \"xor%? %0,%2,%1%&\"; | |
3431 | case 4: case 7: | |
3432 | return \"bxor%? %0,%1,%z2\"; | |
3433 | default: | |
3434 | gcc_unreachable (); | |
3435 | } | |
3436 | " | |
3437 | [(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false,false,false,false") | |
3438 | (set_attr "type" "binary") | |
3439 | (set_attr "length" "*,*,4,4,4,4,4,4,4,8,8") | |
3440 | (set_attr "predicable" "no,no,yes,yes,yes,no,no,no,no,yes,no") | |
3441 | (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,canuse_limm,canuse,nocond")]) | |
3442 | ||
3443 | (define_insn "negsi2" | |
3444 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcqq,Rcw,w") | |
3445 | (neg:SI (match_operand:SI 1 "register_operand" "0,Rcqq,0,c")))] | |
3446 | "" | |
3447 | "neg%? %0,%1%&" | |
3448 | [(set_attr "type" "unary") | |
3449 | (set_attr "iscompact" "maybe,true,false,false") | |
3450 | (set_attr "predicable" "no,no,yes,no")]) | |
3451 | ||
3452 | (define_insn "one_cmplsi2" | |
3453 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w") | |
3454 | (not:SI (match_operand:SI 1 "register_operand" "Rcqq,c")))] | |
3455 | "" | |
3456 | "not%? %0,%1%&" | |
3457 | [(set_attr "type" "unary,unary") | |
3458 | (set_attr "iscompact" "true,false")]) | |
3459 | ||
3460 | (define_insn_and_split "one_cmpldi2" | |
3461 | [(set (match_operand:DI 0 "dest_reg_operand" "=q,w") | |
3462 | (not:DI (match_operand:DI 1 "register_operand" "q,c")))] | |
3463 | "" | |
3464 | "#" | |
3465 | "&& reload_completed" | |
3466 | [(set (match_dup 2) (not:SI (match_dup 3))) | |
3467 | (set (match_dup 4) (not:SI (match_dup 5)))] | |
3468 | { | |
3469 | int swap = (true_regnum (operands[0]) == true_regnum (operands[1]) + 1); | |
3470 | ||
3471 | operands[2] = operand_subword (operands[0], 0+swap, 0, DImode); | |
3472 | operands[3] = operand_subword (operands[1], 0+swap, 0, DImode); | |
3473 | operands[4] = operand_subword (operands[0], 1-swap, 0, DImode); | |
3474 | operands[5] = operand_subword (operands[1], 1-swap, 0, DImode); | |
3475 | } | |
3476 | [(set_attr "type" "unary,unary") | |
3477 | (set_attr "cond" "nocond,nocond") | |
3478 | (set_attr "length" "4,8")]) | |
3479 | ||
3480 | ;; Shift instructions. | |
3481 | ||
3482 | (define_expand "ashlsi3" | |
3483 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
3484 | (ashift:SI (match_operand:SI 1 "register_operand" "") | |
3485 | (match_operand:SI 2 "nonmemory_operand" "")))] | |
3486 | "" | |
3487 | " | |
3488 | { | |
3489 | if (!TARGET_BARREL_SHIFTER) | |
3490 | { | |
3491 | emit_shift (ASHIFT, operands[0], operands[1], operands[2]); | |
3492 | DONE; | |
3493 | } | |
3494 | }") | |
3495 | ||
3496 | (define_expand "ashrsi3" | |
3497 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
3498 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "") | |
3499 | (match_operand:SI 2 "nonmemory_operand" "")))] | |
3500 | "" | |
3501 | " | |
3502 | { | |
3503 | if (!TARGET_BARREL_SHIFTER) | |
3504 | { | |
3505 | emit_shift (ASHIFTRT, operands[0], operands[1], operands[2]); | |
3506 | DONE; | |
3507 | } | |
3508 | }") | |
3509 | ||
3510 | (define_expand "lshrsi3" | |
3511 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
3512 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "") | |
3513 | (match_operand:SI 2 "nonmemory_operand" "")))] | |
3514 | "" | |
3515 | " | |
3516 | { | |
3517 | if (!TARGET_BARREL_SHIFTER) | |
3518 | { | |
3519 | emit_shift (LSHIFTRT, operands[0], operands[1], operands[2]); | |
3520 | DONE; | |
3521 | } | |
3522 | }") | |
3523 | ||
3524 | (define_insn "shift_si3" | |
3525 | [(set (match_operand:SI 0 "dest_reg_operand" "=r") | |
3526 | (match_operator:SI 3 "shift4_operator" | |
3527 | [(match_operand:SI 1 "register_operand" "0") | |
3528 | (match_operand:SI 2 "const_int_operand" "n")])) | |
3529 | (clobber (match_scratch:SI 4 "=&r")) | |
3530 | (clobber (reg:CC CC_REG)) | |
3531 | ] | |
3532 | "!TARGET_BARREL_SHIFTER" | |
3533 | "* return output_shift (operands);" | |
3534 | [(set_attr "type" "shift") | |
3535 | (set_attr "length" "16")]) | |
3536 | ||
3537 | (define_insn "shift_si3_loop" | |
3538 | [(set (match_operand:SI 0 "dest_reg_operand" "=r,r") | |
3539 | (match_operator:SI 3 "shift_operator" | |
3540 | [(match_operand:SI 1 "register_operand" "0,0") | |
3541 | (match_operand:SI 2 "nonmemory_operand" "rn,Cal")])) | |
3542 | (clobber (match_scratch:SI 4 "=X,X")) | |
3543 | (clobber (reg:SI LP_COUNT)) | |
526b7aee SV |
3544 | (clobber (reg:CC CC_REG)) |
3545 | ] | |
3546 | "!TARGET_BARREL_SHIFTER" | |
3547 | "* return output_shift (operands);" | |
3548 | [(set_attr "type" "shift") | |
3549 | (set_attr "length" "16,20")]) | |
3550 | ||
3551 | ; asl, asr, lsr patterns: | |
3552 | ; There is no point in including an 'I' alternative since only the lowest 5 | |
3553 | ; bits are used for the shift. OTOH Cal can be useful if the shift amount | |
3554 | ; is defined in an external symbol, as we don't have special relocations | |
3555 | ; to truncate a symbol in a u6 immediate; but that's rather exotic, so only | |
3556 | ; provide one alternatice for this, without condexec support. | |
3557 | (define_insn "*ashlsi3_insn" | |
3558 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcqq,Rcqq,Rcw, w, w") | |
e04108c7 | 3559 | (ashift:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq, 0, 0, c,cCsz") |
526b7aee SV |
3560 | (match_operand:SI 2 "nonmemory_operand" "K, K,RcqqM, cL,cL,cCal")))] |
3561 | "TARGET_BARREL_SHIFTER | |
3562 | && (register_operand (operands[1], SImode) | |
3563 | || register_operand (operands[2], SImode))" | |
3564 | "asl%? %0,%1,%2%&" | |
3565 | [(set_attr "type" "shift") | |
3566 | (set_attr "iscompact" "maybe,maybe,maybe,false,false,false") | |
3567 | (set_attr "predicable" "no,no,no,yes,no,no") | |
3568 | (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")]) | |
3569 | ||
3570 | (define_insn "*ashrsi3_insn" | |
3571 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcqq,Rcqq,Rcw, w, w") | |
e04108c7 | 3572 | (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq, 0, 0, c,cCsz") |
526b7aee SV |
3573 | (match_operand:SI 2 "nonmemory_operand" "K, K,RcqqM, cL,cL,cCal")))] |
3574 | "TARGET_BARREL_SHIFTER | |
3575 | && (register_operand (operands[1], SImode) | |
3576 | || register_operand (operands[2], SImode))" | |
3577 | "asr%? %0,%1,%2%&" | |
3578 | [(set_attr "type" "shift") | |
3579 | (set_attr "iscompact" "maybe,maybe,maybe,false,false,false") | |
3580 | (set_attr "predicable" "no,no,no,yes,no,no") | |
3581 | (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")]) | |
3582 | ||
3583 | (define_insn "*lshrsi3_insn" | |
3584 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcqq,Rcqq,Rcw, w, w") | |
3585 | (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq, 0, 0, c,cCal") | |
3586 | (match_operand:SI 2 "nonmemory_operand" "N, N,RcqqM, cL,cL,cCal")))] | |
3587 | "TARGET_BARREL_SHIFTER | |
3588 | && (register_operand (operands[1], SImode) | |
3589 | || register_operand (operands[2], SImode))" | |
3590 | "*return (which_alternative <= 1 && !arc_ccfsm_cond_exec_p () | |
3591 | ? \"lsr%? %0,%1%&\" : \"lsr%? %0,%1,%2%&\");" | |
3592 | [(set_attr "type" "shift") | |
3593 | (set_attr "iscompact" "maybe,maybe,maybe,false,false,false") | |
3594 | (set_attr "predicable" "no,no,no,yes,no,no") | |
3595 | (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")]) | |
3596 | ||
3597 | (define_insn "rotrsi3" | |
3598 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw, w, w") | |
e04108c7 | 3599 | (rotatert:SI (match_operand:SI 1 "register_operand" " 0,cL,cCsz") |
526b7aee SV |
3600 | (match_operand:SI 2 "nonmemory_operand" "cL,cL,cCal")))] |
3601 | "TARGET_BARREL_SHIFTER" | |
3602 | "ror%? %0,%1,%2" | |
3603 | [(set_attr "type" "shift,shift,shift") | |
3604 | (set_attr "predicable" "yes,no,no") | |
3605 | (set_attr "length" "4,4,8")]) | |
3606 | ||
3607 | ;; Compare / branch instructions. | |
3608 | ||
3609 | (define_expand "cbranchsi4" | |
3610 | [(set (reg:CC CC_REG) | |
3611 | (compare:CC (match_operand:SI 1 "nonmemory_operand" "") | |
3612 | (match_operand:SI 2 "nonmemory_operand" ""))) | |
3613 | (set (pc) | |
3614 | (if_then_else | |
3615 | (match_operator 0 "ordered_comparison_operator" [(reg CC_REG) | |
3616 | (const_int 0)]) | |
3617 | (label_ref (match_operand 3 "" "")) | |
3618 | (pc)))] | |
3619 | "" | |
3620 | { | |
3621 | gcc_assert (XEXP (operands[0], 0) == operands[1]); | |
3622 | gcc_assert (XEXP (operands[0], 1) == operands[2]); | |
3623 | operands[0] = gen_compare_reg (operands[0], VOIDmode); | |
3624 | emit_jump_insn (gen_branch_insn (operands[3], operands[0])); | |
3625 | DONE; | |
3626 | }) | |
3627 | ||
3628 | ;; ??? Could add a peephole to generate compare with swapped operands and | |
3629 | ;; modifed cc user if second, but not first operand is a compact register. | |
3630 | (define_insn "cmpsi_cc_insn_mixed" | |
3631 | [(set (reg:CC CC_REG) | |
0e03cebd CZ |
3632 | (compare:CC (match_operand:SI 0 "register_operand" "Rcq#q,Rcqq, h, c, c,qRcq,c") |
3633 | (match_operand:SI 1 "nonmemory_operand" "cO, hO,Cm1,cI,cL, Cal,Cal")))] | |
526b7aee SV |
3634 | "" |
3635 | "cmp%? %0,%B1%&" | |
3636 | [(set_attr "type" "compare") | |
0e03cebd CZ |
3637 | (set_attr "iscompact" "true,true,true,false,false,true_limm,false") |
3638 | (set_attr "predicable" "no,no,no,no,yes,no,yes") | |
526b7aee | 3639 | (set_attr "cond" "set") |
0e03cebd CZ |
3640 | (set_attr "length" "*,*,*,4,4,*,8") |
3641 | (set_attr "cpu_facility" "av1,av2,*,*,*,*,*")]) | |
526b7aee SV |
3642 | |
3643 | (define_insn "*cmpsi_cc_zn_insn" | |
3644 | [(set (reg:CC_ZN CC_REG) | |
3645 | (compare:CC_ZN (match_operand:SI 0 "register_operand" "qRcq,c") | |
3646 | (const_int 0)))] | |
3647 | "" | |
3648 | "tst%? %0,%0%&" | |
3649 | [(set_attr "type" "compare,compare") | |
3650 | (set_attr "iscompact" "true,false") | |
3651 | (set_attr "predicable" "no,yes") | |
3652 | (set_attr "cond" "set_zn") | |
3653 | (set_attr "length" "*,4")]) | |
3654 | ||
3655 | ; combiner pattern observed for unwind-dw2-fde.c:linear_search_fdes. | |
3656 | (define_insn "*btst" | |
3657 | [(set (reg:CC_ZN CC_REG) | |
3658 | (compare:CC_ZN | |
3659 | (zero_extract:SI (match_operand:SI 0 "register_operand" "Rcqq,c") | |
3660 | (const_int 1) | |
3661 | (match_operand:SI 1 "nonmemory_operand" "L,Lc")) | |
3662 | (const_int 0)))] | |
3663 | "" | |
3664 | "btst%? %0,%1" | |
3665 | [(set_attr "iscompact" "true,false") | |
3666 | (set_attr "predicable" "no,yes") | |
3667 | (set_attr "cond" "set") | |
3668 | (set_attr "type" "compare") | |
3669 | (set_attr "length" "*,4")]) | |
3670 | ||
3671 | ; combine suffers from 'simplifications' that replace a one-bit zero | |
3672 | ; extract with a shift if it can prove that the upper bits are zero. | |
3673 | ; arc_reorg sees the code after sched2, which can have caused our | |
3674 | ; inputs to be clobbered even if they were not clobbered before. | |
3675 | ; Therefore, add a third way to convert btst / b{eq,ne} to bbit{0,1} | |
3676 | ; OTOH, this is somewhat marginal, and can leat to out-of-range | |
3677 | ; bbit (i.e. bad scheduling) and missed conditional execution, | |
3678 | ; so make this an option. | |
3679 | (define_peephole2 | |
3680 | [(set (reg:CC_ZN CC_REG) | |
3681 | (compare:CC_ZN | |
3682 | (zero_extract:SI (match_operand:SI 0 "register_operand" "") | |
3683 | (const_int 1) | |
3684 | (match_operand:SI 1 "nonmemory_operand" "")) | |
3685 | (const_int 0))) | |
3686 | (set (pc) | |
3687 | (if_then_else (match_operator 3 "equality_comparison_operator" | |
3688 | [(reg:CC_ZN CC_REG) (const_int 0)]) | |
3689 | (label_ref (match_operand 2 "" "")) | |
3690 | (pc)))] | |
3691 | "TARGET_BBIT_PEEPHOLE && peep2_regno_dead_p (2, CC_REG)" | |
3692 | [(parallel [(set (pc) | |
3693 | (if_then_else | |
3694 | (match_op_dup 3 | |
3695 | [(zero_extract:SI (match_dup 0) | |
3696 | (const_int 1) (match_dup 1)) | |
3697 | (const_int 0)]) | |
3698 | (label_ref (match_dup 2)) | |
3699 | (pc))) | |
3700 | (clobber (reg:CC_ZN CC_REG))])]) | |
3701 | ||
3702 | (define_insn "*cmpsi_cc_z_insn" | |
3703 | [(set (reg:CC_Z CC_REG) | |
3704 | (compare:CC_Z (match_operand:SI 0 "register_operand" "qRcq,c") | |
3705 | (match_operand:SI 1 "p2_immediate_operand" "O,n")))] | |
3706 | "" | |
3707 | "@ | |
3708 | cmp%? %0,%1%& | |
3709 | bxor.f 0,%0,%z1" | |
3710 | [(set_attr "type" "compare,compare") | |
3711 | (set_attr "iscompact" "true,false") | |
3712 | (set_attr "cond" "set,set_zn") | |
3713 | (set_attr "length" "*,4")]) | |
3714 | ||
3715 | (define_insn "*cmpsi_cc_c_insn" | |
3716 | [(set (reg:CC_C CC_REG) | |
0e03cebd CZ |
3717 | (compare:CC_C (match_operand:SI 0 "register_operand" "Rcqq,Rcqq, h, c,Rcqq, c") |
3718 | (match_operand:SI 1 "nonmemory_operand" "cO, hO,Cm1,cI, Cal,Cal")))] | |
526b7aee | 3719 | "" |
6b55f8c9 | 3720 | "cmp%? %0,%1%&" |
526b7aee | 3721 | [(set_attr "type" "compare") |
0e03cebd | 3722 | (set_attr "iscompact" "true,true,true,false,true_limm,false") |
526b7aee | 3723 | (set_attr "cond" "set") |
0e03cebd CZ |
3724 | (set_attr "length" "*,*,*,4,*,8") |
3725 | (set_attr "cpu_facility" "av1,av2,*,*,*,*")]) | |
526b7aee SV |
3726 | |
3727 | ;; Next come the scc insns. | |
3728 | ||
3729 | (define_expand "cstoresi4" | |
f50bb868 | 3730 | [(set (match_operand:SI 0 "dest_reg_operand" "") |
2a42e339 CZ |
3731 | (match_operator:SI 1 "ordered_comparison_operator" |
3732 | [(match_operand:SI 2 "nonmemory_operand" "") | |
3733 | (match_operand:SI 3 "nonmemory_operand" "")]))] | |
526b7aee SV |
3734 | "" |
3735 | { | |
f50bb868 CZ |
3736 | if (!TARGET_CODE_DENSITY) |
3737 | { | |
3738 | gcc_assert (XEXP (operands[1], 0) == operands[2]); | |
3739 | gcc_assert (XEXP (operands[1], 1) == operands[3]); | |
3740 | operands[1] = gen_compare_reg (operands[1], SImode); | |
3741 | emit_insn (gen_scc_insn (operands[0], operands[1])); | |
3742 | DONE; | |
3743 | } | |
2a42e339 CZ |
3744 | if (!register_operand (operands[2], SImode)) |
3745 | operands[2] = force_reg (SImode, operands[2]); | |
3746 | ||
526b7aee SV |
3747 | }) |
3748 | ||
8f3304d0 | 3749 | (define_mode_iterator SDF [(SF "TARGET_FP_SP_BASE || TARGET_OPTFPE") |
48f13fb1 | 3750 | (DF "TARGET_FP_DP_BASE || TARGET_OPTFPE")]) |
526b7aee SV |
3751 | |
3752 | (define_expand "cstore<mode>4" | |
3753 | [(set (reg:CC CC_REG) | |
3754 | (compare:CC (match_operand:SDF 2 "register_operand" "") | |
3755 | (match_operand:SDF 3 "register_operand" ""))) | |
3756 | (set (match_operand:SI 0 "dest_reg_operand" "") | |
3757 | (match_operator:SI 1 "comparison_operator" [(reg CC_REG) | |
3758 | (const_int 0)]))] | |
3759 | ||
48f13fb1 | 3760 | "TARGET_HARD_FLOAT || TARGET_OPTFPE" |
526b7aee SV |
3761 | { |
3762 | gcc_assert (XEXP (operands[1], 0) == operands[2]); | |
3763 | gcc_assert (XEXP (operands[1], 1) == operands[3]); | |
3764 | operands[1] = gen_compare_reg (operands[1], SImode); | |
3765 | emit_insn (gen_scc_insn (operands[0], operands[1])); | |
3766 | DONE; | |
3767 | }) | |
3768 | ||
3769 | ; We need a separate expander for this lest we loose the mode of CC_REG | |
3770 | ; when match_operator substitutes the literal operand into the comparison. | |
3771 | (define_expand "scc_insn" | |
3772 | [(set (match_operand:SI 0 "dest_reg_operand" "=w") (match_operand:SI 1 ""))]) | |
3773 | ||
3774 | (define_insn_and_split "*scc_insn" | |
3775 | [(set (match_operand:SI 0 "dest_reg_operand" "=w") | |
3776 | (match_operator:SI 1 "proper_comparison_operator" [(reg CC_REG) (const_int 0)]))] | |
3777 | "" | |
3778 | "#" | |
3779 | "reload_completed" | |
3780 | [(set (match_dup 0) (const_int 1)) | |
3781 | (cond_exec | |
3782 | (match_dup 1) | |
3783 | (set (match_dup 0) (const_int 0)))] | |
3784 | { | |
3785 | operands[1] | |
3786 | = gen_rtx_fmt_ee (REVERSE_CONDITION (GET_CODE (operands[1]), | |
3787 | GET_MODE (XEXP (operands[1], 0))), | |
3788 | VOIDmode, | |
3789 | XEXP (operands[1], 0), XEXP (operands[1], 1)); | |
3790 | } | |
3791 | [(set_attr "type" "unary")]) | |
3792 | ||
526b7aee SV |
3793 | ; cond_exec patterns |
3794 | (define_insn "*movsi_ne" | |
3795 | [(cond_exec | |
5fcb3f62 CZ |
3796 | (ne (match_operand:CC_Z 2 "cc_use_register" "Rcc,Rcc,Rcc,Rcc,Rcc") (const_int 0)) |
3797 | (set (match_operand:SI 0 "dest_reg_operand" "=q, q, r, q, r") | |
3798 | (match_operand:SI 1 "nonmemory_operand" "C_0, h, Lr,Cal,Cal")))] | |
526b7aee SV |
3799 | "" |
3800 | "@ | |
5fcb3f62 CZ |
3801 | * current_insn_predicate = 0; return \"sub%?.ne\\t%0,%0,%0\"; |
3802 | * current_insn_predicate = 0; return \"mov%?.ne\\t%0,%1\"; | |
3803 | mov.ne\\t%0,%1 | |
3804 | * current_insn_predicate = 0; return \"mov%?.ne\\t%0,%1\"; | |
3805 | mov.ne\\t%0,%1" | |
fc1c2d04 | 3806 | [(set_attr "type" "cmove") |
5fcb3f62 CZ |
3807 | (set_attr "iscompact" "true,true,false,true_limm,false") |
3808 | (set_attr "length" "2,2,4,6,8") | |
3809 | (set_attr "cpu_facility" "*,av2,*,av2,*")]) | |
526b7aee SV |
3810 | |
3811 | (define_insn "*movsi_cond_exec" | |
3812 | [(cond_exec | |
3813 | (match_operator 3 "proper_comparison_operator" | |
3814 | [(match_operand 2 "cc_register" "Rcc,Rcc") (const_int 0)]) | |
3815 | (set (match_operand:SI 0 "dest_reg_operand" "=w,w") | |
27ffcc36 | 3816 | (match_operand:SI 1 "nonmemory_operand" "LRac,?Cal")))] |
526b7aee | 3817 | "" |
6b55f8c9 | 3818 | "mov.%d3 %0,%1" |
526b7aee SV |
3819 | [(set_attr "type" "cmove") |
3820 | (set_attr "length" "4,8")]) | |
3821 | ||
3822 | (define_insn "*commutative_cond_exec" | |
3823 | [(cond_exec | |
3824 | (match_operator 5 "proper_comparison_operator" | |
3825 | [(match_operand 4 "cc_register" "Rcc,Rcc") (const_int 0)]) | |
3826 | (set (match_operand:SI 0 "dest_reg_operand" "=w,w") | |
3827 | (match_operator:SI 3 "commutative_operator" | |
3828 | [(match_operand:SI 1 "register_operand" "%0,0") | |
3829 | (match_operand:SI 2 "nonmemory_operand" "cL,?Cal")])))] | |
3830 | "" | |
3831 | { | |
3832 | arc_output_commutative_cond_exec (operands, true); | |
3833 | return ""; | |
3834 | } | |
3835 | [(set_attr "cond" "use") | |
3836 | (set_attr "type" "cmove") | |
3837 | (set_attr_alternative "length" | |
3838 | [(const_int 4) | |
3839 | (cond | |
3840 | [(eq (symbol_ref "arc_output_commutative_cond_exec (operands, false)") | |
3841 | (const_int 4)) | |
3842 | (const_int 4)] | |
3843 | (const_int 8))])]) | |
3844 | ||
3845 | (define_insn "*sub_cond_exec" | |
3846 | [(cond_exec | |
3847 | (match_operator 4 "proper_comparison_operator" | |
3848 | [(match_operand 3 "cc_register" "Rcc,Rcc,Rcc") (const_int 0)]) | |
3849 | (set (match_operand:SI 0 "dest_reg_operand" "=w,w,w") | |
3850 | (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,cL,Cal") | |
3851 | (match_operand:SI 2 "nonmemory_operand" "cL,0,0"))))] | |
3852 | "" | |
3853 | "@ | |
3854 | sub.%d4 %0,%1,%2 | |
3855 | rsub.%d4 %0,%2,%1 | |
3856 | rsub.%d4 %0,%2,%1" | |
3857 | [(set_attr "cond" "use") | |
3858 | (set_attr "type" "cmove") | |
3859 | (set_attr "length" "4,4,8")]) | |
3860 | ||
3861 | (define_insn "*noncommutative_cond_exec" | |
3862 | [(cond_exec | |
3863 | (match_operator 5 "proper_comparison_operator" | |
3864 | [(match_operand 4 "cc_register" "Rcc,Rcc") (const_int 0)]) | |
3865 | (set (match_operand:SI 0 "dest_reg_operand" "=w,w") | |
3866 | (match_operator:SI 3 "noncommutative_operator" | |
3867 | [(match_operand:SI 1 "register_operand" "0,0") | |
3868 | (match_operand:SI 2 "nonmemory_operand" "cL,Cal")])))] | |
3869 | "" | |
3870 | "%O3.%d5 %0,%1,%2" | |
3871 | [(set_attr "cond" "use") | |
3872 | (set_attr "type" "cmove") | |
3873 | (set_attr "length" "4,8")]) | |
3874 | ||
3875 | ;; These control RTL generation for conditional jump insns | |
3876 | ;; Match both normal and inverted jump. | |
3877 | ||
3878 | ; We need a separate expander for this lest we loose the mode of CC_REG | |
3879 | ; when match_operator substitutes the literal operand into the comparison. | |
3880 | (define_expand "branch_insn" | |
3881 | [(set (pc) | |
3882 | (if_then_else (match_operand 1 "" "") | |
3883 | (label_ref (match_operand 0 "" "")) | |
3884 | (pc)))]) | |
3885 | ||
3886 | ; When estimating sizes during arc_reorg, when optimizing for speed, there | |
3887 | ; are three reasons why we need to consider branches to be length 6: | |
3888 | ; - annull-false delay slot insns are implemented using conditional execution, | |
3889 | ; thus preventing short insn formation where used. | |
3890 | ; - for ARC600: annull-true delay slot isnns are implemented where possile | |
3891 | ; using conditional execution, preventing short insn formation where used. | |
3892 | ; - for ARC700: likely or somewhat likely taken branches are made long and | |
3893 | ; unaligned if possible to avoid branch penalty. | |
3894 | (define_insn "*branch_insn" | |
3895 | [(set (pc) | |
3896 | (if_then_else (match_operator 1 "proper_comparison_operator" | |
3897 | [(reg CC_REG) (const_int 0)]) | |
3898 | (label_ref (match_operand 0 "" "")) | |
3899 | (pc)))] | |
3900 | "" | |
3901 | "* | |
3902 | { | |
3903 | if (arc_ccfsm_branch_deleted_p ()) | |
3904 | { | |
3905 | arc_ccfsm_record_branch_deleted (); | |
3906 | return \"; branch deleted, next insns conditionalized\"; | |
3907 | } | |
3908 | else | |
3909 | { | |
3910 | arc_ccfsm_record_condition (operands[1], false, insn, 0); | |
3911 | if (get_attr_length (insn) == 2) | |
3912 | return \"b%d1%? %^%l0%&\"; | |
3913 | else | |
3914 | return \"b%d1%# %^%l0\"; | |
3915 | } | |
3916 | }" | |
3917 | [(set_attr "type" "branch") | |
3918 | (set | |
3919 | (attr "length") | |
3920 | (cond [ | |
3921 | (eq_attr "delay_slot_filled" "yes") | |
3922 | (const_int 4) | |
3923 | ||
3924 | (ne | |
3925 | (if_then_else | |
3926 | (match_operand 1 "equality_comparison_operator" "") | |
3927 | (ior (lt (minus (match_dup 0) (pc)) (const_int -512)) | |
3928 | (gt (minus (match_dup 0) (pc)) | |
3929 | (minus (const_int 506) | |
3930 | (symbol_ref "get_attr_delay_slot_length (insn)")))) | |
3931 | (ior (match_test "!arc_short_comparison_p (operands[1], -64)") | |
3932 | (lt (minus (match_dup 0) (pc)) (const_int -64)) | |
3933 | (gt (minus (match_dup 0) (pc)) | |
3934 | (minus (const_int 58) | |
3935 | (symbol_ref "get_attr_delay_slot_length (insn)"))))) | |
3936 | (const_int 0)) | |
3937 | (const_int 4)] | |
3938 | (const_int 2))) | |
3939 | ||
3940 | (set (attr "iscompact") | |
3941 | (cond [(match_test "get_attr_length (insn) == 2") (const_string "true")] | |
3942 | (const_string "false")))]) | |
3943 | ||
3944 | (define_insn "*rev_branch_insn" | |
3945 | [(set (pc) | |
3946 | (if_then_else (match_operator 1 "proper_comparison_operator" | |
3947 | [(reg CC_REG) (const_int 0)]) | |
3948 | (pc) | |
3949 | (label_ref (match_operand 0 "" ""))))] | |
3950 | "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))" | |
3951 | "* | |
3952 | { | |
3953 | if (arc_ccfsm_branch_deleted_p ()) | |
3954 | { | |
3955 | arc_ccfsm_record_branch_deleted (); | |
3956 | return \"; branch deleted, next insns conditionalized\"; | |
3957 | } | |
3958 | else | |
3959 | { | |
3960 | arc_ccfsm_record_condition (operands[1], true, insn, 0); | |
3961 | if (get_attr_length (insn) == 2) | |
3962 | return \"b%D1%? %^%l0\"; | |
3963 | else | |
3964 | return \"b%D1%# %^%l0\"; | |
3965 | } | |
3966 | }" | |
3967 | [(set_attr "type" "branch") | |
3968 | (set | |
3969 | (attr "length") | |
3970 | (cond [ | |
3971 | (eq_attr "delay_slot_filled" "yes") | |
3972 | (const_int 4) | |
3973 | ||
3974 | (ne | |
3975 | (if_then_else | |
3976 | (match_operand 1 "equality_comparison_operator" "") | |
3977 | (ior (lt (minus (match_dup 0) (pc)) (const_int -512)) | |
3978 | (gt (minus (match_dup 0) (pc)) | |
3979 | (minus (const_int 506) | |
3980 | (symbol_ref "get_attr_delay_slot_length (insn)")))) | |
3981 | (ior (match_test "!arc_short_comparison_p (operands[1], -64)") | |
3982 | (lt (minus (match_dup 0) (pc)) (const_int -64)) | |
3983 | (gt (minus (match_dup 0) (pc)) | |
3984 | (minus (const_int 58) | |
3985 | (symbol_ref "get_attr_delay_slot_length (insn)"))))) | |
3986 | (const_int 0)) | |
3987 | (const_int 4)] | |
3988 | (const_int 2))) | |
3989 | ||
3990 | (set (attr "iscompact") | |
3991 | (cond [(match_test "get_attr_length (insn) == 2") (const_string "true")] | |
3992 | (const_string "false")))]) | |
3993 | ||
3994 | ;; Unconditional and other jump instructions. | |
3995 | ||
3996 | (define_expand "jump" | |
3997 | [(set (pc) (label_ref (match_operand 0 "" "")))] | |
3998 | "" | |
3999 | "") | |
4000 | ||
4001 | (define_insn "jump_i" | |
4002 | [(set (pc) (label_ref (match_operand 0 "" "")))] | |
339ba33b | 4003 | "!TARGET_LONG_CALLS_SET || !CROSSING_JUMP_P (insn)" |
526b7aee SV |
4004 | "b%!%* %^%l0%&" |
4005 | [(set_attr "type" "uncond_branch") | |
4006 | (set (attr "iscompact") | |
4007 | (if_then_else (match_test "get_attr_length (insn) == 2") | |
4008 | (const_string "true") (const_string "false"))) | |
4009 | (set_attr "cond" "canuse") | |
4010 | (set (attr "length") | |
4011 | (cond [ | |
4012 | ; In arc_reorg we just guesstimate; might be more or less than 4. | |
4013 | (match_test "arc_branch_size_unknown_p ()") | |
4014 | (const_int 4) | |
4015 | ||
4016 | (eq_attr "delay_slot_filled" "yes") | |
4017 | (const_int 4) | |
4018 | ||
339ba33b | 4019 | (match_test "CROSSING_JUMP_P (insn)") |
526b7aee SV |
4020 | (const_int 4) |
4021 | ||
4022 | (ior (lt (minus (match_dup 0) (pc)) (const_int -512)) | |
4023 | (gt (minus (match_dup 0) (pc)) | |
4024 | (minus (const_int 506) | |
4025 | (symbol_ref "get_attr_delay_slot_length (insn)")))) | |
4026 | (const_int 4)] | |
4027 | (const_int 2)))]) | |
4028 | ||
4029 | (define_insn "indirect_jump" | |
4030 | [(set (pc) (match_operand:SI 0 "nonmemory_operand" "L,I,Cal,Rcqq,r"))] | |
4031 | "" | |
b5a5ade8 CZ |
4032 | "@ |
4033 | j%!%* %0%& | |
4034 | j%!%* %0%& | |
4035 | j%!%* %0%& | |
4036 | j%!%* [%0]%& | |
4037 | j%!%* [%0]%&" | |
526b7aee SV |
4038 | [(set_attr "type" "jump") |
4039 | (set_attr "iscompact" "false,false,false,maybe,false") | |
4040 | (set_attr "cond" "canuse,canuse_limm,canuse,canuse,canuse")]) | |
4041 | ||
4042 | ;; Implement a switch statement. | |
526b7aee | 4043 | (define_expand "casesi" |
aac1c11c CZ |
4044 | [(match_operand:SI 0 "register_operand" "") ; Index |
4045 | (match_operand:SI 1 "const_int_operand" "") ; Lower bound | |
4046 | (match_operand:SI 2 "const_int_operand" "") ; Total range | |
4047 | (match_operand:SI 3 "" "") ; Table label | |
4048 | (match_operand:SI 4 "" "")] ; Out of range label | |
526b7aee | 4049 | "" |
526b7aee | 4050 | { |
aac1c11c | 4051 | if (operands[1] != const0_rtx) |
526b7aee | 4052 | { |
aac1c11c CZ |
4053 | rtx reg = gen_reg_rtx (SImode); |
4054 | emit_insn (gen_subsi3 (reg, operands[0], operands[1])); | |
4055 | operands[0] = reg; | |
526b7aee | 4056 | } |
aac1c11c CZ |
4057 | emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, operands[0], |
4058 | operands[2]), | |
4059 | operands[0], operands[2], operands[4])); | |
4060 | if (TARGET_BI_BIH) | |
4061 | emit_jump_insn (gen_casesi_dispatch (operands[0], operands[3])); | |
526b7aee SV |
4062 | else |
4063 | { | |
aac1c11c CZ |
4064 | rtx reg = gen_reg_rtx (SImode); |
4065 | rtx lbl = operands[3]; | |
526b7aee | 4066 | operands[3] = gen_rtx_LABEL_REF (VOIDmode, operands[3]); |
aac1c11c | 4067 | if (flag_pic) |
526b7aee | 4068 | operands[3] = force_reg (Pmode, operands[3]); |
aac1c11c CZ |
4069 | emit_insn (gen_casesi_load (reg, |
4070 | operands[3], operands[0], lbl)); | |
526b7aee | 4071 | if (CASE_VECTOR_PC_RELATIVE || flag_pic) |
aac1c11c CZ |
4072 | emit_insn (gen_addsi3 (reg, reg, operands[3])); |
4073 | emit_jump_insn (gen_casesi_jump (reg, lbl)); | |
526b7aee SV |
4074 | } |
4075 | DONE; | |
aac1c11c CZ |
4076 | }) |
4077 | ||
4078 | (define_insn "casesi_dispatch" | |
4079 | [(set (pc) | |
4080 | (unspec:SI [(match_operand:SI 0 "register_operand" "r") | |
4081 | (label_ref (match_operand 1 "" ""))] | |
4082 | UNSPEC_ARC_CASESI))] | |
4083 | "TARGET_BI_BIH" | |
4084 | { | |
4085 | rtx diff_vec = PATTERN (next_nonnote_insn (as_a<rtx_insn *> (operands[1]))); | |
4086 | gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); | |
4087 | switch (GET_MODE (diff_vec)) | |
4088 | { | |
4089 | case E_SImode: | |
4090 | return \"bi\\t[%0]\"; | |
4091 | case E_HImode: | |
4092 | case E_QImode: | |
4093 | return \"bih\\t[%0]\"; | |
4094 | default: gcc_unreachable (); | |
4095 | } | |
4096 | } | |
4097 | [(set_attr "type" "brcc_no_delay_slot") | |
4098 | (set_attr "iscompact" "false") | |
4099 | (set_attr "length" "4")]) | |
526b7aee SV |
4100 | |
4101 | (define_insn "casesi_load" | |
aac1c11c CZ |
4102 | [(set (match_operand:SI 0 "register_operand" "=q,r,r") |
4103 | (mem:SI (unspec:SI [(match_operand:SI 1 "nonmemory_operand" "q,r,Cal") | |
4104 | (match_operand:SI 2 "register_operand" "q,r,r")] | |
4105 | UNSPEC_ARC_CASESI))) | |
4106 | (use (label_ref (match_operand 3 "" "")))] | |
526b7aee SV |
4107 | "" |
4108 | "* | |
4109 | { | |
c9b0a227 | 4110 | rtx diff_vec = PATTERN (next_nonnote_insn (as_a<rtx_insn *> (operands[3]))); |
526b7aee SV |
4111 | |
4112 | if (GET_CODE (diff_vec) != ADDR_DIFF_VEC) | |
4113 | { | |
4114 | gcc_assert (GET_CODE (diff_vec) == ADDR_VEC); | |
4115 | gcc_assert (GET_MODE (diff_vec) == SImode); | |
4116 | gcc_assert (!CASE_VECTOR_PC_RELATIVE && !flag_pic); | |
4117 | } | |
4118 | ||
4119 | switch (GET_MODE (diff_vec)) | |
4120 | { | |
4e10a5a7 | 4121 | case E_SImode: |
aac1c11c | 4122 | return \"ld.as\\t%0,[%1,%2]%&\"; |
4e10a5a7 | 4123 | case E_HImode: |
526b7aee | 4124 | if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) |
aac1c11c CZ |
4125 | return \"ld%_.as\\t%0,[%1,%2]\"; |
4126 | return \"ld%_.x.as\\t%0,[%1,%2]\"; | |
4e10a5a7 | 4127 | case E_QImode: |
526b7aee | 4128 | if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) |
aac1c11c CZ |
4129 | return \"ldb%?\\t%0,[%1,%2]%&\"; |
4130 | return \"ldb.x\\t%0,[%1,%2]\"; | |
526b7aee SV |
4131 | default: |
4132 | gcc_unreachable (); | |
4133 | } | |
4134 | }" | |
4135 | [(set_attr "type" "load") | |
4136 | (set_attr_alternative "iscompact" | |
4137 | [(cond | |
c9b0a227 TS |
4138 | [(ne (symbol_ref "GET_MODE (PATTERN (next_nonnote_insn |
4139 | (as_a<rtx_insn *> (operands[3]))))") | |
526b7aee SV |
4140 | (symbol_ref "QImode")) |
4141 | (const_string "false") | |
c9b0a227 TS |
4142 | (match_test "!ADDR_DIFF_VEC_FLAGS (PATTERN (next_nonnote_insn |
4143 | (as_a<rtx_insn *> (operands[3])))).offset_unsigned") | |
526b7aee SV |
4144 | (const_string "false")] |
4145 | (const_string "true")) | |
4146 | (const_string "false") | |
4147 | (const_string "false")]) | |
4148 | (set_attr_alternative "length" | |
4149 | [(cond | |
220c1a51 JR |
4150 | [(eq_attr "iscompact" "false") (const_int 4) |
4151 | ; We have to mention (match_dup 3) to convince genattrtab.c that this | |
4152 | ; is a varying length insn. | |
4153 | (eq (symbol_ref "1+1") (const_int 2)) (const_int 2) | |
4154 | (gt (minus (match_dup 3) (pc)) (const_int 42)) (const_int 4)] | |
526b7aee SV |
4155 | (const_int 2)) |
4156 | (const_int 4) | |
4157 | (const_int 8)])]) | |
4158 | ||
4159 | ; Unlike the canonical tablejump, this pattern always uses a jump address, | |
4160 | ; even for CASE_VECTOR_PC_RELATIVE. | |
4161 | (define_insn "casesi_jump" | |
4162 | [(set (pc) (match_operand:SI 0 "register_operand" "Cal,Rcqq,c")) | |
4163 | (use (label_ref (match_operand 1 "" "")))] | |
4164 | "" | |
4165 | "j%!%* [%0]%&" | |
4166 | [(set_attr "type" "jump") | |
4167 | (set_attr "iscompact" "false,maybe,false") | |
4168 | (set_attr "cond" "canuse")]) | |
4169 | ||
526b7aee SV |
4170 | (define_expand "call" |
4171 | ;; operands[1] is stack_size_rtx | |
4172 | ;; operands[2] is next_arg_register | |
4173 | [(parallel [(call (match_operand:SI 0 "call_operand" "") | |
4174 | (match_operand 1 "" "")) | |
4175 | (clobber (reg:SI 31))])] | |
4176 | "" | |
4177 | "{ | |
4178 | rtx callee; | |
4179 | ||
4180 | gcc_assert (MEM_P (operands[0])); | |
4181 | callee = XEXP (operands[0], 0); | |
526b7aee SV |
4182 | /* This is to decide if we should generate indirect calls by loading the |
4183 | 32 bit address of the callee into a register before performing the | |
4184 | branch and link - this exposes cse opportunities. | |
4185 | Also, in weird cases like compile/20010107-1.c, we may get a PLUS. */ | |
4186 | if (GET_CODE (callee) != REG | |
4187 | && (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee))) | |
4188 | XEXP (operands[0], 0) = force_reg (Pmode, callee); | |
4189 | } | |
4190 | ") | |
4191 | ||
526b7aee SV |
4192 | ; Rcq, which is used in alternative 0, checks for conditional execution. |
4193 | ; At instruction output time, if it doesn't match and we end up with | |
4194 | ; alternative 1 ("q"), that means that we can't use the short form. | |
4195 | (define_insn "*call_i" | |
4196 | [(call (mem:SI (match_operand:SI 0 | |
7778a1ad | 4197 | "call_address_operand" "Rcq,q,c,Cji,Csc,Cbp,Cbr,L,I,Cal")) |
526b7aee SV |
4198 | (match_operand 1 "" "")) |
4199 | (clobber (reg:SI 31))] | |
4200 | "" | |
4201 | "@ | |
4202 | jl%!%* [%0]%& | |
4203 | jl%!%* [%0]%& | |
4204 | jl%!%* [%0] | |
6b55f8c9 | 4205 | jli_s %S0 |
7778a1ad | 4206 | sjli %S0 |
526b7aee SV |
4207 | bl%!%* %P0 |
4208 | bl%!%* %P0 | |
6b55f8c9 CZ |
4209 | jl%!%* %0 |
4210 | jl%* %0 | |
4211 | jl%! %0" | |
7778a1ad CZ |
4212 | [(set_attr "type" "call,call,call,call_no_delay_slot,call_no_delay_slot,call,call,call,call,call_no_delay_slot") |
4213 | (set_attr "iscompact" "maybe,false,*,true,*,*,*,*,*,*") | |
4214 | (set_attr "predicable" "no,no,yes,no,no,yes,no,yes,no,yes") | |
4215 | (set_attr "length" "*,*,4,2,4,4,4,4,4,8")]) | |
526b7aee | 4216 | |
526b7aee SV |
4217 | (define_expand "call_value" |
4218 | ;; operand 2 is stack_size_rtx | |
4219 | ;; operand 3 is next_arg_register | |
4220 | [(parallel [(set (match_operand 0 "dest_reg_operand" "=r") | |
4221 | (call (match_operand:SI 1 "call_operand" "") | |
4222 | (match_operand 2 "" ""))) | |
4223 | (clobber (reg:SI 31))])] | |
4224 | "" | |
4225 | " | |
4226 | { | |
4227 | rtx callee; | |
4228 | ||
4229 | gcc_assert (MEM_P (operands[1])); | |
4230 | callee = XEXP (operands[1], 0); | |
526b7aee SV |
4231 | /* See the comment in define_expand \"call\". */ |
4232 | if (GET_CODE (callee) != REG | |
4233 | && (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee))) | |
4234 | XEXP (operands[1], 0) = force_reg (Pmode, callee); | |
4235 | }") | |
4236 | ||
526b7aee SV |
4237 | ; Rcq, which is used in alternative 0, checks for conditional execution. |
4238 | ; At instruction output time, if it doesn't match and we end up with | |
4239 | ; alternative 1 ("q"), that means that we can't use the short form. | |
4240 | (define_insn "*call_value_i" | |
7778a1ad | 4241 | [(set (match_operand 0 "dest_reg_operand" "=Rcq,q,w, w, w, w, w,w,w, w") |
526b7aee | 4242 | (call (mem:SI (match_operand:SI 1 |
7778a1ad | 4243 | "call_address_operand" "Rcq,q,c,Cji,Csc,Cbp,Cbr,L,I,Cal")) |
526b7aee SV |
4244 | (match_operand 2 "" ""))) |
4245 | (clobber (reg:SI 31))] | |
4246 | "" | |
4247 | "@ | |
4248 | jl%!%* [%1]%& | |
4249 | jl%!%* [%1]%& | |
4250 | jl%!%* [%1] | |
6b55f8c9 | 4251 | jli_s %S1 |
7778a1ad | 4252 | sjli %S1 |
526b7aee SV |
4253 | bl%!%* %P1;1 |
4254 | bl%!%* %P1;1 | |
6b55f8c9 CZ |
4255 | jl%!%* %1 |
4256 | jl%* %1 | |
4257 | jl%! %1" | |
7778a1ad CZ |
4258 | [(set_attr "type" "call,call,call,call_no_delay_slot,call_no_delay_slot,call,call,call,call,call_no_delay_slot") |
4259 | (set_attr "iscompact" "maybe,false,*,true,false,*,*,*,*,*") | |
4260 | (set_attr "predicable" "no,no,yes,no,no,yes,no,yes,no,yes") | |
4261 | (set_attr "length" "*,*,4,2,4,4,4,4,4,8")]) | |
526b7aee | 4262 | |
f55d4a20 JR |
4263 | ; There is a bl_s instruction (16 bit opcode branch-and-link), but we can't |
4264 | ; use it for lack of inter-procedural branch shortening. | |
4265 | ; Link-time relaxation would help... | |
526b7aee | 4266 | |
f521d500 CZ |
4267 | (define_insn "trap" |
4268 | [(trap_if (const_int 1) (const_int 0))] | |
4269 | "!TARGET_ARC600_FAMILY" | |
4270 | "trap_s\\t5" | |
4271 | [(set_attr "type" "misc") | |
4272 | (set_attr "length" "2")]) | |
4273 | ||
526b7aee SV |
4274 | (define_insn "nop" |
4275 | [(const_int 0)] | |
4276 | "" | |
4277 | "nop%?" | |
4278 | [(set_attr "type" "misc") | |
4279 | (set_attr "iscompact" "true") | |
4280 | (set_attr "cond" "canuse") | |
4281 | (set_attr "length" "2")]) | |
4282 | ||
f50bb868 | 4283 | (define_insn "nopv" |
c69899f0 | 4284 | [(unspec_volatile [(const_int 0)] VUNSPEC_ARC_NOP)] |
f50bb868 CZ |
4285 | "" |
4286 | "nop%?" | |
4287 | [(set_attr "type" "misc") | |
16493b57 CZ |
4288 | (set_attr "iscompact" "maybe") |
4289 | (set_attr "length" "*")]) | |
4290 | ||
4291 | (define_insn "blockage" | |
4292 | [(unspec_volatile [(const_int 0)] VUNSPEC_ARC_BLOCKAGE)] | |
4293 | "" | |
4294 | "" | |
4295 | [(set_attr "length" "0") | |
4296 | (set_attr "type" "block")] | |
4297 | ) | |
f50bb868 | 4298 | |
526b7aee SV |
4299 | ;; Split up troublesome insns for better scheduling. |
4300 | ||
4301 | ;; Peepholes go at the end. | |
4302 | ;;asl followed by add can be replaced by an add{1,2,3} | |
4303 | ;; Three define_peepholes have been added for this optimization | |
4304 | ;; ??? This used to target non-canonical rtl. Now we use add_n, which | |
4305 | ;; can be generated by combine. Check if these peepholes still provide | |
4306 | ;; any benefit. | |
4307 | ||
4308 | ;; ------------------------------------------------------------- | |
4309 | ;; Pattern 1 : r0 = r1 << {i} | |
4310 | ;; r3 = r4/INT + r0 ;;and commutative | |
4311 | ;; || | |
4312 | ;; \/ | |
4313 | ;; add{i} r3,r4/INT,r1 | |
4314 | ;; ------------------------------------------------------------- | |
4315 | ;; ??? This should be covered by combine, alas, at times combine gets | |
4316 | ;; too clever for it's own good: when the shifted input is known to be | |
4317 | ;; either 0 or 1, the operation will be made into an if-then-else, and | |
4318 | ;; thus fail to match the add_n pattern. Example: _mktm_r, line 85 in | |
4319 | ;; newlib/libc/time/mktm_r.c . | |
4320 | ||
4321 | (define_peephole2 | |
4322 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
4323 | (ashift:SI (match_operand:SI 1 "register_operand" "") | |
e04108c7 | 4324 | (match_operand:SI 2 "_1_2_3_operand" ""))) |
526b7aee SV |
4325 | (set (match_operand:SI 3 "dest_reg_operand" "") |
4326 | (plus:SI (match_operand:SI 4 "nonmemory_operand" "") | |
4327 | (match_operand:SI 5 "nonmemory_operand" "")))] | |
e04108c7 | 4328 | "(true_regnum (operands[4]) == true_regnum (operands[0]) |
526b7aee | 4329 | || true_regnum (operands[5]) == true_regnum (operands[0])) |
e04108c7 CZ |
4330 | && (peep2_reg_dead_p (2, operands[0]) |
4331 | || (true_regnum (operands[3]) == true_regnum (operands[0]))) | |
4332 | && !(optimize_size && satisfies_constraint_I (operands[4])) | |
4333 | && !(optimize_size && satisfies_constraint_I (operands[5]))" | |
526b7aee SV |
4334 | ;; the preparation statements take care to put proper operand in operands[4] |
4335 | ;; operands[4] will always contain the correct operand. This is added to satisfy commutativity | |
4336 | [(set (match_dup 3) | |
4337 | (plus:SI (mult:SI (match_dup 1) | |
4338 | (match_dup 2)) | |
4339 | (match_dup 4)))] | |
4340 | "if (true_regnum (operands[4]) == true_regnum (operands[0])) | |
4341 | operands[4] = operands[5]; | |
4342 | operands[2] = GEN_INT (1 << INTVAL (operands[2]));" | |
4343 | ) | |
4344 | ||
4345 | ;; ------------------------------------------------------------- | |
4346 | ;; Pattern 1 : r0 = r1 << {i} | |
4347 | ;; r3 = r4 - r0 | |
4348 | ;; || | |
4349 | ;; \/ | |
4350 | ;; sub{i} r3,r4,r1 | |
4351 | ;; ------------------------------------------------------------- | |
4352 | ;; ??? This should be covered by combine, alas, at times combine gets | |
4353 | ;; too clever for it's own good: when the shifted input is known to be | |
4354 | ;; either 0 or 1, the operation will be made into an if-then-else, and | |
4355 | ;; thus fail to match the sub_n pattern. Example: __ieee754_yn, line 239 in | |
4356 | ;; newlib/libm/math/e_jn.c . | |
4357 | ||
4358 | (define_peephole2 | |
4359 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
4360 | (ashift:SI (match_operand:SI 1 "register_operand" "") | |
4361 | (match_operand:SI 2 "const_int_operand" ""))) | |
4362 | (set (match_operand:SI 3 "dest_reg_operand" "") | |
4363 | (minus:SI (match_operand:SI 4 "nonmemory_operand" "") | |
4364 | (match_dup 0)))] | |
4365 | "(INTVAL (operands[2]) == 1 | |
4366 | || INTVAL (operands[2]) == 2 | |
4367 | || INTVAL (operands[2]) == 3) | |
4368 | && (peep2_reg_dead_p (2, operands[0]) | |
4369 | || (true_regnum (operands[3]) == true_regnum (operands[0])))" | |
4370 | [(set (match_dup 3) | |
4371 | (minus:SI (match_dup 4) | |
4372 | (mult:SI (match_dup 1) | |
4373 | (match_dup 2))))] | |
4374 | "operands[2] = GEN_INT (1 << INTVAL (operands[2]));" | |
4375 | ) | |
4376 | ||
4377 | ||
4378 | ||
4379 | ; When using the high single bit, the result of a multiply is either | |
4380 | ; the original number or zero. But MPY costs 4 cycles, which we | |
4381 | ; can replace with the 2 cycles for the pair of TST_S and ADD.NE. | |
4382 | (define_peephole2 | |
4383 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
4384 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "") | |
4385 | (const_int 31))) | |
4386 | (set (match_operand:SI 4 "register_operand" "") | |
4387 | (mult:SI (match_operand:SI 2 "register_operand") | |
4388 | (match_operand:SI 3 "nonmemory_operand" "")))] | |
f50bb868 | 4389 | "TARGET_ARC700_MPY |
526b7aee SV |
4390 | && (rtx_equal_p (operands[0], operands[2]) |
4391 | || rtx_equal_p (operands[0], operands[3])) | |
4392 | && peep2_regno_dead_p (0, CC_REG) | |
4393 | && (rtx_equal_p (operands[0], operands[4]) | |
4394 | || (peep2_reg_dead_p (2, operands[0]) | |
4395 | && peep2_reg_dead_p (1, operands[4])))" | |
4396 | [(parallel [(set (reg:CC_Z CC_REG) | |
4397 | (compare:CC_Z (lshiftrt:SI (match_dup 1) (const_int 31)) | |
4398 | (const_int 0))) | |
4399 | (set (match_dup 4) (lshiftrt:SI (match_dup 1) (const_int 31)))]) | |
4400 | (cond_exec | |
4401 | (ne (reg:CC_Z CC_REG) (const_int 0)) | |
4402 | (set (match_dup 4) (match_dup 5)))] | |
4403 | { | |
4404 | if (!rtx_equal_p (operands[0], operands[2])) | |
4405 | operands[5] = operands[2]; | |
4406 | else if (!rtx_equal_p (operands[0], operands[3])) | |
4407 | operands[5] = operands[3]; | |
4408 | else | |
4409 | operands[5] = operands[4]; /* Actually a no-op... presumably rare. */ | |
4410 | }) | |
4411 | ||
4412 | (define_peephole2 | |
4413 | [(set (match_operand:SI 0 "dest_reg_operand" "") | |
4414 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "") | |
4415 | (const_int 31))) | |
4416 | (set (match_operand:SI 4 "register_operand" "") | |
4417 | (mult:SI (match_operand:SI 2 "register_operand") | |
4418 | (match_operand:SI 3 "nonmemory_operand" "")))] | |
f50bb868 | 4419 | "TARGET_ARC700_MPY |
526b7aee SV |
4420 | && (rtx_equal_p (operands[0], operands[2]) |
4421 | || rtx_equal_p (operands[0], operands[3])) | |
4422 | && peep2_regno_dead_p (2, CC_REG)" | |
4423 | [(parallel [(set (reg:CC_Z CC_REG) | |
4424 | (compare:CC_Z (lshiftrt:SI (match_dup 1) (const_int 31)) | |
4425 | (const_int 0))) | |
4426 | (set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))]) | |
4427 | (set (match_dup 4) (match_dup 5)) | |
4428 | (cond_exec | |
4429 | (eq (reg:CC_Z CC_REG) (const_int 0)) | |
4430 | (set (match_dup 4) (const_int 0)))] | |
4431 | "operands[5] = operands[rtx_equal_p (operands[0], operands[2]) ? 3 : 2];") | |
4432 | ||
4433 | ;; Instructions generated through builtins | |
4434 | ||
4435 | (define_insn "clrsbsi2" | |
4436 | [(set (match_operand:SI 0 "dest_reg_operand" "=w,w") | |
4437 | (clrsb:SI (match_operand:SI 1 "general_operand" "cL,Cal")))] | |
4438 | "TARGET_NORM" | |
4439 | "@ | |
4440 | norm \t%0, %1 | |
6b55f8c9 | 4441 | norm \t%0, %1" |
526b7aee SV |
4442 | [(set_attr "length" "4,8") |
4443 | (set_attr "type" "two_cycle_core,two_cycle_core")]) | |
4444 | ||
4445 | (define_insn "norm_f" | |
4446 | [(set (match_operand:SI 0 "dest_reg_operand" "=w,w") | |
4447 | (clrsb:SI (match_operand:SI 1 "general_operand" "cL,Cal"))) | |
4448 | (set (reg:CC_ZN CC_REG) | |
4449 | (compare:CC_ZN (match_dup 1) (const_int 0)))] | |
4450 | "TARGET_NORM" | |
4451 | "@ | |
4452 | norm.f\t%0, %1 | |
6b55f8c9 | 4453 | norm.f\t%0, %1" |
526b7aee SV |
4454 | [(set_attr "length" "4,8") |
4455 | (set_attr "type" "two_cycle_core,two_cycle_core")]) | |
4456 | ||
4457 | (define_insn_and_split "clrsbhi2" | |
4458 | [(set (match_operand:HI 0 "dest_reg_operand" "=w,w") | |
4459 | (clrsb:HI (match_operand:HI 1 "general_operand" "cL,Cal")))] | |
4460 | "TARGET_NORM" | |
4461 | "#" | |
4462 | "reload_completed" | |
4463 | [(set (match_dup 0) (zero_extend:SI (clrsb:HI (match_dup 1))))] | |
4464 | "operands[0] = simplify_gen_subreg (SImode, operands[0], HImode, 0);") | |
4465 | ||
4466 | (define_insn "normw" | |
4467 | [(set (match_operand:SI 0 "dest_reg_operand" "=w,w") | |
4468 | (zero_extend:SI | |
4469 | (clrsb:HI (match_operand:HI 1 "general_operand" "cL,Cal"))))] | |
4470 | "TARGET_NORM" | |
4471 | "@ | |
f50bb868 | 4472 | norm%_ \t%0, %1 |
6b55f8c9 | 4473 | norm%_ \t%0, %1" |
526b7aee SV |
4474 | [(set_attr "length" "4,8") |
4475 | (set_attr "type" "two_cycle_core,two_cycle_core")]) | |
4476 | ||
4477 | (define_expand "clzsi2" | |
ac66951a CZ |
4478 | [(parallel |
4479 | [(set (match_operand:SI 0 "register_operand" "") | |
4480 | (clz:SI (match_operand:SI 1 "register_operand" ""))) | |
4481 | (clobber (match_dup 2))])] | |
4482 | "TARGET_NORM" | |
4483 | "operands[2] = gen_rtx_REG (CC_ZNmode, CC_REG);") | |
4484 | ||
4485 | (define_insn_and_split "*arc_clzsi2" | |
4486 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4487 | (clz:SI (match_operand:SI 1 "register_operand" "r"))) | |
4488 | (clobber (reg:CC_ZN CC_REG))] | |
526b7aee | 4489 | "TARGET_NORM" |
ac66951a CZ |
4490 | "#" |
4491 | "reload_completed" | |
4492 | [(const_int 0)] | |
526b7aee SV |
4493 | { |
4494 | emit_insn (gen_norm_f (operands[0], operands[1])); | |
4495 | emit_insn | |
4496 | (gen_rtx_COND_EXEC | |
4497 | (VOIDmode, | |
4498 | gen_rtx_LT (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx), | |
f7df4a84 | 4499 | gen_rtx_SET (operands[0], const0_rtx))); |
526b7aee SV |
4500 | emit_insn |
4501 | (gen_rtx_COND_EXEC | |
4502 | (VOIDmode, | |
4503 | gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx), | |
f7df4a84 | 4504 | gen_rtx_SET (operands[0], plus_constant (SImode, operands[0], 1)))); |
526b7aee | 4505 | DONE; |
1370fccf CZ |
4506 | } |
4507 | [(set_attr "type" "unary") | |
4508 | (set_attr "length" "12")]) | |
526b7aee SV |
4509 | |
4510 | (define_expand "ctzsi2" | |
ac66951a CZ |
4511 | [(match_operand:SI 0 "register_operand" "") |
4512 | (match_operand:SI 1 "register_operand" "")] | |
526b7aee | 4513 | "TARGET_NORM" |
ac66951a CZ |
4514 | " |
4515 | emit_insn (gen_arc_ctzsi2 (operands[0], operands[1])); | |
4516 | DONE; | |
4517 | ") | |
4518 | ||
4519 | (define_insn_and_split "arc_ctzsi2" | |
4520 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4521 | (ctz:SI (match_operand:SI 1 "register_operand" "r"))) | |
4522 | (clobber (reg:CC_ZN CC_REG)) | |
4523 | (clobber (match_scratch:SI 2 "=&r"))] | |
4524 | "TARGET_NORM" | |
4525 | "#" | |
4526 | "reload_completed" | |
4527 | [(const_int 0)] | |
526b7aee SV |
4528 | { |
4529 | rtx temp = operands[0]; | |
4530 | ||
4531 | if (reg_overlap_mentioned_p (temp, operands[1]) | |
4532 | || (REGNO (temp) < FIRST_PSEUDO_REGISTER | |
4533 | && !TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], | |
4534 | REGNO (temp)))) | |
ac66951a | 4535 | temp = operands[2]; |
526b7aee SV |
4536 | emit_insn (gen_addsi3 (temp, operands[1], constm1_rtx)); |
4537 | emit_insn (gen_bic_f_zn (temp, temp, operands[1])); | |
ac66951a | 4538 | emit_insn (gen_clrsbsi2 (operands[0], temp)); |
526b7aee SV |
4539 | emit_insn |
4540 | (gen_rtx_COND_EXEC | |
4541 | (VOIDmode, | |
4542 | gen_rtx_LT (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx), | |
f7df4a84 | 4543 | gen_rtx_SET (operands[0], GEN_INT (32)))); |
526b7aee SV |
4544 | emit_insn |
4545 | (gen_rtx_COND_EXEC | |
4546 | (VOIDmode, | |
4547 | gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx), | |
ac66951a CZ |
4548 | gen_rtx_SET (operands[0], gen_rtx_MINUS (SImode, GEN_INT (31), |
4549 | operands[0])))); | |
526b7aee | 4550 | DONE; |
1370fccf CZ |
4551 | } |
4552 | [(set_attr "type" "unary") | |
4553 | (set_attr "length" "20")]) | |
526b7aee SV |
4554 | |
4555 | (define_insn "swap" | |
4556 | [(set (match_operand:SI 0 "dest_reg_operand" "=w,w,w") | |
4557 | (unspec:SI [(match_operand:SI 1 "general_operand" "L,Cal,c")] | |
c69899f0 | 4558 | UNSPEC_ARC_SWAP))] |
526b7aee SV |
4559 | "TARGET_SWAP" |
4560 | "@ | |
4561 | swap \t%0, %1 | |
6b55f8c9 | 4562 | swap \t%0, %1 |
526b7aee SV |
4563 | swap \t%0, %1" |
4564 | [(set_attr "length" "4,8,4") | |
4565 | (set_attr "type" "two_cycle_core,two_cycle_core,two_cycle_core")]) | |
4566 | ||
526b7aee SV |
4567 | (define_insn "divaw" |
4568 | [(set (match_operand:SI 0 "dest_reg_operand" "=&w,&w,&w") | |
4569 | (unspec:SI [(div:SI (match_operand:SI 1 "general_operand" "r,Cal,r") | |
4570 | (match_operand:SI 2 "general_operand" "r,r,Cal"))] | |
c69899f0 | 4571 | UNSPEC_ARC_DIVAW))] |
526b7aee SV |
4572 | "TARGET_ARC700 || TARGET_EA_SET" |
4573 | "@ | |
4574 | divaw \t%0, %1, %2 | |
6b55f8c9 CZ |
4575 | divaw \t%0, %1, %2 |
4576 | divaw \t%0, %1, %2" | |
526b7aee SV |
4577 | [(set_attr "length" "4,8,8") |
4578 | (set_attr "type" "divaw,divaw,divaw")]) | |
4579 | ||
4580 | (define_insn "flag" | |
4581 | [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "rL,I,Cal")] | |
c69899f0 | 4582 | VUNSPEC_ARC_FLAG)] |
526b7aee SV |
4583 | "" |
4584 | "@ | |
4585 | flag%? %0 | |
4586 | flag %0 | |
6b55f8c9 | 4587 | flag%? %0" |
526b7aee SV |
4588 | [(set_attr "length" "4,4,8") |
4589 | (set_attr "type" "misc,misc,misc") | |
4590 | (set_attr "predicable" "yes,no,yes") | |
4591 | (set_attr "cond" "clob,clob,clob")]) | |
4592 | ||
4593 | (define_insn "brk" | |
4594 | [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")] | |
c69899f0 | 4595 | VUNSPEC_ARC_BRK)] |
526b7aee SV |
4596 | "" |
4597 | "brk" | |
4598 | [(set_attr "length" "4") | |
4599 | (set_attr "type" "misc")]) | |
4600 | ||
4601 | (define_insn "rtie" | |
ce9dbf20 CZ |
4602 | [(return) |
4603 | (unspec_volatile [(const_int 0)] VUNSPEC_ARC_RTIE)] | |
4604 | "!TARGET_ARC600_FAMILY" | |
526b7aee SV |
4605 | "rtie" |
4606 | [(set_attr "length" "4") | |
ce9dbf20 CZ |
4607 | (set_attr "type" "rtie") |
4608 | (set_attr "cond" "clob")]) | |
526b7aee SV |
4609 | |
4610 | (define_insn "sync" | |
4611 | [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")] | |
c69899f0 | 4612 | VUNSPEC_ARC_SYNC)] |
526b7aee SV |
4613 | "" |
4614 | "sync" | |
4615 | [(set_attr "length" "4") | |
4616 | (set_attr "type" "misc")]) | |
4617 | ||
4618 | (define_insn "swi" | |
4619 | [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")] | |
c69899f0 | 4620 | VUNSPEC_ARC_SWI)] |
526b7aee SV |
4621 | "" |
4622 | "* | |
4623 | { | |
4624 | if(TARGET_ARC700) | |
4625 | return \"trap0\"; | |
4626 | else | |
4627 | return \"swi\"; | |
4628 | }" | |
4629 | [(set_attr "length" "4") | |
4630 | (set_attr "type" "misc")]) | |
4631 | ||
4632 | ||
4633 | (define_insn "sleep" | |
31d2e01a | 4634 | [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "Lr")] |
c69899f0 | 4635 | VUNSPEC_ARC_SLEEP)] |
31d2e01a | 4636 | "" |
526b7aee SV |
4637 | "sleep %0" |
4638 | [(set_attr "length" "4") | |
4639 | (set_attr "type" "misc")]) | |
4640 | ||
4641 | (define_insn "core_read" | |
4642 | [(set (match_operand:SI 0 "dest_reg_operand" "=r,r") | |
4643 | (unspec_volatile:SI [(match_operand:SI 1 "general_operand" "Hn,!r")] | |
c69899f0 | 4644 | VUNSPEC_ARC_CORE_READ))] |
526b7aee SV |
4645 | "" |
4646 | "* | |
4647 | if (check_if_valid_regno_const (operands, 1)) | |
4648 | return \"mov \t%0, r%1\"; | |
4649 | return \"mov \t%0, r%1\"; | |
4650 | " | |
4651 | [(set_attr "length" "4") | |
4652 | (set_attr "type" "unary")]) | |
4653 | ||
4654 | (define_insn "core_write" | |
4655 | [(unspec_volatile [(match_operand:SI 0 "general_operand" "r,r") | |
4656 | (match_operand:SI 1 "general_operand" "Hn,!r")] | |
c69899f0 | 4657 | VUNSPEC_ARC_CORE_WRITE)] |
526b7aee SV |
4658 | "" |
4659 | "* | |
4660 | if (check_if_valid_regno_const (operands, 1)) | |
4661 | return \"mov \tr%1, %0\"; | |
4662 | return \"mov \tr%1, %0\"; | |
4663 | " | |
4664 | [(set_attr "length" "4") | |
4665 | (set_attr "type" "unary")]) | |
4666 | ||
4667 | (define_insn "lr" | |
4668 | [(set (match_operand:SI 0 "dest_reg_operand" "=r,r,r,r") | |
4669 | (unspec_volatile:SI [(match_operand:SI 1 "general_operand" "I,HCal,r,D")] | |
c69899f0 | 4670 | VUNSPEC_ARC_LR))] |
526b7aee SV |
4671 | "" |
4672 | "lr\t%0, [%1]" | |
4673 | [(set_attr "length" "4,8,4,8") | |
4674 | (set_attr "type" "lr,lr,lr,lr")]) | |
4675 | ||
4676 | (define_insn "sr" | |
4677 | [(unspec_volatile [(match_operand:SI 0 "general_operand" "Cal,r,r,r") | |
4678 | (match_operand:SI 1 "general_operand" "Ir,I,HCal,r")] | |
c69899f0 | 4679 | VUNSPEC_ARC_SR)] |
526b7aee | 4680 | "" |
6b55f8c9 | 4681 | "sr\t%0, [%1]" |
526b7aee SV |
4682 | [(set_attr "length" "8,4,8,4") |
4683 | (set_attr "type" "sr,sr,sr,sr")]) | |
4684 | ||
4685 | (define_insn "trap_s" | |
4686 | [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "L,Cal")] | |
c69899f0 CZ |
4687 | VUNSPEC_ARC_TRAP_S)] |
4688 | "!TARGET_ARC600_FAMILY" | |
526b7aee SV |
4689 | { |
4690 | if (which_alternative == 0) | |
4691 | { | |
4692 | arc_toggle_unalign (); | |
4693 | return \"trap_s %0\"; | |
4694 | } | |
4695 | ||
4696 | /* Keep this message in sync with the one in arc.c:arc_expand_builtin, | |
4697 | because *.md files do not get scanned by exgettext. */ | |
40fecdd6 JM |
4698 | fatal_error (input_location, |
4699 | \"operand to trap_s should be an unsigned 6-bit value\"); | |
526b7aee SV |
4700 | } |
4701 | [(set_attr "length" "2") | |
4702 | (set_attr "type" "misc")]) | |
4703 | ||
4704 | (define_insn "unimp_s" | |
4705 | [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")] | |
c69899f0 CZ |
4706 | VUNSPEC_ARC_UNIMP_S)] |
4707 | "!TARGET_ARC600_FAMILY" | |
526b7aee SV |
4708 | "unimp_s" |
4709 | [(set_attr "length" "4") | |
4710 | (set_attr "type" "misc")]) | |
4711 | ||
4712 | ;; End of instructions generated through builtins | |
4713 | ||
4714 | ; Since the demise of REG_N_SETS as reliable data readily available to the | |
4715 | ; target, it is no longer possible to find out | |
4716 | ; in the prologue / epilogue expanders how many times blink is set. | |
4717 | ; Using df_regs_ever_live_p to decide if blink needs saving means that | |
4718 | ; any explicit use of blink will cause it to be saved; hence we cannot | |
4719 | ; represent the blink use in return / sibcall instructions themselves, and | |
4720 | ; instead have to show it in EPILOGUE_USES and must explicitly | |
4721 | ; forbid instructions that change blink in the return / sibcall delay slot. | |
4722 | (define_expand "sibcall" | |
4723 | [(parallel [(call (match_operand 0 "memory_operand" "") | |
4724 | (match_operand 1 "general_operand" "")) | |
4725 | (simple_return) | |
4726 | (use (match_operand 2 "" ""))])] | |
4727 | "" | |
4728 | " | |
4729 | { | |
4730 | rtx callee = XEXP (operands[0], 0); | |
4731 | ||
4732 | if (operands[2] == NULL_RTX) | |
4733 | operands[2] = const0_rtx; | |
526b7aee SV |
4734 | if (GET_CODE (callee) != REG |
4735 | && (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee))) | |
4736 | XEXP (operands[0], 0) = force_reg (Pmode, callee); | |
4737 | }" | |
4738 | ) | |
4739 | ||
4740 | (define_expand "sibcall_value" | |
4741 | [(parallel [(set (match_operand 0 "dest_reg_operand" "") | |
4742 | (call (match_operand 1 "memory_operand" "") | |
4743 | (match_operand 2 "general_operand" ""))) | |
4744 | (simple_return) | |
4745 | (use (match_operand 3 "" ""))])] | |
4746 | "" | |
4747 | " | |
4748 | { | |
4749 | rtx callee = XEXP (operands[1], 0); | |
4750 | ||
4751 | if (operands[3] == NULL_RTX) | |
4752 | operands[3] = const0_rtx; | |
526b7aee SV |
4753 | if (GET_CODE (callee) != REG && arc_is_longcall_p (callee)) |
4754 | XEXP (operands[1], 0) = force_reg (Pmode, callee); | |
4755 | }" | |
4756 | ) | |
4757 | ||
4758 | (define_insn "*sibcall_insn" | |
4759 | [(call (mem:SI (match_operand:SI 0 "call_address_operand" | |
fa27cbfe | 4760 | "Cbp,Cbr,!Rcd,Rsc,Cal")) |
526b7aee SV |
4761 | (match_operand 1 "" "")) |
4762 | (simple_return) | |
4763 | (use (match_operand 2 "" ""))] | |
4764 | "" | |
4765 | "@ | |
fa27cbfe CZ |
4766 | b%!%*\\t%P0 |
4767 | b%!%*\\t%P0 | |
4768 | j%!%*\\t[%0] | |
4769 | j%!%*\\t[%0] | |
4770 | j%!\\t%P0" | |
526b7aee SV |
4771 | [(set_attr "type" "call,call,call,call,call_no_delay_slot") |
4772 | (set_attr "predicable" "yes,no,no,yes,yes") | |
4773 | (set_attr "iscompact" "false,false,maybe,false,false") | |
4774 | (set_attr "is_SIBCALL" "yes")] | |
4775 | ) | |
4776 | ||
4777 | (define_insn "*sibcall_value_insn" | |
4778 | [(set (match_operand 0 "dest_reg_operand" "") | |
4779 | (call (mem:SI (match_operand:SI 1 "call_address_operand" | |
fa27cbfe | 4780 | "Cbp,Cbr,!Rcd,Rsc,Cal")) |
526b7aee SV |
4781 | (match_operand 2 "" ""))) |
4782 | (simple_return) | |
4783 | (use (match_operand 3 "" ""))] | |
4784 | "" | |
4785 | "@ | |
fa27cbfe CZ |
4786 | b%!%*\\t%P1 |
4787 | b%!%*\\t%P1 | |
4788 | j%!%*\\t[%1] | |
4789 | j%!%*\\t[%1] | |
4790 | j%!\\t%P1" | |
526b7aee SV |
4791 | [(set_attr "type" "call,call,call,call,call_no_delay_slot") |
4792 | (set_attr "predicable" "yes,no,no,yes,yes") | |
4793 | (set_attr "iscompact" "false,false,maybe,false,false") | |
4794 | (set_attr "is_SIBCALL" "yes")] | |
4795 | ) | |
4796 | ||
526b7aee SV |
4797 | (define_expand "prologue" |
4798 | [(pc)] | |
4799 | "" | |
4800 | { | |
4801 | arc_expand_prologue (); | |
4802 | DONE; | |
4803 | }) | |
4804 | ||
4805 | (define_expand "epilogue" | |
4806 | [(pc)] | |
4807 | "" | |
4808 | { | |
4809 | arc_expand_epilogue (0); | |
4810 | DONE; | |
4811 | }) | |
4812 | ||
4813 | (define_expand "sibcall_epilogue" | |
4814 | [(pc)] | |
4815 | "" | |
4816 | { | |
4817 | arc_expand_epilogue (1); | |
4818 | DONE; | |
4819 | }) | |
4820 | ||
4821 | ; Since the demise of REG_N_SETS, it is no longer possible to find out | |
4822 | ; in the prologue / epilogue expanders how many times blink is set. | |
4823 | ; Using df_regs_ever_live_p to decide if blink needs saving means that | |
4824 | ; any explicit use of blink will cause it to be saved; hence we cannot | |
4825 | ; represent the blink use in return / sibcall instructions themselves, and | |
4826 | ; instead have to show it in EPILOGUE_USES and must explicitly | |
4827 | ; forbid instructions that change blink in the return / sibcall delay slot. | |
4828 | (define_insn "simple_return" | |
4829 | [(simple_return)] | |
ce9dbf20 CZ |
4830 | "" |
4831 | "j%!%*\\t[blink]" | |
4832 | [(set_attr "type" "return") | |
4833 | (set_attr "cond" "canuse") | |
4834 | (set_attr "iscompact" "maybe") | |
4835 | (set_attr "length" "*")]) | |
526b7aee | 4836 | |
ce9dbf20 CZ |
4837 | (define_insn "arc600_rtie" |
4838 | [(return) | |
4839 | (unspec_volatile [(match_operand 0 "pmode_register_operand" "")] | |
4840 | VUNSPEC_ARC_ARC600_RTIE)] | |
4841 | "TARGET_ARC600_FAMILY" | |
4842 | "j.f\\t[%0]" | |
4843 | [(set_attr "length" "4") | |
4844 | (set_attr "type" "rtie") | |
4845 | (set_attr "cond" "clob")]) | |
526b7aee SV |
4846 | |
4847 | (define_insn "p_return_i" | |
4848 | [(set (pc) | |
4849 | (if_then_else (match_operator 0 "proper_comparison_operator" | |
4850 | [(reg CC_REG) (const_int 0)]) | |
4851 | (simple_return) (pc)))] | |
ce9dbf20 | 4852 | "reload_completed" |
526b7aee | 4853 | { |
ce9dbf20 | 4854 | output_asm_insn (\"j%d0%!%#\\t[blink]\", operands); |
526b7aee | 4855 | /* record the condition in case there is a delay insn. */ |
ce9dbf20 | 4856 | arc_ccfsm_record_condition (operands[0], false, insn, 0); |
526b7aee SV |
4857 | return \"\"; |
4858 | } | |
4859 | [(set_attr "type" "return") | |
4860 | (set_attr "cond" "use") | |
ce9dbf20 | 4861 | (set_attr "iscompact" "maybe" ) |
526b7aee | 4862 | (set (attr "length") |
ce9dbf20 | 4863 | (cond [(not (match_operand 0 "equality_comparison_operator" "")) |
526b7aee SV |
4864 | (const_int 4) |
4865 | (eq_attr "delay_slot_filled" "yes") | |
4866 | (const_int 4)] | |
4867 | (const_int 2)))]) | |
4868 | ||
ce9dbf20 CZ |
4869 | ;; Return nonzero if this function is known to have a null epilogue. |
4870 | ;; This allows the optimizer to omit jumps to jumps if no stack | |
4871 | ;; was created. | |
526b7aee SV |
4872 | (define_expand "return" |
4873 | [(return)] | |
ce9dbf20 CZ |
4874 | "arc_can_use_return_insn ()" |
4875 | "") | |
526b7aee SV |
4876 | |
4877 | ;; Comment in final.c (insn_current_reference_address) says | |
4878 | ;; forward branch addresses are calculated from the next insn after branch | |
4879 | ;; and for backward branches, it is calculated from the branch insn start. | |
9c582551 | 4880 | ;; The shortening logic here is tuned to accomodate this behavior |
526b7aee SV |
4881 | ;; ??? This should be grokked by the ccfsm machinery. |
4882 | (define_insn "cbranchsi4_scratch" | |
4883 | [(set (pc) | |
4884 | (if_then_else (match_operator 0 "proper_comparison_operator" | |
4885 | [(match_operand:SI 1 "register_operand" "c,c, c") | |
4886 | (match_operand:SI 2 "nonmemory_operand" "L,c,?Cal")]) | |
4887 | (label_ref (match_operand 3 "" "")) | |
4888 | (pc))) | |
4889 | (clobber (match_operand 4 "cc_register" ""))] | |
4890 | "(reload_completed | |
4891 | || (TARGET_EARLY_CBRANCHSI | |
4892 | && brcc_nolimm_operator (operands[0], VOIDmode))) | |
339ba33b | 4893 | && !CROSSING_JUMP_P (insn)" |
526b7aee SV |
4894 | "* |
4895 | switch (get_attr_length (insn)) | |
4896 | { | |
4897 | case 2: return \"br%d0%? %1, %2, %^%l3%&\"; | |
4898 | case 4: return \"br%d0%* %1, %B2, %^%l3\"; | |
4899 | case 8: if (!brcc_nolimm_operator (operands[0], VOIDmode)) | |
4900 | return \"br%d0%* %1, %B2, %^%l3\"; | |
3bbe0b82 | 4901 | /* FALLTHRU */ |
526b7aee | 4902 | case 6: case 10: |
0e03cebd | 4903 | case 12:return \"cmp%? %1, %B2\\n\\tb%d0%* %^%l3%& ;br%d0 out of range\"; |
526b7aee SV |
4904 | default: fprintf (stderr, \"unexpected length %d\\n\", get_attr_length (insn)); fflush (stderr); gcc_unreachable (); |
4905 | } | |
4906 | " | |
4907 | [(set_attr "cond" "clob, clob, clob") | |
4908 | (set (attr "type") | |
4909 | (if_then_else | |
4910 | (match_test "valid_brcc_with_delay_p (operands)") | |
4911 | (const_string "brcc") | |
4912 | (const_string "brcc_no_delay_slot"))) | |
4913 | ; For forward branches, we need to account not only for the distance to | |
4914 | ; the target, but also the difference between pcl and pc, the instruction | |
4915 | ; length, and any delay insn, if present. | |
4916 | (set | |
4917 | (attr "length") | |
4918 | (cond ; the outer cond does a test independent of branch shortening. | |
4919 | [(match_operand 0 "brcc_nolimm_operator" "") | |
4920 | (cond | |
4921 | [(and (match_operand:CC_Z 4 "cc_register") | |
4922 | (eq_attr "delay_slot_filled" "no") | |
4923 | (ge (minus (match_dup 3) (pc)) (const_int -128)) | |
4924 | (le (minus (match_dup 3) (pc)) | |
4925 | (minus (const_int 122) | |
4926 | (symbol_ref "get_attr_delay_slot_length (insn)")))) | |
4927 | (const_int 2) | |
4928 | (and (ge (minus (match_dup 3) (pc)) (const_int -256)) | |
4929 | (le (minus (match_dup 3) (pc)) | |
4930 | (minus (const_int 244) | |
4931 | (symbol_ref "get_attr_delay_slot_length (insn)")))) | |
4932 | (const_int 4) | |
0e03cebd CZ |
4933 | (and (match_operand:SI 1 "compact_register_operand" "") |
4934 | (match_operand:SI 2 "compact_hreg_operand" "")) | |
526b7aee SV |
4935 | (const_int 6)] |
4936 | (const_int 8))] | |
4937 | (cond [(and (ge (minus (match_dup 3) (pc)) (const_int -256)) | |
4938 | (le (minus (match_dup 3) (pc)) (const_int 244))) | |
4939 | (const_int 8) | |
0e03cebd CZ |
4940 | (and (match_operand:SI 1 "compact_register_operand" "") |
4941 | (match_operand:SI 2 "compact_hreg_operand" "")) | |
526b7aee SV |
4942 | (const_int 10)] |
4943 | (const_int 12)))) | |
4944 | (set (attr "iscompact") | |
4945 | (if_then_else (match_test "get_attr_length (insn) & 2") | |
4946 | (const_string "true") (const_string "false")))]) | |
4947 | ||
4948 | ; combiner pattern observed for unwind-dw2-fde.c:linear_search_fdes. | |
4949 | (define_insn "*bbit" | |
4950 | [(set (pc) | |
4951 | (if_then_else | |
4952 | (match_operator 3 "equality_comparison_operator" | |
4953 | [(zero_extract:SI (match_operand:SI 1 "register_operand" "Rcqq,c") | |
4954 | (const_int 1) | |
4955 | (match_operand:SI 2 "nonmemory_operand" "L,Lc")) | |
4956 | (const_int 0)]) | |
4957 | (label_ref (match_operand 0 "" "")) | |
4958 | (pc))) | |
4959 | (clobber (reg:CC_ZN CC_REG))] | |
339ba33b | 4960 | "!CROSSING_JUMP_P (insn)" |
526b7aee SV |
4961 | { |
4962 | switch (get_attr_length (insn)) | |
4963 | { | |
4964 | case 4: return (GET_CODE (operands[3]) == EQ | |
4965 | ? \"bbit0%* %1,%2,%0\" : \"bbit1%* %1,%2,%0\"); | |
4966 | case 6: | |
4967 | case 8: return \"btst%? %1,%2\n\tb%d3%* %0; bbit out of range\"; | |
4968 | default: gcc_unreachable (); | |
4969 | } | |
4970 | } | |
4971 | [(set_attr "type" "brcc") | |
4972 | (set_attr "cond" "clob") | |
4973 | (set (attr "length") | |
4974 | (cond [(and (ge (minus (match_dup 0) (pc)) (const_int -254)) | |
4975 | (le (minus (match_dup 0) (pc)) | |
4976 | (minus (const_int 248) | |
4977 | (symbol_ref "get_attr_delay_slot_length (insn)")))) | |
4978 | (const_int 4) | |
4979 | (eq (symbol_ref "which_alternative") (const_int 0)) | |
4980 | (const_int 6)] | |
4981 | (const_int 8))) | |
4982 | (set (attr "iscompact") | |
4983 | (if_then_else (match_test "get_attr_length (insn) == 6") | |
4984 | (const_string "true") (const_string "false")))]) | |
4985 | ||
4986 | ; ??? When testing a bit from a DImode register, combine creates a | |
4987 | ; zero_extract in DImode. This goes via an AND with a DImode constant, | |
4988 | ; so can only be observed on 64 bit hosts. | |
4989 | (define_insn_and_split "*bbit_di" | |
4990 | [(set (pc) | |
4991 | (if_then_else | |
4992 | (match_operator 3 "equality_comparison_operator" | |
4993 | [(zero_extract:DI (match_operand:SI 1 "register_operand" "Rcqq,c") | |
4994 | (const_int 1) | |
4995 | (match_operand 2 "immediate_operand" "L,L")) | |
4996 | (const_int 0)]) | |
4997 | (label_ref (match_operand 0 "" "")) | |
4998 | (pc))) | |
4999 | (clobber (reg:CC_ZN CC_REG))] | |
339ba33b | 5000 | "!CROSSING_JUMP_P (insn)" |
526b7aee SV |
5001 | "#" |
5002 | "" | |
5003 | [(parallel | |
5004 | [(set (pc) (if_then_else (match_dup 3) (label_ref (match_dup 0)) (pc))) | |
5005 | (clobber (reg:CC_ZN CC_REG))])] | |
5006 | { | |
5007 | rtx xtr; | |
5008 | ||
5009 | xtr = gen_rtx_ZERO_EXTRACT (SImode, operands[1], const1_rtx, operands[2]); | |
5010 | operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]), | |
5011 | xtr, const0_rtx); | |
5012 | }) | |
5013 | ||
a2de90a4 CZ |
5014 | ;; ------------------------------------------------------------------- |
5015 | ;; Hardware loop | |
5016 | ;; ------------------------------------------------------------------- | |
5017 | ||
526b7aee | 5018 | ; operand 0 is the loop count pseudo register |
a2de90a4 CZ |
5019 | ; operand 1 is the label to jump to at the top of the loop |
5020 | (define_expand "doloop_end" | |
5021 | [(parallel [(set (pc) | |
5022 | (if_then_else | |
5023 | (ne (match_operand 0 "" "") | |
5024 | (const_int 1)) | |
5025 | (label_ref (match_operand 1 "" "")) | |
5026 | (pc))) | |
5027 | (set (match_dup 0) (plus (match_dup 0) (const_int -1))) | |
5028 | (unspec [(const_int 0)] UNSPEC_ARC_LP) | |
5029 | (clobber (match_dup 2))])] | |
526b7aee SV |
5030 | "" |
5031 | { | |
a2de90a4 CZ |
5032 | if (GET_MODE (operands[0]) != SImode) |
5033 | FAIL; | |
5034 | operands[2] = gen_rtx_SCRATCH (SImode); | |
526b7aee SV |
5035 | }) |
5036 | ||
a2de90a4 | 5037 | (define_insn "arc_lp" |
73dac59b | 5038 | [(unspec:SI [(reg:SI LP_COUNT)] |
a2de90a4 | 5039 | UNSPEC_ARC_LP) |
73dac59b CZ |
5040 | (use (label_ref (match_operand 0 "" ""))) |
5041 | (use (label_ref (match_operand 1 "" "")))] | |
526b7aee | 5042 | "" |
73dac59b | 5043 | "lp\\t@%l1\\t; lp_count:@%l0->@%l1" |
526b7aee | 5044 | [(set_attr "type" "loop_setup") |
a2de90a4 | 5045 | (set_attr "length" "4")]) |
526b7aee | 5046 | |
a2de90a4 CZ |
5047 | ;; if by any chance the lp_count is not used, then use an 'r' |
5048 | ;; register, instead of going to memory. | |
5049 | (define_insn "loop_end" | |
526b7aee | 5050 | [(set (pc) |
73dac59b | 5051 | (if_then_else (ne (match_operand:SI 2 "nonimmediate_operand" "0,m") |
a2de90a4 | 5052 | (const_int 1)) |
526b7aee SV |
5053 | (label_ref (match_operand 1 "" "")) |
5054 | (pc))) | |
73dac59b | 5055 | (set (match_operand:SI 0 "nonimmediate_operand" "=r,m") |
a2de90a4 CZ |
5056 | (plus (match_dup 2) (const_int -1))) |
5057 | (unspec [(const_int 0)] UNSPEC_ARC_LP) | |
5058 | (clobber (match_scratch:SI 3 "=X,&r"))] | |
526b7aee | 5059 | "" |
73dac59b | 5060 | "; ZOL_END, begins @%l1" |
a2de90a4 CZ |
5061 | [(set_attr "length" "0") |
5062 | (set_attr "predicable" "no") | |
5063 | (set_attr "type" "loop_end")]) | |
526b7aee | 5064 | |
a2de90a4 CZ |
5065 | ;; split pattern for the very slim chance when the loop register is |
5066 | ;; memory. | |
5067 | (define_split | |
5068 | [(set (pc) | |
5069 | (if_then_else (ne (match_operand:SI 0 "memory_operand") | |
5070 | (const_int 1)) | |
5071 | (label_ref (match_operand 1 "")) | |
5072 | (pc))) | |
5073 | (set (match_dup 0) (plus (match_dup 0) (const_int -1))) | |
5074 | (unspec [(const_int 0)] UNSPEC_ARC_LP) | |
5075 | (clobber (match_scratch:SI 2))] | |
5076 | "memory_operand (operands[0], SImode)" | |
5077 | [(set (match_dup 2) (match_dup 0)) | |
5078 | (set (match_dup 2) (plus:SI (match_dup 2) (const_int -1))) | |
5079 | (set (match_dup 0) (match_dup 2)) | |
5080 | (set (reg:CC CC_REG) (compare:CC (match_dup 2) (const_int 0))) | |
5081 | (set (pc) | |
5082 | (if_then_else (ne (reg:CC CC_REG) | |
5083 | (const_int 0)) | |
5084 | (label_ref (match_dup 1)) | |
5085 | (pc)))] | |
5086 | "") | |
526b7aee | 5087 | |
a2de90a4 CZ |
5088 | (define_insn "loop_fail" |
5089 | [(set (reg:SI LP_COUNT) | |
5090 | (plus:SI (reg:SI LP_COUNT) (const_int -1))) | |
5091 | (set (reg:CC_ZN CC_REG) | |
5092 | (compare:CC_ZN (plus:SI (reg:SI LP_COUNT) (const_int -1)) | |
5093 | (const_int 0)))] | |
5094 | "" | |
5095 | "sub.f%?\\tlp_count,lp_count,1" | |
5096 | [(set_attr "iscompact" "false") | |
5097 | (set_attr "type" "compare") | |
5098 | (set_attr "cond" "set_zn") | |
5099 | (set_attr "length" "4") | |
5100 | (set_attr "predicable" "yes")]) | |
5101 | ||
5102 | (define_insn_and_split "dbnz" | |
5103 | [(set (pc) | |
5104 | (if_then_else | |
73dac59b | 5105 | (ne (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+rl,m") |
a2de90a4 CZ |
5106 | (const_int -1)) |
5107 | (const_int 0)) | |
5108 | (label_ref (match_operand 1 "" "")) | |
5109 | (pc))) | |
5110 | (set (match_dup 0) | |
5111 | (plus:SI (match_dup 0) | |
5112 | (const_int -1))) | |
5113 | (clobber (match_scratch:SI 2 "=X,r"))] | |
62f26645 | 5114 | "TARGET_DBNZ" |
a2de90a4 CZ |
5115 | "@ |
5116 | dbnz%#\\t%0,%l1 | |
5117 | #" | |
62f26645 | 5118 | "TARGET_DBNZ && reload_completed && memory_operand (operands[0], SImode)" |
a2de90a4 CZ |
5119 | [(set (match_dup 2) (match_dup 0)) |
5120 | (set (match_dup 2) (plus:SI (match_dup 2) (const_int -1))) | |
5121 | (set (reg:CC CC_REG) (compare:CC (match_dup 2) (const_int 0))) | |
5122 | (set (match_dup 0) (match_dup 2)) | |
5123 | (set (pc) (if_then_else (ge (reg:CC CC_REG) | |
5124 | (const_int 0)) | |
5125 | (label_ref (match_dup 1)) | |
5126 | (pc)))] | |
5127 | "" | |
5128 | [(set_attr "iscompact" "false") | |
5129 | (set_attr "type" "loop_end") | |
5130 | (set_attr "length" "4,20")]) | |
526b7aee | 5131 | |
76715c32 | 5132 | (define_expand "cpymemsi" |
526b7aee SV |
5133 | [(match_operand:BLK 0 "" "") |
5134 | (match_operand:BLK 1 "" "") | |
5135 | (match_operand:SI 2 "nonmemory_operand" "") | |
5136 | (match_operand 3 "immediate_operand" "")] | |
5137 | "" | |
76715c32 | 5138 | "if (arc_expand_cpymem (operands)) DONE; else FAIL;") |
526b7aee SV |
5139 | |
5140 | ;; Close http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35803 if this works | |
5141 | ;; to the point that we can generate cmove instructions. | |
5142 | (define_expand "cbranch<mode>4" | |
5143 | [(set (reg:CC CC_REG) | |
5144 | (compare:CC (match_operand:SDF 1 "register_operand" "") | |
5145 | (match_operand:SDF 2 "register_operand" ""))) | |
5146 | (set (pc) | |
5147 | (if_then_else | |
8f3304d0 CZ |
5148 | (match_operator 0 "comparison_operator" [(reg CC_REG) |
5149 | (const_int 0)]) | |
5150 | (label_ref (match_operand 3 "" "")) | |
5151 | (pc)))] | |
526b7aee | 5152 | |
8f3304d0 | 5153 | "TARGET_FP_SP_BASE || TARGET_OPTFPE" |
526b7aee SV |
5154 | { |
5155 | gcc_assert (XEXP (operands[0], 0) == operands[1]); | |
5156 | gcc_assert (XEXP (operands[0], 1) == operands[2]); | |
5157 | operands[0] = gen_compare_reg (operands[0], VOIDmode); | |
5158 | emit_jump_insn (gen_branch_insn (operands[3], operands[0])); | |
5159 | DONE; | |
5160 | }) | |
5161 | ||
5162 | (define_expand "cmp_float" | |
5163 | [(parallel [(set (match_operand 0 "") (match_operand 1 "")) | |
5164 | (clobber (reg:SI RETURN_ADDR_REGNUM)) | |
5165 | (clobber (reg:SI R12_REG))])] | |
5166 | "" | |
5167 | "") | |
5168 | ||
5169 | (define_mode_iterator OPTFPE_CMP [CC_Z CC_FP_GT CC_FP_GE CC_FP_UNEQ CC_FP_ORD]) | |
5170 | (define_mode_attr cmp [(CC_Z "eq") (CC_FP_GT "gt") (CC_FP_GE "ge") | |
5171 | (CC_FP_UNEQ "uneq") (CC_FP_ORD "ord")]) | |
5172 | ||
5173 | (define_insn "*cmpsf_<cmp>" | |
5174 | [(set (reg:OPTFPE_CMP CC_REG) (compare:OPTFPE_CMP (reg:SF 0) (reg:SF 1))) | |
5175 | (clobber (reg:SI RETURN_ADDR_REGNUM)) | |
5176 | (clobber (reg:SI R12_REG))] | |
5177 | "TARGET_OPTFPE && (!TARGET_ARGONAUT_SET || !TARGET_SPFP) | |
5178 | && SFUNC_CHECK_PREDICABLE" | |
5179 | "*return arc_output_libcall (\"__<cmp>sf2\");" | |
5180 | [(set_attr "is_sfunc" "yes") | |
5181 | (set_attr "predicable" "yes")]) | |
5182 | ||
5183 | ;; N.B. for "*cmpdf_ord": | |
5184 | ;; double precision fpx sets bit 31 for NaNs. We need bit 51 set | |
5185 | ;; for the floating point emulation to recognize the NaN. | |
5186 | (define_insn "*cmpdf_<cmp>" | |
5187 | [(set (reg:OPTFPE_CMP CC_REG) (compare:OPTFPE_CMP (reg:DF 0) (reg:DF 2))) | |
5188 | (clobber (reg:SI RETURN_ADDR_REGNUM)) | |
5189 | (clobber (reg:SI R12_REG))] | |
5190 | "TARGET_OPTFPE && (!TARGET_ARGONAUT_SET || !TARGET_DPFP) | |
5191 | && SFUNC_CHECK_PREDICABLE" | |
5192 | "*return arc_output_libcall (\"__<cmp>df2\");" | |
5193 | [(set_attr "is_sfunc" "yes") | |
5194 | (set_attr "predicable" "yes")]) | |
5195 | ||
5196 | (define_insn "abssf2" | |
5197 | [(set (match_operand:SF 0 "dest_reg_operand" "=Rcq#q,Rcw,w") | |
5198 | (abs:SF (match_operand:SF 1 "register_operand" "0, 0,c")))] | |
5199 | "" | |
5200 | "bclr%? %0,%1,31%&" | |
5201 | [(set_attr "type" "unary") | |
5202 | (set_attr "iscompact" "maybe,false,false") | |
5203 | (set_attr "length" "2,4,4") | |
5204 | (set_attr "predicable" "no,yes,no")]) | |
5205 | ||
5206 | (define_insn "negsf2" | |
5207 | [(set (match_operand:SF 0 "dest_reg_operand" "=Rcw,w") | |
5208 | (neg:SF (match_operand:SF 1 "register_operand" "0,c")))] | |
5209 | "" | |
5210 | "bxor%? %0,%1,31" | |
5211 | [(set_attr "type" "unary") | |
5212 | (set_attr "predicable" "yes,no")]) | |
5213 | ||
5214 | ;; ??? Should this use arc_output_libcall and set is_sfunc? | |
5215 | (define_insn "*millicode_thunk_st" | |
5216 | [(match_parallel 0 "millicode_store_operation" | |
6b55f8c9 | 5217 | [(set (mem:SI (reg:SI SP_REG)) (reg:SI 13))])] |
526b7aee SV |
5218 | "" |
5219 | { | |
5220 | output_asm_insn ("bl%* __st_r13_to_%0", | |
5221 | &SET_SRC (XVECEXP (operands[0], 0, | |
5222 | XVECLEN (operands[0], 0) - 2))); | |
5223 | return ""; | |
5224 | } | |
5225 | [(set_attr "type" "call")]) | |
5226 | ||
5227 | (define_insn "*millicode_thunk_ld" | |
5228 | [(match_parallel 0 "millicode_load_clob_operation" | |
6b55f8c9 | 5229 | [(set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])] |
526b7aee SV |
5230 | "" |
5231 | { | |
5232 | output_asm_insn ("bl%* __ld_r13_to_%0", | |
5233 | &SET_DEST (XVECEXP (operands[0], 0, | |
5234 | XVECLEN (operands[0], 0) - 2))); | |
5235 | return ""; | |
5236 | } | |
5237 | [(set_attr "type" "call")]) | |
5238 | ||
5239 | ; the sibthunk restores blink, so we use the return rtx. | |
5240 | (define_insn "*millicode_sibthunk_ld" | |
5241 | [(match_parallel 0 "millicode_load_operation" | |
6b55f8c9 CZ |
5242 | [(return) |
5243 | (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (reg:SI 12))) | |
5244 | (set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])] | |
526b7aee SV |
5245 | "" |
5246 | { | |
5247 | output_asm_insn ("b%* __ld_r13_to_%0_ret", | |
5248 | &SET_DEST (XVECEXP (operands[0], 0, | |
5249 | XVECLEN (operands[0], 0) - 1))); | |
5250 | return ""; | |
5251 | } | |
5252 | [(set_attr "type" "call") | |
5253 | (set_attr "is_SIBCALL" "yes")]) | |
5254 | ||
28633bbd CZ |
5255 | ;; For thread pointer builtins |
5256 | (define_expand "get_thread_pointersi" | |
5257 | [(set (match_operand:SI 0 "register_operand") (match_dup 1))] | |
5258 | "" | |
5259 | "operands[1] = gen_rtx_REG (Pmode, arc_tp_regno);") | |
5260 | ||
5261 | (define_expand "set_thread_pointersi" | |
5262 | [(set (match_dup 1) (match_operand:SI 0 "register_operand"))] | |
5263 | "" | |
5264 | "operands[1] = gen_rtx_REG (Pmode, arc_tp_regno);") | |
5265 | ||
526b7aee SV |
5266 | ;; If hardware floating point is available, don't define a negdf pattern; |
5267 | ;; it would be something like: | |
5268 | ;;(define_insn "negdf2" | |
5269 | ;; [(set (match_operand:DF 0 "register_operand" "=w,w,D,?r") | |
5270 | ;; (neg:DF (match_operand:DF 1 "register_operand" "0,c,D,D"))) | |
5271 | ;; (clobber (match_scratch:DF 2 "=X,X,X,X,D1"))] | |
5272 | ;; "" | |
5273 | ;; "@ | |
5274 | ;; bxor%? %H0,%H1,31 | |
5275 | ;; bxor %H0,%H1,31 ` mov %L0,%L1 | |
5276 | ;; drsubh%F0%F1 0,0,0 | |
5277 | ;; drsubh%F2%F1 %H0,0,0 ` dexcl%F2 %L0,%H0,%L0" | |
5278 | ;; [(set_attr "type" "unary,unary,dpfp_addsub,dpfp_addsub") | |
5279 | ;; (set_attr "iscompact" "false,false,false,false") | |
5280 | ;; (set_attr "length" "4,4,8,12") | |
5281 | ;; (set_attr "cond" "canuse,nocond,nocond,nocond")]) | |
5282 | ;; and this suffers from always requiring a long immediate when using | |
5283 | ;; the floating point hardware. | |
5284 | ;; We then want the sub[sd]f patterns to be used, so that we can load the | |
5285 | ;; constant zero efficiently into a register when we want to do the | |
5286 | ;; computation using the floating point hardware. There should be a special | |
5287 | ;; subdf alternative that matches a zero operand 1, which then can allow | |
5288 | ;; to use bxor to flip the high bit of an integer register. | |
5289 | ;; ??? we actually can't use the floating point hardware for neg, because | |
5290 | ;; this would not work right for -0. OTOH optabs.c has already code | |
5291 | ;; to synthesyze negate by flipping the sign bit. | |
5292 | ||
f50bb868 CZ |
5293 | ;;V2 instructions |
5294 | (define_insn "bswapsi2" | |
5295 | [(set (match_operand:SI 0 "register_operand" "= r,r") | |
5296 | (bswap:SI (match_operand:SI 1 "nonmemory_operand" "rL,Cal")))] | |
5297 | "TARGET_V2 && TARGET_SWAP" | |
5298 | "swape %0, %1" | |
5299 | [(set_attr "length" "4,8") | |
5300 | (set_attr "type" "two_cycle_core")]) | |
5301 | ||
5302 | (define_expand "prefetch" | |
5303 | [(prefetch (match_operand:SI 0 "address_operand" "") | |
5304 | (match_operand:SI 1 "const_int_operand" "") | |
5305 | (match_operand:SI 2 "const_int_operand" ""))] | |
5306 | "TARGET_HS" | |
5307 | "") | |
5308 | ||
5309 | (define_insn "prefetch_1" | |
5310 | [(prefetch (match_operand:SI 0 "register_operand" "r") | |
5311 | (match_operand:SI 1 "const_int_operand" "n") | |
5312 | (match_operand:SI 2 "const_int_operand" "n"))] | |
5313 | "TARGET_HS" | |
5314 | { | |
5315 | if (INTVAL (operands[1])) | |
5316 | return "prefetchw [%0]"; | |
5317 | else | |
5318 | return "prefetch [%0]"; | |
5319 | } | |
5320 | [(set_attr "type" "load") | |
5321 | (set_attr "length" "4")]) | |
5322 | ||
5323 | (define_insn "prefetch_2" | |
5324 | [(prefetch (plus:SI (match_operand:SI 0 "register_operand" "r,r,r") | |
5325 | (match_operand:SI 1 "nonmemory_operand" "r,Cm2,Cal")) | |
5326 | (match_operand:SI 2 "const_int_operand" "n,n,n") | |
5327 | (match_operand:SI 3 "const_int_operand" "n,n,n"))] | |
5328 | "TARGET_HS" | |
5329 | { | |
5330 | if (INTVAL (operands[2])) | |
5331 | return "prefetchw [%0, %1]"; | |
5332 | else | |
5333 | return "prefetch [%0, %1]"; | |
5334 | } | |
5335 | [(set_attr "type" "load") | |
5336 | (set_attr "length" "4,4,8")]) | |
5337 | ||
5338 | (define_insn "prefetch_3" | |
5339 | [(prefetch (match_operand:SI 0 "address_operand" "p") | |
5340 | (match_operand:SI 1 "const_int_operand" "n") | |
5341 | (match_operand:SI 2 "const_int_operand" "n"))] | |
5342 | "TARGET_HS" | |
5343 | { | |
5344 | operands[0] = gen_rtx_MEM (SImode, operands[0]); | |
5345 | if (INTVAL (operands[1])) | |
5346 | return "prefetchw%U0 %0"; | |
5347 | else | |
5348 | return "prefetch%U0 %0"; | |
5349 | } | |
5350 | [(set_attr "type" "load") | |
5351 | (set_attr "length" "8")]) | |
5352 | ||
5353 | (define_insn "divsi3" | |
5354 | [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r, r, r") | |
5355 | (div:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal,0,r,0, 0, r") | |
5356 | (match_operand:SI 2 "nonmemory_operand" "r,r, r,L,L,I,Cal,Cal")))] | |
5357 | "TARGET_DIVREM" | |
5358 | "div%? %0, %1, %2" | |
5359 | [(set_attr "length" "4,4,8,4,4,4,8,8") | |
5360 | (set_attr "iscompact" "false") | |
5361 | (set_attr "type" "div_rem") | |
5362 | (set_attr "predicable" "yes,no,no,yes,no,no,yes,no") | |
5363 | (set_attr "cond" "canuse,nocond,nocond,canuse,nocond,nocond,canuse,nocond") | |
5364 | ]) | |
5365 | ||
5366 | (define_insn "udivsi3" | |
5367 | [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r, r, r") | |
5368 | (udiv:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal,0,r,0, 0, r") | |
5369 | (match_operand:SI 2 "nonmemory_operand" "r,r, r,L,L,I,Cal,Cal")))] | |
5370 | "TARGET_DIVREM" | |
5371 | "divu%? %0, %1, %2" | |
5372 | [(set_attr "length" "4,4,8,4,4,4,8,8") | |
5373 | (set_attr "iscompact" "false") | |
5374 | (set_attr "type" "div_rem") | |
5375 | (set_attr "predicable" "yes,no,no,yes,no,no,yes,no") | |
5376 | (set_attr "cond" "canuse,nocond,nocond,canuse,nocond,nocond,canuse,nocond") | |
5377 | ]) | |
5378 | ||
5379 | (define_insn "modsi3" | |
5380 | [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r, r, r") | |
5381 | (mod:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal,0,r,0, 0, r") | |
5382 | (match_operand:SI 2 "nonmemory_operand" "r,r, r,L,L,I,Cal,Cal")))] | |
5383 | "TARGET_DIVREM" | |
5384 | "rem%? %0, %1, %2" | |
5385 | [(set_attr "length" "4,4,8,4,4,4,8,8") | |
5386 | (set_attr "iscompact" "false") | |
5387 | (set_attr "type" "div_rem") | |
5388 | (set_attr "predicable" "yes,no,no,yes,no,no,yes,no") | |
5389 | (set_attr "cond" "canuse,nocond,nocond,canuse,nocond,nocond,canuse,nocond") | |
5390 | ]) | |
5391 | ||
5392 | (define_insn "umodsi3" | |
5393 | [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r, r, r") | |
5394 | (umod:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal,0,r,0, 0, r") | |
5395 | (match_operand:SI 2 "nonmemory_operand" "r,r, r,L,L,I,Cal,Cal")))] | |
5396 | "TARGET_DIVREM" | |
5397 | "remu%? %0, %1, %2" | |
5398 | [(set_attr "length" "4,4,8,4,4,4,8,8") | |
5399 | (set_attr "iscompact" "false") | |
5400 | (set_attr "type" "div_rem") | |
5401 | (set_attr "predicable" "yes,no,no,yes,no,no,yes,no") | |
5402 | (set_attr "cond" "canuse,nocond,nocond,canuse,nocond,nocond,canuse,nocond") | |
5403 | ]) | |
5404 | ||
5405 | ;; SETcc instructions | |
5406 | (define_code_iterator arcCC_cond [eq ne gt lt ge le]) | |
5407 | ||
5408 | (define_insn "arcset<code>" | |
5409 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r") | |
2a42e339 | 5410 | (arcCC_cond:SI (match_operand:SI 1 "register_operand" "0,r,0,r,0,0,r") |
f50bb868 CZ |
5411 | (match_operand:SI 2 "nonmemory_operand" "r,r,L,L,I,n,n")))] |
5412 | "TARGET_V2 && TARGET_CODE_DENSITY" | |
5413 | "set<code>%? %0, %1, %2" | |
5414 | [(set_attr "length" "4,4,4,4,4,8,8") | |
5415 | (set_attr "iscompact" "false") | |
5416 | (set_attr "type" "compare") | |
5417 | (set_attr "predicable" "yes,no,yes,no,no,yes,no") | |
5418 | (set_attr "cond" "canuse,nocond,canuse,nocond,nocond,canuse,nocond") | |
5419 | ]) | |
5420 | ||
5421 | (define_insn "arcsetltu" | |
5422 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r, r, r") | |
2a42e339 | 5423 | (ltu:SI (match_operand:SI 1 "register_operand" "0,r,0,r,0, 0, r") |
f50bb868 CZ |
5424 | (match_operand:SI 2 "nonmemory_operand" "r,r,L,L,I, n, n")))] |
5425 | "TARGET_V2 && TARGET_CODE_DENSITY" | |
5426 | "setlo%? %0, %1, %2" | |
5427 | [(set_attr "length" "4,4,4,4,4,8,8") | |
5428 | (set_attr "iscompact" "false") | |
5429 | (set_attr "type" "compare") | |
5430 | (set_attr "predicable" "yes,no,yes,no,no,yes,no") | |
5431 | (set_attr "cond" "canuse,nocond,canuse,nocond,nocond,canuse,nocond") | |
5432 | ]) | |
5433 | ||
5434 | (define_insn "arcsetgeu" | |
5435 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r, r, r") | |
2a42e339 | 5436 | (geu:SI (match_operand:SI 1 "register_operand" "0,r,0,r,0, 0, r") |
f50bb868 CZ |
5437 | (match_operand:SI 2 "nonmemory_operand" "r,r,L,L,I, n, n")))] |
5438 | "TARGET_V2 && TARGET_CODE_DENSITY" | |
5439 | "seths%? %0, %1, %2" | |
5440 | [(set_attr "length" "4,4,4,4,4,8,8") | |
5441 | (set_attr "iscompact" "false") | |
5442 | (set_attr "type" "compare") | |
5443 | (set_attr "predicable" "yes,no,yes,no,no,yes,no") | |
5444 | (set_attr "cond" "canuse,nocond,canuse,nocond,nocond,canuse,nocond") | |
5445 | ]) | |
5446 | ||
5447 | ;; Special cases of SETCC | |
5448 | (define_insn_and_split "arcsethi" | |
5449 | [(set (match_operand:SI 0 "register_operand" "=r,r, r,r") | |
2a42e339 | 5450 | (gtu:SI (match_operand:SI 1 "register_operand" "r,r, r,r") |
f50bb868 CZ |
5451 | (match_operand:SI 2 "nonmemory_operand" "0,r,C62,n")))] |
5452 | "TARGET_V2 && TARGET_CODE_DENSITY" | |
5453 | "setlo%? %0, %2, %1" | |
5454 | "reload_completed | |
5455 | && CONST_INT_P (operands[2]) | |
5456 | && satisfies_constraint_C62 (operands[2])" | |
5457 | [(const_int 0)] | |
5458 | "{ | |
5459 | /* sethi a,b,u6 => seths a,b,u6 + 1. */ | |
5460 | operands[2] = GEN_INT (INTVAL (operands[2]) + 1); | |
5461 | emit_insn (gen_arcsetgeu (operands[0], operands[1], operands[2])); | |
5462 | DONE; | |
5463 | }" | |
5464 | [(set_attr "length" "4,4,4,8") | |
5465 | (set_attr "iscompact" "false") | |
5466 | (set_attr "type" "compare") | |
5467 | (set_attr "predicable" "yes,no,no,no") | |
5468 | (set_attr "cond" "canuse,nocond,nocond,nocond")] | |
5469 | ) | |
5470 | ||
5471 | (define_insn_and_split "arcsetls" | |
5472 | [(set (match_operand:SI 0 "register_operand" "=r,r, r,r") | |
2a42e339 | 5473 | (leu:SI (match_operand:SI 1 "register_operand" "r,r, r,r") |
f50bb868 CZ |
5474 | (match_operand:SI 2 "nonmemory_operand" "0,r,C62,n")))] |
5475 | "TARGET_V2 && TARGET_CODE_DENSITY" | |
5476 | "seths%? %0, %2, %1" | |
5477 | "reload_completed | |
5478 | && CONST_INT_P (operands[2]) | |
5479 | && satisfies_constraint_C62 (operands[2])" | |
5480 | [(const_int 0)] | |
5481 | "{ | |
5482 | /* setls a,b,u6 => setlo a,b,u6 + 1. */ | |
5483 | operands[2] = GEN_INT (INTVAL (operands[2]) + 1); | |
5484 | emit_insn (gen_arcsetltu (operands[0], operands[1], operands[2])); | |
5485 | DONE; | |
5486 | }" | |
5487 | [(set_attr "length" "4,4,4,8") | |
5488 | (set_attr "iscompact" "false") | |
5489 | (set_attr "type" "compare") | |
5490 | (set_attr "predicable" "yes,no,no,no") | |
5491 | (set_attr "cond" "canuse,nocond,nocond,nocond")] | |
5492 | ) | |
5493 | ||
5494 | ; Any mode that needs to be solved by secondary reload | |
5495 | (define_mode_iterator SRI [QI HI]) | |
5496 | ||
5497 | (define_expand "reload_<mode>_load" | |
5498 | [(parallel [(match_operand:SRI 0 "register_operand" "=r") | |
5499 | (match_operand:SRI 1 "memory_operand" "m") | |
5500 | (match_operand:SI 2 "register_operand" "=&r")])] | |
5501 | "" | |
5502 | { | |
5503 | arc_secondary_reload_conv (operands[0], operands[1], operands[2], false); | |
5504 | DONE; | |
5505 | }) | |
5506 | ||
5507 | (define_expand "reload_<mode>_store" | |
5508 | [(parallel [(match_operand:SRI 0 "memory_operand" "=m") | |
5509 | (match_operand:SRI 1 "register_operand" "r") | |
5510 | (match_operand:SI 2 "register_operand" "=&r")])] | |
5511 | "" | |
5512 | { | |
5513 | arc_secondary_reload_conv (operands[1], operands[0], operands[2], true); | |
5514 | DONE; | |
5515 | }) | |
5516 | ||
f50bb868 | 5517 | (define_insn "extzvsi" |
f7ace5d5 CZ |
5518 | [(set (match_operand:SI 0 "register_operand" "=r , r,r,r") |
5519 | (zero_extract:SI (match_operand:SI 1 "register_operand" "0 , r,r,0") | |
5520 | (match_operand:SI 2 "const_int_operand" "C3p,C3p,n,n") | |
5521 | (match_operand:SI 3 "const_int_operand" "n , n,n,n")))] | |
f50bb868 CZ |
5522 | "TARGET_HS && TARGET_BARREL_SHIFTER" |
5523 | { | |
5524 | int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL (operands[3]) & 0x1f); | |
5525 | operands[2] = GEN_INT (assemble_op2); | |
f7ace5d5 | 5526 | return "xbfu%?\\t%0,%1,%2"; |
f50bb868 CZ |
5527 | } |
5528 | [(set_attr "type" "shift") | |
5529 | (set_attr "iscompact" "false") | |
f7ace5d5 CZ |
5530 | (set_attr "length" "4,4,8,8") |
5531 | (set_attr "predicable" "yes,no,no,yes") | |
5532 | (set_attr "cond" "canuse,nocond,nocond,canuse_limm")]) | |
526b7aee | 5533 | |
c69899f0 CZ |
5534 | (define_insn "kflag" |
5535 | [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "rL,I,Cal")] | |
5536 | VUNSPEC_ARC_KFLAG)] | |
5537 | "TARGET_V2" | |
5538 | "@ | |
5539 | kflag%? %0 | |
5540 | kflag %0 | |
6b55f8c9 | 5541 | kflag%? %0" |
c69899f0 CZ |
5542 | [(set_attr "length" "4,4,8") |
5543 | (set_attr "type" "misc,misc,misc") | |
5544 | (set_attr "predicable" "yes,no,yes") | |
5545 | (set_attr "cond" "clob,clob,clob")]) | |
5546 | ||
5547 | (define_insn "clri" | |
5548 | [(set (match_operand:SI 0 "dest_reg_operand" "=r") | |
5549 | (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "N")] | |
5550 | VUNSPEC_ARC_CLRI))] | |
5551 | "TARGET_V2" | |
5552 | "clri %0" | |
5553 | [(set_attr "length" "4") | |
5554 | (set_attr "type" "misc")]) | |
5555 | ||
5556 | (define_insn "ffs" | |
5557 | [(set (match_operand:SI 0 "dest_reg_operand" "=w,w") | |
5558 | (unspec:SI [(match_operand:SI 1 "general_operand" "cL,Cal")] | |
5559 | UNSPEC_ARC_FFS))] | |
5560 | "TARGET_NORM && TARGET_V2" | |
5561 | "@ | |
5562 | ffs \t%0, %1 | |
6b55f8c9 | 5563 | ffs \t%0, %1" |
c69899f0 CZ |
5564 | [(set_attr "length" "4,8") |
5565 | (set_attr "type" "two_cycle_core,two_cycle_core")]) | |
5566 | ||
5567 | (define_insn "ffs_f" | |
5568 | [(set (match_operand:SI 0 "dest_reg_operand" "=w,w") | |
5569 | (unspec:SI [(match_operand:SI 1 "general_operand" "cL,Cal")] | |
5570 | UNSPEC_ARC_FFS)) | |
5571 | (set (reg:CC_ZN CC_REG) | |
5572 | (compare:CC_ZN (match_dup 1) (const_int 0)))] | |
5573 | "TARGET_NORM && TARGET_V2" | |
5574 | "@ | |
5575 | ffs.f\t%0, %1 | |
6b55f8c9 | 5576 | ffs.f\t%0, %1" |
c69899f0 CZ |
5577 | [(set_attr "length" "4,8") |
5578 | (set_attr "type" "two_cycle_core,two_cycle_core")]) | |
5579 | ||
5580 | (define_expand "ffssi2" | |
5581 | [(parallel [(set (match_dup 2) | |
5582 | (unspec:SI [(match_operand:SI 1 "register_operand" "")] | |
5583 | UNSPEC_ARC_FFS)) | |
5584 | (set (reg:CC_ZN CC_REG) | |
5585 | (compare:CC_ZN (match_dup 1) (const_int 0)))]) | |
5586 | (set (match_dup 2) (plus:SI (match_dup 2) (const_int 1))) | |
5587 | (set (match_operand:SI 0 "dest_reg_operand" "") | |
5588 | (if_then_else:SI (eq:SI (reg:CC_ZN CC_REG) (const_int 0)) | |
5589 | (const_int 0) | |
5590 | (match_dup 2)))] | |
5591 | "TARGET_NORM && TARGET_V2" | |
5592 | { | |
5593 | operands[2] = gen_reg_rtx (SImode); | |
5594 | }) | |
5595 | ||
5596 | (define_insn "fls" | |
9ba5e5fc CZ |
5597 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
5598 | (unspec:SI [(match_operand:SI 1 "nonmemory_operand" "rL,Cal")] | |
c69899f0 CZ |
5599 | UNSPEC_ARC_FLS))] |
5600 | "TARGET_NORM && TARGET_V2" | |
9ba5e5fc | 5601 | "fls\\t%0,%1" |
c69899f0 CZ |
5602 | [(set_attr "length" "4,8") |
5603 | (set_attr "type" "two_cycle_core,two_cycle_core")]) | |
5604 | ||
5605 | (define_insn "seti" | |
9ba5e5fc | 5606 | [(unspec_volatile:SI [(match_operand:SI 0 "nonmemory_operand" "rL")] |
c69899f0 CZ |
5607 | VUNSPEC_ARC_SETI)] |
5608 | "TARGET_V2" | |
9ba5e5fc | 5609 | "seti\\t%0" |
c69899f0 CZ |
5610 | [(set_attr "length" "4") |
5611 | (set_attr "type" "misc")]) | |
5612 | ||
8f3304d0 CZ |
5613 | ;; FPU/FPX expands |
5614 | ||
5615 | ;;add | |
5616 | (define_expand "addsf3" | |
5617 | [(set (match_operand:SF 0 "register_operand" "") | |
5618 | (plus:SF (match_operand:SF 1 "nonmemory_operand" "") | |
5619 | (match_operand:SF 2 "nonmemory_operand" "")))] | |
5620 | "TARGET_FP_SP_BASE || TARGET_SPFP" | |
5621 | " | |
5622 | if (!register_operand (operands[1], SFmode) | |
5623 | && !register_operand (operands[2], SFmode)) | |
5624 | operands[1] = force_reg (SFmode, operands[1]); | |
5625 | ") | |
5626 | ||
5627 | ;;sub | |
5628 | (define_expand "subsf3" | |
5629 | [(set (match_operand:SF 0 "register_operand" "") | |
5630 | (minus:SF (match_operand:SF 1 "nonmemory_operand" "") | |
5631 | (match_operand:SF 2 "nonmemory_operand" "")))] | |
5632 | "TARGET_FP_SP_BASE || TARGET_SPFP" | |
5633 | " | |
5634 | if (!register_operand (operands[1], SFmode) | |
5635 | && !register_operand (operands[2], SFmode)) | |
5636 | operands[1] = force_reg (SFmode, operands[1]); | |
5637 | ") | |
5638 | ||
5639 | ;;mul | |
5640 | (define_expand "mulsf3" | |
5641 | [(set (match_operand:SF 0 "register_operand" "") | |
5642 | (mult:SF (match_operand:SF 1 "nonmemory_operand" "") | |
5643 | (match_operand:SF 2 "nonmemory_operand" "")))] | |
5644 | "TARGET_FP_SP_BASE || TARGET_SPFP" | |
5645 | " | |
5646 | if (!register_operand (operands[1], SFmode) | |
5647 | && !register_operand (operands[2], SFmode)) | |
5648 | operands[1] = force_reg (SFmode, operands[1]); | |
5649 | ") | |
5650 | ||
5651 | ;;add | |
5652 | (define_expand "adddf3" | |
5653 | [(set (match_operand:DF 0 "double_register_operand" "") | |
5654 | (plus:DF (match_operand:DF 1 "double_register_operand" "") | |
5655 | (match_operand:DF 2 "nonmemory_operand" "")))] | |
5656 | "TARGET_FP_DP_BASE || TARGET_DPFP" | |
5657 | " | |
5658 | if (TARGET_DPFP) | |
5659 | { | |
5660 | if (GET_CODE (operands[2]) == CONST_DOUBLE) | |
5661 | { | |
7d81a567 CZ |
5662 | rtx first, second, tmp; |
5663 | split_double (operands[2], &first, &second); | |
5664 | tmp = force_reg (SImode, TARGET_BIG_ENDIAN ? first : second); | |
8f3304d0 CZ |
5665 | emit_insn (gen_adddf3_insn (operands[0], operands[1], |
5666 | operands[2], tmp, const0_rtx)); | |
5667 | } | |
5668 | else | |
5669 | emit_insn (gen_adddf3_insn (operands[0], operands[1], | |
5670 | operands[2], const1_rtx, const1_rtx)); | |
5671 | DONE; | |
5672 | } | |
5673 | else if (TARGET_FP_DP_BASE) | |
5674 | { | |
5675 | if (!even_register_operand (operands[2], DFmode)) | |
5676 | operands[2] = force_reg (DFmode, operands[2]); | |
5677 | ||
5678 | if (!even_register_operand (operands[1], DFmode)) | |
5679 | operands[1] = force_reg (DFmode, operands[1]); | |
5680 | } | |
5681 | else | |
5682 | gcc_unreachable (); | |
5683 | ") | |
5684 | ||
5685 | ;;sub | |
5686 | (define_expand "subdf3" | |
5687 | [(set (match_operand:DF 0 "double_register_operand" "") | |
5688 | (minus:DF (match_operand:DF 1 "nonmemory_operand" "") | |
5689 | (match_operand:DF 2 "nonmemory_operand" "")))] | |
5690 | "TARGET_FP_DP_BASE || TARGET_DPFP" | |
5691 | " | |
5692 | if (TARGET_DPFP) | |
5693 | { | |
4ac2f36e CZ |
5694 | if (TARGET_FP_DP_AX && (GET_CODE (operands[1]) == CONST_DOUBLE)) |
5695 | operands[1] = force_reg (DFmode, operands[1]); | |
8f3304d0 CZ |
5696 | if ((GET_CODE (operands[1]) == CONST_DOUBLE) |
5697 | || GET_CODE (operands[2]) == CONST_DOUBLE) | |
5698 | { | |
7d81a567 | 5699 | rtx first, second, tmp; |
8f3304d0 | 5700 | int const_index = ((GET_CODE (operands[1]) == CONST_DOUBLE) ? 1 : 2); |
7d81a567 CZ |
5701 | split_double (operands[const_index], &first, &second); |
5702 | tmp = force_reg (SImode, TARGET_BIG_ENDIAN ? first : second); | |
8f3304d0 CZ |
5703 | emit_insn (gen_subdf3_insn (operands[0], operands[1], |
5704 | operands[2], tmp, const0_rtx)); | |
5705 | } | |
5706 | else | |
5707 | emit_insn (gen_subdf3_insn (operands[0], operands[1], | |
5708 | operands[2], const1_rtx, const1_rtx)); | |
5709 | DONE; | |
5710 | } | |
5711 | else if (TARGET_FP_DP_BASE) | |
5712 | { | |
5713 | if (!even_register_operand (operands[2], DFmode)) | |
5714 | operands[2] = force_reg (DFmode, operands[2]); | |
5715 | ||
5716 | if (!even_register_operand (operands[1], DFmode)) | |
5717 | operands[1] = force_reg (DFmode, operands[1]); | |
5718 | } | |
5719 | else | |
5720 | gcc_unreachable (); | |
5721 | ") | |
5722 | ||
5723 | ;;mul | |
5724 | (define_expand "muldf3" | |
5725 | [(set (match_operand:DF 0 "double_register_operand" "") | |
5726 | (mult:DF (match_operand:DF 1 "double_register_operand" "") | |
5727 | (match_operand:DF 2 "nonmemory_operand" "")))] | |
5728 | "TARGET_FP_DP_BASE || TARGET_DPFP" | |
5729 | " | |
5730 | if (TARGET_DPFP) | |
5731 | { | |
5732 | if (GET_CODE (operands[2]) == CONST_DOUBLE) | |
5733 | { | |
7d81a567 CZ |
5734 | rtx first, second, tmp; |
5735 | split_double (operands[2], &first, &second); | |
5736 | tmp = force_reg (SImode, TARGET_BIG_ENDIAN ? first : second); | |
8f3304d0 CZ |
5737 | emit_insn (gen_muldf3_insn (operands[0], operands[1], |
5738 | operands[2], tmp, const0_rtx)); | |
5739 | } | |
5740 | else | |
5741 | emit_insn (gen_muldf3_insn (operands[0], operands[1], | |
5742 | operands[2], const1_rtx, const1_rtx)); | |
5743 | DONE; | |
5744 | } | |
5745 | else if (TARGET_FP_DP_BASE) | |
5746 | { | |
5747 | if (!even_register_operand (operands[2], DFmode)) | |
5748 | operands[2] = force_reg (DFmode, operands[2]); | |
5749 | ||
5750 | if (!even_register_operand (operands[1], DFmode)) | |
5751 | operands[1] = force_reg (DFmode, operands[1]); | |
5752 | } | |
5753 | else | |
5754 | gcc_unreachable (); | |
5755 | ") | |
5756 | ||
c4014855 CZ |
5757 | ;;div |
5758 | (define_expand "divsf3" | |
5759 | [(set (match_operand:SF 0 "register_operand" "") | |
5760 | (div:SF (match_operand:SF 1 "nonmemory_operand" "") | |
5761 | (match_operand:SF 2 "nonmemory_operand" "")))] | |
5762 | "TARGET_FPX_QUARK || TARGET_FP_SP_SQRT" | |
5763 | " | |
5764 | if (TARGET_FPX_QUARK) | |
5765 | { | |
5766 | operands[1] = force_reg (SFmode, operands[1]); | |
5767 | operands[2] = force_reg (SFmode, operands[2]); | |
5768 | } | |
5769 | else | |
5770 | { | |
5771 | if (!register_operand (operands[1], SFmode) | |
5772 | && !register_operand (operands[2], SFmode)) | |
5773 | operands[1] = force_reg (SFmode, operands[1]); | |
5774 | } | |
5775 | ") | |
5776 | ||
5777 | ;; Square root | |
5778 | (define_expand "sqrtsf2" | |
5779 | [(set (match_operand:SF 0 "register_operand" "") | |
5780 | (sqrt:SF (match_operand:SF 1 "nonmemory_operand" "")))] | |
5781 | "TARGET_FPX_QUARK || TARGET_FP_SP_SQRT" | |
5782 | " | |
5783 | if (TARGET_FPX_QUARK) | |
5784 | { | |
5785 | operands[1] = force_reg (SFmode, operands[1]); | |
5786 | } | |
5787 | ") | |
5788 | ||
5789 | ;; SF->SI (using rounding towards zero) | |
5790 | (define_expand "fix_truncsfsi2" | |
5791 | [(set (match_operand:SI 0 "register_operand" "") | |
5792 | (fix:SI (fix:SF (match_operand:SF 1 "register_operand" ""))))] | |
5793 | "TARGET_FPX_QUARK || TARGET_FP_SP_CONV" | |
5794 | "") | |
5795 | ||
5796 | ;; SI->SF | |
5797 | (define_expand "floatsisf2" | |
5798 | [(set (match_operand:SF 0 "register_operand" "") | |
5799 | (float:SF (match_operand:SI 1 "register_operand" "")))] | |
5800 | "TARGET_FPX_QUARK || TARGET_FP_SP_CONV" | |
5801 | "") | |
5802 | ||
ceaaa9fe JR |
5803 | (define_expand "extzv" |
5804 | [(set (match_operand:SI 0 "register_operand" "") | |
5805 | (zero_extract:SI (match_operand:SI 1 "register_operand" "") | |
5806 | (match_operand:SI 2 "const_int_operand" "") | |
5807 | (match_operand:SI 3 "const_int_operand" "")))] | |
5808 | "TARGET_NPS_BITOPS") | |
5809 | ||
5810 | ; We need a sanity check in the instuction predicate because combine | |
5811 | ; will throw any old rubbish at us and see what sticks. | |
5812 | (define_insn "*extzv_i" | |
5813 | [(set (match_operand:SI 0 "register_operand" "=Rrq") | |
5814 | (zero_extract:SI (match_operand:SI 1 "register_operand" "Rrq") | |
5815 | (match_operand:SI 2 "const_int_operand" "n") | |
5816 | (match_operand:SI 3 "const_int_operand" "n")))] | |
5817 | "TARGET_NPS_BITOPS && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32" | |
5818 | "movb.cl %0,%1,0,%3,%2" | |
5819 | [(set_attr "type" "shift") | |
5820 | (set_attr "length" "4")]) | |
5821 | ||
5822 | (define_expand "insv" | |
5823 | [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "") | |
5824 | (match_operand:SI 1 "const_int_operand" "") | |
5825 | (match_operand:SI 2 "const_int_operand" "")) | |
5826 | (match_operand:SI 3 "nonmemory_operand" ""))] | |
5827 | "TARGET_NPS_BITOPS" | |
5828 | { | |
5829 | int size = INTVAL (operands[1]); | |
5830 | ||
5831 | if (size != 1 && size != 2 && size != 4 && size != 8) | |
5832 | operands[3] = force_reg (SImode, operands[3]); | |
5833 | }) | |
5834 | ||
5835 | (define_insn "*insv_i" | |
5836 | [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+w,Rrq") | |
5837 | (match_operand:SI 1 "const_int_operand" "C18,n") | |
5838 | (match_operand:SI 2 "const_int_operand" "n,n")) | |
5839 | (match_operand:SI 3 "nonmemory_operand" "P,Rrq"))] | |
5840 | "TARGET_NPS_BITOPS | |
5841 | && (register_operand (operands[3], SImode) | |
5842 | || satisfies_constraint_C18 (operands[1]))" | |
5843 | "@ | |
5844 | movbi %0,%0,%3,%2,%1 | |
5845 | movb %0,%0,%3,%2,0,%1" | |
5846 | [(set_attr "type" "shift") | |
5847 | (set_attr "length" "4")]) | |
5848 | ||
5849 | (define_insn "*movb" | |
5850 | [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq") | |
5851 | (match_operand:SI 1 "const_int_operand" "n") | |
5852 | (match_operand:SI 2 "const_int_operand" "n")) | |
5853 | (zero_extract:SI (match_operand:SI 3 "register_operand" "Rrq") | |
5854 | (match_dup 1) | |
5855 | (match_operand:SI 4 "const_int_operand" "n")))] | |
5856 | "TARGET_NPS_BITOPS" | |
5857 | "movb %0,%0,%3,%2,%4,%1" | |
5858 | [(set_attr "type" "shift") | |
5859 | (set_attr "length" "4")]) | |
5860 | ||
5861 | (define_insn "*movb_signed" | |
5862 | [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq") | |
5863 | (match_operand:SI 1 "const_int_operand" "n") | |
5864 | (match_operand:SI 2 "const_int_operand" "n")) | |
5865 | (sign_extract:SI (match_operand:SI 3 "register_operand" "Rrq") | |
5866 | (match_dup 1) | |
5867 | (match_operand:SI 4 "const_int_operand" "n")))] | |
5868 | "TARGET_NPS_BITOPS" | |
5869 | "movb %0,%0,%3,%2,%4,%1" | |
5870 | [(set_attr "type" "shift") | |
5871 | (set_attr "length" "4")]) | |
5872 | ||
5873 | (define_insn "*movb_high" | |
5874 | [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq") | |
5875 | (match_operand:SI 1 "const_int_operand" "n") | |
5876 | (match_operand:SI 2 "const_int_operand" "n")) | |
5877 | (lshiftrt:SI (match_operand:SI 3 "register_operand" "Rrq") | |
5878 | (match_operand:SI 4 "const_int_operand" "n")))] | |
5879 | "TARGET_NPS_BITOPS | |
5880 | && INTVAL (operands[4]) + INTVAL (operands[1]) <= 32" | |
5881 | "movb %0,%0,%3,%2,%4,%1" | |
5882 | [(set_attr "type" "shift") | |
5883 | (set_attr "length" "4")]) | |
5884 | ||
5885 | ; N.B.: when processing signed bitfields that fit in the top half of | |
5886 | ; a word, gcc will use a narrow sign extending load, and in this case | |
5887 | ; we will see INTVAL (operands[4]) + INTVAL (operands[1]) == 16 (or 8) | |
5888 | (define_insn "*movb_high_signed" | |
5889 | [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq") | |
5890 | (match_operand:SI 1 "const_int_operand" "n") | |
5891 | (match_operand:SI 2 "const_int_operand" "n")) | |
5892 | (ashiftrt:SI (match_operand:SI 3 "register_operand" "Rrq") | |
5893 | (match_operand:SI 4 "const_int_operand" "n")))] | |
5894 | "TARGET_NPS_BITOPS | |
5895 | && INTVAL (operands[4]) + INTVAL (operands[1]) <= 32" | |
5896 | "movb %0,%0,%3,%2,%4,%1" | |
5897 | [(set_attr "type" "shift") | |
5898 | (set_attr "length" "4")]) | |
5899 | ||
5900 | (define_split | |
5901 | [(set (match_operand:SI 0 "register_operand" "") | |
5902 | (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "") | |
5903 | (match_operand:SI 2 "const_int_operand" "")) | |
5904 | (subreg:SI (match_operand 3 "") 0)))] | |
5905 | "TARGET_NPS_BITOPS | |
5906 | && GET_MODE_BITSIZE (GET_MODE (operands[3])) <= INTVAL (operands[2]) | |
5907 | && !reg_overlap_mentioned_p (operands[0], operands[1])" | |
5908 | [(set (match_dup 0) (zero_extend:SI (match_dup 3))) | |
5909 | (set (zero_extract:SI (match_dup 0) (match_dup 4) (match_dup 2)) | |
5910 | (match_dup 1))] | |
5911 | "operands[4] = GEN_INT (32 - INTVAL (operands[2]));") | |
5912 | ||
5913 | (define_insn "*mrgb" | |
5914 | [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq") | |
5915 | (match_operand:SI 1 "const_int_operand" "n") | |
5916 | (match_operand:SI 2 "const_int_operand" "n")) | |
5917 | (zero_extract:SI (match_dup 0) (match_dup 1) | |
5918 | (match_operand:SI 3 "const_int_operand" "n"))) | |
5919 | (set (zero_extract:SI (match_dup 0) | |
5920 | (match_operand:SI 4 "const_int_operand" "n") | |
5921 | (match_operand:SI 5 "const_int_operand" "n")) | |
5922 | (zero_extract:SI (match_operand:SI 6 "register_operand" "Rrq") | |
5923 | (match_dup 4) | |
5924 | (match_operand:SI 7 "const_int_operand" "n")))] | |
5925 | "TARGET_NPS_BITOPS" | |
5926 | { | |
5927 | output_asm_insn ("mrgb %0,%0,%6,%2,%3,%1,%5,%7,%4", operands); | |
5928 | /* The ;%? updates the known unalignment. */ | |
5929 | return arc_short_long (insn, ";%?", "nop_s"); | |
5930 | } | |
5931 | [(set_attr "type" "shift") | |
5932 | (set_attr "length" "6") | |
5933 | (set_attr "iscompact" "true")]) | |
5934 | ||
5935 | ;; combine fumbles combination of two movb patterns, and then the | |
5936 | ;; combination is rejected by combinable_i3pat. | |
5937 | ;; Thus, we can only use a peephole2 to combine two such insns. | |
5938 | ||
5939 | (define_peephole2 | |
5940 | [(set (match_operand:SI 0 "register_operand" "") | |
5941 | (match_operand:SI 1 "register_operand" "")) | |
5942 | (set (zero_extract:SI (match_dup 0) | |
5943 | (match_operand:SI 2 "const_int_operand" "") | |
5944 | (match_operand:SI 3 "const_int_operand" "")) | |
5945 | (zero_extract:SI (match_dup 1) | |
5946 | (match_dup 2) | |
5947 | (match_operand:SI 4 "const_int_operand" ""))) | |
5948 | (match_operand 9) ; unrelated insn scheduled here | |
5949 | (set (zero_extract:SI (match_dup 0) | |
5950 | (match_operand:SI 5 "const_int_operand" "") | |
5951 | (match_operand:SI 6 "const_int_operand" "")) | |
5952 | (zero_extract:SI (match_operand:SI 7 "register_operand" "") | |
5953 | (match_dup 5) | |
5954 | (match_operand:SI 8 "const_int_operand" "")))] | |
5955 | "TARGET_NPS_BITOPS | |
5956 | // Check that the second movb doesn't clobber an input of the extra insn. | |
5957 | && !reg_overlap_mentioned_p (operands[0], operands[9]) | |
5958 | // And vice versa. | |
5959 | && !reg_set_p (operands[0], operands[9]) | |
5960 | && !reg_set_p (operands[7], operands[9])" | |
5961 | [(set (match_dup 0) (match_dup 1)) | |
5962 | (parallel [(set (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2)) | |
5963 | (zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 4))) | |
5964 | (set (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2)) | |
5965 | (zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 4)))]) | |
5966 | (match_dup 9)]) | |
5967 | ||
5968 | (define_peephole2 | |
5969 | [(set (match_operand:SI 0 "register_operand" "") | |
5970 | (match_operand:SI 1 "register_operand" "")) | |
5971 | (set (zero_extract:SI (match_dup 0) | |
5972 | (match_operand:SI 2 "const_int_operand" "") | |
5973 | (match_operand:SI 3 "const_int_operand" "")) | |
5974 | (zero_extract:SI (match_dup 1) | |
5975 | (match_dup 2) | |
5976 | (match_operand:SI 4 "const_int_operand" ""))) | |
5977 | (set (match_dup 1) (match_operand 8)) | |
5978 | (set (zero_extract:SI (match_dup 0) | |
5979 | (match_operand:SI 5 "const_int_operand" "") | |
5980 | (match_operand:SI 6 "const_int_operand" "")) | |
5981 | (zero_extract:SI (match_dup 1) (match_dup 5) | |
5982 | (match_operand:SI 7 "const_int_operand" "")))] | |
5983 | "TARGET_NPS_BITOPS | |
5984 | && !reg_overlap_mentioned_p (operands[0], operands[8])" | |
5985 | [(set (match_dup 0) (match_dup 1)) | |
5986 | (set (match_dup 1) (match_dup 8)) | |
5987 | (parallel [(set (zero_extract:SI (match_dup 0) (match_dup 2) (match_dup 3)) | |
5988 | (zero_extract:SI (match_dup 0) (match_dup 2) (match_dup 4))) | |
5989 | (set (zero_extract:SI (match_dup 0) (match_dup 5) (match_dup 6)) | |
5990 | (zero_extract:SI (match_dup 1) (match_dup 5) (match_dup 7)))]) | |
5991 | (match_dup 1)]) | |
5992 | ||
c6d66e90 | 5993 | (define_insn "*rotrsi3_cnt1" |
03301dcc CZ |
5994 | [(set (match_operand:SI 0 "dest_reg_operand" "=r") |
5995 | (rotatert:SI (match_operand:SI 1 "nonmemory_operand" "rL") | |
c6d66e90 CZ |
5996 | (const_int 1)))] |
5997 | "" | |
03301dcc CZ |
5998 | "ror\\t%0,%1" |
5999 | [(set_attr "type" "shift") | |
6000 | (set_attr "predicable" "no") | |
6001 | (set_attr "length" "4")]) | |
6002 | ||
6003 | (define_insn "*rotrsi3_cnt8" | |
6004 | [(set (match_operand:SI 0 "register_operand" "=r") | |
6005 | (rotatert:SI (match_operand:SI 1 "nonmemory_operand" "rL") | |
6006 | (const_int 8)))] | |
6007 | "TARGET_BARREL_SHIFTER && TARGET_V2" | |
6008 | "ror8\\t%0,%1" | |
c6d66e90 CZ |
6009 | [(set_attr "type" "shift") |
6010 | (set_attr "predicable" "no") | |
6011 | (set_attr "length" "4")]) | |
6012 | ||
6013 | (define_insn "*ashlsi2_cnt1" | |
6014 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w") | |
6015 | (ashift:SI (match_operand:SI 1 "register_operand" "Rcqq,c") | |
6016 | (const_int 1)))] | |
6017 | "" | |
6018 | "asl%? %0,%1%&" | |
6019 | [(set_attr "type" "shift") | |
6020 | (set_attr "iscompact" "maybe,false") | |
03301dcc | 6021 | (set_attr "length" "4") |
c6d66e90 CZ |
6022 | (set_attr "predicable" "no,no")]) |
6023 | ||
03301dcc CZ |
6024 | (define_insn "*ashlsi2_cnt8" |
6025 | [(set (match_operand:SI 0 "register_operand" "=r") | |
6026 | (ashift:SI (match_operand:SI 1 "nonmemory_operand" "rL") | |
6027 | (const_int 8)))] | |
6028 | "TARGET_BARREL_SHIFTER && TARGET_V2" | |
6029 | "lsl8\\t%0,%1" | |
6030 | [(set_attr "type" "shift") | |
6031 | (set_attr "iscompact" "false") | |
6032 | (set_attr "length" "4") | |
6033 | (set_attr "predicable" "no")]) | |
6034 | ||
6035 | (define_insn "*ashlsi2_cnt16" | |
6036 | [(set (match_operand:SI 0 "register_operand" "=r") | |
6037 | (ashift:SI (match_operand:SI 1 "nonmemory_operand" "rL") | |
6038 | (const_int 16)))] | |
6039 | "TARGET_BARREL_SHIFTER && TARGET_V2" | |
6040 | "lsl16\\t%0,%1" | |
6041 | [(set_attr "type" "shift") | |
6042 | (set_attr "iscompact" "false") | |
6043 | (set_attr "length" "4") | |
6044 | (set_attr "predicable" "no")]) | |
6045 | ||
c6d66e90 CZ |
6046 | (define_insn "*lshrsi3_cnt1" |
6047 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w") | |
6048 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "Rcqq,c") | |
6049 | (const_int 1)))] | |
6050 | "" | |
6051 | "lsr%? %0,%1%&" | |
6052 | [(set_attr "type" "shift") | |
6053 | (set_attr "iscompact" "maybe,false") | |
6054 | (set_attr "predicable" "no,no")]) | |
6055 | ||
6056 | (define_insn "*ashrsi3_cnt1" | |
6057 | [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w") | |
6058 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "Rcqq,c") | |
6059 | (const_int 1)))] | |
6060 | "" | |
6061 | "asr%? %0,%1%&" | |
6062 | [(set_attr "type" "shift") | |
6063 | (set_attr "iscompact" "maybe,false") | |
6064 | (set_attr "predicable" "no,no")]) | |
6065 | ||
3e077364 AB |
6066 | (define_peephole2 |
6067 | [(set (match_operand:SI 0 "register_operand" "") | |
6068 | (zero_extract:SI (match_dup 0) | |
6069 | (match_operand:SI 1 "const_int_operand" "") | |
6070 | (match_operand:SI 2 "const_int_operand" ""))) | |
6071 | (set (zero_extract:SI (match_operand:SI 3 "register_operand" "") | |
6072 | (match_dup 1) | |
6073 | (match_dup 2)) | |
6074 | (match_dup 0))] | |
6075 | "TARGET_NPS_BITOPS | |
6076 | && !reg_overlap_mentioned_p (operands[0], operands[3])" | |
6077 | [(set (zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 2)) | |
6078 | (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2)))]) | |
6079 | ||
41453183 CZ |
6080 | ;; Dummy pattern used as a place holder for automatically saved |
6081 | ;; registers. | |
6082 | (define_insn "stack_irq_dwarf" | |
6083 | [(unspec_volatile [(const_int 1)] VUNSPEC_ARC_STACK_IRQ)] | |
6084 | "" | |
6085 | "" | |
6086 | [(set_attr "length" "0")]) | |
6087 | ||
79557bae | 6088 | ;; MAC and DMPY instructions |
0cf0bc67 CZ |
6089 | (define_expand "maddsidi4" |
6090 | [(match_operand:DI 0 "register_operand" "") | |
6091 | (match_operand:SI 1 "register_operand" "") | |
6092 | (match_operand:SI 2 "extend_operand" "") | |
6093 | (match_operand:DI 3 "register_operand" "")] | |
6094 | "TARGET_PLUS_DMPY" | |
6095 | "{ | |
6096 | emit_insn (gen_maddsidi4_split (operands[0], operands[1], operands[2], operands[3])); | |
6097 | DONE; | |
6098 | }") | |
6099 | ||
6100 | (define_insn_and_split "maddsidi4_split" | |
79557bae CZ |
6101 | [(set (match_operand:DI 0 "register_operand" "=r") |
6102 | (plus:DI | |
6103 | (mult:DI | |
6104 | (sign_extend:DI (match_operand:SI 1 "register_operand" "%r")) | |
6105 | (sign_extend:DI (match_operand:SI 2 "extend_operand" "ri"))) | |
0cf0bc67 CZ |
6106 | (match_operand:DI 3 "register_operand" "r"))) |
6107 | (clobber (reg:DI ARCV2_ACC))] | |
79557bae CZ |
6108 | "TARGET_PLUS_DMPY" |
6109 | "#" | |
6110 | "TARGET_PLUS_DMPY && reload_completed" | |
6111 | [(const_int 0)] | |
6112 | "{ | |
6113 | rtx acc_reg = gen_rtx_REG (DImode, ACC_REG_FIRST); | |
6114 | emit_move_insn (acc_reg, operands[3]); | |
97e1d32c | 6115 | if (TARGET_PLUS_MACD && even_register_operand (operands[0], DImode)) |
79557bae CZ |
6116 | emit_insn (gen_macd (operands[0], operands[1], operands[2])); |
6117 | else | |
6118 | { | |
6119 | emit_insn (gen_mac (operands[1], operands[2])); | |
6120 | emit_move_insn (operands[0], acc_reg); | |
6121 | } | |
6122 | DONE; | |
6123 | }" | |
6124 | [(set_attr "type" "multi") | |
6125 | (set_attr "length" "36")]) | |
6126 | ||
6127 | (define_insn "macd" | |
6128 | [(set (match_operand:DI 0 "even_register_operand" "=Rcr,r,r") | |
6129 | (plus:DI | |
6130 | (mult:DI | |
6131 | (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,c,c")) | |
6132 | (sign_extend:DI (match_operand:SI 2 "extend_operand" " c,cI,Cal"))) | |
6133 | (reg:DI ARCV2_ACC))) | |
6134 | (set (reg:DI ARCV2_ACC) | |
6135 | (plus:DI | |
6136 | (mult:DI (sign_extend:DI (match_dup 1)) | |
6137 | (sign_extend:DI (match_dup 2))) | |
6138 | (reg:DI ARCV2_ACC)))] | |
6139 | "TARGET_PLUS_MACD" | |
6140 | "macd %0,%1,%2" | |
6141 | [(set_attr "length" "4,4,8") | |
6142 | (set_attr "type" "multi") | |
6143 | (set_attr "predicable" "yes,no,no") | |
6144 | (set_attr "cond" "canuse,nocond,nocond")]) | |
6145 | ||
6146 | (define_insn "mac" | |
6147 | [(set (reg:DI ARCV2_ACC) | |
6148 | (plus:DI | |
6149 | (mult:DI (sign_extend:DI (match_operand:SI 0 "register_operand" "%r,r")) | |
6150 | (sign_extend:DI (match_operand:SI 1 "extend_operand" "rI,i"))) | |
6151 | (reg:DI ARCV2_ACC)))] | |
6152 | "TARGET_PLUS_DMPY" | |
6153 | "mac 0,%0,%1" | |
6154 | [(set_attr "length" "4,8") | |
6155 | (set_attr "type" "multi") | |
6156 | (set_attr "predicable" "no") | |
6157 | (set_attr "cond" "nocond")]) | |
6158 | ||
6159 | (define_peephole2 | |
6160 | [(set (reg:DI ARCV2_ACC) | |
6161 | (plus:DI | |
6162 | (mult:DI (sign_extend:DI (match_operand:SI 0 "register_operand" "")) | |
6163 | (sign_extend:DI (match_operand:SI 1 "extend_operand" ""))) | |
6164 | (reg:DI ARCV2_ACC))) | |
6165 | (set (match_operand:SI 2 "register_operand" "") | |
6166 | (match_operand:SI 3 "accl_operand" ""))] | |
6167 | "TARGET_PLUS_DMPY" | |
6168 | [(const_int 0)] | |
6169 | { | |
6170 | emit_insn (gen_mac_r (operands[2], operands[0], operands[1])); | |
6171 | DONE; | |
6172 | }) | |
6173 | ||
6174 | (define_insn "mac_r" | |
6175 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
6176 | (truncate:SI | |
6177 | (plus:DI | |
6178 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%r,r")) | |
6179 | (sign_extend:DI (match_operand:SI 2 "extend_operand" "rI,i"))) | |
6180 | (reg:DI ARCV2_ACC)))) | |
6181 | (clobber (reg:DI ARCV2_ACC))] | |
6182 | "TARGET_PLUS_DMPY" | |
6183 | "mac %0,%1,%2" | |
6184 | [(set_attr "length" "4,8") | |
6185 | (set_attr "type" "multi") | |
6186 | (set_attr "predicable" "no") | |
6187 | (set_attr "cond" "nocond")]) | |
6188 | ||
0cf0bc67 CZ |
6189 | (define_expand "umaddsidi4" |
6190 | [(match_operand:DI 0 "register_operand" "") | |
6191 | (match_operand:SI 1 "register_operand" "") | |
6192 | (match_operand:SI 2 "extend_operand" "") | |
6193 | (match_operand:DI 3 "register_operand" "")] | |
6194 | "TARGET_PLUS_DMPY" | |
6195 | "{ | |
6196 | emit_insn (gen_umaddsidi4_split (operands[0], operands[1], operands[2], operands[3])); | |
6197 | DONE; | |
6198 | }") | |
6199 | ||
6200 | (define_insn_and_split "umaddsidi4_split" | |
79557bae CZ |
6201 | [(set (match_operand:DI 0 "register_operand" "=r") |
6202 | (plus:DI | |
6203 | (mult:DI | |
6204 | (zero_extend:DI (match_operand:SI 1 "register_operand" "%r")) | |
6205 | (zero_extend:DI (match_operand:SI 2 "extend_operand" "ri"))) | |
0cf0bc67 CZ |
6206 | (match_operand:DI 3 "register_operand" "r"))) |
6207 | (clobber (reg:DI ARCV2_ACC))] | |
79557bae CZ |
6208 | "TARGET_PLUS_DMPY" |
6209 | "#" | |
6210 | "TARGET_PLUS_DMPY && reload_completed" | |
6211 | [(const_int 0)] | |
6212 | "{ | |
6213 | rtx acc_reg = gen_rtx_REG (DImode, ACC_REG_FIRST); | |
6214 | emit_move_insn (acc_reg, operands[3]); | |
97e1d32c | 6215 | if (TARGET_PLUS_MACD && even_register_operand (operands[0], DImode)) |
79557bae CZ |
6216 | emit_insn (gen_macdu (operands[0], operands[1], operands[2])); |
6217 | else | |
6218 | { | |
6219 | emit_insn (gen_macu (operands[1], operands[2])); | |
6220 | emit_move_insn (operands[0], acc_reg); | |
6221 | } | |
6222 | DONE; | |
6223 | }" | |
6224 | [(set_attr "type" "multi") | |
6225 | (set_attr "length" "36")]) | |
6226 | ||
6227 | (define_insn "macdu" | |
6228 | [(set (match_operand:DI 0 "even_register_operand" "=Rcr,r,r") | |
6229 | (plus:DI | |
6230 | (mult:DI | |
6231 | (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,c,c")) | |
6232 | (zero_extend:DI (match_operand:SI 2 "extend_operand" " c,cI,i"))) | |
6233 | (reg:DI ARCV2_ACC))) | |
6234 | (set (reg:DI ARCV2_ACC) | |
6235 | (plus:DI | |
6236 | (mult:DI (zero_extend:DI (match_dup 1)) | |
6237 | (zero_extend:DI (match_dup 2))) | |
6238 | (reg:DI ARCV2_ACC)))] | |
6239 | "TARGET_PLUS_MACD" | |
6240 | "macdu %0,%1,%2" | |
6241 | [(set_attr "length" "4,4,8") | |
6242 | (set_attr "type" "multi") | |
6243 | (set_attr "predicable" "yes,no,no") | |
6244 | (set_attr "cond" "canuse,nocond,nocond")]) | |
6245 | ||
6246 | (define_insn "macu" | |
6247 | [(set (reg:DI ARCV2_ACC) | |
6248 | (plus:DI | |
6249 | (mult:DI (zero_extend:DI (match_operand:SI 0 "register_operand" "%r,r")) | |
6250 | (zero_extend:DI (match_operand:SI 1 "extend_operand" "rI,i"))) | |
6251 | (reg:DI ARCV2_ACC)))] | |
6252 | "TARGET_PLUS_DMPY" | |
6253 | "macu 0,%0,%1" | |
6254 | [(set_attr "length" "4,8") | |
6255 | (set_attr "type" "multi") | |
6256 | (set_attr "predicable" "no") | |
6257 | (set_attr "cond" "nocond")]) | |
6258 | ||
6259 | (define_peephole2 | |
6260 | [(set (reg:DI ARCV2_ACC) | |
6261 | (plus:DI | |
6262 | (mult:DI (zero_extend:DI (match_operand:SI 0 "register_operand" "")) | |
6263 | (zero_extend:DI (match_operand:SI 1 "extend_operand" ""))) | |
6264 | (reg:DI ARCV2_ACC))) | |
6265 | (set (match_operand:SI 2 "register_operand" "") | |
6266 | (match_operand:SI 3 "accl_operand" ""))] | |
6267 | "TARGET_PLUS_DMPY" | |
6268 | [(const_int 0)] | |
6269 | { | |
6270 | emit_insn (gen_macu_r (operands[2], operands[0], operands[1])); | |
6271 | DONE; | |
6272 | }) | |
6273 | ||
6274 | (define_insn "macu_r" | |
6275 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
6276 | (truncate:SI | |
6277 | (plus:DI | |
6278 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%r,r")) | |
6279 | (zero_extend:DI (match_operand:SI 2 "extend_operand" "rI,i"))) | |
6280 | (reg:DI ARCV2_ACC)))) | |
6281 | (clobber (reg:DI ARCV2_ACC))] | |
6282 | "TARGET_PLUS_DMPY" | |
6283 | "macu %0,%1,%2" | |
6284 | [(set_attr "length" "4,8") | |
6285 | (set_attr "type" "multi") | |
6286 | (set_attr "predicable" "no") | |
6287 | (set_attr "cond" "nocond")]) | |
6288 | ||
6289 | (define_insn "mpyd_arcv2hs" | |
6290 | [(set (match_operand:DI 0 "even_register_operand" "=Rcr, r") | |
6291 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " 0, c")) | |
6292 | (sign_extend:DI (match_operand:SI 2 "register_operand" " c, c")))) | |
6293 | (set (reg:DI ARCV2_ACC) | |
6294 | (mult:DI | |
6295 | (sign_extend:DI (match_dup 1)) | |
6296 | (sign_extend:DI (match_dup 2))))] | |
6297 | "TARGET_PLUS_MACD" | |
6298 | "mpyd%? %0,%1,%2" | |
6299 | [(set_attr "length" "4,4") | |
6300 | (set_attr "iscompact" "false") | |
6301 | (set_attr "type" "multi") | |
6302 | (set_attr "predicable" "yes,no") | |
6303 | (set_attr "cond" "canuse,nocond")]) | |
6304 | ||
6305 | (define_insn "mpyd_imm_arcv2hs" | |
6306 | [(set (match_operand:DI 0 "even_register_operand" "=Rcr, r,r,Rcr, r") | |
6307 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " 0, c,0, 0, c")) | |
6308 | (match_operand 2 "immediate_operand" " L, L,I,Cal,Cal"))) | |
6309 | (set (reg:DI ARCV2_ACC) | |
6310 | (mult:DI (sign_extend:DI (match_dup 1)) | |
6311 | (match_dup 2)))] | |
6312 | "TARGET_PLUS_MACD" | |
6313 | "mpyd%? %0,%1,%2" | |
6314 | [(set_attr "length" "4,4,4,8,8") | |
6315 | (set_attr "iscompact" "false") | |
6316 | (set_attr "type" "multi") | |
6317 | (set_attr "predicable" "yes,no,no,yes,no") | |
6318 | (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")]) | |
6319 | ||
6320 | (define_insn "mpydu_arcv2hs" | |
6321 | [(set (match_operand:DI 0 "even_register_operand" "=Rcr, r") | |
6322 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " 0, c")) | |
6323 | (zero_extend:DI (match_operand:SI 2 "register_operand" " c, c")))) | |
6324 | (set (reg:DI ARCV2_ACC) | |
6325 | (mult:DI (zero_extend:DI (match_dup 1)) | |
6326 | (zero_extend:DI (match_dup 2))))] | |
6327 | "TARGET_PLUS_MACD" | |
6328 | "mpydu%? %0,%1,%2" | |
6329 | [(set_attr "length" "4,4") | |
6330 | (set_attr "iscompact" "false") | |
6331 | (set_attr "type" "multi") | |
6332 | (set_attr "predicable" "yes,no") | |
6333 | (set_attr "cond" "canuse,nocond")]) | |
6334 | ||
6335 | (define_insn "mpydu_imm_arcv2hs" | |
6336 | [(set (match_operand:DI 0 "even_register_operand" "=Rcr, r,r,Rcr, r") | |
6337 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " 0, c,0, 0, c")) | |
6338 | (match_operand 2 "immediate_operand" " L, L,I,Cal,Cal"))) | |
6339 | (set (reg:DI ARCV2_ACC) | |
6340 | (mult:DI (zero_extend:DI (match_dup 1)) | |
6341 | (match_dup 2)))] | |
6342 | "TARGET_PLUS_MACD" | |
6343 | "mpydu%? %0,%1,%2" | |
6344 | [(set_attr "length" "4,4,4,8,8") | |
6345 | (set_attr "iscompact" "false") | |
6346 | (set_attr "type" "multi") | |
6347 | (set_attr "predicable" "yes,no,no,yes,no") | |
6348 | (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")]) | |
6349 | ||
f7ace5d5 CZ |
6350 | (define_insn "*add_shift" |
6351 | [(set (match_operand:SI 0 "register_operand" "=q,r,r") | |
6352 | (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "q,r,r") | |
6353 | (match_operand:SI 2 "_1_2_3_operand" "")) | |
e04108c7 | 6354 | (match_operand:SI 3 "nonmemory_operand" "0,r,Csz")))] |
f7ace5d5 CZ |
6355 | "" |
6356 | "add%2%?\\t%0,%3,%1" | |
6357 | [(set_attr "length" "*,4,8") | |
6358 | (set_attr "predicable" "yes,no,no") | |
6359 | (set_attr "iscompact" "maybe,false,false") | |
6360 | (set_attr "cond" "canuse,nocond,nocond")]) | |
6361 | ||
6362 | (define_insn "*add_shift2" | |
6363 | [(set (match_operand:SI 0 "register_operand" "=q,r,r") | |
6364 | (plus:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal") | |
6365 | (ashift:SI (match_operand:SI 2 "register_operand" "q,r,r") | |
6366 | (match_operand:SI 3 "_1_2_3_operand" ""))))] | |
6367 | "" | |
6368 | "add%3%?\\t%0,%1,%2" | |
6369 | [(set_attr "length" "*,4,8") | |
6370 | (set_attr "predicable" "yes,no,no") | |
6371 | (set_attr "iscompact" "maybe,false,false") | |
6372 | (set_attr "cond" "canuse,nocond,nocond")]) | |
6373 | ||
6374 | (define_insn "*sub_shift" | |
6375 | [(set (match_operand:SI 0"register_operand" "=r,r,r") | |
6376 | (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal") | |
6377 | (ashift:SI (match_operand:SI 2 "register_operand" "r,r,r") | |
6378 | (match_operand:SI 3 "_1_2_3_operand" ""))))] | |
6379 | "" | |
6380 | "sub%3\\t%0,%1,%2" | |
6381 | [(set_attr "length" "4,4,8") | |
6382 | (set_attr "cond" "canuse,nocond,nocond") | |
6383 | (set_attr "predicable" "yes,no,no")]) | |
6384 | ||
6385 | (define_insn "*sub_shift_cmp0_noout" | |
6386 | [(set (match_operand 0 "cc_set_register" "") | |
6387 | (compare:CC | |
6388 | (minus:SI (match_operand:SI 1 "register_operand" "r") | |
6389 | (ashift:SI (match_operand:SI 2 "register_operand" "r") | |
6390 | (match_operand:SI 3 "_1_2_3_operand" ""))) | |
6391 | (const_int 0)))] | |
6392 | "" | |
6393 | "sub%3.f\\t0,%1,%2" | |
6394 | [(set_attr "length" "4")]) | |
6395 | ||
6396 | (define_insn "*compare_si_ashiftsi" | |
6397 | [(set (match_operand 0 "cc_set_register" "") | |
6398 | (compare:CC (match_operand:SI 1 "register_operand" "r") | |
6399 | (ashift:SI (match_operand:SI 2 "register_operand" "r") | |
6400 | (match_operand:SI 3 "_1_2_3_operand" ""))))] | |
6401 | "" | |
6402 | "sub%3.f\\t0,%1,%2" | |
6403 | [(set_attr "length" "4")]) | |
6404 | ||
6405 | ;; Convert the sequence | |
6406 | ;; asl rd,rn,_1_2_3 | |
6407 | ;; cmp ra,rd | |
6408 | ;; into | |
6409 | ;; sub{123}.f 0,ra,rn | |
6410 | (define_peephole2 | |
6411 | [(set (match_operand:SI 0 "register_operand" "") | |
6412 | (ashift:SI (match_operand:SI 1 "register_operand" "") | |
6413 | (match_operand:SI 2 "_1_2_3_operand" ""))) | |
6414 | (set (reg:CC CC_REG) | |
6415 | (compare:CC (match_operand:SI 3 "register_operand" "") | |
6416 | (match_dup 0)))] | |
6417 | "peep2_reg_dead_p (2, operands[0])" | |
6418 | [(set (reg:CC CC_REG) (compare:CC (match_dup 3) | |
6419 | (ashift:SI (match_dup 1) (match_dup 2))))]) | |
6420 | ||
8fa2c211 CZ |
6421 | (define_peephole2 ; std |
6422 | [(set (match_operand:SI 2 "memory_operand" "") | |
6423 | (match_operand:SI 0 "register_operand" "")) | |
6424 | (set (match_operand:SI 3 "memory_operand" "") | |
6425 | (match_operand:SI 1 "register_operand" ""))] | |
6426 | "TARGET_LL64" | |
6427 | [(const_int 0)] | |
6428 | { | |
6429 | if (!gen_operands_ldd_std (operands, false, false)) | |
6430 | FAIL; | |
6431 | operands[0] = gen_rtx_REG (DImode, REGNO (operands[0])); | |
6432 | operands[2] = adjust_address (operands[2], DImode, 0); | |
6433 | emit_insn (gen_rtx_SET (operands[2], operands[0])); | |
6434 | DONE; | |
6435 | }) | |
6436 | ||
6437 | (define_peephole2 ; ldd | |
6438 | [(set (match_operand:SI 0 "register_operand" "") | |
6439 | (match_operand:SI 2 "memory_operand" "")) | |
6440 | (set (match_operand:SI 1 "register_operand" "") | |
6441 | (match_operand:SI 3 "memory_operand" ""))] | |
6442 | "TARGET_LL64" | |
6443 | [(const_int 0)] | |
6444 | { | |
6445 | if (!gen_operands_ldd_std (operands, true, false)) | |
6446 | FAIL; | |
6447 | operands[0] = gen_rtx_REG (DImode, REGNO (operands[0])); | |
6448 | operands[2] = adjust_address (operands[2], DImode, 0); | |
6449 | emit_insn (gen_rtx_SET (operands[0], operands[2])); | |
6450 | DONE; | |
6451 | }) | |
6452 | ||
6453 | ;; We require consecutive registers for LDD instruction. Check if we | |
6454 | ;; can reorder them and use an LDD. | |
6455 | ||
6456 | (define_peephole2 ; swap the destination registers of two loads | |
6457 | ; before a commutative operation. | |
6458 | [(set (match_operand:SI 0 "register_operand" "") | |
6459 | (match_operand:SI 2 "memory_operand" "")) | |
6460 | (set (match_operand:SI 1 "register_operand" "") | |
6461 | (match_operand:SI 3 "memory_operand" "")) | |
6462 | (set (match_operand:SI 4 "register_operand" "") | |
6463 | (match_operator:SI 5 "commutative_operator" | |
6464 | [(match_operand 6 "register_operand" "") | |
6465 | (match_operand 7 "register_operand" "") ]))] | |
6466 | "TARGET_LL64 | |
6467 | && (((rtx_equal_p (operands[0], operands[6])) | |
6468 | && (rtx_equal_p (operands[1], operands[7]))) | |
6469 | || ((rtx_equal_p (operands[0], operands[7])) | |
6470 | && (rtx_equal_p (operands[1], operands[6])))) | |
6471 | && (peep2_reg_dead_p (3, operands[0]) | |
6472 | || rtx_equal_p (operands[0], operands[4])) | |
6473 | && (peep2_reg_dead_p (3, operands[1]) | |
6474 | || rtx_equal_p (operands[1], operands[4]))" | |
6475 | [(set (match_dup 0) (match_dup 2)) | |
6476 | (set (match_dup 4) (match_op_dup 5 [(match_dup 6) (match_dup 7)]))] | |
6477 | { | |
6478 | if (!gen_operands_ldd_std (operands, true, true)) | |
6479 | { | |
6480 | FAIL; | |
6481 | } | |
6482 | else | |
6483 | { | |
6484 | operands[0] = gen_rtx_REG (DImode, REGNO (operands[0])); | |
6485 | operands[2] = adjust_address (operands[2], DImode, 0); | |
6486 | } | |
6487 | } | |
6488 | ) | |
6489 | ||
90b48013 CZ |
6490 | (define_insn "*push_multi_fp" |
6491 | [(match_parallel 0 "push_multi_operand" | |
6492 | [(set (reg:SI SP_REG) | |
6493 | (plus:SI (reg:SI SP_REG) | |
6494 | (match_operand 1 "immediate_operand" ""))) | |
6495 | (set (mem:SI (plus:SI (reg:SI SP_REG) | |
f5d56cf9 CZ |
6496 | (match_operand 2 "immediate_operand" |
6497 | ""))) | |
90b48013 CZ |
6498 | (reg:SI 13))])] |
6499 | "TARGET_CODE_DENSITY" | |
6500 | { | |
6501 | int len = XVECLEN (operands[0], 0); | |
6502 | rtx tmp = XVECEXP (operands[0], 0, len - 1); | |
6503 | if (MEM_P (XEXP (tmp, 0))) | |
6504 | { | |
f5d56cf9 CZ |
6505 | operands[3] = XEXP (tmp, 1); |
6506 | return "enter_s\\t{r13-%3} ; sp=sp+(%1)"; | |
90b48013 CZ |
6507 | } |
6508 | else | |
6509 | { | |
6510 | tmp = XVECEXP (operands[0], 0, len - 3); | |
f5d56cf9 CZ |
6511 | operands[3] = XEXP (tmp, 1); |
6512 | return "enter_s\\t{r13-%3, fp} ; sp=sp+(%1)"; | |
90b48013 CZ |
6513 | } |
6514 | } | |
6515 | [(set_attr "type" "call_no_delay_slot") | |
6516 | (set_attr "length" "2")]) | |
6517 | ||
6518 | (define_insn "*push_multi_fp_blink" | |
6519 | [(match_parallel 0 "push_multi_operand" | |
6520 | [(set (reg:SI SP_REG) | |
6521 | (plus:SI (reg:SI SP_REG) | |
6522 | (match_operand 1 "immediate_operand" ""))) | |
6523 | (set (mem:SI (plus:SI (reg:SI SP_REG) | |
f5d56cf9 CZ |
6524 | (match_operand 2 "immediate_operand" |
6525 | ""))) | |
90b48013 CZ |
6526 | (reg:SI RETURN_ADDR_REGNUM))])] |
6527 | "TARGET_CODE_DENSITY" | |
6528 | { | |
6529 | int len = XVECLEN (operands[0], 0); | |
6530 | rtx tmp = XVECEXP (operands[0], 0, len - 1); | |
6531 | if (MEM_P (XEXP (tmp, 0))) | |
6532 | { | |
f5d56cf9 CZ |
6533 | operands[3] = XEXP (tmp, 1); |
6534 | return "enter_s\\t{r13-%3, blink} ; sp=sp+(%1)"; | |
90b48013 CZ |
6535 | } |
6536 | else | |
6537 | { | |
6538 | tmp = XVECEXP (operands[0], 0, len - 3); | |
f5d56cf9 CZ |
6539 | operands[3] = XEXP (tmp, 1); |
6540 | return "enter_s\\t{r13-%3, fp, blink} ; sp=sp+(%1)"; | |
90b48013 CZ |
6541 | } |
6542 | } | |
6543 | [(set_attr "type" "call_no_delay_slot") | |
6544 | (set_attr "length" "2")]) | |
6545 | ||
6546 | (define_insn "*pop_multi_fp" | |
6547 | [(match_parallel 0 "pop_multi_operand" | |
6548 | [(set (reg:SI SP_REG) | |
6549 | (plus:SI (reg:SI SP_REG) | |
6550 | (match_operand 1 "immediate_operand" ""))) | |
6551 | (set (reg:SI 13) | |
6552 | (mem:SI | |
6553 | (plus:SI | |
6554 | (reg:SI SP_REG) | |
6555 | (match_operand 2 "immediate_operand" ""))))])] | |
6556 | "TARGET_CODE_DENSITY" | |
6557 | { | |
6558 | int len = XVECLEN (operands[0], 0); | |
6559 | rtx tmp = XVECEXP (operands[0], 0, len - 1); | |
47d8cb23 | 6560 | if (XEXP (tmp, 0) != hard_frame_pointer_rtx) |
90b48013 CZ |
6561 | { |
6562 | operands[3] = XEXP (tmp, 0); | |
6563 | gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); | |
6564 | return "leave_s\\t{r13-%3} ; sp=sp+%1"; | |
6565 | } | |
6566 | else | |
6567 | { | |
6568 | tmp = XVECEXP (operands[0], 0, len - 2); | |
6569 | operands[3] = XEXP (tmp, 0); | |
6570 | return "leave_s\\t{r13-%3, fp} ; sp=sp+%1"; | |
6571 | } | |
6572 | } | |
6573 | [(set_attr "type" "call_no_delay_slot") | |
6574 | (set_attr "length" "2")]) | |
6575 | ||
6576 | (define_insn "*pop_multi_fp_blink" | |
6577 | [(match_parallel 0 "pop_multi_operand" | |
6578 | [(set (reg:SI SP_REG) | |
6579 | (plus:SI (reg:SI SP_REG) | |
6580 | (match_operand 1 "immediate_operand" ""))) | |
6581 | (set (reg:SI RETURN_ADDR_REGNUM) | |
6582 | (mem:SI | |
6583 | (plus:SI | |
6584 | (reg:SI SP_REG) | |
6585 | (match_operand 2 "immediate_operand" ""))))])] | |
6586 | "TARGET_CODE_DENSITY" | |
6587 | { | |
6588 | int len = XVECLEN (operands[0], 0); | |
6589 | rtx tmp = XVECEXP (operands[0], 0, len - 1); | |
47d8cb23 | 6590 | if (XEXP (tmp, 0) != hard_frame_pointer_rtx) |
90b48013 CZ |
6591 | { |
6592 | operands[3] = XEXP (tmp, 0); | |
6593 | gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); | |
6594 | return "leave_s\\t{r13-%3, blink} ; sp=sp+%1"; | |
6595 | } | |
6596 | else | |
6597 | { | |
6598 | tmp = XVECEXP (operands[0], 0, len - 2); | |
6599 | operands[3] = XEXP (tmp, 0); | |
6600 | return "leave_s\\t{r13-%3, fp, blink} ; sp=sp+%1"; | |
6601 | } | |
6602 | } | |
6603 | [(set_attr "type" "call_no_delay_slot") | |
6604 | (set_attr "length" "2")]) | |
6605 | ||
6606 | (define_insn "*pop_multi_fp_ret" | |
6607 | [(match_parallel 0 "pop_multi_operand" | |
6608 | [(return) | |
6609 | (set (reg:SI SP_REG) | |
6610 | (plus:SI (reg:SI SP_REG) | |
6611 | (match_operand 1 "immediate_operand" ""))) | |
6612 | (set (reg:SI 13) | |
6613 | (mem:SI | |
6614 | (plus:SI | |
6615 | (reg:SI SP_REG) | |
6616 | (match_operand 2 "immediate_operand" ""))))])] | |
6617 | "TARGET_CODE_DENSITY" | |
6618 | { | |
6619 | int len = XVECLEN (operands[0], 0); | |
6620 | rtx tmp = XVECEXP (operands[0], 0, len - 1); | |
47d8cb23 | 6621 | if (XEXP (tmp, 0) != hard_frame_pointer_rtx) |
90b48013 CZ |
6622 | { |
6623 | operands[3] = XEXP (tmp, 0); | |
6624 | gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); | |
6625 | return "leave_s\\t{r13-%3, pcl} ; sp=sp+%1"; | |
6626 | } | |
6627 | else | |
6628 | { | |
6629 | tmp = XVECEXP (operands[0], 0, len - 2); | |
6630 | operands[3] = XEXP (tmp, 0); | |
6631 | return "leave_s\\t{r13-%3, fp, pcl} ; sp=sp+%1"; | |
6632 | } | |
6633 | } | |
6634 | [(set_attr "type" "call_no_delay_slot") | |
6635 | (set_attr "length" "2")]) | |
6636 | ||
6637 | (define_insn "*pop_multi_fp_blink_ret" | |
6638 | [(match_parallel 0 "pop_multi_operand" | |
6639 | [(return) | |
6640 | (set (reg:SI SP_REG) | |
6641 | (plus:SI (reg:SI SP_REG) | |
6642 | (match_operand 1 "immediate_operand" ""))) | |
6643 | (set (reg:SI RETURN_ADDR_REGNUM) | |
6644 | (mem:SI | |
6645 | (plus:SI | |
6646 | (reg:SI SP_REG) | |
6647 | (match_operand 2 "immediate_operand" ""))))])] | |
6648 | "TARGET_CODE_DENSITY" | |
6649 | { | |
6650 | int len = XVECLEN (operands[0], 0); | |
6651 | rtx tmp = XVECEXP (operands[0], 0, len - 1); | |
47d8cb23 | 6652 | if (XEXP (tmp, 0) != hard_frame_pointer_rtx) |
90b48013 CZ |
6653 | { |
6654 | operands[3] = XEXP (tmp, 0); | |
6655 | gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); | |
6656 | return "leave_s\\t{r13-%3, blink, pcl} ; sp=sp+%1"; | |
6657 | } | |
6658 | else | |
6659 | { | |
6660 | tmp = XVECEXP (operands[0], 0, len - 2); | |
6661 | operands[3] = XEXP (tmp, 0); | |
6662 | return "leave_s\\t{r13-%3, fp, blink, pcl} ; sp=sp+%1"; | |
6663 | } | |
6664 | } | |
6665 | [(set_attr "type" "call_no_delay_slot") | |
6666 | (set_attr "length" "2")]) | |
6667 | ||
3fd6ae8a CZ |
6668 | ;; Patterns for exception handling |
6669 | (define_insn_and_split "eh_return" | |
6670 | [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] | |
6671 | VUNSPEC_ARC_EH_RETURN)] | |
6672 | "" | |
6673 | "#" | |
6674 | "reload_completed" | |
6675 | [(const_int 0)] | |
6676 | " | |
6677 | { | |
6678 | arc_eh_return_address_location (operands[0]); | |
6679 | DONE; | |
6680 | }" | |
6681 | ) | |
526b7aee SV |
6682 | ;; include the arc-FPX instructions |
6683 | (include "fpx.md") | |
6684 | ||
8f3304d0 CZ |
6685 | ;; include the arc-FPU instructions |
6686 | (include "fpu.md") | |
6687 | ||
526b7aee | 6688 | (include "simdext.md") |
b8a64b7f CZ |
6689 | |
6690 | ;; include atomic extensions | |
6691 | (include "atomic.md") |