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